Merge m-c to inbound, a=merge CLOSED TREE
authorWes Kocher <wkocher@mozilla.com>
Thu, 21 Jul 2016 15:59:28 -0700
changeset 346246 3e6ee8c6b56b84368c3a464c86067af78971ada0
parent 346245 b2508db54956f6ab4e1a5b91cb46db6ab9e2ca2c (current diff)
parent 346126 2e3390571fdb3a1ff3d2f7f828adf67dbc237bc8 (diff)
child 346247 1da606ef3da99b620f05dbae76570646f69af5b2
push id6389
push userraliiev@mozilla.com
push dateMon, 19 Sep 2016 13:38:22 +0000
treeherdermozilla-beta@01d67bfe6c81 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone50.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 m-c to inbound, a=merge CLOSED TREE
--- a/dom/media/webrtc/MediaEngineGonkVideoSource.cpp
+++ b/dom/media/webrtc/MediaEngineGonkVideoSource.cpp
@@ -99,17 +99,17 @@ MediaEngineGonkVideoSource::NotifyPull(M
     segment.AppendFrame(image.forget(), delta, size, aPrincipalHandle);
     // This can fail if either a) we haven't added the track yet, or b)
     // we've removed or finished the track.
     aSource->AppendToTrack(aID, &(segment));
   }
 }
 
 size_t
-MediaEngineGonkVideoSource::NumCapabilities()
+MediaEngineGonkVideoSource::NumCapabilities() const
 {
   // TODO: Stop hardcoding. Use GetRecorderProfiles+GetProfileInfo (Bug 1128550)
   //
   // The camera-selecting constraints algorithm needs a set of capabilities to
   // work on. In lieu of something better, here are some generic values based on
   // http://en.wikipedia.org/wiki/Comparison_of_Firefox_OS_devices on Jan 2015.
   // When unknown, better overdo it with choices to not block legitimate asks.
   // TODO: Match with actual hardware or add code to query hardware.
@@ -145,38 +145,45 @@ MediaEngineGonkVideoSource::NumCapabilit
   }
   return mHardcodedCapabilities.Length();
 }
 
 nsresult
 MediaEngineGonkVideoSource::Allocate(const dom::MediaTrackConstraints& aConstraints,
                                      const MediaEnginePrefs& aPrefs,
                                      const nsString& aDeviceId,
-                                     const nsACString& aOrigin)
+                                     const nsACString& aOrigin,
+                                     BaseAllocationHandle** aOutHandle,
+                                     const char** aOutBadConstraint)
 {
   LOG((__FUNCTION__));
 
   ReentrantMonitorAutoEnter sync(mCallbackMonitor);
   if (mState == kReleased && mInitDone) {
-    ChooseCapability(aConstraints, aPrefs, aDeviceId);
+    NormalizedConstraints constraints(aConstraints);
+    ChooseCapability(constraints, aPrefs, aDeviceId);
     NS_DispatchToMainThread(WrapRunnable(RefPtr<MediaEngineGonkVideoSource>(this),
                                          &MediaEngineGonkVideoSource::AllocImpl));
     mCallbackMonitor.Wait();
     if (mState != kAllocated) {
       return NS_ERROR_FAILURE;
     }
   }
 
+  aOutHandle = nullptr;
   return NS_OK;
 }
 
 nsresult
-MediaEngineGonkVideoSource::Deallocate()
+MediaEngineGonkVideoSource::Deallocate(BaseAllocationHandle* aHandle)
 {
   LOG((__FUNCTION__));
+  AssertIsOnOwningThread();
+  MOZ_ASSERT(!aHandle);
+
   bool empty;
   {
     MonitorAutoLock lock(mMonitor);
     empty = mSources.IsEmpty();
   }
   if (empty) {
 
     ReentrantMonitorAutoEnter sync(mCallbackMonitor);
@@ -327,19 +334,21 @@ MediaEngineGonkVideoSource::Stop(SourceM
 
   NS_DispatchToMainThread(WrapRunnable(RefPtr<MediaEngineGonkVideoSource>(this),
                                        &MediaEngineGonkVideoSource::StopImpl));
 
   return NS_OK;
 }
 
 nsresult
-MediaEngineGonkVideoSource::Restart(const dom::MediaTrackConstraints& aConstraints,
+MediaEngineGonkVideoSource::Restart(BaseAllocationHandle* aHandle,
+                                    const dom::MediaTrackConstraints& aConstraints,
                                     const MediaEnginePrefs& aPrefs,
-                                    const nsString& aDeviceId)
+                                    const nsString& aDeviceId,
+                                    const char** aOutBadConstraint)
 {
   return NS_OK;
 }
 
 /**
 * Initialization and Shutdown functions for the video source, called by the
 * constructor and destructor respectively.
 */
@@ -379,17 +388,17 @@ MediaEngineGonkVideoSource::Shutdown()
         source = mSources[0];
       }
       Stop(source, kVideoTrack); // XXX change to support multiple tracks
     }
     MOZ_ASSERT(mState == kStopped);
   }
 
   if (mState == kAllocated || mState == kStopped) {
-    Deallocate();
+    Deallocate(nullptr);
   }
 
   mState = kReleased;
   mInitDone = false;
 }
 
 // All these functions must be run on MainThread!
 void
--- a/dom/media/webrtc/MediaEngineGonkVideoSource.h
+++ b/dom/media/webrtc/MediaEngineGonkVideoSource.h
@@ -58,24 +58,28 @@ public:
     , mOrientationChanged(true) // Correct the orientation at first time takePhoto.
     {
       Init();
     }
 
   nsresult Allocate(const dom::MediaTrackConstraints &aConstraints,
                     const MediaEnginePrefs &aPrefs,
                     const nsString& aDeviceId,
-                    const nsACString& aOrigin) override;
-  nsresult Deallocate() override;
+                    const nsACString& aOrigin,
+                    BaseAllocationHandle** aOutHandle,
+                    const char** aOutBadConstraint) override;
+  nsresult Deallocate(BaseAllocationHandle* aHandle) override;
   nsresult Start(SourceMediaStream* aStream, TrackID aID,
                  const PrincipalHandle& aPrincipalHandle) override;
   nsresult Stop(SourceMediaStream* aSource, TrackID aID) override;
-  nsresult Restart(const dom::MediaTrackConstraints& aConstraints,
+  nsresult Restart(BaseAllocationHandle* aHandle,
+                   const dom::MediaTrackConstraints& aConstraints,
                    const MediaEnginePrefs &aPrefs,
-                   const nsString& aDeviceId) override;
+                   const nsString& aDeviceId,
+                   const char** aOutBadConstraint) override;
   void NotifyPull(MediaStreamGraph* aGraph,
                   SourceMediaStream* aSource,
                   TrackID aId,
                   StreamTime aDesiredTime,
                   const PrincipalHandle& aPrincipalHandle) override;
   dom::MediaSourceEnum GetMediaSource() const override {
     return dom::MediaSourceEnum::Camera;
   }
@@ -109,17 +113,17 @@ public:
 protected:
   ~MediaEngineGonkVideoSource()
   {
     Shutdown();
   }
   // Initialize the needed Video engine interfaces.
   void Init();
   void Shutdown();
-  size_t NumCapabilities() override;
+  size_t NumCapabilities() const override;
   // Initialize the recording frame (MediaBuffer) callback and Gonk camera.
   // MediaBuffer will transfers to MediaStreamGraph via AppendToTrack.
   nsresult InitDirectMediaBuffer();
 
   mozilla::ReentrantMonitor mCallbackMonitor; // Monitor for camera callback handling
   // This is only modified on MainThread (AllocImpl and DeallocImpl)
   RefPtr<ICameraControl> mCameraControl;
   RefPtr<dom::File> mLastCapture;
--- a/dom/system/gonk/mozstumbler/UploadStumbleRunnable.cpp
+++ b/dom/system/gonk/mozstumbler/UploadStumbleRunnable.cpp
@@ -45,17 +45,17 @@ UploadStumbleRunnable::Upload()
   nsCOMPtr<nsIScriptSecurityManager> secman =
     do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIPrincipal> systemPrincipal;
   rv = secman->GetSystemPrincipal(getter_AddRefs(systemPrincipal));
   NS_ENSURE_SUCCESS(rv, rv);
 
-  rv = xhr->Init(systemPrincipal, nullptr, nullptr, nullptr, nullptr);
+  rv = xhr->Init(systemPrincipal, nullptr, nullptr, nullptr);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIURLFormatter> formatter =
     do_CreateInstance("@mozilla.org/toolkit/URLFormatterService;1", &rv);
   NS_ENSURE_SUCCESS(rv, rv);
   nsString url;
   rv = formatter->FormatURLPref(NS_LITERAL_STRING("geo.stumbler.url"), url);
   NS_ENSURE_SUCCESS(rv, rv);
--- a/security/sandbox/linux/common/SandboxInfo.cpp
+++ b/security/sandbox/linux/common/SandboxInfo.cpp
@@ -254,33 +254,23 @@ SandboxInfo::ThreadingCheck()
   flags &= ~(kHasUserNamespaces | kHasPrivilegedUserNamespaces);
   sSingleton.mFlags = static_cast<Flags>(flags);
 }
 
 /* static */ void
 SandboxInfo::SubmitTelemetry()
 {
   SandboxInfo sandboxInfo = Get();
-  if (sandboxInfo.Test(SandboxInfo::kHasSeccompBPF)) {
-    Telemetry::Accumulate(Telemetry::SANDBOX_CAPABILITIES_SECCOMP_BPF, true);
-  }
-  if (sandboxInfo.Test(SandboxInfo::kHasSeccompTSync)) {
-    Telemetry::Accumulate(Telemetry::SANDBOX_CAPABILITIES_SECCOMP_TSYNC, true);
-  }
-  if (sandboxInfo.Test(SandboxInfo::kHasPrivilegedUserNamespaces)) {
-    Telemetry::Accumulate(
-      Telemetry::SANDBOX_CAPABILITIES_USER_NAMESPACES_PRIVILEGED, true);
-  }
-  if (sandboxInfo.Test(SandboxInfo::kHasUserNamespaces)) {
-    Telemetry::Accumulate(
-      Telemetry::SANDBOX_CAPABILITIES_USER_NAMESPACES, true);
-  }
-  if (sandboxInfo.Test(SandboxInfo::kEnabledForContent)) {
-    Telemetry::Accumulate(
-      Telemetry::SANDBOX_CAPABILITIES_ENABLED_CONTENT, true);
-  }
-  if (sandboxInfo.Test(SandboxInfo::kEnabledForMedia)) {
-    Telemetry::Accumulate(
-      Telemetry::SANDBOX_CAPABILITIES_ENABLED_MEDIA, true);
-  }
+  Telemetry::Accumulate(Telemetry::SANDBOX_HAS_SECCOMP_BPF,
+                        sandboxInfo.Test(SandboxInfo::kHasSeccompBPF));
+  Telemetry::Accumulate(Telemetry::SANDBOX_HAS_SECCOMP_TSYNC,
+                        sandboxInfo.Test(SandboxInfo::kHasSeccompTSync));
+  Telemetry::Accumulate(Telemetry::SANDBOX_HAS_USER_NAMESPACES_PRIVILEGED,
+                        sandboxInfo.Test(SandboxInfo::kHasPrivilegedUserNamespaces));
+  Telemetry::Accumulate(Telemetry::SANDBOX_HAS_USER_NAMESPACES,
+                        sandboxInfo.Test(SandboxInfo::kHasUserNamespaces));
+  Telemetry::Accumulate(Telemetry::SANDBOX_CONTENT_ENABLED,
+                        sandboxInfo.Test(SandboxInfo::kEnabledForContent));
+  Telemetry::Accumulate(Telemetry::SANDBOX_MEDIA_ENABLED,
+                        sandboxInfo.Test(SandboxInfo::kEnabledForMedia));
 }
 
 } // namespace mozilla
--- a/testing/marionette/harness/marionette/tests/unit/test_screenshot.py
+++ b/testing/marionette/harness/marionette/tests/unit/test_screenshot.py
@@ -1,17 +1,16 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 import base64
 import hashlib
 import imghdr
 import struct
-import time
 import urllib
 
 from unittest import skip
 
 from marionette import MarionetteTestCase
 from marionette_driver.by import By
 
 
@@ -82,26 +81,31 @@ class Chrome(ScreenCaptureTestCase):
         chrome = self.marionette.screenshot()
         self.assertNotEqual(content, chrome)
 
     # This tests that GeckoDriver#takeScreenshot uses
     # currentContext.document.documentElement instead of looking for a
     # <window> element, which does not exist for secondary windows.
     def test_secondary_windows(self):
         ss = self.marionette.screenshot()
-        self.marionette.execute_script("""
-            window.open('chrome://marionette/content/doesnotexist.xul',
+        self.marionette.execute_async_script("""
+            win = window.open('chrome://marionette/content/doesnotexist.xul',
             'foo',
             'chrome');
+
+            // Bug 1288339 - We don't wait for readyState to be complete yet
+            waitForWindow = function() {
+              if (win.document.readyState != 'complete') {
+                win.setTimeout(this, 100);
+              }
+
+              marionetteScriptFinished(true);
+            }()
             """)
         self.marionette.switch_to_window("foo")
-        # there can be a race between opening and registering the window
-        # and switching to it. Waiting a tiny amount of time is enough not to
-        # break anything.
-        time.sleep(0.002)
         ss = self.marionette.screenshot()
         size = self.get_image_dimensions(ss)
         self.assert_png(ss)
         self.assertNotEqual(self.primary_window_dimensions, size)
 
 
 class Content(ScreenCaptureTestCase):
     @property
--- a/toolkit/components/telemetry/Histograms.json
+++ b/toolkit/components/telemetry/Histograms.json
@@ -9851,61 +9851,61 @@
   },
   "SANDBOX_BROKER_INITIALIZED": {
     "alert_emails": ["bowen@mozilla.com"],
     "bug_numbers": [1256992],
     "expires_in_version": "55",
     "kind": "boolean",
     "description": "Result of call to SandboxBroker::Initialize"
   },
-  "SANDBOX_CAPABILITIES_SECCOMP_BPF": {
+  "SANDBOX_HAS_SECCOMP_BPF": {
     "alert_emails": ["gcp@mozilla.com"],
     "bug_numbers": [1098428],
     "expires_in_version": "55",
-    "kind": "flag",
+    "kind": "boolean",
     "cpp_guard": "XP_LINUX",
     "description": "Whether the system has seccomp-bpf capability"
   },
-  "SANDBOX_CAPABILITIES_SECCOMP_TSYNC": {
+  "SANDBOX_HAS_SECCOMP_TSYNC": {
     "alert_emails": ["gcp@mozilla.com"],
     "bug_numbers": [1098428],
     "expires_in_version": "55",
-    "kind": "flag",
+    "kind": "boolean",
     "cpp_guard": "XP_LINUX",
     "description": "Whether the system has seccomp-bpf thread-sync capability"
   },
-  "SANDBOX_CAPABILITIES_USER_NAMESPACES": {
+  "SANDBOX_HAS_USER_NAMESPACES": {
     "alert_emails": ["gcp@mozilla.com"],
     "bug_numbers": [1098428],
     "expires_in_version": "55",
-    "kind": "flag",
+    "kind": "boolean",
     "cpp_guard": "XP_LINUX",
     "description": "Whether our process succedeed in creating a user namespace"
   },
-  "SANDBOX_CAPABILITIES_USER_NAMESPACES_PRIVILEGED": {
+  "SANDBOX_HAS_USER_NAMESPACES_PRIVILEGED": {
     "alert_emails": ["gcp@mozilla.com"],
     "bug_numbers": [1098428],
     "expires_in_version": "55",
-    "kind": "flag",
+    "kind": "boolean",
     "cpp_guard": "XP_LINUX",
     "description": "Whether the system has the capability to create privileged user namespaces"
   },
- "SANDBOX_CAPABILITIES_ENABLED_MEDIA": {
+ "SANDBOX_MEDIA_ENABLED": {
     "alert_emails": ["gcp@mozilla.com"],
     "bug_numbers": [1098428],
     "expires_in_version": "55",
-    "kind": "flag",
+    "kind": "boolean",
     "cpp_guard": "XP_LINUX",
     "description": "Whether the sandbox is enabled for media/GMP plugins"
   },
- "SANDBOX_CAPABILITIES_ENABLED_CONTENT": {
+ "SANDBOX_CONTENT_ENABLED": {
     "alert_emails": ["gcp@mozilla.com"],
     "bug_numbers": [1098428],
     "expires_in_version": "55",
-    "kind": "flag",
+    "kind": "boolean",
     "cpp_guard": "XP_LINUX",
     "description": "Whether the sandbox is enabled for the content process"
   },
   "SYNC_WORKER_OPERATION": {
     "alert_emails": ["amarchesini@mozilla.com", "khuey@mozilla.com" ],
     "bug_numbers": [1267904],
     "expires_in_version": "never",
     "kind": "exponential",
--- a/toolkit/mozapps/extensions/amWebAPI.js
+++ b/toolkit/mozapps/extensions/amWebAPI.js
@@ -36,23 +36,19 @@ const APIBroker = {
     let payload = message.data;
 
     switch (message.name) {
       case MSG_PROMISE_RESULT: {
         if (!this._promises.has(payload.callbackID)) {
           return;
         }
 
-        let { resolve, reject } = this._promises.get(payload.callbackID);
+        let resolve = this._promises.get(payload.callbackID);
         this._promises.delete(payload.callbackID);
-
-        if ("resolve" in payload)
-          resolve(payload.resolve);
-        else
-          reject(payload.reject);
+        resolve(payload);
         break;
       }
 
       case MSG_INSTALL_EVENT: {
         let install = this._installMap.get(payload.id);
         if (!install) {
           let err = new Error(`Got install event for unknown install ${payload.id}`);
           Cu.reportError(err);
@@ -66,20 +62,20 @@ const APIBroker = {
         if (this._eventListener) {
           this._eventListener(payload);
         }
       }
     }
   },
 
   sendRequest: function(type, ...args) {
-    return new Promise((resolve, reject) => {
+    return new Promise(resolve => {
       let callbackID = this._nextID++;
 
-      this._promises.set(callbackID, { resolve, reject });
+      this._promises.set(callbackID, resolve);
       Services.cpmm.sendAsyncMessage(MSG_PROMISE_REQUEST, { type, callbackID, args });
     });
   },
 
   setAddonListener(callback) {
     this._eventListener = callback;
     if (callback) {
       Services.cpmm.addMessageListener(MSG_ADDON_EVENT, this);
@@ -115,51 +111,69 @@ function AddonInstall(window, properties
   this.handlers = new Map();
 
   for (let key of Object.keys(properties)) {
     this[key] = properties[key];
   }
 }
 
 /**
- * API methods should return promises from the page, this is a simple wrapper
- * to make sure of that. It also automatically wraps objects when necessary.
+ * API methods all return promises from content.  They also follow a
+ * similar pattern of sending a request to the parent process, then
+ * wrapping the returned object or error appropriately for the page.
+ * We must take care only to wrap and reject with errors that are meant
+ * to be visible to content, and not internal errors.
+ * This function is a wrapper to handle the common bits.
+ *
+ *   apiRequest is the name of the command to invoke in the parent process
+ *   apiArgs is a callable that takes the content-provided args for the
+ *           method and returns the arguments to send in the request to
+ *           the parent process.
+ *   if processor is non-null, it is called on the returned object to
+ *           convert the result from the parent process back to an
+ *           object appropriate for content.
+ *
+ * Both apiArgs and processor are called with "this" bound to the value
+ * that is held when the actual api method was called.
  */
-function WebAPITask(generator) {
+function WebAPITask(apiRequest, apiArgs, processor) {
   return function(...args) {
-    let task = Task.async(generator.bind(this));
-
     let win = this.window;
-
-    let wrapForContent = (obj) => {
-      if (obj instanceof Addon) {
-        return win.Addon._create(win, obj);
-      }
-      if (obj instanceof AddonInstall) {
-        return win.AddonInstall._create(win, obj);
-      }
-
-      return obj;
-    }
+    let boundApiArgs = apiArgs.bind(this);
+    let boundProcessor = processor ? processor.bind(this) : null;
 
     return new win.Promise((resolve, reject) => {
-      task(...args).then(wrapForContent)
-                   .then(resolve, reject);
+      Task.spawn(function* () {
+        let sendArgs = boundApiArgs(...args);
+        let result = yield APIBroker.sendRequest(apiRequest, ...sendArgs);
+        if ("reject" in result) {
+          let err = new win.Error(result.reject.message);
+          // We don't currently put any other properties onto Errors
+          // generated by mozAddonManager.  If/when we do, they will
+          // need to get copied here.
+          reject(err);
+          return;
+        }
+
+        let obj = result.resolve;
+        if (boundProcessor) {
+          obj = boundProcessor(obj);
+        }
+        resolve(obj);
+      }).catch(err => {
+        Cu.reportError(err);
+        reject(new win.Error("Unexpected internal error"));
+      });
     });
   }
 }
 
 Addon.prototype = {
-  uninstall: WebAPITask(function*() {
-    return yield APIBroker.sendRequest("addonUninstall", this.id);
-  }),
-
-  setEnabled: WebAPITask(function* (value) {
-    return yield APIBroker.sendRequest("addonSetEnabled", this.id, value);
-  }),
+  uninstall: WebAPITask("addonUninstall", function() { return [this.id]; }),
+  setEnabled: WebAPITask("addonSetEnabled", function(value) {return [this.id, value]; }),
 };
 
 const INSTALL_EVENTS = [
   "onDownloadStarted",
   "onDownloadProgress",
   "onDownloadEnded",
   "onDownloadCancelled",
   "onDownloadFailed",
@@ -176,52 +190,49 @@ AddonInstall.prototype = {
     for (let key of Object.keys(data)) {
       this[key] = data[key];
     }
 
     let event = new this.window.Event(data.event);
     this.__DOM_IMPL__.dispatchEvent(event);
   },
 
-  install: WebAPITask(function*() {
-    yield APIBroker.sendRequest("addonInstallDoInstall", this.id);
-  }),
-
-  cancel: WebAPITask(function*() {
-    yield APIBroker.sendRequest("addonInstallCancel", this.id);
-  }),
+  install: WebAPITask("addonInstallDoInstall", function() { return  [this.id]; }),
+  cancel: WebAPITask("addonInstallCancel", function() { return  [this.id]; }),
 };
 
 function WebAPI() {
 }
 
 WebAPI.prototype = {
   init(window) {
     this.window = window;
     this.allInstalls = [];
     this.listenerCount = 0;
 
     window.addEventListener("unload", event => {
       APIBroker.sendCleanup(this.allInstalls);
     });
   },
 
-  getAddonByID: WebAPITask(function*(id) {
-    let addonInfo = yield APIBroker.sendRequest("getAddonByID", id);
-    return addonInfo ? new Addon(this.window, addonInfo) : null;
+  getAddonByID: WebAPITask("getAddonByID", id => [id], function(addonInfo) {
+    if (!addonInfo) {
+      return null;
+    }
+    let addon = new Addon(this.window, addonInfo);
+    return this.window.Addon._create(this.window, addon);
   }),
 
-  createInstall: WebAPITask(function*(options) {
-    let installInfo = yield APIBroker.sendRequest("createInstall", options);
+  createInstall: WebAPITask("createInstall", options => [options], function(installInfo) {
     if (!installInfo) {
       return null;
     }
     let install = new AddonInstall(this.window, installInfo);
     this.allInstalls.push(installInfo.id);
-    return install;
+    return this.window.AddonInstall._create(this.window, install);
   }),
 
   eventListenerWasAdded(type) {
     if (this.listenerCount == 0) {
       APIBroker.setAddonListener(data => {
         let event = new this.window.AddonEvent(data.event, data);
         this.__DOM_IMPL__.dispatchEvent(event);
       });
--- a/widget/gonk/nsScreenManagerGonk.cpp
+++ b/widget/gonk/nsScreenManagerGonk.cpp
@@ -34,16 +34,17 @@
 #include "mozilla/ProcessPriorityManager.h"
 #include "nsIdleService.h"
 #include "nsIObserverService.h"
 #include "nsAppShell.h"
 #include "nsProxyRelease.h"
 #include "nsTArray.h"
 #include "pixelflinger/format.h"
 #include "nsIDisplayInfo.h"
+#include "base/task.h"
 
 #if ANDROID_VERSION >= 17
 #include "libdisplay/DisplaySurface.h"
 #endif
 
 #define LOG(args...)  __android_log_print(ANDROID_LOG_INFO, "nsScreenGonk" , ## args)
 #define LOGW(args...) __android_log_print(ANDROID_LOG_WARN, "nsScreenGonk", ## args)
 #define LOGE(args...) __android_log_print(ANDROID_LOG_ERROR, "nsScreenGonk", ## args)