merge fx-team into m-c
authorGavin Sharp <gavin@gavinsharp.com>
Fri, 23 Mar 2012 16:20:23 -0700
changeset 93443 8bc3c696e0a7cdf4ad64e27c69b919fea253eeb1
parent 93440 6470fe2fc4de48077605605aa052448c6586b7a6 (current diff)
parent 93442 4173214920c3dab17c187375eb53b73e95eea3c6 (diff)
child 93444 1699897f0c0527f9052280e4ebb133a31b2e2432
push id886
push userlsblakk@mozilla.com
push dateMon, 04 Jun 2012 19:57:52 +0000
treeherdermozilla-beta@bbd8d5efd6d1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone14.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
merge fx-team into m-c
browser/base/content/abouthome/aboutHome.xhtml
browser/base/content/browser.js
--- a/browser/base/content/abouthome/aboutHome.css
+++ b/browser/base/content/abouthome/aboutHome.css
@@ -250,16 +250,17 @@ body[narrow] #launcher[session] > .launc
 .launchButton:hover:active {
   background-image: -moz-linear-gradient(hsla(211,79%,6%,.02), hsla(211,79%,6%,.05));
   border-color: hsla(210,54%,20%,.2) hsla(210,54%,20%,.23) hsla(210,54%,20%,.25);
   box-shadow: 0 1px 1px hsla(211,79%,6%,.05) inset,
               0 0 1px hsla(211,79%,6%,.1) inset;
   -moz-transition-duration: 0ms;
 }
 
+.launchButton[hidden],
 #launcher:not([session]) > #restorePreviousSessionSeparator,
 #launcher:not([session]) > #restorePreviousSession {
   display: none;
 }
 
 #restorePreviousSessionSeparator {
   width: 3px;
   height: 116px;
@@ -293,38 +294,42 @@ body[narrow] #restorePreviousSession {
 
 .launchButton::before {
   display: block;
   height: 32px;
   margin-bottom: 6px;
   line-height: 0; /* remove extra vertical space due to non-zero font-size */
 }
 
+#downloads::before {
+  content: url("chrome://browser/content/abouthome/downloads.png");
+}
+
 #bookmarks::before {
   content: url("chrome://browser/content/abouthome/bookmarks.png");
 }
 
 #history::before {
   content: url("chrome://browser/content/abouthome/history.png");
 }
 
-#settings::before {
-  content: url("chrome://browser/content/abouthome/settings.png");
+#apps::before {
+  content: url("chrome://browser/content/abouthome/apps.png");
 }
 
 #addons::before {
   content: url("chrome://browser/content/abouthome/addons.png");
 }
 
-#downloads::before {
-  content: url("chrome://browser/content/abouthome/downloads.png");
+#sync::before {
+  content: url("chrome://browser/content/abouthome/sync.png");
 }
 
-#sync::before {
-  content: url("chrome://browser/content/abouthome/sync.png");
+#settings::before {
+  content: url("chrome://browser/content/abouthome/settings.png");
 }
 
 #restorePreviousSession::before {
   content: url("chrome://browser/content/abouthome/restore-large.png");
   height: 48px;
   width: 48px;
   display: inline-block; /* display on same line as text label */
   vertical-align: middle;
--- a/browser/base/content/abouthome/aboutHome.xhtml
+++ b/browser/base/content/abouthome/aboutHome.xhtml
@@ -87,21 +87,22 @@
           <span id="defaultSnippet2">&abouthome.defaultSnippet2.v1;</span>
         </div>
         <div id="snippets"/>
       </div>
     </div>
     <div class="spacer"/>
 
     <div id="launcher" session="true">
+      <button class="launchButton" id="downloads">&abouthome.downloadsButton.label;</button>
       <button class="launchButton" id="bookmarks">&abouthome.bookmarksButton.label;</button>
       <button class="launchButton" id="history">&abouthome.historyButton.label;</button>
-      <button class="launchButton" id="settings">&abouthome.settingsButton.label;</button>
+      <button class="launchButton" id="apps" hidden="true">&abouthome.appsButton.label;</button>
       <button class="launchButton" id="addons">&abouthome.addonsButton.label;</button>
-      <button class="launchButton" id="downloads">&abouthome.downloadsButton.label;</button>
       <button class="launchButton" id="sync">&syncBrand.shortName.label;</button>
+      <button class="launchButton" id="settings">&abouthome.settingsButton.label;</button>
       <div id="restorePreviousSessionSeparator"/>
       <button class="launchButton" id="restorePreviousSession">&historyRestoreLastSession.label;</button>
     </div>
 
-    <a id="aboutMozilla" href="http://www.mozilla.com/about/"/>
+    <a id="aboutMozilla" href="http://www.mozilla.org/about/"/>
   </body>
 </html>
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..c6907b2006fa30d7aec833e3cff99706014babac
GIT binary patch
literal 438
zc$@*Y0ZIOeP)<h;3K|Lk000e1NJLTq001BW001Be1^@s6b9#F80004fNkl<ZSi`kf
z%Wi})44j~@T4^bdo*{()|H&RYM%jqP4sjz{LMXAvPVBLPzZC#{0T?Ks{O7eg>L1Va
z2LMk13xJ&xx!D6mpstwdUuhE{vfQ{x0x&g#2-J~I^sfLOAiDjHBmgr*cqi=h8{;B9
zcqjXXY&SrN@lDa)gAZa+q7VW67(sO08x`-5D+ojq4Is2gi07K|O}x(^%b<iTDc6yQ
zT{AwMJ?=bRk^-d6j;q&RM)5Me1;lDlCW_>YwtuzOmX6+7BQY91pK3BG2eCIwwej*g
zwg%&yM@b)UMk4a83z>XZf`~lh#;8Hzj8Z1}()p3+RsiFFc%Lc&Brgz_3RhDx-TB-C
z;#NOl<#TH-m}{$`h0i6=wTfBQPgwa}^4wY{O#MU)pEvgt9(-QgPjtEGgA<?E_7lfk
zV7WglrCR%mXqgM{^0~F2Q0IacKDYD}mvey^pTFxTUgm;wI9-U&YdGx-{V&6*tPgJN
g`R%=O{SW#13ymv4XFC>~ZvX%Q07*qoM6N<$g36e}C;$Ke
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -2702,16 +2702,20 @@ function PageProxyClickHandler(aEvent)
 }
 
 /**
  *  Handle load of some pages (about:*) so that we can make modifications
  *  to the DOM for unprivileged pages.
  */
 function BrowserOnAboutPageLoad(document) {
   if (/^about:home$/i.test(document.documentURI)) {
+    // XXX bug 738646 - when Marketplace is launched, remove this statement and
+    // the hidden attribute set on the apps button in aboutHome.xhtml
+    if (getBoolPref("browser.aboutHome.apps", false))
+      document.getElementById("apps").removeAttribute("hidden");
     let ss = Components.classes["@mozilla.org/browser/sessionstore;1"].
              getService(Components.interfaces.nsISessionStore);
     if (!ss.canRestoreLastSession)
       document.getElementById("launcher").removeAttribute("session");
   }
 }
 
 /**
@@ -2844,34 +2848,37 @@ function BrowserOnClick(event) {
     else if (/^about:home$/i.test(ownerDoc.documentURI)) {
       if (ot == ownerDoc.getElementById("restorePreviousSession")) {
         let ss = Cc["@mozilla.org/browser/sessionstore;1"].
                  getService(Ci.nsISessionStore);
         if (ss.canRestoreLastSession)
           ss.restoreLastSession();
         ownerDoc.getElementById("launcher").removeAttribute("session");
       }
+      else if (ot == ownerDoc.getElementById("downloads")) {
+        BrowserDownloadsUI();
+      }
       else if (ot == ownerDoc.getElementById("bookmarks")) {
         PlacesCommandHook.showPlacesOrganizer("AllBookmarks");
       }
       else if (ot == ownerDoc.getElementById("history")) {
         PlacesCommandHook.showPlacesOrganizer("History");
       }
-      else if (ot == ownerDoc.getElementById("settings")) {
-        openPreferences();
+      else if (ot == ownerDoc.getElementById("apps")) {
+        openUILinkIn("https://marketplace.mozilla.org/", "tab");
       }
       else if (ot == ownerDoc.getElementById("addons")) {
         BrowserOpenAddonsMgr();
       }
-      else if (ot == ownerDoc.getElementById("downloads")) {
-        BrowserDownloadsUI();
-      }
       else if (ot == ownerDoc.getElementById("sync")) {
         openPreferences("paneSync");
       }
+      else if (ot == ownerDoc.getElementById("settings")) {
+        openPreferences();
+      }
     }
 }
 
 /**
  * Re-direct the browser to a known-safe page.  This function is
  * used when, for example, the user browses to a known malware page
  * and is presented with about:blocked.  The "Get me out of here!"
  * button should take the user to the default start page so that even
--- a/browser/base/jar.mn
+++ b/browser/base/jar.mn
@@ -16,22 +16,23 @@ browser.jar:
 *       content/browser/aboutDialog.js                (content/aboutDialog.js)
 *       content/browser/aboutDialog.css               (content/aboutDialog.css)
 *       content/browser/aboutRobots.xhtml             (content/aboutRobots.xhtml)
 *       content/browser/abouthome/aboutHome.xhtml     (content/abouthome/aboutHome.xhtml)
 *       content/browser/abouthome/aboutHome.js        (content/abouthome/aboutHome.js)
 *       content/browser/abouthome/aboutHome.css       (content/abouthome/aboutHome.css)
         content/browser/abouthome/snippet1.png        (content/abouthome/snippet1.png)
         content/browser/abouthome/snippet2.png        (content/abouthome/snippet2.png)
+        content/browser/abouthome/downloads.png       (content/abouthome/downloads.png)
         content/browser/abouthome/bookmarks.png       (content/abouthome/bookmarks.png)
         content/browser/abouthome/history.png         (content/abouthome/history.png)
-        content/browser/abouthome/settings.png        (content/abouthome/settings.png)
+        content/browser/abouthome/apps.png            (content/abouthome/apps.png)
         content/browser/abouthome/addons.png          (content/abouthome/addons.png)
-        content/browser/abouthome/downloads.png       (content/abouthome/downloads.png)
         content/browser/abouthome/sync.png            (content/abouthome/sync.png)
+        content/browser/abouthome/settings.png        (content/abouthome/settings.png)
         content/browser/abouthome/restore.png         (content/abouthome/restore.png)
         content/browser/abouthome/restore-large.png   (content/abouthome/restore-large.png)
         content/browser/abouthome/mozilla.png         (content/abouthome/mozilla.png)
         content/browser/abouthome/noise.png           (content/abouthome/noise.png)
         content/browser/aboutRobots-icon.png          (content/aboutRobots-icon.png)
         content/browser/aboutRobots-widget-left.png   (content/aboutRobots-widget-left.png)
 *       content/browser/browser.css                   (content/browser.css)
 *       content/browser/browser.js                    (content/browser.js)
--- a/browser/components/thumbnails/PageThumbs.jsm
+++ b/browser/components/thumbnails/PageThumbs.jsm
@@ -105,23 +105,40 @@ let PageThumbs = {
 
   /**
    * Captures a thumbnail for the given browser and stores it to the cache.
    * @param aBrowser The browser to capture a thumbnail for.
    * @param aCallback The function to be called when finished (optional).
    */
   captureAndStore: function PageThumbs_captureAndStore(aBrowser, aCallback) {
     let url = aBrowser.currentURI.spec;
+    let channel = aBrowser.docShell.currentDocumentChannel;
+    let originalURL = channel.originalURI.spec;
+
     this.capture(aBrowser.contentWindow, function (aInputStream) {
       let telemetryStoreTime = new Date();
 
       function finish(aSuccessful) {
         if (aSuccessful) {
           Services.telemetry.getHistogramById("FX_THUMBNAILS_STORE_TIME_MS")
             .add(new Date() - telemetryStoreTime);
+
+          // We've been redirected. Create a copy of the current thumbnail for
+          // the redirect source. We need to do this because:
+          //
+          // 1) Users can drag any kind of links onto the newtab page. If those
+          //    links redirect to a different URL then we want to be able to
+          //    provide thumbnails for both of them.
+          //
+          // 2) The newtab page should actually display redirect targets, only.
+          //    Because of bug 559175 this information can get lost when using
+          //    Sync and therefore also redirect sources appear on the newtab
+          //    page. We also want thumbnails for those.
+          if (url != originalURL)
+            PageThumbsCache._copy(url, originalURL);
         }
 
         if (aCallback)
           aCallback(aSuccessful);
       }
 
       // Get a writeable cache entry.
       PageThumbsCache.getWriteEntry(url, function (aEntry) {
@@ -202,16 +219,64 @@ let PageThumbsCache = {
    * @param aCallback The callback that is called when the cache entry is ready.
    */
   getWriteEntry: function Cache_getWriteEntry(aKey, aCallback) {
     // Try to open the desired cache entry.
     this._openCacheEntry(aKey, Ci.nsICache.ACCESS_WRITE, aCallback);
   },
 
   /**
+   * Copies an existing cache entry's data to a new cache entry.
+   * @param aSourceKey The key that contains the data to copy.
+   * @param aTargetKey The key that will be the copy of aSourceKey's data.
+   */
+  _copy: function Cache_copy(aSourceKey, aTargetKey) {
+    let sourceEntry, targetEntry, waitingCount = 2;
+
+    function finish() {
+      if (sourceEntry)
+        sourceEntry.close();
+
+      if (targetEntry)
+        targetEntry.close();
+    }
+
+    function copyDataWhenReady() {
+      if (--waitingCount > 0)
+        return;
+
+      if (!sourceEntry || !targetEntry) {
+        finish();
+        return;
+      }
+
+      let inputStream = sourceEntry.openInputStream(0);
+      let outputStream = targetEntry.openOutputStream(0);
+
+      // Copy the image data to a new entry.
+      NetUtil.asyncCopy(inputStream, outputStream, function (aResult) {
+        if (Components.isSuccessCode(aResult))
+          targetEntry.markValid();
+
+        finish();
+      });
+    }
+
+    this.getReadEntry(aSourceKey, function (aSourceEntry) {
+      sourceEntry = aSourceEntry;
+      copyDataWhenReady();
+    });
+
+    this.getWriteEntry(aTargetKey, function (aTargetEntry) {
+      targetEntry = aTargetEntry;
+      copyDataWhenReady();
+    });
+  },
+
+  /**
    * Opens the cache entry identified by the given key.
    * @param aKey The key identifying the desired cache entry.
    * @param aAccess The desired access mode (see nsICache.ACCESS_* constants).
    * @param aCallback The function to be called when the cache entry was opened.
    */
   _openCacheEntry: function Cache_openCacheEntry(aKey, aAccess, aCallback) {
     function onCacheEntryAvailable(aEntry, aAccessGranted, aStatus) {
       let validAccess = aAccess == aAccessGranted;
--- a/browser/components/thumbnails/test/Makefile.in
+++ b/browser/components/thumbnails/test/Makefile.in
@@ -8,14 +8,17 @@ srcdir		= @srcdir@
 VPATH		= @srcdir@
 relativesrcdir  = browser/components/thumbnails/test
 
 include $(DEPTH)/config/autoconf.mk
 include $(topsrcdir)/config/rules.mk
 
 _BROWSER_FILES = \
 	browser_thumbnails_capture.js \
+	browser_thumbnails_redirect.js \
 	browser_thumbnails_bug726727.js \
 	head.js \
+	background_red.html \
+	background_red_redirect.sjs \
 	$(NULL)
 
 libs::	$(_BROWSER_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/browser/components/thumbnails/test/background_red.html
@@ -0,0 +1,3 @@
+<html>
+  <body bgcolor=ff0000></body>
+</html>
new file mode 100644
--- /dev/null
+++ b/browser/components/thumbnails/test/background_red_redirect.sjs
@@ -0,0 +1,10 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+function handleRequest(aRequest, aResponse) {
+ // Set HTTP Status.
+ aResponse.setStatusLine(aRequest.httpVersion, 301, "Moved Permanently");
+
+ // Set redirect URI.
+ aResponse.setHeader("Location", "http://mochi.test:8888/browser/browser/components/thumbnails/test/background_red.html");
+}
new file mode 100644
--- /dev/null
+++ b/browser/components/thumbnails/test/browser_thumbnails_redirect.js
@@ -0,0 +1,51 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+const URL = "http://mochi.test:8888/browser/browser/components/thumbnails/" +
+            "test/background_red_redirect.sjs";
+
+let cacheService = Cc["@mozilla.org/network/cache-service;1"]
+                   .getService(Ci.nsICacheService);
+
+/**
+ * These tests ensure that we save and provide thumbnails for redirecting sites.
+ */
+function runTests() {
+  // Kick off history by loading a tab first or the test fails in single mode.
+  yield addTab(URL);
+  gBrowser.removeTab(gBrowser.selectedTab);
+
+  // Create a tab, redirecting to a page with a red background.
+  yield addTab(URL);
+  yield captureAndCheckColor(255, 0, 0, "we have a red thumbnail");
+
+  // Wait until the referrer's thumbnail's cache entry has been written.
+  yield whenCacheEntryExists(URL);
+  yield checkThumbnailColor(URL, 255, 0, 0, "referrer has a red thumbnail");
+}
+
+function whenCacheEntryExists(aKey) {
+  let callback = next;
+
+  checkCacheEntryExists(aKey, function (aExists) {
+    if (!aExists)
+      callback = function () whenCacheEntryExists(aKey);
+
+    executeSoon(callback);
+  });
+}
+
+function checkCacheEntryExists(aKey, aCallback) {
+  PageThumbsCache.getReadEntry(aKey, function (aEntry) {
+    let inputStream = aEntry && aEntry.openInputStream(0);
+    let exists = inputStream && inputStream.available();
+
+    if (inputStream)
+      inputStream.close();
+
+    if (aEntry)
+      aEntry.close();
+
+    aCallback(exists);
+  });
+}
--- a/browser/components/thumbnails/test/head.js
+++ b/browser/components/thumbnails/test/head.js
@@ -93,36 +93,48 @@ function whenLoaded(aElement, aCallback)
  * @param aBlue The blue component's intensity.
  * @param aMessage The info message to print when comparing the pixel color.
  */
 function captureAndCheckColor(aRed, aGreen, aBlue, aMessage) {
   let browser = gBrowser.selectedBrowser;
 
   // Capture the screenshot.
   PageThumbs.captureAndStore(browser, function () {
-    let width = 100, height = 100;
-    let thumb = PageThumbs.getThumbnailURL(browser.currentURI.spec, width, height);
+    checkThumbnailColor(browser.currentURI.spec, aRed, aGreen, aBlue, aMessage);
+  });
+}
 
-    getXULDocument(function (aDocument) {
-      let htmlns = "http://www.w3.org/1999/xhtml";
-      let img = aDocument.createElementNS(htmlns, "img");
-      img.setAttribute("src", thumb);
+/**
+ * Retrieve a thumbnail from the cache and compare its pixel color values.
+ * @param aURL The URL of the thumbnail's page.
+ * @param aRed The red component's intensity.
+ * @param aGreen The green component's intensity.
+ * @param aBlue The blue component's intensity.
+ * @param aMessage The info message to print when comparing the pixel color.
+ */
+function checkThumbnailColor(aURL, aRed, aGreen, aBlue, aMessage) {
+  let width = 100, height = 100;
+  let thumb = PageThumbs.getThumbnailURL(aURL, width, height);
 
-      whenLoaded(img, function () {
-        let canvas = aDocument.createElementNS(htmlns, "canvas");
-        canvas.setAttribute("width", width);
-        canvas.setAttribute("height", height);
+  getXULDocument(function (aDocument) {
+    let htmlns = "http://www.w3.org/1999/xhtml";
+    let img = aDocument.createElementNS(htmlns, "img");
+    img.setAttribute("src", thumb);
 
-        // Draw the image to a canvas and compare the pixel color values.
-        let ctx = canvas.getContext("2d");
-        ctx.drawImage(img, 0, 0, width, height);
-        checkCanvasColor(ctx, aRed, aGreen, aBlue, aMessage);
+    whenLoaded(img, function () {
+      let canvas = aDocument.createElementNS(htmlns, "canvas");
+      canvas.setAttribute("width", width);
+      canvas.setAttribute("height", height);
 
-        next();
-      });
+      // Draw the image to a canvas and compare the pixel color values.
+      let ctx = canvas.getContext("2d");
+      ctx.drawImage(img, 0, 0, width, height);
+      checkCanvasColor(ctx, aRed, aGreen, aBlue, aMessage);
+
+      next();
     });
   });
 }
 
 /**
  * Passes a XUL document (created if necessary) to the given callback.
  * @param aCallback The function to be called when the XUL document has been
  *                  created. The first argument will be the document.