Bug 677630 - Extend 'Add to Home Screen' to Bookmark Popup [r=mbrubeck]
authorMark Finkle <mfinkle@mozilla.com>
Tue, 09 Aug 2011 21:32:22 -0400
changeset 75222 04dfb49d3a3d3469be379c76405f18f3592ac48b
parent 75221 2805d0fc9d91f4548e563bf78d1a1023a773c9a6
child 75223 a00864f6c1a7122f46d74a974d200eedcd8c30fa
push idunknown
push userunknown
push dateunknown
reviewersmbrubeck
bugs677630
milestone8.0a1
Bug 677630 - Extend 'Add to Home Screen' to Bookmark Popup [r=mbrubeck]
mobile/chrome/content/BookmarkHelper.js
mobile/chrome/content/BookmarkPopup.js
mobile/chrome/content/ContextCommands.js
mobile/chrome/content/browser.xul
mobile/locales/en-US/chrome/browser.dtd
mobile/themes/core/browser.css
mobile/themes/core/gingerbread/browser.css
--- a/mobile/chrome/content/BookmarkHelper.js
+++ b/mobile/chrome/content/BookmarkHelper.js
@@ -68,16 +68,41 @@ var BookmarkHelper = {
     // this method is called, since this method is called via the "close" event.
     this._editor.parentNode.removeChild(this._editor);
     this._editor = null;
 
     BrowserUI.popDialog();
     this.box.hidden = true;
   },
 
+  createShortcut: function BH_createShortcut(aTitle, aURL, aIconURL) {
+    const kIconSize = 64;
+
+    let canvas = document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
+    canvas.setAttribute("style", "display: none");
+
+    let self = this;
+    let image = new Image();
+    image.onload = function() {
+      canvas.width = canvas.height = kIconSize; // clears the canvas
+      let ctx = canvas.getContext("2d");
+      ctx.drawImage(image, 0, 0, kIconSize, kIconSize);
+      let icon = canvas.toDataURL("image/png", "");
+      canvas = null;
+      try {
+        let shell = Cc["@mozilla.org/browser/shell-service;1"].createInstance(Ci.nsIShellService);
+        shell.createShortcut(aTitle, aURL, icon, "bookmark");
+      } catch(e) {
+        Cu.reportError(e);
+      }
+    }
+
+    image.src = aIconURL;
+  },
+
   removeBookmarksForURI: function BH_removeBookmarksForURI(aURI) {
     //XXX blargle xpconnect! might not matter, but a method on
     // nsINavBookmarksService that takes an array of items to
     // delete would be faster. better yet, a method that takes a URI!
     let itemIds = PlacesUtils.getBookmarksForURI(aURI);
     itemIds.forEach(PlacesUtils.bookmarks.removeItem);
 
     BrowserUI.updateStar();
--- a/mobile/chrome/content/BookmarkPopup.js
+++ b/mobile/chrome/content/BookmarkPopup.js
@@ -38,10 +38,17 @@ var BookmarkPopup = {
     BrowserUI.pushPopup(this, [this.box, button]);
   },
 
   toggle : function toggle() {
     if (this.box.hidden)
       this.show();
     else
       this.hide();
+  },
+
+  addToHome: function addToHome() {
+    this.hide();
+
+    let browser = getBrowser();
+    BookmarkHelper.createShortcut(browser.contentTitle, browser.currentURI.spec, browser.mIconURL);
   }
 };
--- a/mobile/chrome/content/ContextCommands.js
+++ b/mobile/chrome/content/ContextCommands.js
@@ -106,33 +106,12 @@ var ContextCommands = {
   },
 
   removeBookmark: function cc_removeBookmark() {
     let target = ContextHelper.popupState.target;
     target.remove();
   },
 
   shortcutBookmark: function cc_shortcutBookmark() {
-    const kIconSize = 64;
-
     let target = ContextHelper.popupState.target;
-    let canvas = document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
-    canvas.setAttribute("style", "display: none");
-
-    let self = this;
-    let image = new Image();
-    image.onload = function() {
-      canvas.width = canvas.height = kIconSize; // clears the canvas
-      let ctx = canvas.getContext("2d");
-      ctx.drawImage(image, 0, 0, kIconSize, kIconSize);
-      let icon = canvas.toDataURL("image/png", "");
-      canvas = null;
-      try {
-        let shell = Cc["@mozilla.org/browser/shell-service;1"].createInstance(Ci.nsIShellService);
-        shell.createShortcut(target.getAttribute("title"), target.getAttribute("uri"), icon, "bookmark");
-      } catch(e) {
-        Cu.reportError(e);
-      }
-    }
-
-    image.src = target.getAttribute("src");
+    BookmarkHelper.createShortcut(target.getAttribute("title"), target.getAttribute("uri"), target.getAttribute("src"));
   }
 };
--- a/mobile/chrome/content/browser.xul
+++ b/mobile/chrome/content/browser.xul
@@ -352,24 +352,33 @@
         <pageaction id="pageaction-reset" title="&pageactions.reset;"
           onclick="PageActions.clearPagePermissions(event);"/>
         <pageaction id="pageaction-search" title="&pageactions.search.addNew;"/>
         <pageaction id="pageaction-charset" title="&pageactions.charEncoding;" onclick="CharsetMenu.show();"/>
         <pageaction id="pageaction-webapps-install" title="&pageactions.webapps.install;" onclick="WebappsUI.show();"/>
       </hbox>
     </arrowbox>
 
-    <arrowbox id="bookmark-popup" class="arrowbox-dark" hidden="true" align="center" offset="12">
-      <label value="&bookmarkPopup.label;"/>
-      <separator class="thin"/>
-      <vbox>
-        <button id="bookmark-popup-edit" label="&bookmarkEdit.label;" oncommand="BookmarkHelper.edit();"/>
-        <spacer/>
-        <button id="bookmark-popup-remove" label="&bookmarkRemove.label;" oncommand="BookmarkPopup.hide(); BookmarkHelper.removeBookmarksForURI(getBrowser().currentURI);"/>
-      </vbox>
+    <arrowbox id="bookmark-popup" hidden="true" align="stretch" offset="12">
+      <hbox id="bookmark-popup-title">
+        <label value="&bookmarkPopup.label;"/>
+      </hbox>
+      <richlistbox id="bookmark-popup-commands" class="action-buttons" onclick="BookmarkPopup.hide();" flex="1">
+        <richlistitem class="action-button" id="bookmark-popup-edit" onclick="BookmarkHelper.edit();">
+          <label value="&bookmarkEdit.label;"/>
+        </richlistitem>
+        <richlistitem class="action-button" id="bookmark-popup-remove" onclick="BookmarkPopup.hide(); BookmarkHelper.removeBookmarksForURI(getBrowser().currentURI);">
+          <label value="&bookmarkRemove.label;"/>
+        </richlistitem>
+#ifdef ANDROID
+        <richlistitem class="action-button" id="bookmark-popup-shortcut" onclick="BookmarkPopup.addToHome();">
+          <label value="&bookmarkShortcut.label;"/>
+        </richlistitem>
+#endif
+      </richlistbox>
     </arrowbox>
 
     <box id="bookmark-container" class="perm-modal-block window-width window-height" hidden="true">
       <dialog id="bookmark-dialog" class="content-dialog" flex="1">
         <hbox id="bookmark-form-title" class="prompt-title">
           <description>&editBookmarkDialog.title;</description>
         </hbox>
         <separator id="bookmark-form-line" class="prompt-line"/>
--- a/mobile/locales/en-US/chrome/browser.dtd
+++ b/mobile/locales/en-US/chrome/browser.dtd
@@ -63,16 +63,17 @@
 <!ENTITY downloadFailed.label      "Failed">
 
 <!ENTITY noResults.label           "No results">
 <!ENTITY allBookmarks.label        "See all bookmarks">
 
 <!ENTITY bookmarkPopup.label       "Page Bookmarked">
 <!ENTITY bookmarkRemove.label      "Remove">
 <!ENTITY bookmarkEdit.label        "Edit">
+<!ENTITY bookmarkShortcut.label    "Add to Home Screen">
 
 <!ENTITY identity.unverifiedsite2 "This web site does not supply identity information.">
 <!ENTITY identity.connectedTo2 "Connected to">
 <!-- Localization note (identity.runBy2)
  The layout of the identity dialog prevents combining this into a single string with
  substitution variables.  If it is difficult to translate the sense of the string
  with that structure, consider a translation which ignores the preceding domain and
  just addresses the organization to follow, e.g. "This site is run by " -->
--- a/mobile/themes/core/browser.css
+++ b/mobile/themes/core/browser.css
@@ -1013,16 +1013,20 @@ documenttab[reload="true"] > stack > .do
   height: @sidebar_button_height@;
 }
 
 /* bookmark editor   ------------------------------------------------------- */
 #bookmark-form .bookmark-controls {
   display: none;
 }
 
+#bookmark-popup .action-button {
+  -moz-border-right-colors: white;
+}
+
 /* Identity popup   -------------------------------------------------------- */
 #identity-popup-container {
   padding: @padding_normal@; /* core spacing */
   padding-bottom: @padding_xxxnormal@;
 }
 
 /* Popup Icons */
 #identity-popup-icon {
@@ -1194,16 +1198,17 @@ pageaction:not([image]) > hbox >.pageact
   color: #414141;
 }
 
 .pageaction-desc[value=""] {
   display: none;
 }
 
 #share-title,
+#bookmark-popup-title,
 #context-hint {
   font-size: @font_small@;
   padding: @padding_small@;
 }
 
 #context-hint[value=""] {
   visibility: collapse;
 }
--- a/mobile/themes/core/gingerbread/browser.css
+++ b/mobile/themes/core/gingerbread/browser.css
@@ -976,16 +976,20 @@ documenttab[reload="true"] > stack > .do
   height: @sidebar_button_height@;
 }
 
 /* bookmark editor   ------------------------------------------------------- */
 #bookmark-form .bookmark-controls {
   display: none;
 }
 
+#bookmark-popup-title {
+  background-color: @color_background_default@;
+}
+
 /* Identity popup   -------------------------------------------------------- */
 #identity-popup-container {
   background-color: @color_background_panel@;
   padding: @padding_normal@; /* core spacing */
   padding-bottom: @padding_xxxnormal@;
 }
 
 /* Popup Icons */
@@ -1166,16 +1170,17 @@ pageaction:not([image]) > hbox >.pageact
   display: none;
 }
 
 #context-header {
   background-color: @color_background_default@;
 }
 
 #share-title,
+#bookmark-popup-title,
 #context-hint {
   color: @color_text_default@;
   font-size: @font_small@;
   padding: @padding_small@;
 }
 
 #context-hint[value=""] {
   visibility: collapse;