Bug 1162713 - Implement "Save Link to Pocket" context menu item. r=dolske
authorJared Wein <jwein@mozilla.com>
Thu, 14 May 2015 14:04:05 -0400
changeset 243956 d5a378327e88b886d397a978e5cba2937578c9eb
parent 243955 34a03726e05906e3c3cdb6676148114b92a13b78
child 243957 43512d4631b70cbe514131b4ee98644f86770b87
push id28761
push usercbook@mozilla.com
push dateFri, 15 May 2015 14:50:10 +0000
treeherdermozilla-central@c0e709a5baca [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdolske
bugs1162713
milestone41.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1162713 - Implement "Save Link to Pocket" context menu item. r=dolske
browser/base/content/browser-context.inc
browser/base/content/browser-pocket-de.properties
browser/base/content/browser-pocket-es-ES.properties
browser/base/content/browser-pocket-ja.properties
browser/base/content/browser-pocket-ru.properties
browser/base/content/browser-pocket.dtd
browser/base/content/nsContextMenu.js
browser/components/pocket/Pocket.jsm
--- a/browser/base/content/browser-context.inc
+++ b/browser/base/content/browser-context.inc
@@ -74,16 +74,20 @@
       <menuitem id="context-sharelink"
                 label="&shareLink.label;"
                 accesskey="&shareLink.accesskey;"
                 oncommand="gContextMenu.shareLink();"/>
       <menuitem id="context-savelink"
                 label="&saveLinkCmd.label;"
                 accesskey="&saveLinkCmd.accesskey;"
                 oncommand="gContextMenu.saveLink();"/>
+      <menuitem id="context-savelinktopocket"
+                label="&saveLinkToPocketCmd.label;"
+                accesskey="&saveLinkToPocketCmd.accesskey;"
+                oncommand="gContextMenu.saveLinkToPocket();"/>
       <menu id="context-marklinkMenu" label="&social.marklinkMenu.label;"
             accesskey="&social.marklinkMenu.accesskey;">
         <menupopup/>
       </menu>
       <menuitem id="context-copyemail"
                 label="&copyEmailCmd.label;"
                 accesskey="&copyEmailCmd.accesskey;"
                 oncommand="gContextMenu.copyEmail();"/>
@@ -264,17 +268,17 @@
                 oncommand="SocialShare.sharePage();"/>
       <menuitem id="context-savepage"
                 label="&savePageCmd.label;"
                 accesskey="&savePageCmd.accesskey2;"
                 oncommand="gContextMenu.savePageAs();"/>
       <menuitem id="context-pocket"
                 label="&saveToPocketCmd.label;"
                 accesskey="&saveToPocketCmd.accesskey;"
-                oncommand="gContextMenu.saveToPocket();"/>
+                oncommand="gContextMenu.savePageToPocket();"/>
       <menu id="context-markpageMenu" label="&social.markpageMenu.label;"
             accesskey="&social.markpageMenu.accesskey;">
         <menupopup/>
       </menu>
       <menuseparator id="context-sep-viewbgimage"/>
       <menuitem id="context-viewbgimage"
                 label="&viewBGImageCmd.label;"
                 accesskey="&viewBGImageCmd.accesskey;"
--- a/browser/base/content/browser-pocket-de.properties
+++ b/browser/base/content/browser-pocket-de.properties
@@ -6,9 +6,11 @@
 # browser.properties in the usual L10N location.
 
 pocket-button.label = Pocket
 pocket-button.tooltiptext = Bei Pocket speichern
 
 # From browser-pocket.dtd
 saveToPocketCmd.label = Seite bei Pocket speichern
 saveToPocketCmd.accesskey = k
+saveLinkToPocketCmd.label = Link in Pocket speichern
+saveLinkToPocketCmd.accesskey = o
 pocketMenuitem.label = Pocket-Liste anzeigen
--- a/browser/base/content/browser-pocket-es-ES.properties
+++ b/browser/base/content/browser-pocket-es-ES.properties
@@ -6,9 +6,11 @@
 # browser.properties in the usual L10N location.
 
 pocket-button.label = Pocket
 pocket-button.tooltiptext = Guardar en Pocket
 
 # From browser-pocket.dtd
 saveToPocketCmd.label = Guardar página en Pocket
 saveToPocketCmd.accesskey = k
+saveLinkToPocketCmd.label = Guardar enlace en Pocket
+saveLinkToPocketCmd.accesskey = k
 pocketMenuitem.label = Ver lista de Pocket
--- a/browser/base/content/browser-pocket-ja.properties
+++ b/browser/base/content/browser-pocket-ja.properties
@@ -6,9 +6,11 @@
 # browser.properties in the usual L10N location.
 
 pocket-button.label = Pocket
 pocket-button.tooltiptext = Pocket に保存
 
 # From browser-pocket.dtd
 saveToPocketCmd.label = Pocket にページを保存
 saveToPocketCmd.accesskey = k
+saveLinkToPocketCmd.label = Pocket にリンクを保存
+saveLinkToPocketCmd.accesskey = o
 pocketMenuitem.label = Pocket のマイリストを表示
--- a/browser/base/content/browser-pocket-ru.properties
+++ b/browser/base/content/browser-pocket-ru.properties
@@ -6,9 +6,11 @@
 # browser.properties in the usual L10N location.
 
 pocket-button.label = Pocket
 pocket-button.tooltiptext = Сохранить в Pocket
 
 # From browser-pocket.dtd
 saveToPocketCmd.label = Сохранить страницу в Pocket
 saveToPocketCmd.accesskey = х
+saveLinkToPocketCmd.label = Сохранить ссылку в Pocket
+saveLinkToPocketCmd.accesskey = P
 pocketMenuitem.label = Показать список Pocket
--- a/browser/base/content/browser-pocket.dtd
+++ b/browser/base/content/browser-pocket.dtd
@@ -2,9 +2,11 @@
    - License, v. 2.0. If a copy of the MPL was not distributed with this
    - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
 
 <!-- This is a temporary file and not meant for localization; later versions
    - of Firefox include these strings in browser.dtd -->
 
 <!ENTITY saveToPocketCmd.label     "Save Page to Pocket">
 <!ENTITY saveToPocketCmd.accesskey "k">
+<!ENTITY saveLinkToPocketCmd.label     "Save Link to Pocket">
+<!ENTITY saveLinkToPocketCmd.accesskey "o">
 <!ENTITY pocketMenuitem.label      "View Pocket List">
--- a/browser/base/content/nsContextMenu.js
+++ b/browser/base/content/nsContextMenu.js
@@ -1,16 +1,22 @@
 /* vim: set ts=2 sw=2 sts=2 et tw=80: */
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 Components.utils.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
 Components.utils.import("resource://gre/modules/InlineSpellChecker.jsm");
 Components.utils.import("resource://gre/modules/BrowserUtils.jsm");
+Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
+
+XPCOMUtils.defineLazyModuleGetter(this, "CustomizableUI",
+  "resource:///modules/CustomizableUI.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "Pocket",
+  "resource:///modules/Pocket.jsm");
 
 var gContextMenuContentData = null;
 
 function nsContextMenu(aXulMenu, aIsShift) {
   this.shouldDisplay = true;
   this.initMenu(aXulMenu, aIsShift);
 }
 
@@ -173,46 +179,57 @@ nsContextMenu.prototype = {
     // to be already loaded, since we load it on startup in nsBrowserGlue,
     // and CastingApps isn't, so check SimpleServiceDiscovery.services first
     // to avoid needing to load CastingApps.jsm if we don't need to.
     shouldShowCast = shouldShowCast && this.mediaURL &&
                      SimpleServiceDiscovery.services.length > 0 &&
                      CastingApps.getServicesForVideo(this.target).length > 0;
     this.setItemAttr("context-castvideo", "disabled", !shouldShowCast);
 
-    let canPocket = false;
-    if (shouldShow && window.gBrowser &&
-        this.browser.getTabBrowser() == window.gBrowser) {
-      let uri = this.browser.currentURI;
-      canPocket =
-        CustomizableUI.getPlacementOfWidget("pocket-button") &&
-        (uri.schemeIs("http") || uri.schemeIs("https") ||
-         (uri.schemeIs("about") && ReaderMode.getOriginalUrl(uri.spec)));
-      if (canPocket) {
-        let locale = Cc["@mozilla.org/chrome/chrome-registry;1"].
-                     getService(Ci.nsIXULChromeRegistry).
-                     getSelectedLocale("browser");
-        if (locale != "en-US") {
-          if (locale == "ja-JP-mac")
-            locale = "ja";
-          let url = "chrome://browser/content/browser-pocket-" + locale + ".properties";
-          let bundle = Services.strings.createBundle(url);
-          let item = document.getElementById("context-pocket");
-          try {
-            item.setAttribute("label", bundle.GetStringFromName("saveToPocketCmd.label"));
-            item.setAttribute("accesskey", bundle.GetStringFromName("saveToPocketCmd.accesskey"));
-          } catch (err) {
-            // GetStringFromName throws when the bundle doesn't exist.  In that
-            // case, the item will retain the browser-pocket.dtd en-US string that
-            // it has in the markup.
-          }
+    this.initPocketItems();
+  },
+
+  initPocketItems: function CM_initPocketItems() {
+    var showSaveCurrentPageToPocket = !(this.onTextInput || this.onLink ||
+                                        this.isContentSelected || this.onImage ||
+                                        this.onCanvas || this.onVideo || this.onAudio);
+    let targetURI = (this.onSaveableLink || this.onPlainTextLink) ? this.linkURI : this.browser.currentURI;
+    let canPocket = CustomizableUI.getPlacementOfWidget("pocket-button") &&
+                    window.pktApi && window.pktApi.isUserLoggedIn();
+    canPocket = canPocket && (targetURI.schemeIs("http") || targetURI.schemeIs("https") ||
+                              (targetURI.schemeIs("about") && ReaderMode.getOriginalUrl(targetURI.spec)));
+    canPocket = canPocket && window.gBrowser && this.browser.getTabBrowser() == window.gBrowser;
+
+    if (canPocket) {
+      let locale = Cc["@mozilla.org/chrome/chrome-registry;1"].
+                   getService(Ci.nsIXULChromeRegistry).
+                   getSelectedLocale("browser");
+      if (locale != "en-US") {
+        if (locale == "ja-JP-mac")
+          locale = "ja";
+        let url = "chrome://browser/content/browser-pocket-" + locale + ".properties";
+        let bundle = Services.strings.createBundle(url);
+        let saveToPocketItem = document.getElementById("context-pocket");
+        let saveLinkToPocketItem = document.getElementById("context-savelinktopocket");
+        try {
+          saveToPocketItem.setAttribute("label", bundle.GetStringFromName("saveToPocketCmd.label"));
+          saveToPocketItem.setAttribute("accesskey", bundle.GetStringFromName("saveToPocketCmd.accesskey"));
+          saveLinkToPocketItem.setAttribute("label", bundle.GetStringFromName("saveLinkToPocketCmd.label"));
+          saveLinkToPocketItem.setAttribute("accesskey", bundle.GetStringFromName("saveLinkToPocketCmd.accesskey"));
+        } catch (err) {
+          // GetStringFromName throws when the bundle doesn't exist.  In that
+          // case, the item will retain the browser-pocket.dtd en-US string that
+          // it has in the markup.
         }
       }
     }
-    this.showItem("context-pocket", canPocket && window.pktApi && window.pktApi.isUserLoggedIn());
+    this.showItem("context-pocket", canPocket && showSaveCurrentPageToPocket);
+    let showSaveLinkToPocket = canPocket && !showSaveCurrentPageToPocket &&
+                               (this.onSaveableLink || this.onPlainTextLink);
+    this.showItem("context-savelinktopocket", showSaveLinkToPocket);
   },
 
   initViewItems: function CM_initViewItems() {
     // View source is always OK, unless in directory listing.
     this.showItem("context-viewpartialsource-selection",
                   this.isContentSelected);
     this.showItem("context-viewpartialsource-mathml",
                   this.onMathML && !this.isContentSelected);
@@ -1656,30 +1673,22 @@ nsContextMenu.prototype = {
   shareSelect: function CM_shareSelect() {
     SocialShare.sharePage(null, { url: this.browser.currentURI.spec, text: this.textSelected }, this.target);
   },
 
   savePageAs: function CM_savePageAs() {
     saveDocument(this.browser.contentDocumentAsCPOW);
   },
 
-  saveToPocket: function CM_saveToPocket() {
-    let pocketWidget = document.getElementById("pocket-button");
-    let placement = CustomizableUI.getPlacementOfWidget("pocket-button");
-    if (!placement)
-      return;
+  saveLinkToPocket: function CM_saveLinkToPocket() {
+    Pocket.savePage(this.browser, this.linkURL);
+  },
 
-    if (placement.area == CustomizableUI.AREA_PANEL) {
-      PanelUI.show().then(function() {
-        pocketWidget = document.getElementById("pocket-button");
-        pocketWidget.doCommand();
-      });
-    } else {
-      pocketWidget.doCommand();
-    }
+  savePageToPocket: function CM_saveToPocket() {
+    Pocket.savePage(this.browser, this.browser.currentURI.spec, this.browser.contentTitle);
   },
 
   printFrame: function CM_printFrame() {
     PrintUtils.print(this.target.ownerDocument.defaultView, this.browser);
   },
 
   switchPageDirection: function CM_switchPageDirection() {
     this.browser.messageManager.sendAsyncMessage("SwitchDocumentDirection");
--- a/browser/components/pocket/Pocket.jsm
+++ b/browser/components/pocket/Pocket.jsm
@@ -22,24 +22,31 @@ let Pocket = {
   /**
    * Functions related to the Pocket panel UI.
    */
   onPanelViewShowing(event) {
     let document = event.target.ownerDocument;
     let window = document.defaultView;
     let iframe = document.getElementById('pocket-panel-iframe');
 
+    let urlToSave = Pocket._urlToSave;
+    let titleToSave = Pocket._titleToSave;
+    Pocket._urlToSave = null;
+    Pocket._titleToSave = null;
     // ViewShowing fires immediately before it creates the contents,
     // in lieu of an AfterViewShowing event, just spin the event loop.
     window.setTimeout(function() {
-      window.pktUI.pocketButtonOnCommand();
+      if (urlToSave) {
+        window.pktUI.tryToSaveUrl(urlToSave, titleToSave);
+      } else {
+        window.pktUI.pocketButtonOnCommand();
+      }
 
       if (iframe.contentDocument &&
-          iframe.contentDocument.readyState == "complete")
-      {
+          iframe.contentDocument.readyState == "complete") {
         window.pktUI.pocketPanelDidShow();
       } else {
         // iframe didn't load yet. This seems to always be the case when in
         // the toolbar panel, but never the case for a subview.
         // XXX this only being fired when it's a _capturing_ listener!
         iframe.addEventListener("load", Pocket.onFrameLoaded, true);
       }
     }, 0);
@@ -77,9 +84,31 @@ let Pocket = {
         node.disabled = win.pktApi.isUserLoggedIn() &&
                         !locationURI.schemeIs("http") &&
                         !locationURI.schemeIs("https") &&
                         !(locationURI.schemeIs("about") &&
                           locationURI.spec.toLowerCase().startsWith("about:reader?url="));
       }
     }
   },
+
+  _urlToSave: null,
+  _titleToSave: null,
+  savePage(browser, url, title) {
+    let document = browser.ownerDocument;
+    let pocketWidget = document.getElementById("pocket-button");
+    let placement = CustomizableUI.getPlacementOfWidget("pocket-button");
+    if (!placement)
+      return;
+
+    this._urlToSave = url;
+    this._titleToSave = title;
+    if (placement.area == CustomizableUI.AREA_PANEL) {
+      let win = document.defaultView;
+      win.PanelUI.show().then(function() {
+        pocketWidget = document.getElementById("pocket-button");
+        pocketWidget.doCommand();
+      });
+    } else {
+      pocketWidget.doCommand();
+    }
+  },
 };