Merge mozilla-central to autoland. a=merge CLOSED TREE
authorGurzau Raul <rgurzau@mozilla.com>
Sat, 20 Oct 2018 01:09:52 +0300
changeset 500719 a14911472fe733a76c7703a29e35440f8f1c75cd
parent 500718 a92220bcf4fee3a6ae87d76474cff73daf9c1471 (current diff)
parent 500717 9e9ca4e2ef17b85d0e49979049b227f3bd9915b1 (diff)
child 500720 9217bce3d56119840999271a3627f8a4b55b9d9d
push id1864
push userffxbld-merge
push dateMon, 03 Dec 2018 15:51:40 +0000
treeherdermozilla-release@f040763d99ad [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone64.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 mozilla-central to autoland. a=merge CLOSED TREE
browser/components/payments/res/paymentRequest.js
browser/components/payments/test/browser/browser_payments_onboarding_wizard.js
devtools/client/netmonitor/src/components/HeadersPanel.js
devtools/client/netmonitor/src/utils/mdn-utils.js
mobile/android/extensions/webcompat/webextension/background.js
mobile/android/extensions/webcompat/webextension/injections/js/bug0000000-dummy-js-injection.js
mobile/android/extensions/webcompat/webextension/injections/js/bug1452707-window.controllers-shim-ib.absa.co.za.js
mobile/android/extensions/webcompat/webextension/injections/js/bug1457335-histography.io-ua-change.js
mobile/android/extensions/webcompat/webextension/injections/js/bug1472075-bankofamerica.com-ua-change.js
mobile/android/extensions/webcompat/webextension/injections/js/bug1472081-election.gov.np-window.sidebar-shim.js
mobile/android/extensions/webcompat/webextension/injections/js/bug1482066-portalminasnet.com-window.sidebar-shim.js
--- a/browser/components/payments/res/containers/basic-card-form.js
+++ b/browser/components/payments/res/containers/basic-card-form.js
@@ -146,16 +146,20 @@ export default class BasicCardForm exten
       "basic-card-page": basicCardPage,
     } = state;
 
     if (this.id && page && page.id !== this.id) {
       log.debug(`BasicCardForm: no need to further render inactive page: ${page.id}`);
       return;
     }
 
+    if (!basicCardPage.selectedStateKey) {
+      throw new Error("A `selectedStateKey` is required");
+    }
+
     let editing = !!basicCardPage.guid;
     this.cancelButton.textContent = this.dataset.cancelButtonLabel;
     this.backButton.textContent = this.dataset.backButtonLabel;
     if (editing) {
       this.saveButton.textContent = this.dataset.updateButtonLabel;
     } else {
       this.saveButton.textContent = this.dataset.nextButtonLabel;
     }
--- a/browser/components/payments/res/mixins/PaymentStateSubscriberMixin.js
+++ b/browser/components/payments/res/mixins/PaymentStateSubscriberMixin.js
@@ -12,17 +12,17 @@ import PaymentsStore from "../PaymentsSt
  * State of the payment request dialog.
  */
 export let requestStore = new PaymentsStore({
   changesPrevented: false,
   orderDetailsShowing: false,
   "basic-card-page": {
     guid: null,
     // preserveFieldValues: true,
-    selectedStateKey: null,
+    selectedStateKey: "selectedPaymentCard",
   },
   "address-page": {
     guid: null,
     selectedStateKey: null,
     title: "",
   },
   "payment-summary": {
   },
--- a/browser/components/payments/res/paymentRequest.js
+++ b/browser/components/payments/res/paymentRequest.js
@@ -162,16 +162,19 @@ var paymentRequest = {
           title: paymentDialog.dataset.billingAddressTitleAdd,
         });
       }
     } else if (!hasSavedCards) {
       state.page = {
         id: "basic-card-page",
         onboardingWizard: true,
       };
+      state["basic-card-page"] = {
+        selectedStateKey: "selectedPaymentCard",
+      };
     }
 
     paymentDialog.setStateFromParent(state);
   },
 
   openPreferences() {
     this.sendMessageToChrome("openPreferences");
   },
--- a/browser/components/payments/test/browser/browser.ini
+++ b/browser/components/payments/test/browser/browser.ini
@@ -9,19 +9,19 @@ support-files =
 
 [browser_address_edit.js]
 skip-if = verify && debug && os == 'mac'
 [browser_card_edit.js]
 skip-if = os == 'linux' && debug # bug 1465673
 [browser_change_shipping.js]
 [browser_dropdowns.js]
 [browser_host_name.js]
+[browser_onboarding_wizard.js]
 [browser_openPreferences.js]
 [browser_payment_completion.js]
-[browser_payments_onboarding_wizard.js]
 [browser_profile_storage.js]
 [browser_request_serialization.js]
 [browser_request_shipping.js]
 [browser_retry.js]
 [browser_shippingaddresschange_error.js]
 [browser_show_dialog.js]
 skip-if = os == 'win' && debug # bug 1418385
 [browser_total.js]
rename from browser/components/payments/test/browser/browser_payments_onboarding_wizard.js
rename to browser/components/payments/test/browser/browser_onboarding_wizard.js
--- a/browser/components/payments/test/mochitest/test_basic_card_form.html
+++ b/browser/components/payments/test/mochitest/test_basic_card_form.html
@@ -88,16 +88,17 @@ add_task(async function test_backButton(
   let form = new BasicCardForm();
   form.dataset.backButtonLabel = "Back";
   form.dataset.addBasicCardTitle = "Sample page title 2";
   await form.requestStore.setState({
     page: {
       id: "basic-card-page",
     },
     "basic-card-page": {
+      selectedStateKey: "selectedPaymentCard",
     },
   });
   await form.promiseReady;
   display.appendChild(form);
   await asyncElementRendered();
 
   let stateChangePromise = promiseStateChange(form.requestStore);
   is(form.pageTitleHeading.textContent, "Sample page title 2", "Check title");
@@ -364,16 +365,17 @@ add_task(async function test_edit() {
     request: {
       paymentMethods,
     },
     page: {
       id: "basic-card-page",
     },
     "basic-card-page": {
       guid: card1.guid,
+      selectedStateKey: "selectedPaymentCard",
     },
     savedAddresses: {
       [address1.guid]: deepClone(address1),
     },
     savedBasicCards: {
       [card1.guid]: deepClone(card1),
     },
   });
@@ -417,16 +419,17 @@ add_task(async function test_edit() {
     guid: "9gnjdhen46",
   };
   await form.requestStore.setState({
     page: {
       id: "basic-card-page",
     },
     "basic-card-page": {
       guid: minimalCard.guid,
+      selectedStateKey: "selectedPaymentCard",
     },
     savedBasicCards: {
       [minimalCard.guid]: deepClone(minimalCard),
     },
   });
   await asyncElementRendered();
   ok(form.querySelectorAll(":-moz-ui-invalid").length > 0,
      "Check fields are visibly invalid on an 'edit' form with missing fields");
@@ -434,16 +437,17 @@ add_task(async function test_edit() {
 
   info("change to no selected card");
   await form.requestStore.setState({
     page: {
       id: "basic-card-page",
     },
     "basic-card-page": {
       guid: null,
+      selectedStateKey: "selectedPaymentCard",
     },
   });
   await asyncElementRendered();
   is(form.querySelectorAll(":-moz-ui-invalid").length, 0,
      "Check no fields are visibly invalid after converting to an 'add' form");
   checkCCForm(form, {
     billingAddressGUID: address1.guid, // Default selected
   });
@@ -521,16 +525,17 @@ add_task(async function test_numberCusto
   ok(form.querySelector("#cc-number:-moz-ui-invalid"), "cc-number field is visibly invalid");
 
   info("simulate triggering an add again to reset the form");
   await form.requestStore.setState({
     page: {
       id: "basic-card-page",
     },
     "basic-card-page": {
+      selectedStateKey: "selectedPaymentCard",
     },
   });
 
   ok(!form.querySelector("#cc-number:-moz-ui-invalid"), "cc-number field is not visibly invalid");
 
   form.remove();
 });
 
@@ -546,16 +551,17 @@ add_task(async function test_noCardNetwo
   delete card1["cc-type"];
 
   await form.requestStore.setState({
     page: {
       id: "basic-card-page",
     },
     "basic-card-page": {
       guid: card1.guid,
+      selectedStateKey: "selectedPaymentCard",
     },
     savedBasicCards: {
       [card1.guid]: deepClone(card1),
     },
   });
   await asyncElementRendered();
   checkCCForm(form, card1);
   is(document.getElementById("cc-type").selectedIndex, 0, "Initial empty option is selected");
--- a/browser/modules/Sanitizer.jsm
+++ b/browser/modules/Sanitizer.jsm
@@ -706,24 +706,16 @@ async function sanitizeOnShutdown(progre
 }
 
 async function sanitizeSessionPrincipals() {
   if (Services.prefs.getIntPref(PREF_COOKIE_LIFETIME,
                                 Ci.nsICookieService.ACCEPT_NORMALLY) != Ci.nsICookieService.ACCEPT_SESSION) {
     return;
   }
 
-  // When PREF_COOKIE_LIFETIME is set to ACCEPT_SESSION, any new cookie will be
-  // marked as session only. But we don't touch the existing ones. For this
-  // reason, here we delete any existing cookie, at shutdown.
-  await new Promise(resolve => {
-    Services.clearData.deleteData(Ci.nsIClearDataService.CLEAR_COOKIES,
-                                  resolve);
-  });
-
   let principals = await new Promise(resolve => {
     quotaManagerService.getUsage(request => {
       if (request.resultCode != Cr.NS_OK) {
         // We are probably shutting down. We don't want to propagate the
         // error, rejecting the promise.
         resolve([]);
         return;
       }
--- a/dom/file/MemoryBlobImpl.cpp
+++ b/dom/file/MemoryBlobImpl.cpp
@@ -13,16 +13,17 @@ namespace mozilla {
 namespace dom {
 
 NS_IMPL_ADDREF(MemoryBlobImpl::DataOwnerAdapter)
 NS_IMPL_RELEASE(MemoryBlobImpl::DataOwnerAdapter)
 
 NS_INTERFACE_MAP_BEGIN(MemoryBlobImpl::DataOwnerAdapter)
   NS_INTERFACE_MAP_ENTRY(nsIInputStream)
   NS_INTERFACE_MAP_ENTRY(nsISeekableStream)
+  NS_INTERFACE_MAP_ENTRY(nsITellableStream)
   NS_INTERFACE_MAP_ENTRY(nsICloneableInputStream)
   NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIIPCSerializableInputStream,
                                      mSerializableInputStream)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIInputStream)
 NS_INTERFACE_MAP_END
 
 nsresult MemoryBlobImpl::DataOwnerAdapter::Create(DataOwner* aDataOwner,
                                                   uint32_t aStart,
--- a/gfx/src/nsDeviceContext.cpp
+++ b/gfx/src/nsDeviceContext.cpp
@@ -74,19 +74,44 @@ protected:
     // productive because it can then take too long to scan the cache.
     static const int32_t kMaxCacheEntries = 128;
 
     ~nsFontCache() {}
 
     nsDeviceContext*          mContext; // owner
     RefPtr<nsAtom>         mLocaleLanguage;
 
-    // We don't allow this array to grow beyond kMaxCacheEntries,
-    // so use an autoarray to avoid separate allocation.
-    AutoTArray<nsFontMetrics*,kMaxCacheEntries> mFontMetrics;
+    // We may not flush older entries immediately the array reaches
+    // kMaxCacheEntries length, because this usually happens on a stylo
+    // thread where we can't safely delete metrics objects. So we allocate an
+    // oversized autoarray buffer here, so that we're unlikely to overflow
+    // it and need separate heap allocation before the flush happens on the
+    // main thread.
+    AutoTArray<nsFontMetrics*,kMaxCacheEntries*2> mFontMetrics;
+
+    bool mFlushPending = false;
+
+    class FlushFontMetricsTask : public mozilla::Runnable
+    {
+    public:
+        explicit FlushFontMetricsTask(nsFontCache* aCache)
+            : mozilla::Runnable("FlushFontMetricsTask")
+            , mCache(aCache)
+        { }
+        NS_IMETHOD Run() override
+        {
+            // Partially flush the cache, leaving the kMaxCacheEntries/2 most
+            // recent entries.
+            mCache->Flush(mCache->mFontMetrics.Length() - kMaxCacheEntries / 2);
+            mCache->mFlushPending = false;
+            return NS_OK;
+        }
+    private:
+        RefPtr<nsFontCache> mCache;
+    };
 };
 
 NS_IMPL_ISUPPORTS(nsFontCache, nsIObserver)
 
 // The Init and Destroy methods are necessary because it's not
 // safe to call AddObserver from a constructor or RemoveObserver
 // from a destructor.  That should be fixed.
 void
@@ -145,19 +170,26 @@ nsFontCache::GetMetricsFor(const nsFont&
             }
             fm->GetThebesFontGroup()->UpdateUserFonts();
             return do_AddRef(fm);
         }
     }
 
     // It's not in the cache. Get font metrics and then cache them.
     // If the cache has reached its size limit, drop the older half of the
-    // entries.
-    if (n >= kMaxCacheEntries - 1) {
-        Flush(kMaxCacheEntries / 2);
+    // entries; but if we're on a stylo thread (the usual case), we have
+    // to post a task back to the main thread to do the flush.
+    if (n >= kMaxCacheEntries - 1 && !mFlushPending) {
+        if (NS_IsMainThread()) {
+            Flush(mFontMetrics.Length() - kMaxCacheEntries / 2);
+        } else {
+            mFlushPending = true;
+            nsCOMPtr<nsIRunnable> flushTask = new FlushFontMetricsTask(this);
+            MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(flushTask));
+        }
     }
 
     nsFontMetrics::Params params = aParams;
     params.language = language;
     RefPtr<nsFontMetrics> fm = new nsFontMetrics(aFont, params, mContext);
     // the mFontMetrics list has the "head" at the end, because append
     // is cheaper than insert
     mFontMetrics.AppendElement(do_AddRef(fm).take());
--- a/taskcluster/ci/cron-bouncer-check/kind.yml
+++ b/taskcluster/ci/cron-bouncer-check/kind.yml
@@ -7,38 +7,39 @@ loader: taskgraph.loader.transform:loade
 transforms:
     - taskgraph.transforms.bouncer_check:transforms
     - taskgraph.transforms.job:transforms
     - taskgraph.transforms.task:transforms
 
 job-defaults:
     name: bouncer-check
     description: bouncer check
-    run-on-projects: []  # to make sure this never runs as part of CI
     worker-type: aws-provisioner-v1/gecko-{level}-b-linux
     worker:
         max-run-time: 1200
         docker-image: {in-tree: "update-verify"}
     run:
         using: run-task
         sparse-profile: mozharness
     attributes:
         build_platform: linux64
         build_type: opt
+        cron: true
     treeherder:
         symbol: Rel(ckbouncer)
         kind: test
         tier: 1
 
 jobs:
     firefox:
         shipping-product: firefox
         index:
             product: firefox
             job-name: firefox-bouncer-check
+        run-on-projects: [release]
         run:
             config:
                 by-project:
                     mozilla-beta:
                         - releases/bouncer_firefox_beta.py
                     mozilla-release:
                         - releases/bouncer_firefox_release.py
                     mozilla-esr60:
@@ -54,16 +55,17 @@ jobs:
                     mozilla-esr60: FIREFOX_ESR
                     default: LATEST_FIREFOX_DEVEL_VERSION
             products-url: https://product-details.mozilla.org/1.0/firefox_versions.json
         treeherder:
             platform: firefox-release/opt
 
     devedition:
         shipping-product: devedition
+        run-on-projects: [mozilla-beta]
         index:
             product: devedition
             job-name: devedition-bouncer-check
         run:
             config:
                 by-project:
                     mozilla-beta:
                         - releases/bouncer_firefox_devedition.py
--- a/taskcluster/docs/attributes.rst
+++ b/taskcluster/docs/attributes.rst
@@ -233,8 +233,13 @@ lot of places. To support private artifa
 overrideable per-task.
 
 enable-full-crashsymbols
 ========================
 In automation, full crashsymbol package generation is normally disabled.  For
 build kinds where the full crashsymbols should be enabled, set this attribute
 to True. The full symbol packages will then be generated and uploaded on
 release branches and on try.
+
+cron
+====
+Indicates that a task is meant to be run via cron tasks, and should not be run
+on push.
--- a/taskcluster/taskgraph/target_tasks.py
+++ b/taskcluster/taskgraph/target_tasks.py
@@ -23,16 +23,23 @@ def get_method(method):
     """Get a target_task_method to pass to a TaskGraphGenerator."""
     return _target_task_methods[method]
 
 
 def filter_out_nightly(task, parameters):
     return not task.attributes.get('nightly') or parameters.get('include_nightly')
 
 
+def filter_out_cron(task, parameters):
+    """
+    Filter out tasks that run via cron.
+    """
+    return not task.attributes.get('cron')
+
+
 def filter_for_project(task, parameters):
     """Filter tasks by project.  Optionally enable nightlies."""
     run_on_projects = set(task.attributes.get('run_on_projects', []))
     return match_run_on_projects(parameters['project'], run_on_projects)
 
 
 def filter_on_platforms(task, platforms):
     """Filter tasks on the given platform"""
@@ -86,17 +93,17 @@ def filter_beta_release_tasks(task, para
         return False
 
     return True
 
 
 def standard_filter(task, parameters):
     return all(
         filter_func(task, parameters) for filter_func in
-        (filter_out_nightly, filter_for_project)
+        (filter_out_nightly, filter_out_cron, filter_for_project)
     )
 
 
 def _try_task_config(full_task_graph, parameters, graph_config):
     requested_tasks = parameters['try_task_config']['tasks']
     return list(set(requested_tasks) & full_task_graph.graph.nodes)
 
 
@@ -563,16 +570,18 @@ def target_tasks_file_update(full_task_g
     return [l for l, t in full_task_graph.tasks.iteritems() if filter(t)]
 
 
 @_target_task('cron_bouncer_check')
 def target_tasks_bouncer_check(full_task_graph, parameters, graph_config):
     """Select the set of tasks required to perform bouncer version verification.
     """
     def filter(task):
+        if not filter_for_project(task, parameters):
+            return False
         # For now any task in the repo-update kind is ok
         return task.kind in ['cron-bouncer-check']
     return [l for l, t in full_task_graph.tasks.iteritems() if filter(t)]
 
 
 @_target_task('staging_release_builds')
 def target_tasks_staging_release(full_task_graph, parameters, graph_config):
     """
--- a/testing/mozharness/mozharness/mozilla/testing/android.py
+++ b/testing/mozharness/mozharness/mozilla/testing/android.py
@@ -50,25 +50,25 @@ class AndroidMixin(object):
                 # have completed initialization. We recover afterwards
                 # when additional attemps occur after initialization
                 # is completed.
                 pass
         return self._adb_path
 
     @property
     def device(self):
-        if not self._device:
+        if not self._device and self.adb_path:
             try:
                 import mozdevice
                 self._device = mozdevice.ADBAndroid(adb=self.adb_path,
                                                     device=self.device_serial,
                                                     verbose=True)
                 self.info("New mozdevice with adb=%s, device=%s" %
                           (self.adb_path, self.device_serial))
-            except Exception:
+            except AttributeError:
                 # As in adb_path, above.
                 pass
         return self._device
 
     @property
     def is_android(self):
         try:
             c = self.config
--- a/xpcom/tests/gtest/TestNonBlockingAsyncInputStream.cpp
+++ b/xpcom/tests/gtest/TestNonBlockingAsyncInputStream.cpp
@@ -282,18 +282,20 @@ public:
   // nsIIPCSerializableInputStream
   void Serialize(mozilla::ipc::InputStreamParams&, FileDescriptorArray&) override {}
   bool Deserialize(const mozilla::ipc::InputStreamParams&,
                    const FileDescriptorArray&) override { return false; }
   mozilla::Maybe<uint64_t> ExpectedSerializedLength() override { return mozilla::Nothing(); }
 
   // nsISeekableStream
   NS_IMETHOD Seek(int32_t, int64_t) override { return NS_ERROR_NOT_IMPLEMENTED; }
+  NS_IMETHOD SetEOF() override { return NS_ERROR_NOT_IMPLEMENTED; }
+
+  // nsITellableStream
   NS_IMETHOD Tell(int64_t*) override { return NS_ERROR_NOT_IMPLEMENTED; }
-  NS_IMETHOD SetEOF() override { return NS_ERROR_NOT_IMPLEMENTED; }
 
 private:
   ~QIInputStream() = default;
 
   bool mNonBlockingError;
   bool mCloneable;
   bool mIPCSerializable;
   bool mSeekable;
@@ -302,16 +304,17 @@ private:
 NS_IMPL_ADDREF(QIInputStream);
 NS_IMPL_RELEASE(QIInputStream);
 
 NS_INTERFACE_MAP_BEGIN(QIInputStream)
   NS_INTERFACE_MAP_ENTRY(nsIInputStream)
   NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsICloneableInputStream, mCloneable)
   NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIIPCSerializableInputStream, mIPCSerializable)
   NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsISeekableStream, mSeekable)
+  NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsITellableStream, mSeekable)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIInputStream)
 NS_INTERFACE_MAP_END
 
 TEST(TestNonBlockingAsyncInputStream, QI) {
   // Let's test ::Create() returning error.
 
   nsCOMPtr<nsIAsyncInputStream> async;
   {