Merge fx-team to m-c
authorWes Kocher <wkocher@mozilla.com>
Wed, 21 May 2014 20:29:05 -0700
changeset 184336 b40296602083f9ce81f0a0945f7a92edd0282a90
parent 184327 4505506929eab5a6fc498aafba49c37d863cd7d9 (current diff)
parent 184335 0685ea0268b7d5714192a85fb433ddb5a16a605c (diff)
child 184344 4623a4cfe024870a77bfbfeeaffb9c9cc70eee07
child 184393 e06ed340ebcd63256c2503b4dccceae8bfd4ef2f
child 184402 3d4aedbd3784847b91e2ce04aa1e0f836b7d420a
push id26818
push userkwierso@gmail.com
push dateThu, 22 May 2014 03:29:24 +0000
treeherdermozilla-central@b40296602083 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone32.0a1
first release with
nightly linux32
b40296602083 / 32.0a1 / 20140522030204 / files
nightly linux64
b40296602083 / 32.0a1 / 20140522030204 / files
nightly mac
b40296602083 / 32.0a1 / 20140522030204 / files
nightly win32
b40296602083 / 32.0a1 / 20140522030204 / files
nightly win64
b40296602083 / 32.0a1 / 20140522030204 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge fx-team to m-c
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -1023,20 +1023,16 @@ var gBrowserInit = {
       else if (window.arguments.length >= 3) {
         loadURI(uriToLoad, window.arguments[2], window.arguments[3] || null,
                 window.arguments[4] || false);
         window.focus();
       }
       // Note: loadOneOrMoreURIs *must not* be called if window.arguments.length >= 3.
       // Such callers expect that window.arguments[0] is handled as a single URI.
       else {
-        if (uriToLoad == "about:newtab" &&
-            Services.prefs.getBoolPref("browser.newtabpage.enabled")) {
-          Services.telemetry.getHistogramById("NEWTAB_PAGE_SHOWN").add(true);
-        }
         loadOneOrMoreURIs(uriToLoad);
       }
     }
 
 #ifdef MOZ_SAFE_BROWSING
     // Bug 778855 - Perf regression if we do this here. To be addressed in bug 779008.
     setTimeout(function() { SafeBrowsing.init(); }, 2000);
 #endif
@@ -4447,21 +4443,16 @@ var TabsInTitlebar = {
       // Otherwise, get the height and margins separately for the menubar
       let menuHeight = rect(menubar).height;
       let menuStyles = window.getComputedStyle(menubar);
       let fullMenuHeight = verticalMargins(menuStyles) + menuHeight;
       let tabsStyles = window.getComputedStyle(tabsToolbar);
       fullTabsHeight += verticalMargins(tabsStyles);
 #endif
 
-      // If the navbar overlaps the tabbar using negative margins, we need to take those into
-      // account so we don't overlap it
-      let navbarMarginTop = parseFloat(window.getComputedStyle($("nav-bar")).marginTop);
-      navbarMarginTop = Math.min(navbarMarginTop, 0);
-
       // And get the height of what's in the titlebar:
       let titlebarContentHeight = rect(titlebarContent).height;
 
       // Begin setting CSS properties which will cause a reflow
 
       // If the menubar is around (menuHeight is non-zero), try to adjust
       // its full height (i.e. including margins) to match the titlebar,
       // by changing the menubar's bottom padding
@@ -4492,19 +4483,16 @@ var TabsInTitlebar = {
       // Next, we calculate how much we need to stretch the titlebar down to
       // go all the way to the bottom of the tab strip, if necessary.
       let tabAndMenuHeight = fullTabsHeight + fullMenuHeight;
 
       if (tabAndMenuHeight > titlebarContentHeight) {
         // We need to increase the titlebar content's outer height (ie including margins)
         // to match the tab and menu height:
         let extraMargin = tabAndMenuHeight - titlebarContentHeight;
-        // We need to reduce the height by the amount of navbar overlap
-        // (this value is 0 or negative):
-        extraMargin += navbarMarginTop;
         // On non-OSX, we can just use bottom margin:
 #ifndef XP_MACOSX
         titlebarContent.style.marginBottom = extraMargin + "px";
 #endif
         titlebarContentHeight += extraMargin;
       }
 
       // Then we bring up the titlebar by the same amount, but we add any negative margin:
--- a/browser/modules/ContentSearch.jsm
+++ b/browser/modules/ContentSearch.jsm
@@ -115,17 +115,22 @@ this.ContentSearch = {
           this._broadcast("State", this._currentStateObj());
         }
         break;
       }
     });
   },
 
   _reply: function (msg, type, data) {
-    msg.target.messageManager.sendAsyncMessage(...this._msgArgs(type, data));
+    // Due to _initService, we reply asyncly to messages, and by the time we
+    // reply the browser we're responding to may have been destroyed.  In that
+    // case messageManager is null.
+    if (msg.target.messageManager) {
+      msg.target.messageManager.sendAsyncMessage(...this._msgArgs(type, data));
+    }
   },
 
   _broadcast: function (type, data) {
     Cc["@mozilla.org/globalmessagemanager;1"].
       getService(Ci.nsIMessageListenerManager).
       broadcastAsyncMessage(...this._msgArgs(type, data));
   },
 
--- a/browser/themes/windows/browser-aero.css
+++ b/browser/themes/windows/browser-aero.css
@@ -183,34 +183,16 @@
     width: 1px;
   }
   #main-window[sizemode=normal] #browser-bottombox {
     border: 1px solid @toolbarShadowColor@;
     border-top-style: none;
     background-clip: padding-box;
   }
 
-  /* Toolbar shadow behind tabs */
-  #nav-bar {
-    border-top: 1px solid @toolbarShadowColor@ !important;
-    background-clip: padding-box;
-  }
-
-  /* This code is only needed for restored windows (i.e. sizemode=normal)
-     because of the border radius on the toolbar below the tab bar. */
-  #main-window[sizemode=normal] #nav-bar {
-    border-top: 1px solid @toolbarShadowColor@;
-    background-clip: padding-box;
-  }
-
-  /* Cover the top border of the adjacent toolbar */
-  #TabsToolbar {
-    margin-bottom: -1px;
-  }
-
   #main-window[sizemode=normal] #TabsToolbar {
     padding-left: 1px;
     padding-right: 1px;
   }
 
   /* Make the window draggable by glassed toolbars (bug 555081) */
   #toolbar-menubar:not([autohide="true"]),
   #TabsToolbar,
@@ -224,21 +206,16 @@
 
   #main-menubar:not(:-moz-lwtheme):not(:-moz-window-inactive) {
     background-color: rgba(255,255,255,.5);
     color: black;
   }
 
   @media (-moz-os-version: windows-vista),
          (-moz-os-version: windows-win7) {
-    #main-window[sizemode=normal] #nav-bar {
-      border-top-left-radius: 2.5px;
-      border-top-right-radius: 2.5px;
-    }
-
     #main-menubar:not(:-moz-lwtheme):not(:-moz-window-inactive) {
       border-radius: 4px;
     }
   }
 
   #ctrlTab-panel {
     background: transparent;
     -moz-appearance: -moz-win-glass;
@@ -252,25 +229,29 @@
   #tab-view:-moz-lwtheme {
     background-image: url("chrome://browser/skin/tabview/grain.png"),
                       linear-gradient(rgba(255,255,255,0), #CCD9EA 200px, #C7D5E7);
     background-attachment: fixed;
   }
 }
 
 @media (-moz-windows-glass) {
+  #main-window[sizemode=normal] #nav-bar {
+    border-top-left-radius: 2.5px;
+    border-top-right-radius: 2.5px;
+  }
+
   #main-window[sizemode=fullscreen]:not(:-moz-lwtheme) {
     -moz-appearance: none;
     background-color: #556;
   }
 
   /* Glass Fog */
 
   #TabsToolbar:not(:-moz-lwtheme) {
-    background-image: none;
     position: relative;
   }
 
   #TabsToolbar:not(:-moz-lwtheme)::after {
     /* Because we use placeholders for window controls etc. in the tabstrip,
      * and position those with ordinal attributes, and because our layout code
      * expects :before/:after nodes to come first/last in the frame list,
      * we have to reorder this element to come last, hence the
--- a/browser/themes/windows/browser.css
+++ b/browser/themes/windows/browser.css
@@ -91,20 +91,16 @@
   #main-window[tabsintitlebar]:not([inFullscreen]) #toolbar-menubar:not(:-moz-lwtheme):-moz-window-inactive,
   #main-window[tabsintitlebar]:not([inFullscreen]) #TabsToolbar:not(:-moz-lwtheme):-moz-window-inactive {
     color: InactiveCaptionText;
   }
 
   #main-window[tabsintitlebar] #main-menubar > menu:not(:-moz-lwtheme) {
     color: inherit;
   }
-
-  #TabsToolbar:-moz-lwtheme {
-    background: linear-gradient(to top, @toolbarShadowColor@ 2px, transparent 2px);
-  }
 %ifdef WINDOWS_AERO
 }
 %endif
 
 %ifdef WINDOWS_AERO
 @media not all and (-moz-windows-compositor) {
 %endif
   #main-window[tabsintitlebar] #titlebar:-moz-lwtheme {
@@ -267,27 +263,39 @@
         rgb(207, 214, 188) 0, rgb(207, 214, 188) 1px,
         rgb(224, 226, 200) 1px, rgb(224, 226, 200) 2px,
         rgb(214, 216, 190) 2px, rgb(214, 216, 190) 3px,
         transparent 3px);
   }
 }
 
 #TabsToolbar:not([collapsed="true"]) + #nav-bar {
-  margin-top: -@tabToolbarNavbarOverlap@; /* Move up into the TabsToolbar */
+  margin-top: -1px; /* Move up into the TabsToolbar for the inner highlight at the top of the nav-bar */
   /* Position the toolbar above the bottom of background tabs */
   position: relative;
   z-index: 1;
 }
 
 #nav-bar {
+  border-top: 1px solid @toolbarShadowColor@ !important;
+  background-clip: padding-box;
   background-image: linear-gradient(@toolbarHighlight@, rgba(255,255,255,0));
   box-shadow: 0 1px 0 @toolbarHighlight@ inset;
 }
 
+%ifdef WINDOWS_AERO
+@media not all and (-moz-windows-compositor) {
+%endif
+  #TabsToolbar[collapsed="true"] + #nav-bar {
+    border-top-style: none !important;
+  }
+%ifdef WINDOWS_AERO
+}
+%endif
+
 #personal-bookmarks {
   min-height: 24px;
 }
 
 #print-preview-toolbar:not(:-moz-lwtheme) {
   -moz-appearance: toolbox;
 }
 
@@ -1741,20 +1749,17 @@ toolbarbutton[type="socialmark"] > .tool
   text-shadow: none;
 }
 
 /* Tabstrip */
 
 #TabsToolbar {
   min-height: 0;
   padding: 0;
-}
-
-#main-window:not([customizing]) #TabsToolbar:not(:-moz-lwtheme) {
-  background-image: linear-gradient(to top, @toolbarShadowColor@ 2px, rgba(0,0,0,.05) 2px, transparent 50%);
+  margin-bottom: -@tabToolbarNavbarOverlap@; /* overlap the nav-bar's top border */
 }
 
 #main-window[tabsintitlebar] #TabsToolbar {
   background-color: transparent;
 }
 
 %ifndef WINDOWS_AERO
 @media (-moz-windows-default-theme) {
--- a/mobile/android/base/prompts/IconGridInput.java
+++ b/mobile/android/base/prompts/IconGridInput.java
@@ -12,16 +12,17 @@ import org.json.JSONArray;
 import org.json.JSONObject;
 import org.mozilla.gecko.GeckoAppShell;
 import org.mozilla.gecko.R;
 import org.mozilla.gecko.gfx.BitmapUtils;
 
 import android.content.Context;
 import android.graphics.drawable.Drawable;
 import android.text.TextUtils;
+import android.os.Build;
 import android.view.Display;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.WindowManager;
 import android.widget.AdapterView;
 import android.widget.AdapterView.OnItemClickListener;
 import android.widget.ArrayAdapter;
@@ -33,17 +34,17 @@ public class IconGridInput extends Promp
     public static final String INPUT_TYPE = "icongrid";
     public static final String LOGTAG = "GeckoIconGridInput";
 
     private ArrayAdapter<IconGridItem> mAdapter; // An adapter holding a list of items to show in the grid
 
     private static int mColumnWidth = -1;  // The maximum width of columns
     private static int mMaxColumns = -1;  // The maximum number of columns to show
     private static int mIconSize = -1;    // Size of icons in the grid
-    private int mSelected = -1;           // Current selection
+    private int mSelected = 0;           // Current selection
     private JSONArray mArray;
 
     public IconGridInput(JSONObject obj) {
         super(obj);
         mArray = obj.optJSONArray("items");
     }
 
     @Override
@@ -71,22 +72,27 @@ public class IconGridInput extends Promp
         view.setColumnWidth(mColumnWidth);
 
         final ArrayList<IconGridItem> items = new ArrayList<IconGridItem>(mArray.length());
         for (int i = 0; i < mArray.length(); i++) {
             IconGridItem item = new IconGridItem(context, mArray.optJSONObject(i));
             items.add(item);
             if (item.selected) {
                 mSelected = i;
-                view.setSelection(i);
             }
         }
 
         view.setNumColumns(Math.min(items.size(), maxColumns));
         view.setOnItemClickListener(this);
+        // Despite what the docs say, setItemChecked was not moved into the AbsListView class until sometime between
+        // Android 2.3.7 and Android 4.0.3. For other versions the item won't be visually highlighted, BUT we really only
+        // mSelected will still be set so that we default to its behavior.
+        if (Build.VERSION.SDK_INT >= 11 && mSelected > -1) {
+            view.setItemChecked(mSelected, true);
+        }
 
         mAdapter = new IconGridAdapter(context, -1, items);
         view.setAdapter(mAdapter);
         mView = view;
         return mView;
     }
 
     @Override
--- a/mobile/android/base/resources/drawable/icon_grid_item_bg.xml
+++ b/mobile/android/base/resources/drawable/icon_grid_item_bg.xml
@@ -14,13 +14,15 @@
      limitations under the License.
 -->
 
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
 
     <item android:state_focused="true"
           android:state_pressed="true"
           android:drawable="@drawable/grid_icon_bg_focused" />
+
     <item android:state_activated="true"
           android:drawable="@drawable/grid_icon_bg_activated" />
+
     <item android:drawable="@android:color/transparent" />
 
 </selector>
--- a/mobile/android/base/widget/GeckoActionProvider.java
+++ b/mobile/android/base/widget/GeckoActionProvider.java
@@ -4,16 +4,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.widget;
 
 import org.mozilla.gecko.GeckoAppShell;
 import org.mozilla.gecko.Telemetry;
 import org.mozilla.gecko.TelemetryContract;
 import org.mozilla.gecko.menu.MenuItemActionView;
+import org.mozilla.gecko.util.ThreadUtils;
 
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.graphics.drawable.Drawable;
 import android.view.MenuItem;
 import android.view.MenuItem.OnMenuItemClickListener;
@@ -177,27 +178,33 @@ public class GeckoActionProvider {
     }
 
     /**
      * Listener for handling default activity / menu item clicks.
      */
     private class Callbacks implements OnMenuItemClickListener,
                                        OnClickListener {
         private void chooseActivity(int index) { 
-            ActivityChooserModel dataModel = ActivityChooserModel.get(mContext, mHistoryFileName);
-            Intent launchIntent = dataModel.chooseActivity(index);
+            final ActivityChooserModel dataModel = ActivityChooserModel.get(mContext, mHistoryFileName);
+            final Intent launchIntent = dataModel.chooseActivity(index);
             if (launchIntent != null) {
-                // Share image syncrhonously downloads the image before sharing it.
-                String type = launchIntent.getType();
-                if (Intent.ACTION_SEND.equals(launchIntent.getAction()) && type != null && type.startsWith("image/")) {
-                    GeckoAppShell.downloadImageForIntent(launchIntent);
-                }
+                // This may cause a download to happen. Make sure we're on the background thread.
+                ThreadUtils.postToBackgroundThread(new Runnable() {
+                    @Override
+                    public void run() {
+                        // Share image downloads the image before sharing it.
+                        String type = launchIntent.getType();
+                        if (Intent.ACTION_SEND.equals(launchIntent.getAction()) && type != null && type.startsWith("image/")) {
+                            GeckoAppShell.downloadImageForIntent(launchIntent);
+                        }
 
-                launchIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
-                mContext.startActivity(launchIntent);
+                        launchIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
+                        mContext.startActivity(launchIntent);
+                    }
+                });
             }
 
             if (mOnTargetListener != null) {
                 mOnTargetListener.onTargetSelected();
             }
         }
 
         @Override
--- a/mobile/android/chrome/content/aboutReader.js
+++ b/mobile/android/chrome/content/aboutReader.js
@@ -284,20 +284,18 @@ AboutReader.prototype = {
 
   _onReaderToggle: function Reader_onToggle() {
     if (!this._article)
       return;
 
     this._isReadingListItem = (this._isReadingListItem == 1) ? 0 : 1;
     this._updateToggleButton();
 
-    // Create a relative timestamp for telemetry
-    let uptime = Date.now() - Services.startup.getStartupInfo().linkerInitialized;
-
     if (this._isReadingListItem == 1) {
+      let uptime = UITelemetry.uptimeMillis();
       gChromeWin.Reader.storeArticleInCache(this._article, function(success) {
         dump("Reader:Add (in reader) success=" + success);
 
         let result = gChromeWin.Reader.READER_ADD_FAILED;
         if (success) {
           result = gChromeWin.Reader.READER_ADD_SUCCESS;
           UITelemetry.addEvent("save.1", "button", uptime, "reader");
         }
@@ -315,33 +313,31 @@ AboutReader.prototype = {
         });
       }.bind(this));
     } else {
       // In addition to removing the article from the cache (handled in
       // browser.js), sending this message will cause the toggle button to be
       // updated (handled in this file).
       Services.obs.notifyObservers(null, "Reader:Remove", this._article.url);
 
-      UITelemetry.addEvent("unsave.1", "button", uptime, "reader");
+      UITelemetry.addEvent("unsave.1", "button", null, "reader");
     }
   },
 
   _onShare: function Reader_onShare() {
     if (!this._article)
       return;
 
     gChromeWin.sendMessageToJava({
       type: "Reader:Share",
       url: this._article.url,
       title: this._article.title
     });
 
-    // Create a relative timestamp for telemetry
-    let uptime = Date.now() - Services.startup.getStartupInfo().linkerInitialized;
-    UITelemetry.addEvent("share.1", "list", uptime);
+    UITelemetry.addEvent("share.1", "list", null);
   },
 
   _setFontSize: function Reader_setFontSize(newFontSize) {
     let bodyClasses = this._doc.body.classList;
 
     if (this._fontSize > 0)
       bodyClasses.remove("font-size" + this._fontSize);
 
@@ -699,21 +695,19 @@ AboutReader.prototype = {
       segmentedButton.appendChild(item);
 
       link.addEventListener("click", function(aEvent) {
         if (!aEvent.isTrusted)
           return;
 
         aEvent.stopPropagation();
 
-        // Create a relative timestamp for telemetry
-        let uptime = Date.now() - Services.startup.getStartupInfo().linkerInitialized;
         // Just pass the ID of the button as an extra and hope the ID doesn't change
         // unless the context changes
-        UITelemetry.addEvent("action.1", "button", uptime, id);
+        UITelemetry.addEvent("action.1", "button", null, id);
 
         let items = segmentedButton.children;
         for (let j = items.length - 1; j >= 0; j--) {
           items[j].classList.remove("selected");
         }
 
         item.classList.add("selected");
         callback(option.value);
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -7358,47 +7358,42 @@ let Reader = {
       });
     },
 
     readerModeActiveCallback: function(){
       sendMessageToJava({
         type: "Reader:LongClick",
       });
 
-      // Create a relative timestamp for telemetry
-      let uptime = Date.now() - Services.startup.getStartupInfo().linkerInitialized;
-      UITelemetry.addEvent("save.1", "pageaction", uptime, "reader");
+      UITelemetry.addEvent("save.1", "pageaction", null, "reader");
     },
   },
 
   updatePageAction: function(tab) {
     if (this.pageAction.id) {
       NativeWindow.pageactions.remove(this.pageAction.id);
       delete this.pageAction.id;
     }
 
-    // Create a relative timestamp for telemetry
-    let uptime = Date.now() - Services.startup.getStartupInfo().linkerInitialized;
-
     if (tab.readerActive) {
       this.pageAction.id = NativeWindow.pageactions.add({
         title: Strings.browser.GetStringFromName("readerMode.exit"),
         icon: "drawable://reader_active",
         clickCallback: this.pageAction.readerModeCallback,
         important: true
       });
 
       // Only start a reader session if the viewer is in the foreground. We do
       // not track background reader viewers.
-      UITelemetry.startSession("reader.1", uptime);
+      UITelemetry.startSession("reader.1", null);
       return;
     }
 
     // Only stop a reader session if the foreground viewer is not visible.
-    UITelemetry.stopSession("reader.1", "", uptime);
+    UITelemetry.stopSession("reader.1", "", null);
 
     if (tab.readerEnabled) {
       this.pageAction.id = NativeWindow.pageactions.add({
         title: Strings.browser.GetStringFromName("readerMode.enter"),
         icon: "drawable://reader",
         clickCallback:this.pageAction.readerModeCallback,
         longClickCallback: this.pageAction.readerModeActiveCallback,
         important: true
@@ -7962,19 +7957,17 @@ var ExternalApps = {
     if (this._pageActionId != undefined)
       return;
 
     this._pageActionId = NativeWindow.pageactions.add({
       title: Strings.browser.GetStringFromName("openInApp.pageAction"),
       icon: "drawable://icon_openinapp",
 
       clickCallback: () => {
-        // Create a relative timestamp for telemetry
-        let uptime = Date.now() - Services.startup.getStartupInfo().linkerInitialized;
-        UITelemetry.addEvent("launch.1", "pageaction", uptime, "helper");
+        UITelemetry.addEvent("launch.1", "pageaction", null, "helper");
 
         if (apps.length > 1) {
           // Use the HelperApps prompt here to filter out any Http handlers
           HelperApps.prompt(apps, {
             title: Strings.browser.GetStringFromName("openInApp.pageAction"),
             buttons: [
               Strings.browser.GetStringFromName("openInApp.ok"),
               Strings.browser.GetStringFromName("openInApp.cancel")
--- a/mobile/android/components/HelperAppDialog.js
+++ b/mobile/android/components/HelperAppDialog.js
@@ -129,16 +129,17 @@ HelperAppLauncherDialog.prototype = {
       mimeType: aLauncher.MIMEInfo.MIMEType,
     });
 
     // Add a fake intent for save to disk at the top of the list.
     apps.unshift({
       name: bundle.GetStringFromName("helperapps.saveToDisk"),
       packageName: "org.mozilla.gecko.Download",
       iconUri: "drawable://icon",
+      selected: true, // Default to download for files
       launch: function() {
         // Reset the preferredAction here.
         aLauncher.MIMEInfo.preferredAction = Ci.nsIMIMEInfo.saveToDisk;
         aLauncher.saveToDisk(null, false);
         return true;
       }
     });
 
--- a/toolkit/components/telemetry/UITelemetry.jsm
+++ b/toolkit/components/telemetry/UITelemetry.jsm
@@ -80,16 +80,25 @@ this.UITelemetry = {
   /**
    * Holds the functions that provide UITelemetry's simple
    * measurements. Those functions are mapped to unique names,
    * and should be registered with addSimpleMeasureFunction.
    */
   _simpleMeasureFunctions: {},
 
   /**
+   * A hack to generate the relative timestamp from start when we don't have
+   * access to the Java timer.
+   * XXX: Bug 1007647 - Support realtime and/or uptime in JavaScript.
+   */
+  uptimeMillis: function() {
+    return Date.now() - Services.startup.getStartupInfo().process;
+  },
+
+  /**
    * Adds a single event described by a timestamp, an action, and the calling
    * method.
    *
    * Optionally provide a string 'extras', which will be recorded as part of
    * the event.
    *
    * All extant sessions will be recorded by name for each event.
    */
@@ -99,17 +108,17 @@ this.UITelemetry = {
     }
 
     let sessions = Object.keys(this._activeSessions);
     let aEvent = {
       type: "event",
       action: aAction,
       method: aMethod,
       sessions: sessions,
-      timestamp: aTimestamp,
+      timestamp: (aTimestamp == undefined) ? this.uptimeMillis() : aTimestamp,
     };
 
     if (aExtras) {
       aEvent.extras = aExtras;
     }
 
     this._recordEvent(aEvent);
   },
@@ -121,17 +130,17 @@ this.UITelemetry = {
     if (!this.enabled) {
       return;
     }
 
     if (this._activeSessions[aName]) {
       // Do not overwrite a previous event start if it already exists.
       return;
     }
-    this._activeSessions[aName] = aTimestamp;
+    this._activeSessions[aName] = (aTimestamp == undefined) ? this.uptimeMillis() : aTimestamp;
   },
 
   /**
    * Tracks the end of a session with a timestamp.
    */
   stopSession: function(aName, aReason, aTimestamp) {
     if (!this.enabled) {
       return;
@@ -144,17 +153,17 @@ this.UITelemetry = {
       return;
     }
 
     let aEvent = {
       type: "session",
       name: aName,
       reason: aReason,
       start: sessionStart,
-      end: aTimestamp,
+      end: (aTimestamp == undefined) ? this.uptimeMillis() : aTimestamp,
     };
 
     this._recordEvent(aEvent);
   },
 
   _recordEvent: function(aEvent) {
     this._measurements.push(aEvent);
   },
--- a/widget/windows/nsNativeThemeWin.cpp
+++ b/widget/windows/nsNativeThemeWin.cpp
@@ -3841,17 +3841,16 @@ RENDER_AGAIN:
       break;
     }
 
     case NS_THEME_WINDOW_TITLEBAR:
     case NS_THEME_WINDOW_TITLEBAR_MAXIMIZED:
     {
       RECT rect = widgetRect;
       int32_t offset = GetSystemMetrics(SM_CXFRAME);
-      rect.bottom -= 1;
 
       // first fill the area to the color of the window background
       FillRect(hdc, &rect, (HBRUSH)(COLOR_3DFACE+1));
 
       // inset the caption area so it doesn't overflow.
       rect.top += offset;
       // if enabled, draw a gradient titlebar background, otherwise
       // fill with a solid color.