Merge f-t to m-c
authorPhil Ringnalda <philringnalda@gmail.com>
Sun, 08 Dec 2013 18:55:10 -0800
changeset 174164 551efcc4de6f1c965179975e3b12ab9e9e4c208a
parent 174159 5c7612dcd6dc406da18f98719cdb1d74b6730098 (current diff)
parent 174163 ff66c30344abebe0aa9af2cbc551370337e4d4be (diff)
child 174165 1c599e4e665025063bc6219f45bddb64233f1a68
child 174166 e926070b0d18361ecabc60324690f142d2ea47a2
push id3224
push userlsblakk@mozilla.com
push dateTue, 04 Feb 2014 01:06:49 +0000
treeherdermozilla-beta@60c04d0987f1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone28.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 f-t to m-c
--- a/browser/metro/base/content/downloads.js
+++ b/browser/metro/base/content/downloads.js
@@ -13,18 +13,17 @@ var MetroDownloadsView = {
    * downloads if it starts before other downloads have completed.
    */
   _downloadCount: 0,
   _downloadsInProgress: 0,
   _lastDownload: null,
   _inited: false,
   _progressAlert: null,
   _lastSec: Infinity,
-  _notificationBox: null,
-  _progressNotification: null,
+
   _progressNotificationInfo: new Map(),
   _runDownloadBooleanMap: new Map(),
 
   get manager() {
     return Cc["@mozilla.org/download-manager;1"]
              .getService(Ci.nsIDownloadManager);
   },
 
@@ -51,38 +50,83 @@ var MetroDownloadsView = {
 
     this._inited = true;
 
     Services.obs.addObserver(this, "dl-start", true);
     Services.obs.addObserver(this, "dl-done", true);
     Services.obs.addObserver(this, "dl-run", true);
     Services.obs.addObserver(this, "dl-failed", true);
 
-    this._notificationBox = Browser.getNotificationBox();
 
     this._progress = new DownloadProgressListener(this);
     this.manager.addListener(this._progress);
 
+    Elements.tabList.addEventListener("TabClose", this, false);
+
     this._downloadProgressIndicator = document.getElementById("download-progress");
 
     if (this.manager.activeDownloadCount) {
       setTimeout (this._restartWithActiveDownloads.bind(this), 0);
     }
   },
 
   uninit: function dh_uninit() {
     if (this._inited) {
       Services.obs.removeObserver(this, "dl-start");
       Services.obs.removeObserver(this, "dl-done");
       Services.obs.removeObserver(this, "dl-run");
       Services.obs.removeObserver(this, "dl-failed");
+      if (Elements && Elements.tabList)
+        Elements.tabList.removeEventListener("TabClose", this);
     }
   },
 
-  _restartWithActiveDownloads: function() {
+  get _notificationBox() {
+    return Browser.getNotificationBox(Browser.selectedBrowser);
+  },
+
+  get _notificationBoxes() {
+    let currentBox = this._notificationBox;
+    let boxes = [
+      currentBox
+    ];
+    for (let { linkedBrowser } of Elements.tabList.children) {
+      if (linkedBrowser !== Browser.selectedBrowser) {
+        let notificationBox = Browser.getNotificationBox(linkedBrowser);
+        if (notificationBox)
+          boxes.push(notificationBox);
+      }
+    }
+    return boxes;
+  },
+
+  get _progressNotification() {
+    let notn = this._getNotificationWithValue("download-progress");
+    let currentBox = this._notificationBox;
+    // move the progress notification if attached to a different browser
+    if (notn && notn.parentNode !== currentBox) {
+      notn.parentNode.removeNotification(notn);
+      currentBox.insertBefore(notn, currentBox.firstChild);
+    }
+    return notn;
+  },
+
+  _getNotificationWithValue: function(aValue) {
+    let notn;
+    let allNotificationBoxes = this._notificationBoxes;
+    for(let box of allNotificationBoxes) {
+      notn = box.getNotificationWithValue(aValue);
+      if (notn) {
+        break;
+      }
+    }
+    return notn;
+  },
+
+   _restartWithActiveDownloads: function() {
     let activeDownloads = this.manager.activeDownloads;
 
     while (activeDownloads.hasMoreElements()) {
       let dl = activeDownloads.getNext();
       switch (dl.state) {
         case 0: // Downloading
         case 5: // Queued
           this.watchDownload(dl);
@@ -135,19 +179,19 @@ var MetroDownloadsView = {
         file.remove(false);
       this.manager.cancelDownload(aDownload.id);
 
       // If cancelling was successful, stop tracking the download.
       this._progressNotificationInfo.delete(aDownload.guid);
       this._runDownloadBooleanMap.delete(aDownload.targetFile.path);
       this._downloadCount--;
       this._downloadsInProgress--;
-      if (this._downloadsInProgress <= 0) {
-        this._notificationBox.removeNotification(this._progressNotification);
-        this._progressNotification = null;
+      let notn = this._progressNotification;
+      if (notn && this._downloadsInProgress <= 0) {
+        this._notificationBox.removeNotification(notn);
       }
     } catch (ex) {
       Util.dumpLn("Failed to cancel download, with id: "+aDownload.id+", download target URI spec: " + fileURI.spec);
       Util.dumpLn("Failed download source:"+(aDownload.source && aDownload.source.spec));
     }
   },
 
   // Cancels all downloads.
@@ -379,74 +423,77 @@ var MetroDownloadsView = {
       this._progressNotificationInfo.set(aDownload.guid, {});
     }
     let infoObj = this._progressNotificationInfo.get(aDownload.guid);
     infoObj.download = aDownload;
     this._progressNotificationInfo.set(aDownload.guid, infoObj);
   },
 
   onDownloadButton: function dv_onDownloadButton() {
-    if (this._downloadsInProgress) {
-      if (!this._removeNotification("download-progress")) {
-        this.updateInfobar();
-      }
-    } else if (this._downloadCount) {
-      if (!this._removeNotification("download-complete")) {
-        this._showDownloadCompleteNotification();
-      }
+    let progressNotification = this._getNotificationWithValue("download-progress");
+    let wasProgressVisible = (progressNotification &&
+                              progressNotification.parentNode == this._notificationBox);
+    let completeNotification = this._getNotificationWithValue("download-complete");
+    let wasCompleteVisible = (completeNotification &&
+                              completeNotification.parentNode == this._notificationBox);
+
+    this._removeNotification("download-complete");
+    this._removeNotification("download-progress");
+
+    if (this._downloadsInProgress && !wasProgressVisible) {
+      this.updateInfobar();
+    } else if (this._downloadCount && !wasCompleteVisible) {
+      this._showDownloadCompleteNotification();
     }
   },
 
   _removeNotification: function (aValue) {
-    let notification = this._notificationBox.getNotificationWithValue(aValue);
-    if (!notification) {
-      return false;
-    }
-    this._notificationBox.removeNotification(notification);
-    return true;
+    let notification = this._getNotificationWithValue(aValue);
+    return notification &&
+           notification.parentNode.removeNotification(notification);
   },
 
   updateInfobar: function dv_updateInfobar() {
     let message = this._computeDownloadProgressString();
     this._updateCircularProgressMeter();
 
-    if (this._progressNotification == null ||
-        !this._notificationBox.getNotificationWithValue("download-progress")) {
+    let notn = this._progressNotification;
+    if (!notn) {
       let cancelButtonText =
               Strings.browser.GetStringFromName("downloadCancel");
 
       let buttons = [
         {
           isDefault: false,
           label: cancelButtonText,
           accessKey: "",
           callback: function() {
             MetroDownloadsView.cancelDownloads();
             MetroDownloadsView._downloadProgressIndicator.reset();
           }
         }
       ];
 
-      this._progressNotification =
-        this.showNotification("download-progress", message, buttons,
-        this._notificationBox.PRIORITY_WARNING_LOW);
+      notn = this.showNotification("download-progress", message, buttons,
+             this._notificationBox.PRIORITY_WARNING_LOW);
 
       ContextUI.displayNavbar();
     } else {
-      this._progressNotification.label = message;
+      notn.label = message;
     }
   },
 
   updateDownload: function dv_updateDownload(aDownload) {
-    if (this._progressNotification != null) {
-      this._saveDownloadData(aDownload);
-      this._progressNotification.label =
+    this._saveDownloadData(aDownload);
+    let notn = this._progressNotification;
+    if (notn) {
+      notn.label =
         this._computeDownloadProgressString(aDownload);
-      this._updateCircularProgressMeter();
     }
+    this._updateCircularProgressMeter();
   },
 
   watchDownload: function dv_watchDownload(aDownload) {
     this._saveDownloadData(aDownload);
     this._downloadCount++;
     this._downloadsInProgress++;
     if (!this._progressNotificationInfo.get(aDownload.guid)) {
       this._progressNotificationInfo.set(aDownload.guid, {});
@@ -481,27 +528,44 @@ var MetroDownloadsView = {
         }
 
         this._runDownloadBooleanMap.delete(download.targetFile.path);
         if (this._downloadsInProgress == 0) {
           if (this._downloadCount > 1 || !runAfterDownload) {
             this._showDownloadCompleteToast();
             this._showDownloadCompleteNotification();
           }
-          this._notificationBox.removeNotification(this._progressNotification);
-          this._progressNotification = null;
+          let notn = this._progressNotification;
+          if (notn)
+            this._notificationBox.removeNotification(notn);
         }
         break;
       case "dl-failed":
         download = aSubject.QueryInterface(Ci.nsIDownload);
         this._showDownloadFailedNotification(download);
         break;
     }
   },
 
+  handleEvent: function(aEvent) {
+    switch (aEvent.type) {
+      case 'TabClose': {
+        let browser = aEvent.originalTarget.linkedBrowser;
+        dump("DownloadNotificationsView handleEvent, got TabClose event for browser: "+browser+"\n");
+        let notn = this._getNotificationWithValue("download-progress");
+        if (notn && notn.defaultView == browser.contentWindow) {
+          let nextTab = Browser.getNextTab(aEvent.originalTarget);
+          let box = Browser.getNotificationBox(nextTab.linkedBrowser);
+          box.insertBefore(notn, box.firstChild);
+        }
+        break;
+      }
+    }
+  },
+
   QueryInterface: function (aIID) {
     if (!aIID.equals(Ci.nsIObserver) &&
         !aIID.equals(Ci.nsISupportsWeakReference) &&
         !aIID.equals(Ci.nsISupports))
       throw Components.results.NS_ERROR_NO_INTERFACE;
     return this;
   }
 };
--- a/browser/themes/shared/devtools/toolbars.inc.css
+++ b/browser/themes/shared/devtools/toolbars.inc.css
@@ -483,26 +483,26 @@
 .devtools-tab {
   -moz-appearance: none;
   min-width: 32px;
   min-height: 32px;
   max-width: 127px;
   color: #b6babf;
   margin: 0;
   padding: 0;
-  border-left: 1px solid #42484f;
+  -moz-border-start: 1px solid #42484f;
   -moz-box-align: center;
 }
 
 .devtools-tab:first-child {
-  border-left-width: 0;
+  -moz-border-start-width: 0;
 }
 
 .devtools-tab:last-child {
-  border-right: 1px solid #5a6169;
+  -moz-border-end: 1px solid #42484f;
 }
 
 .devtools-tab > image {
   border: none;
   -moz-margin-end: 0;
   -moz-margin-start: 4px;
   opacity: 0.6;
   max-height: 16px;
@@ -517,17 +517,17 @@
   white-space: nowrap;
 }
 
 .devtools-tab:hover > image {
   opacity: 0.8;
 }
 
 .devtools-tab:active > image,
-.devtools-tab[selected=true] > label {
+.devtools-tab[selected=true] > image {
   opacity: 1;
 }
 
 .devtools-tab:hover {
   background-color: hsla(206,37%,4%,.2);
   color: #ced3d9;
 }
 
@@ -541,22 +541,26 @@
   background-color: #1a4666;
   border-width: 0;
   box-shadow: 0 2px 0 #d7f1ff inset,
               0 8px 3px -5px #2b82bf inset,
               0 -2px 0 rgba(0,0,0,.2) inset;
 }
 
 .devtools-tab[selected=true]:not(:first-child) {
-  padding-left: 1px;
+  -moz-padding-start: 1px;
+}
+
+.devtools-tab[selected=true]:last-child {
+  -moz-padding-end: 1px;
 }
 
 .devtools-tab[selected=true] + .devtools-tab {
-  border-left-width: 0;
-  padding-left: 1px;
+  -moz-border-start-width: 0;
+  -moz-padding-start: 1px;
 }
 
 .devtools-tab:not([selected=true]).highlighted {
   color: #f5f7fa;
   background-color: hsla(99,100%,14%,.2);
   box-shadow: 0 2px 0 #7bc107 inset;
 }