terminal: support osc 777 notify sequence for xterm.js

Change-Id: I705d47eb1e1511d19e72052b59ef322ff9a6618f
Reviewed-on: https://chromium-review.googlesource.com/c/apps/libapps/+/4387536
Reviewed-by: Joel Hockey <joelhockey@chromium.org>
Tested-by: kokoro <noreply+kokoro@google.com>
diff --git a/terminal/js/terminal_emulator.js b/terminal/js/terminal_emulator.js
index 83583a0..0d32bbf 100644
--- a/terminal/js/terminal_emulator.js
+++ b/terminal/js/terminal_emulator.js
@@ -125,6 +125,21 @@
 }
 
 /**
+ * Create a notification following hterm's style.
+ *
+ * @param {string} title
+ * @param {?string=} body
+ * @return {!Notification}
+ */
+function createNotification(title, body) {
+  const options = {icon: lib.resource.getDataUrl('hterm/images/icon-96')};
+  if (body) {
+    options.body = body;
+  }
+  return new Notification(`\u266A ${title} \u266A`, options);
+}
+
+/**
  * A "terminal io" class for xterm. We don't want the vanilla hterm.Terminal.IO
  * because it always convert utf8 data to strings, which is not necessary for
  * xterm.
@@ -250,9 +265,7 @@
 
     this.audio_?.play();
     if (this.showNotification && !document.hasFocus() && !this.notification_) {
-      this.notification_ = new Notification(
-          `\u266A ${document.title} \u266A`,
-          {icon: lib.resource.getDataUrl('hterm/images/icon-96')});
+      this.notification_ = createNotification(document.title);
       // Close the notification after a timeout. Note that this is different
       // from hterm's behavior, but I think it makes more sense to do so.
       setTimeout(() => {
@@ -657,6 +670,17 @@
       return true;
     });
 
+    // URxvt perl modules. We only support "notify".
+    this.term.parser.registerOscHandler(777, (args) => {
+      // Match 'notify;<title>[;<message>]'.
+      const match = args.match(/^notify;([^;]*)(?:;(.*))?$/);
+      if (match) {
+        createNotification(match[1], match[2]);
+      }
+
+      return true;
+    });
+
     this.xtermInternal_.installTmuxControlModeHandler(
         (data) => this.onTmuxControlModeLine(data));
     this.xtermInternal_.installEscKHandler();