From f9f684cd4555664bd0a968249c7213e778777987 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 16 Sep 2015 23:01:27 -0700 Subject: [PATCH 001/113] Bug 1204772 - Fix warnings in widget/gonk/libdisplay. r=mwu. dump() has only one instance, which is empty, and no uses. So just remove it. dbgCompositionTypeStr()'s use depends on conditional constants, so just marking it with the unused attribute is the fix for that warning. --HG-- extra : rebase_source : 2dbaca9c85892fe160849c4a1f1db4e454b8d2c0 --- widget/gonk/libdisplay/VirtualDisplaySurface.cpp | 4 +--- widget/gonk/libdisplay/VirtualDisplaySurface.h | 1 - widget/gonk/libdisplay/moz.build | 3 --- 3 files changed, 1 insertion(+), 7 deletions(-) diff --git a/widget/gonk/libdisplay/VirtualDisplaySurface.cpp b/widget/gonk/libdisplay/VirtualDisplaySurface.cpp index 8c0156026a5b..74670788525b 100644 --- a/widget/gonk/libdisplay/VirtualDisplaySurface.cpp +++ b/widget/gonk/libdisplay/VirtualDisplaySurface.cpp @@ -34,6 +34,7 @@ static const bool sForceHwcCopy = false; #define VDS_LOGV(msg, ...) ALOGV("[%s] " msg, \ mDisplayName.string(), ##__VA_ARGS__) +__attribute__((unused)) static const char* dbgCompositionTypeStr(DisplaySurface::CompositionType type) { switch (type) { case DisplaySurface::COMPOSITION_UNKNOWN: return "UNKNOWN"; @@ -264,9 +265,6 @@ void VirtualDisplaySurface::onFrameCommitted() { #endif } -void VirtualDisplaySurface::dump(String8& /* result */) const { -} - void VirtualDisplaySurface::resizeBuffers(const uint32_t w, const uint32_t h) { uint32_t tmpW, tmpH, transformHint, numPendingBuffers; mQueueBufferOutput.deflate(&tmpW, &tmpH, &transformHint, &numPendingBuffers); diff --git a/widget/gonk/libdisplay/VirtualDisplaySurface.h b/widget/gonk/libdisplay/VirtualDisplaySurface.h index 32fb5a3b91c7..9125d87515cf 100644 --- a/widget/gonk/libdisplay/VirtualDisplaySurface.h +++ b/widget/gonk/libdisplay/VirtualDisplaySurface.h @@ -84,7 +84,6 @@ public: virtual status_t compositionComplete(); virtual status_t advanceFrame(); virtual void onFrameCommitted(); - virtual void dump(String8& result) const; virtual void resizeBuffers(const uint32_t w, const uint32_t h); virtual status_t setReleaseFenceFd(int fenceFd) { return INVALID_OPERATION; } diff --git a/widget/gonk/libdisplay/moz.build b/widget/gonk/libdisplay/moz.build index bcdac7f14f01..3cb1426eec29 100644 --- a/widget/gonk/libdisplay/moz.build +++ b/widget/gonk/libdisplay/moz.build @@ -50,9 +50,6 @@ FORCE_STATIC_LIB = True DEFINES['XPCOM_GLUE'] = True -# XXX: We should fix these warnings. -ALLOW_COMPILER_WARNINGS = True - DISABLE_STL_WRAPPING = True CXXFLAGS += [ From 1d6bf38e9b9c859357b10a936f47abda99577e7d Mon Sep 17 00:00:00 2001 From: Simon Montagu Date: Wed, 16 Sep 2015 13:53:18 -0700 Subject: [PATCH 002/113] Bug 843689: make network.IDN.use_whitelist pref default to false preparatory to removing it completely, r=gerv --- modules/libpref/init/all.js | 2 +- netwerk/test/unit/test_idnservice.js | 31 ---------------------------- 2 files changed, 1 insertion(+), 32 deletions(-) diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index 0d1cd48e47f8..8bb51b161ac4 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -1534,7 +1534,7 @@ pref("network.IDN_show_punycode", false); // "network.IDN_show_punycode" is false. In other words, all IDNs will be shown // in punycode if "network.IDN_show_punycode" is true. pref("network.IDN.restriction_profile", "moderate"); -pref("network.IDN.use_whitelist", true); +pref("network.IDN.use_whitelist", false); // ccTLDs pref("network.IDN.whitelist.ac", true); diff --git a/netwerk/test/unit/test_idnservice.js b/netwerk/test/unit/test_idnservice.js index a0f090bdc9f3..e6d659857bd1 100644 --- a/netwerk/test/unit/test_idnservice.js +++ b/netwerk/test/unit/test_idnservice.js @@ -22,35 +22,4 @@ function run_test() { do_check_eq(idnService.convertACEtoUTF8(reference[i][1]), reference[i][0]); do_check_eq(idnService.isACE(reference[i][1]), reference[i][2]); } - - // add an IDN whitelist pref - var pbi = Components.classes["@mozilla.org/preferences-service;1"] - .getService(Components.interfaces.nsIPrefBranch); - pbi.setBoolPref("network.IDN.whitelist.es", true); - - // After bug 722299, set network.IDN.restriction_profile to "ASCII" in - // order not to change the behaviour of non-whitelisted TLDs - var oldProfile = pbi.getCharPref("network.IDN.restriction_profile", "moderate"); - pbi.setCharPref("network.IDN.restriction_profile", "ASCII"); - - // check convertToDisplayIDN against the whitelist - var isASCII = {}; - do_check_eq(idnService.convertToDisplayIDN("b\u00FCcher.es", isASCII), "b\u00FCcher.es"); - do_check_eq(isASCII.value, false); - do_check_eq(idnService.convertToDisplayIDN("xn--bcher-kva.es", isASCII), "b\u00FCcher.es"); - do_check_eq(isASCII.value, false); - do_check_eq(idnService.convertToDisplayIDN("b\u00FCcher.uk", isASCII), "xn--bcher-kva.uk"); - do_check_eq(isASCII.value, true); - do_check_eq(idnService.convertToDisplayIDN("xn--bcher-kva.uk", isASCII), "xn--bcher-kva.uk"); - do_check_eq(isASCII.value, true); - - // check ACE TLD's are handled by the whitelist - pbi.setBoolPref("network.IDN.whitelist.xn--k-dha", true); - do_check_eq(idnService.convertToDisplayIDN("test.\u00FCk", isASCII), "test.\u00FCk"); - do_check_eq(isASCII.value, false); - do_check_eq(idnService.convertToDisplayIDN("test.xn--k-dha", isASCII), "test.\u00FCk"); - do_check_eq(isASCII.value, false); - - // reset pref to default - pbi.setCharPref("network.IDN.restriction_profile", oldProfile); } From da5fa47c15b038003193a786930f0d985a9d82ec Mon Sep 17 00:00:00 2001 From: Lee Salzman Date: Wed, 16 Sep 2015 20:31:43 -0400 Subject: [PATCH 003/113] Bug 1205016: double ClosingService thread stack size to avoid stack overflow r=glandium --- netwerk/base/ClosingService.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/netwerk/base/ClosingService.cpp b/netwerk/base/ClosingService.cpp index ef7f26c9fe4c..b8117dd79b30 100644 --- a/netwerk/base/ClosingService.cpp +++ b/netwerk/base/ClosingService.cpp @@ -108,7 +108,7 @@ ClosingService::StartInternal() { mThread = PR_CreateThread(PR_USER_THREAD, ThreadFunc, this, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, - PR_JOINABLE_THREAD, 4 * 4096); + PR_JOINABLE_THREAD, 32 * 1024); if (!mThread) { return NS_ERROR_FAILURE; } From 2653d7d935abd42395bfa6059db4415c0aef39e5 Mon Sep 17 00:00:00 2001 From: Hannes Verschore Date: Thu, 17 Sep 2015 09:21:40 +0200 Subject: [PATCH 004/113] Bug 1204866 - IonMonkey: Crash when failing to apand to parse finished list, r=bhackett --- js/src/vm/HelperThreads.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/js/src/vm/HelperThreads.cpp b/js/src/vm/HelperThreads.cpp index 3187644fa8f5..203d3a394102 100644 --- a/js/src/vm/HelperThreads.cpp +++ b/js/src/vm/HelperThreads.cpp @@ -1277,7 +1277,8 @@ HelperThread::handleParseWorkload() // FinishOffThreadScript will need to be called on the script to // migrate it into the correct compartment. - HelperThreadState().parseFinishedList().append(parseTask); + if (!HelperThreadState().parseFinishedList().append(parseTask)) + CrashAtUnhandlableOOM("handleParseWorkload"); parseTask = nullptr; From 75548be5e04bbd0937f3ba909e117c0a7accccb3 Mon Sep 17 00:00:00 2001 From: Hannes Verschore Date: Thu, 17 Sep 2015 09:21:42 +0200 Subject: [PATCH 005/113] Bug 1204725 - IonMonkey: Check result when copying frame iter data, r=nbp --- js/src/vm/Stack.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/js/src/vm/Stack.cpp b/js/src/vm/Stack.cpp index 09b6532621db..57efd8f4487e 100644 --- a/js/src/vm/Stack.cpp +++ b/js/src/vm/Stack.cpp @@ -752,6 +752,9 @@ FrameIter::Data* FrameIter::copyData() const { Data* data = data_.cx_->new_(data_); + if (!data) + return nullptr; + MOZ_ASSERT(data_.state_ != ASMJS); if (data && data_.jitFrames_.isIonScripted()) data->ionInlineFrameNo_ = ionInlineFrames_.frameNo(); From bd9849968c29cddf9097b1a22d0d80c009dfe714 Mon Sep 17 00:00:00 2001 From: JW Wang Date: Thu, 17 Sep 2015 15:26:08 +0800 Subject: [PATCH 006/113] Bug 1204434 - Remove check of MediaDecoder::IsMediaSeekable from OggReader::ReadMetadata. r=cpearce. --- dom/media/ogg/OggReader.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dom/media/ogg/OggReader.cpp b/dom/media/ogg/OggReader.cpp index acc9e93ce83f..64ee37186131 100644 --- a/dom/media/ogg/OggReader.cpp +++ b/dom/media/ogg/OggReader.cpp @@ -472,9 +472,9 @@ nsresult OggReader::ReadMetadata(MediaInfo* aInfo, if (HasAudio() || HasVideo()) { ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor()); - if (mInfo.mMetadataDuration.isNothing() && !mDecoder->IsOggDecoderShutdown() && - mResource.GetLength() >= 0 && mDecoder->IsMediaSeekable()) - { + if (mInfo.mMetadataDuration.isNothing() && + !mDecoder->IsOggDecoderShutdown() && + mResource.GetLength() >= 0) { // We didn't get a duration from the index or a Content-Duration header. // Seek to the end of file to find the end time. int64_t length = mResource.GetLength(); From b2e334e690e960d46ce24679a9bef7d01d58a43b Mon Sep 17 00:00:00 2001 From: Albert Crespell Date: Thu, 10 Sep 2015 12:42:02 +0200 Subject: [PATCH 007/113] Bug 1182113 - Test XSLT serviceworker load. r=bkelly --- dom/workers/test/serviceworkers/mochitest.ini | 3 + .../test/serviceworkers/test_xslt.html | 113 ++++++++++++++++++ dom/workers/test/serviceworkers/xslt/test.xml | 6 + dom/workers/test/serviceworkers/xslt/xslt.sjs | 12 ++ .../test/serviceworkers/xslt_worker.js | 52 ++++++++ 5 files changed, 186 insertions(+) create mode 100644 dom/workers/test/serviceworkers/test_xslt.html create mode 100644 dom/workers/test/serviceworkers/xslt/test.xml create mode 100644 dom/workers/test/serviceworkers/xslt/xslt.sjs create mode 100644 dom/workers/test/serviceworkers/xslt_worker.js diff --git a/dom/workers/test/serviceworkers/mochitest.ini b/dom/workers/test/serviceworkers/mochitest.ini index aaa955898c48..d0f642c2bb6e 100644 --- a/dom/workers/test/serviceworkers/mochitest.ini +++ b/dom/workers/test/serviceworkers/mochitest.ini @@ -162,6 +162,8 @@ support-files = eventsource/* sw_clients/file_blob_upload_frame.html redirect_post.sjs + xslt_worker.js + xslt/* [test_app_protocol.html] skip-if = release_build @@ -250,6 +252,7 @@ skip-if = toolkit == "android" || toolkit == "gonk" [test_workerupdatefoundevent.html] [test_opaque_intercept.html] [test_fetch_event_client_postmessage.html] +[test_xslt.html] [test_escapedSlashes.html] [test_eventsource_intercept.html] [test_not_intercept_plugin.html] diff --git a/dom/workers/test/serviceworkers/test_xslt.html b/dom/workers/test/serviceworkers/test_xslt.html new file mode 100644 index 000000000000..be56f50865a1 --- /dev/null +++ b/dom/workers/test/serviceworkers/test_xslt.html @@ -0,0 +1,113 @@ + + + + + Bug 1182113 - Test service worker XSLT interception + + + + +

+
+

+
+
+
+
+
diff --git a/dom/workers/test/serviceworkers/xslt/test.xml b/dom/workers/test/serviceworkers/xslt/test.xml
new file mode 100644
index 000000000000..83c7776339a4
--- /dev/null
+++ b/dom/workers/test/serviceworkers/xslt/test.xml
@@ -0,0 +1,6 @@
+
+
+
+  Example
+  Error
+
diff --git a/dom/workers/test/serviceworkers/xslt/xslt.sjs b/dom/workers/test/serviceworkers/xslt/xslt.sjs
new file mode 100644
index 000000000000..db681ab50013
--- /dev/null
+++ b/dom/workers/test/serviceworkers/xslt/xslt.sjs
@@ -0,0 +1,12 @@
+function handleRequest(request, response) {
+  response.setHeader("Content-Type", "application/xslt+xml", false);
+  response.setHeader("Access-Control-Allow-Origin", "*");
+
+  var body = request.queryString;
+  if (!body) {
+    response.setStatusLine(null, 500, "Invalid querystring");
+    return;
+  }
+
+  response.write(unescape(body));
+}
diff --git a/dom/workers/test/serviceworkers/xslt_worker.js b/dom/workers/test/serviceworkers/xslt_worker.js
new file mode 100644
index 000000000000..bf9bdbc566b5
--- /dev/null
+++ b/dom/workers/test/serviceworkers/xslt_worker.js
@@ -0,0 +1,52 @@
+var testType = 'synthetic';
+
+var xslt = " " +
+           "" +
+           "  " +
+           "    " +
+           "      " +
+           "    " +
+           "  " +
+           "  " +
+           "";
+
+onfetch = function(event) {
+  if (event.request.url.includes('test.xsl')) {
+    if (testType == 'synthetic') {
+      if (event.request.mode != 'cors') {
+        event.respondWith(Response.error());
+        return;
+      }
+
+      event.respondWith(Promise.resolve(
+        new Response(xslt, { headers: {'Content-Type': 'application/xslt+xml'}})
+      ));
+    }
+    else if (testType == 'cors') {
+      if (event.request.mode != 'cors') {
+        event.respondWith(Response.error());
+        return;
+      }
+
+      var url = "http://example.com/tests/dom/workers/test/serviceworkers/xslt/xslt.sjs?" + escape(xslt);
+      event.respondWith(fetch(url, { mode: 'cors' }));
+    }
+    else if (testType == 'opaque') {
+      if (event.request.mode != 'cors') {
+        event.respondWith(Response.error());
+        return;
+      }
+
+      var url = "http://example.com/tests/dom/workers/test/serviceworkers/xslt/xslt.sjs?" + escape(xslt);
+      event.respondWith(fetch(url, { mode: 'no-cors' }));
+    }
+    else {
+      event.respondWith(Response.error());
+    }
+  }
+};
+
+onmessage = function(event) {
+  testType = event.data;
+};

From 7979c10284fe975dedb07cb57aad05ad72191aa7 Mon Sep 17 00:00:00 2001
From: Gian-Carlo Pascutto 
Date: Wed, 16 Sep 2015 16:17:49 +0200
Subject: [PATCH 008/113] Bug 1192203 - Extract a robust version of
 getSupportedPreviewFpsRange. r=jesup

---
 .../videoengine/VideoCaptureAndroid.java      |  4 +-
 .../VideoCaptureDeviceInfoAndroid.java        | 57 +++++++++++--------
 2 files changed, 35 insertions(+), 26 deletions(-)

diff --git a/media/webrtc/trunk/webrtc/modules/video_capture/android/java/src/org/webrtc/videoengine/VideoCaptureAndroid.java b/media/webrtc/trunk/webrtc/modules/video_capture/android/java/src/org/webrtc/videoengine/VideoCaptureAndroid.java
index 49290f5d7f2b..fad1b9326b1c 100644
--- a/media/webrtc/trunk/webrtc/modules/video_capture/android/java/src/org/webrtc/videoengine/VideoCaptureAndroid.java
+++ b/media/webrtc/trunk/webrtc/modules/video_capture/android/java/src/org/webrtc/videoengine/VideoCaptureAndroid.java
@@ -36,6 +36,7 @@ import org.mozilla.gecko.annotation.WebRTCJNITarget;
 import org.mozilla.gecko.GeckoAppShell;
 import org.mozilla.gecko.GeckoAppShell.AppStateListener;
 
+
 // Wrapper for android Camera, with support for direct local preview rendering.
 // Threading notes: this class is called from ViE C++ code, and from Camera &
 // SurfaceHolder Java callbacks.  Since these calls happen on different threads,
@@ -269,7 +270,8 @@ public class VideoCaptureAndroid implements PreviewCallback, Callback, AppStateL
 
       // Check if requested fps range is supported by camera,
       // otherwise calculate frame drop ratio.
-      List supportedFpsRanges = parameters.getSupportedPreviewFpsRange();
+      List supportedFpsRanges =
+          VideoCaptureDeviceInfoAndroid.getFpsRangesRobust(parameters);
       frameDropRatio = Integer.MAX_VALUE;
       for (int i = 0; i < supportedFpsRanges.size(); i++) {
         int[] range = supportedFpsRanges.get(i);
diff --git a/media/webrtc/trunk/webrtc/modules/video_capture/android/java/src/org/webrtc/videoengine/VideoCaptureDeviceInfoAndroid.java b/media/webrtc/trunk/webrtc/modules/video_capture/android/java/src/org/webrtc/videoengine/VideoCaptureDeviceInfoAndroid.java
index fed4e072c293..eff139538f87 100644
--- a/media/webrtc/trunk/webrtc/modules/video_capture/android/java/src/org/webrtc/videoengine/VideoCaptureDeviceInfoAndroid.java
+++ b/media/webrtc/trunk/webrtc/modules/video_capture/android/java/src/org/webrtc/videoengine/VideoCaptureDeviceInfoAndroid.java
@@ -34,6 +34,37 @@ public class VideoCaptureDeviceInfoAndroid {
         ", Orientation "+ info.orientation;
   }
 
+  @WebRTCJNITarget
+  public static List getFpsRangesRobust(Camera.Parameters parameters) {
+      List supportedFpsRanges = null;
+      if (android.os.Build.VERSION.SDK_INT >= 9) {
+          supportedFpsRanges = parameters.getSupportedPreviewFpsRange();
+      }
+      // getSupportedPreviewFpsRange doesn't actually work on a bunch
+      // of Gingerbread devices.
+      if (supportedFpsRanges == null) {
+          supportedFpsRanges = new ArrayList();
+          List frameRates = parameters.getSupportedPreviewFrameRates();
+          if (frameRates != null) {
+              for (Integer rate: frameRates) {
+                  int[] range = new int[2];
+                  // minFPS = maxFPS, convert to milliFPS
+                  range[0] = rate * 1000;
+                  range[1] = rate * 1000;
+                  supportedFpsRanges.add(range);
+              }
+          } else {
+              Log.e(TAG, "Camera doesn't know its own framerate, guessing 30fps.");
+              int[] range = new int[2];
+              // Your guess is as good as mine
+              range[0] = 30 * 1000;
+              range[1] = 30 * 1000;
+              supportedFpsRanges.add(range);
+          }
+      }
+      return supportedFpsRanges;
+  }
+
   // Returns information about all cameras on the device.
   // Since this reflects static information about the hardware present, there is
   // no need to call this function more than once in a single process.  It is
@@ -67,31 +98,7 @@ public class VideoCaptureDeviceInfoAndroid {
               }
               Parameters parameters = camera.getParameters();
               supportedSizes = parameters.getSupportedPreviewSizes();
-              if (android.os.Build.VERSION.SDK_INT >= 9) {
-                  supportedFpsRanges = parameters.getSupportedPreviewFpsRange();
-              }
-              // getSupportedPreviewFpsRange doesn't actually work on a bunch
-              // of Gingerbread devices.
-              if (supportedFpsRanges == null) {
-                  supportedFpsRanges = new ArrayList();
-                  List frameRates = parameters.getSupportedPreviewFrameRates();
-                  if (frameRates != null) {
-                      for (Integer rate: frameRates) {
-                          int[] range = new int[2];
-                          // minFPS = maxFPS, convert to milliFPS
-                          range[0] = rate * 1000;
-                          range[1] = rate * 1000;
-                          supportedFpsRanges.add(range);
-                      }
-                  } else {
-                      Log.e(TAG, "Camera doesn't know its own framerate, guessing 30fps.");
-                      int[] range = new int[2];
-                      // Your guess is as good as mine
-                      range[0] = 30 * 1000;
-                      range[1] = 30 * 1000;
-                      supportedFpsRanges.add(range);
-                  }
-              }
+              supportedFpsRanges = getFpsRangesRobust(parameters);
               camera.release();
               Log.d(TAG, uniqueName);
           } catch (RuntimeException e) {

From 6051bff6eb0d010d625cb19b78f2edab6e60d767 Mon Sep 17 00:00:00 2001
From: Gian-Carlo Pascutto 
Date: Thu, 17 Sep 2015 09:59:26 +0200
Subject: [PATCH 009/113] Bug 1204367 - Only do SafeBrowsing debug logging when
 debug is enabled. r=francois

---
 .../url-classifier/SafeBrowsing.jsm           | 32 +++++++++++--------
 1 file changed, 19 insertions(+), 13 deletions(-)

diff --git a/toolkit/components/url-classifier/SafeBrowsing.jsm b/toolkit/components/url-classifier/SafeBrowsing.jsm
index c4480346ef32..feef58c251eb 100644
--- a/toolkit/components/url-classifier/SafeBrowsing.jsm
+++ b/toolkit/components/url-classifier/SafeBrowsing.jsm
@@ -10,6 +10,23 @@ const Cu = Components.utils;
 
 Cu.import("resource://gre/modules/Services.jsm");
 
+// Log only if browser.safebrowsing.debug is true
+function log(...stuff) {
+  let logging = null;
+  try {
+    logging = Services.prefs.getBoolPref("browser.safebrowsing.debug");
+  } catch(e) {
+    return;
+  }
+  if (!logging) {
+    return;
+  }
+
+  var d = new Date();
+  let msg = "SafeBrowsing: " + d.toTimeString() + ": " + stuff.join(" ");
+  dump(msg + "\n");
+}
+
 // Skip all the ones containining "test", because we never need to ask for
 // updates for them.
 function getLists(prefName) {
@@ -37,17 +54,6 @@ const downloadAllowLists = getLists("urlclassifier.downloadAllowTable");
 const trackingProtectionLists = getLists("urlclassifier.trackingTable");
 const trackingProtectionWhitelists = getLists("urlclassifier.trackingWhitelistTable");
 
-var debug = false;
-function log(...stuff) {
-  if (!debug)
-    return;
-
-  var d = new Date();
-  let msg = "SafeBrowsing: " + d.toTimeString() + ": " + stuff.join(" ");
-  Services.console.logStringMessage(msg);
-  dump(msg + "\n");
-}
-
 this.SafeBrowsing = {
 
   init: function() {
@@ -143,7 +149,7 @@ this.SafeBrowsing = {
   readPrefs: function() {
     log("reading prefs");
 
-    debug = Services.prefs.getBoolPref("browser.safebrowsing.debug");
+    this.debug = Services.prefs.getBoolPref("browser.safebrowsing.debug");
     this.phishingEnabled = Services.prefs.getBoolPref("browser.safebrowsing.enabled");
     this.malwareEnabled = Services.prefs.getBoolPref("browser.safebrowsing.malware.enabled");
     this.trackingEnabled = Services.prefs.getBoolPref("privacy.trackingprotection.enabled") || Services.prefs.getBoolPref("privacy.trackingprotection.pbmode.enabled");
@@ -181,7 +187,7 @@ this.SafeBrowsing = {
       this.providers[providerName] = {};
     }
 
-    if (debug) {
+    if (this.debug) {
       let providerStr = "";
       Object.keys(this.providers).forEach(function(provider) {
         if (providerStr === "") {

From af124192371e13ed4b3ecf86c252e8b8ebd3f889 Mon Sep 17 00:00:00 2001
From: Nikhil Marathe 
Date: Wed, 5 Aug 2015 15:12:11 -0700
Subject: [PATCH 010/113] Bug 914481 - Patch 1 - Push usage and permissions
 telemetry. r=kitcambridge

--HG--
extra : rebase_source : 454b8cb5d061574223fab9f53b649efc5566767b
---
 dom/push/Push.js                             |  8 +++++++
 toolkit/components/telemetry/Histograms.json | 24 ++++++++++++++++++++
 2 files changed, 32 insertions(+)

diff --git a/dom/push/Push.js b/dom/push/Push.js
index 473999ae26a9..05d558137dd7 100644
--- a/dom/push/Push.js
+++ b/dom/push/Push.js
@@ -98,14 +98,20 @@ Push.prototype = {
       principal: principal,
       QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentPermissionRequest]),
       allow: function() {
+        let histogram = Services.telemetry.getHistogramById("PUSH_API_PERMISSION_GRANTED");
+        histogram.add();
         aAllowCallback();
       },
       cancel: function() {
+        let histogram = Services.telemetry.getHistogramById("PUSH_API_PERMISSION_DENIED");
+        histogram.add();
         aCancelCallback();
       },
       window: this._window
     };
 
+    let histogram = Services.telemetry.getHistogramById("PUSH_API_PERMISSION_REQUESTED");
+    histogram.add(1);
     // Using askPermission from nsIDOMWindowUtils that takes care of the
     // remoting if needed.
     let windowUtils = this._window.QueryInterface(Ci.nsIInterfaceRequestor)
@@ -159,6 +165,8 @@ Push.prototype = {
 
   subscribe: function() {
     debug("subscribe()");
+    let histogram = Services.telemetry.getHistogramById("PUSH_API_USED");
+    histogram.add(true);
     return this.getEndpointResponse(this._client.subscribe.bind(this._client));
   },
 
diff --git a/toolkit/components/telemetry/Histograms.json b/toolkit/components/telemetry/Histograms.json
index dcb9c0c23a32..a048ece9fcd4 100644
--- a/toolkit/components/telemetry/Histograms.json
+++ b/toolkit/components/telemetry/Histograms.json
@@ -9348,6 +9348,30 @@
     "releaseChannelCollection": "opt-out",
     "description": "Reason for reporting the Adobe CDM to be unsupported. (1 = NOT_WINDOWS; 2 = WINDOWS_VERSION)"
   },
+  "PUSH_API_USED": {
+    "alert_emails": ["push@mozilla.com"],
+    "expires_in_version": "55",
+    "kind": "flag",
+    "description": "A Push API subscribe() operation was performed at least once this session."
+  },
+  "PUSH_API_PERMISSION_REQUESTED": {
+    "alert_emails": ["push@mozilla.com"],
+    "expires_in_version": "55",
+    "kind": "count",
+    "description": "Count of number of times the PermissionManager explicitly prompted user for Push Notifications permission"
+  },
+  "PUSH_API_PERMISSION_DENIED": {
+    "alert_emails": ["push@mozilla.com"],
+    "expires_in_version": "55",
+    "kind": "count",
+    "description": "User explicitly denied Push Notifications permission"
+  },
+  "PUSH_API_PERMISSION_GRANTED": {
+    "alert_emails": ["push@mozilla.com"],
+    "expires_in_version": "55",
+    "kind": "count",
+    "description": "User explicitly granted Push Notifications permission"
+  },
   "FXA_CONFIGURED": {
     "alert_emails": ["fx-team@mozilla.com"],
     "expires_in_version": "45",

From 3fc51ef7fd9956eab8b8921eb2a0455498abbb02 Mon Sep 17 00:00:00 2001
From: Nikhil Marathe 
Date: Wed, 5 Aug 2015 17:03:49 -0700
Subject: [PATCH 011/113] Bug 914481 - Patch 2 - Track subscribe and
 unsubscribe success/failure. r=kitcambridge

--HG--
extra : rebase_source : 4d605f0557e9e1b5a40e4a518e5f6c9b53e85068
---
 dom/push/PushService.jsm                     | 27 ++++++++++++---
 toolkit/components/telemetry/Histograms.json | 36 ++++++++++++++++++++
 2 files changed, 58 insertions(+), 5 deletions(-)

diff --git a/dom/push/PushService.jsm b/dom/push/PushService.jsm
index 35657522f66e..dc328e7d2a75 100644
--- a/dom/push/PushService.jsm
+++ b/dom/push/PushService.jsm
@@ -273,7 +273,7 @@ this.PushService = {
                   // just for it
                   if (this._ws) {
                     debug("Had a connection, so telling the server");
-                    this._sendRequest("unregister", {channelID: record.channelID})
+                    this._sendUnregister({channelID: record.channelID})
                         .catch(function(e) {
                           debug("Unregister errored " + e);
                         });
@@ -286,7 +286,7 @@ this.PushService = {
                   // just for it
                   if (this._ws) {
                     debug("Had a connection, so telling the server");
-                    this._sendRequest("unregister", {channelID: record.channelID})
+                    this._sendUnregister({channelID: record.channelID})
                         .catch(function(e) {
                           debug("Unregister errored " + e);
                         });
@@ -778,7 +778,7 @@ this.PushService = {
         // Drop the registration in the background. If the user returns to the
         // site, the service worker will be notified on the next `idle-daily`
         // event.
-        this._sendRequest("unregister", record).catch(error => {
+        this._sendUnregister(record).catch(error => {
           debug("receivedPushMessage: Unregister error: " + error);
         });
       }
@@ -853,6 +853,7 @@ this.PushService = {
   _registerWithServer: function(aPageRecord) {
     debug("registerWithServer()" + JSON.stringify(aPageRecord));
 
+    Services.telemetry.getHistogramById("PUSH_API_SUBSCRIBE_ATTEMPT").add();
     return this._sendRequest("register", aPageRecord)
       .then(record => this._onRegisterSuccess(record),
             err => this._onRegisterError(err))
@@ -896,6 +897,17 @@ this.PushService = {
       });
   },
 
+  _sendUnregister: function(aRecord) {
+    Services.telemetry.getHistogramById("PUSH_API_UNSUBSCRIBE_ATTEMPT").add();
+    return this._sendRequest("unregister", aRecord).then(function(v) {
+      Services.telemetry.getHistogramById("PUSH_API_UNSUBSCRIBE_SUCCEEDED").add();
+      return v;
+    }).catch(function(e) {
+      Services.telemetry.getHistogramById("PUSH_API_UNSUBSCRIBE_FAILED").add();
+      return Promise.reject(e);
+    });
+  },
+
   /**
    * Exceptions thrown in _onRegisterSuccess are caught by the promise obtained
    * from _service.request, causing the promise to be rejected instead.
@@ -904,9 +916,13 @@ this.PushService = {
     debug("_onRegisterSuccess()");
 
     return this._db.put(aRecord)
+      .then(_ => {
+        Services.telemetry.getHistogramById("PUSH_API_SUBSCRIBE_SUCCEEDED").add()
+      })
       .catch(error => {
+        Services.telemetry.getHistogramById("PUSH_API_SUBSCRIBE_FAILED").add()
         // Unable to save. Destroy the subscription in the background.
-        this._sendRequest("unregister", aRecord).catch(err => {
+        this._sendUnregister(aRecord).catch(err => {
           debug("_onRegisterSuccess: Error unregistering stale subscription" +
             err);
         });
@@ -920,6 +936,7 @@ this.PushService = {
    */
   _onRegisterError: function(reply) {
     debug("_onRegisterError()");
+    Services.telemetry.getHistogramById("PUSH_API_SUBSCRIBE_FAILED").add()
     if (!reply.error) {
       debug("Called without valid error message!");
       throw "Registration error";
@@ -1043,7 +1060,7 @@ this.PushService = {
         }
 
         return Promise.all([
-          this._sendRequest("unregister", record),
+          this._sendUnregister(record),
           this._db.delete(record.keyID),
         ]).then(() => true);
       });
diff --git a/toolkit/components/telemetry/Histograms.json b/toolkit/components/telemetry/Histograms.json
index a048ece9fcd4..2604a6a7e4ad 100644
--- a/toolkit/components/telemetry/Histograms.json
+++ b/toolkit/components/telemetry/Histograms.json
@@ -9372,6 +9372,42 @@
     "kind": "count",
     "description": "User explicitly granted Push Notifications permission"
   },
+  "PUSH_API_SUBSCRIBE_ATTEMPT": {
+    "alert_emails": ["push@mozilla.com"],
+    "expires_in_version": "55",
+    "kind": "count",
+    "description": "Push Service attempts to subscribe with Push Server."
+  },
+  "PUSH_API_SUBSCRIBE_FAILED": {
+    "alert_emails": ["push@mozilla.com"],
+    "expires_in_version": "55",
+    "kind": "count",
+    "description": "Attempt to subscribe with Push Server failed."
+  },
+  "PUSH_API_SUBSCRIBE_SUCCEEDED": {
+    "alert_emails": ["push@mozilla.com"],
+    "expires_in_version": "55",
+    "kind": "count",
+    "description": "Attempt to subscribe with Push Server succeeded."
+  },
+  "PUSH_API_UNSUBSCRIBE_ATTEMPT": {
+    "alert_emails": ["push@mozilla.com"],
+    "expires_in_version": "55",
+    "kind": "count",
+    "description": "Push Service attempts to unsubscribe with Push Server."
+  },
+  "PUSH_API_UNSUBSCRIBE_FAILED": {
+    "alert_emails": ["push@mozilla.com"],
+    "expires_in_version": "55",
+    "kind": "count",
+    "description": "Attempt to unsubscribe with Push Server failed."
+  },
+  "PUSH_API_UNSUBSCRIBE_SUCCEEDED": {
+    "alert_emails": ["push@mozilla.com"],
+    "expires_in_version": "55",
+    "kind": "count",
+    "description": "Attempt to unsubscribe with Push Server succeeded."
+  },
   "FXA_CONFIGURED": {
     "alert_emails": ["fx-team@mozilla.com"],
     "expires_in_version": "45",

From 6e258d23362a4dc06fa6cca98fe4fe9b5a41b5a2 Mon Sep 17 00:00:00 2001
From: Nikhil Marathe 
Date: Thu, 6 Aug 2015 12:05:47 -0700
Subject: [PATCH 012/113] Bug 914481 - Patch 3 - Subscription and quota
 expiration times. r=kitcambridge, p=ally

--HG--
extra : rebase_source : d6a29b72e95cb8b75492d2f7634dcefed86ae2dd
---
 dom/push/PushRecord.jsm                      |  7 +++++
 dom/push/PushServiceHttp2.jsm                |  3 ++
 dom/push/PushServiceWebSocket.jsm            |  2 ++
 toolkit/components/telemetry/Histograms.json | 32 ++++++++++++++++++++
 4 files changed, 44 insertions(+)

diff --git a/dom/push/PushRecord.jsm b/dom/push/PushRecord.jsm
index 8b92b6f47a5b..d5263888f711 100644
--- a/dom/push/PushRecord.jsm
+++ b/dom/push/PushRecord.jsm
@@ -45,6 +45,7 @@ function PushRecord(props) {
   this.pushCount = props.pushCount || 0;
   this.lastPush = props.lastPush || 0;
   this.setQuota(props.quota);
+  this.ctime = (typeof props.ctime === "number") ? props.ctime : 0;
 }
 
 PushRecord.prototype = {
@@ -74,11 +75,17 @@ PushRecord.prototype = {
         Math.round(8 * Math.pow(daysElapsed, -0.8)),
         prefs.get("maxQuotaPerSubscription")
       );
+      Services.telemetry.getHistogramById("PUSH_API_QUOTA_RESET_TO").add(currentQuota - 1);
     } else {
       // The user hasn't visited the site since the last notification.
       currentQuota = this.quota;
     }
     this.quota = Math.max(currentQuota - 1, 0);
+    // We check for ctime > 0 to skip older records that did not have ctime.
+    if (this.isExpired() && this.ctime > 0) {
+      let duration = Date.now() - this.ctime;
+      Services.telemetry.getHistogramById("PUSH_API_QUOTA_EXPIRATION_TIME").add(duration / 1000);
+    }
   },
 
   receivedPush(lastVisit) {
diff --git a/dom/push/PushServiceHttp2.jsm b/dom/push/PushServiceHttp2.jsm
index e771339bf469..eabb7a9471ee 100644
--- a/dom/push/PushServiceHttp2.jsm
+++ b/dom/push/PushServiceHttp2.jsm
@@ -260,6 +260,7 @@ var SubscriptionListener = function(aSubInfo, aResolve, aReject,
   this._data = '';
   this._serverURI = aServerURI;
   this._service = aPushServiceHttp2;
+  this._ctime = Date.now();
 };
 
 SubscriptionListener.prototype = {
@@ -362,8 +363,10 @@ SubscriptionListener.prototype = {
       scope: this._subInfo.record.scope,
       originAttributes: this._subInfo.record.originAttributes,
       quota: this._subInfo.record.maxQuota,
+      ctime: Date.now(),
     });
 
+    Services.telemetry.getHistogramById("PUSH_API_SUBSCRIBE_HTTP2_TIME").add(Date.now() - this._ctime);
     this._resolve(reply);
   },
 };
diff --git a/dom/push/PushServiceWebSocket.jsm b/dom/push/PushServiceWebSocket.jsm
index d3c37f8b2ca4..995c5afb3a25 100644
--- a/dom/push/PushServiceWebSocket.jsm
+++ b/dom/push/PushServiceWebSocket.jsm
@@ -811,8 +811,10 @@ this.PushServiceWebSocket = {
         originAttributes: tmp.record.originAttributes,
         version: null,
         quota: tmp.record.maxQuota,
+        ctime: Date.now(),
       });
       dump("PushWebSocket " +  JSON.stringify(record));
+      Services.telemetry.getHistogramById("PUSH_API_SUBSCRIBE_WS_TIME").add(Date.now() - tmp.ctime);
       tmp.resolve(record);
     } else {
       tmp.reject(reply);
diff --git a/toolkit/components/telemetry/Histograms.json b/toolkit/components/telemetry/Histograms.json
index 2604a6a7e4ad..aec789c7e6bf 100644
--- a/toolkit/components/telemetry/Histograms.json
+++ b/toolkit/components/telemetry/Histograms.json
@@ -9408,6 +9408,38 @@
     "kind": "count",
     "description": "Attempt to unsubscribe with Push Server succeeded."
   },
+  "PUSH_API_SUBSCRIBE_WS_TIME": {
+    "alert_emails": ["push@mozilla.com"],
+    "expires_in_version": "55",
+    "kind": "exponential",
+    "high": "15000",
+    "n_buckets": 10,
+    "description": "Time taken to subscribe over WebSocket (ms)."
+  },
+  "PUSH_API_SUBSCRIBE_HTTP2_TIME": {
+    "alert_emails": ["push@mozilla.com"],
+    "expires_in_version": "55",
+    "kind": "exponential",
+    "high": "15000",
+    "n_buckets": 10,
+    "description": "Time taken to subscribe over HTTP2 (ms)."
+  },
+  "PUSH_API_QUOTA_EXPIRATION_TIME": {
+    "alert_emails": ["push@mozilla.com"],
+    "expires_in_version": "55",
+    "kind": "exponential",
+    "high": "31622400",
+    "n_buckets": 20,
+    "description": "Time taken for a push subscription to expire its quota (seconds). The maximum is just over an year."
+  }
+  "PUSH_API_QUOTA_RESET_TO": {
+    "alert_emails": ["push@mozilla.com"],
+    "expires_in_version": "55",
+    "kind": "exponential",
+    "high": "200",
+    "n_buckets": 10,
+    "description": "The value a push record quota (a count) is reset to based on the user's browsing history."
+  },
   "FXA_CONFIGURED": {
     "alert_emails": ["fx-team@mozilla.com"],
     "expires_in_version": "45",

From ea76ea7a046ba4994dc9bf8fffc626ac630016ed Mon Sep 17 00:00:00 2001
From: Nikhil Marathe 
Date: Thu, 6 Aug 2015 16:59:35 -0700
Subject: [PATCH 013/113] Bug 914481 - Patch 4 - Track why we fail to deliver
 notifications to Service Workers. r=kitcambridge

--HG--
extra : rebase_source : 66bb02452a4b5ffb77157d0f7a44d56b327c360c
---
 dom/push/PushService.jsm                     | 26 +++++++++++++++++++
 toolkit/components/telemetry/Histograms.json | 27 +++++++++++++++++++-
 2 files changed, 52 insertions(+), 1 deletion(-)

diff --git a/dom/push/PushService.jsm b/dom/push/PushService.jsm
index dc328e7d2a75..0aa907448414 100644
--- a/dom/push/PushService.jsm
+++ b/dom/push/PushService.jsm
@@ -52,6 +52,16 @@ const PUSH_SERVICE_CONNECTION_DISABLE = 3;
 const PUSH_SERVICE_ACTIVE_OFFLINE = 4;
 const PUSH_SERVICE_RUNNING = 5;
 
+// Telemetry failure to send push notification to Service Worker reasons.
+// Key not found in local database.
+const kDROP_NOTIFICATION_REASON_KEY_NOT_FOUND = 0;
+// User cleared history.
+const kDROP_NOTIFICATION_REASON_NO_HISTORY = 1;
+// Version of message received not newer than previous one.
+const kDROP_NOTIFICATION_REASON_NO_VERSION_INCREMENT = 2;
+// Subscription has expired.
+const kDROP_NOTIFICATION_REASON_EXPIRED = 3;
+
 /**
  * State is change only in couple of functions:
  *   init - change state to PUSH_SERVICE_INIT if state was PUSH_SERVICE_UNINIT
@@ -673,6 +683,7 @@ this.PushService = {
       scope: record.scope
     };
 
+    Services.telemetry.getHistogramById("PUSH_API_NOTIFY_REGISTRATION_LOST").add();
     this._notifyListeners('pushsubscriptionchange', data);
   },
 
@@ -724,6 +735,12 @@ this.PushService = {
       .then(record => this._notifySubscriptionChangeObservers(record));
   },
 
+  _recordDidNotNotify: function(reason) {
+    Services.telemetry.
+      getHistogramById("PUSH_API_NOTIFICATION_RECEIVED_BUT_DID_NOT_NOTIFY").
+      add(reason);
+  },
+
   /**
    * Dispatches an incoming message to a service worker, recalculating the
    * quota for the associated push registration. If the quota is exceeded,
@@ -740,10 +757,12 @@ this.PushService = {
    */
   receivedPushMessage: function(keyID, message, updateFunc) {
     debug("receivedPushMessage()");
+    Services.telemetry.getHistogramById("PUSH_API_NOTIFICATION_RECEIVED").add();
 
     let shouldNotify = false;
     return this.getByKeyID(keyID).then(record => {
       if (!record) {
+        this._recordDidNotNotify(kDROP_NOTIFICATION_REASON_KEY_NOT_FOUND);
         throw new Error("No record for key ID " + keyID);
       }
       return record.getLastVisit();
@@ -751,15 +770,21 @@ this.PushService = {
       // As a special case, don't notify the service worker if the user
       // cleared their history.
       shouldNotify = isFinite(lastVisit);
+      if (!shouldNotify) {
+          this._recordDidNotNotify(kDROP_NOTIFICATION_REASON_NO_HISTORY);
+      }
       return this._db.update(keyID, record => {
         let newRecord = updateFunc(record);
         if (!newRecord) {
+          this._recordDidNotNotify(kDROP_NOTIFICATION_REASON_NO_VERSION_INCREMENT);
           return null;
         }
+        // FIXME(nsm): WHY IS expired checked here but then also checked in the next case?
         if (newRecord.isExpired()) {
           // Because `unregister` is advisory only, we can still receive messages
           // for stale registrations from the server.
           debug("receivedPushMessage: Ignoring update for expired key ID " + keyID);
+          this._recordDidNotNotify(kDROP_NOTIFICATION_REASON_EXPIRED);
           return null;
         }
         newRecord.receivedPush(lastVisit);
@@ -825,6 +850,7 @@ this.PushService = {
       scope: aPushRecord.scope
     };
 
+    Services.telemetry.getHistogramById("PUSH_API_NOTIFY").add();
     this._notifyListeners('push', data);
     return true;
   },
diff --git a/toolkit/components/telemetry/Histograms.json b/toolkit/components/telemetry/Histograms.json
index aec789c7e6bf..c840e8627e54 100644
--- a/toolkit/components/telemetry/Histograms.json
+++ b/toolkit/components/telemetry/Histograms.json
@@ -9431,7 +9431,7 @@
     "high": "31622400",
     "n_buckets": 20,
     "description": "Time taken for a push subscription to expire its quota (seconds). The maximum is just over an year."
-  }
+  },
   "PUSH_API_QUOTA_RESET_TO": {
     "alert_emails": ["push@mozilla.com"],
     "expires_in_version": "55",
@@ -9440,6 +9440,31 @@
     "n_buckets": 10,
     "description": "The value a push record quota (a count) is reset to based on the user's browsing history."
   },
+  "PUSH_API_NOTIFICATION_RECEIVED": {
+    "alert_emails": ["push@mozilla.com"],
+    "expires_in_version": "55",
+    "kind": "count",
+    "description": "Push notification was received from server."
+  },
+  "PUSH_API_NOTIFICATION_RECEIVED_BUT_DID_NOT_NOTIFY": {
+    "alert_emails": ["push@mozilla.com"],
+    "expires_in_version": "55",
+    "kind": "enumerated",
+    "n_values": 15,
+    "description": "Push notification was received from server, but not delivered to ServiceWorker. Enumeration values are defined in dom/push/PushService.jsm as kDROP_NOTIFICATION_REASON_*."
+  },
+  "PUSH_API_NOTIFY": {
+    "alert_emails": ["push@mozilla.com"],
+    "expires_in_version": "55",
+    "kind": "count",
+    "description": "Attempt to notify ServiceWorker of push notification."
+  },
+  "PUSH_API_NOTIFY_REGISTRATION_LOST": {
+    "alert_emails": ["push@mozilla.com"],
+    "expires_in_version": "55",
+    "kind": "count",
+    "description": "Attempt to notify ServiceWorker of push notification resubscription."
+  },
   "FXA_CONFIGURED": {
     "alert_emails": ["fx-team@mozilla.com"],
     "expires_in_version": "45",

From 102529365a80d1bd08c805d6af727c54e5de916d Mon Sep 17 00:00:00 2001
From: Dragana Damjanovic 
Date: Wed, 16 Sep 2015 04:46:00 +0200
Subject: [PATCH 014/113] Bug 1027579 - Do not load fonts from the cache if
 LOAD_BYPASS_CACHE is set. r=jfkthame r=bz

--HG--
extra : rebase_source : a98200dacf098aa2de926aebaa54c79c242f8ae3
---
 layout/style/FontFaceSet.cpp | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/layout/style/FontFaceSet.cpp b/layout/style/FontFaceSet.cpp
index 4c00e756d4f8..6158454e819b 100644
--- a/layout/style/FontFaceSet.cpp
+++ b/layout/style/FontFaceSet.cpp
@@ -1338,6 +1338,12 @@ FontFaceSet::CheckFontLoad(const gfxFontFaceSrc* aFontFaceSrc,
         *aBypassCache = true;
       }
     }
+    uint32_t flags;
+    if (NS_SUCCEEDED(docShell->GetDefaultLoadFlags(&flags))) {
+      if (flags & nsIRequest::LOAD_BYPASS_CACHE) {
+        *aBypassCache = true;
+      }
+    }
   }
 
   return rv;

From 41d164744a78c8a5b6a70aec44cc4d6e1ff099ca Mon Sep 17 00:00:00 2001
From: Michael Froman 
Date: Thu, 10 Sep 2015 13:20:09 -0500
Subject: [PATCH 015/113] Bug 1095793 - use mid if provided to place candidate
 in msection. r=bwc

--HG--
extra : rebase_source : e85bbde1c0cbd3733f82a11c98245079ea1cbf5c
---
 .../test_peerConnection_addIceCandidate.html  | 24 ++++++++++++++-
 media/webrtc/signaling/src/sdp/SdpHelper.cpp  | 30 +++++++++++++++++--
 .../signaling/test/jsep_session_unittest.cpp  | 21 +++++++------
 3 files changed, 62 insertions(+), 13 deletions(-)

diff --git a/dom/media/tests/mochitest/test_peerConnection_addIceCandidate.html b/dom/media/tests/mochitest/test_peerConnection_addIceCandidate.html
index 1f0f2f2a0f45..e6f812e9d332 100644
--- a/dom/media/tests/mochitest/test_peerConnection_addIceCandidate.html
+++ b/dom/media/tests/mochitest/test_peerConnection_addIceCandidate.html
@@ -8,7 +8,7 @@
 
-
-
-
+
+
+
 
+
+  
+
+
+
+
+
+
+
+
+
+
+ diff --git a/layout/reftests/transform-3d/preserves3d-nested.html b/layout/reftests/transform-3d/preserves3d-nested.html new file mode 100644 index 000000000000..673a982e99a5 --- /dev/null +++ b/layout/reftests/transform-3d/preserves3d-nested.html @@ -0,0 +1,46 @@ + +preserve-3d consequence nested context + + +
+
+
+
+
+
+
+
+
+
+
+ diff --git a/layout/reftests/transform-3d/reftest.list b/layout/reftests/transform-3d/reftest.list index b337b6bdf1da..aa07ae75bcd1 100644 --- a/layout/reftests/transform-3d/reftest.list +++ b/layout/reftests/transform-3d/reftest.list @@ -11,16 +11,16 @@ == rotatex-perspective-1c.html rotatex-1-ref.html == rotatex-perspective-3a.html rotatex-perspective-3-ref.html == scalez-1a.html scalez-1-ref.html -fuzzy-if(cocoaWidget,17,4) == preserve3d-1a.html preserve3d-1-ref.html +fuzzy-if(gtkWidget||winWidget,8,376) fuzzy-if(Android,8,441) fuzzy-if(cocoaWidget,17,4) == preserve3d-1a.html preserve3d-1-ref.html == preserve3d-1b.html about:blank == preserve3d-clipped.html about:blank == preserve3d-2a.html preserve3d-2-ref.html == preserve3d-2b.html preserve3d-2-ref.html == preserve3d-2c.html preserve3d-2-ref.html == preserve3d-2d.html preserve3d-2-ref.html -== preserve3d-3a.html preserve3d-3-ref.html +fuzzy(4,100) == preserve3d-3a.html preserve3d-3-ref.html skip-if(B2G||Mulet) == preserve3d-4a.html green-rect.html # Initial mulet triage: parity with B2G/B2G Desktop -fuzzy-if(Android&&AndroidVersion>=15,4,300) == preserve3d-5a.html preserve3d-5-ref.html +fuzzy-if(gtkWidget,4,200) fuzzy-if(Android&&AndroidVersion>=15,4,300) == preserve3d-5a.html preserve3d-5-ref.html == scale3d-z.html scalez-1-ref.html fuzzy-if(winWidget,102,580) fuzzy-if(d2d,143,681) fuzzy-if(OSX>=1008,224,924) == scale3d-all.html scale3d-1-ref.html # subpixel AA fuzzy-if(winWidget,102,580) fuzzy-if(d2d,143,681) fuzzy-if(OSX>=1008,224,924) == scale3d-all-separate.html scale3d-1-ref.html # subpixel AA @@ -64,6 +64,7 @@ fuzzy(3,99) fuzzy-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)&&!layersGPUAccele fuzzy(3,99) == animate-cube-degrees.html animate-cube-degrees-ref.html # subpixel AA == animate-cube-degrees-zoom.html animate-cube-degrees-zoom-ref.html != animate-cube-degrees-ref.html animate-cube-degrees-zoom-ref.html +fuzzy-if(B2G,15,100) fuzzy-if(Android,100,100) fuzzy-if(winWidget,90,200) fuzzy-if(B2G,88,100) fuzzy-if(cocoaWidget,90,100) fuzzy-if(gtkWidget,80,200) == preserves3d-nested.html preserves3d-nested-ref.html fuzzy-if(cocoaWidget,128,9) == animate-preserve3d-parent.html animate-preserve3d-ref.html # intermittently fuzzy on Mac fuzzy-if(cocoaWidget,128,9) == animate-preserve3d-child.html animate-preserve3d-ref.html # intermittently fuzzy on Mac == animate-backface-hidden.html about:blank From 577d8148131866e7d5fe73adbe2f209b7f89ed3f Mon Sep 17 00:00:00 2001 From: "Thinker K.F. Li" Date: Thu, 17 Sep 2015 03:31:00 +0200 Subject: [PATCH 036/113] Bug 1097464 - Part 4 - Fix preserve3d wording for layer flags. r=roc --- gfx/layers/Layers.cpp | 2 +- gfx/layers/Layers.h | 2 +- layout/base/nsDisplayList.cpp | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/gfx/layers/Layers.cpp b/gfx/layers/Layers.cpp index c65c0cd7e3fe..cbfd315e2702 100644 --- a/gfx/layers/Layers.cpp +++ b/gfx/layers/Layers.cpp @@ -1250,7 +1250,7 @@ ContainerLayer::SortChildrenBy3DZOrder(nsTArray& aArray) for (Layer* l = GetFirstChild(); l; l = l->GetNextSibling()) { ContainerLayer* container = l->AsContainerLayer(); - if (container && container->GetContentFlags() & CONTENT_PRESERVE_3D) { + if (container && container->GetContentFlags() & CONTENT_EXTEND_3D_CONTEXT) { toSort.AppendElement(l); } else { if (toSort.Length() > 0) { diff --git a/gfx/layers/Layers.h b/gfx/layers/Layers.h index 5fd0a5588a43..7723cc91c373 100644 --- a/gfx/layers/Layers.h +++ b/gfx/layers/Layers.h @@ -784,7 +784,7 @@ public: * If this is set then this layer is part of a preserve-3d group, and should * be sorted with sibling layers that are also part of the same group. */ - CONTENT_PRESERVE_3D = 0x08, + CONTENT_EXTEND_3D_CONTEXT = 0x08, /** * This indicates that the transform may be changed on during an empty * transaction where there is no possibility of redrawing the content, so the diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp index a822eb3990a9..3d5f75a6bb0e 100644 --- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -5257,9 +5257,9 @@ already_AddRefed nsDisplayTransform::BuildLayer(nsDisplayListBuilder *aBu // Add the preserve-3d flag for this layer, BuildContainerLayerFor clears all flags, // so we never need to explicitely unset this flag. if (mFrame->Preserves3D() || mFrame->Preserves3DChildren()) { - container->SetContentFlags(container->GetContentFlags() | Layer::CONTENT_PRESERVE_3D); + container->SetContentFlags(container->GetContentFlags() | Layer::CONTENT_EXTEND_3D_CONTEXT); } else { - container->SetContentFlags(container->GetContentFlags() & ~Layer::CONTENT_PRESERVE_3D); + container->SetContentFlags(container->GetContentFlags() & ~Layer::CONTENT_EXTEND_3D_CONTEXT); } nsDisplayListBuilder::AddAnimationsAndTransitionsToLayer(container, aBuilder, From 31e7d8b95dc5f612d868f1643157238eb309fd52 Mon Sep 17 00:00:00 2001 From: "Thinker K.F. Li" Date: Thu, 17 Sep 2015 03:31:00 +0200 Subject: [PATCH 037/113] Bug 1097464 - Part 5 - Fix preserve3d wording for nsIFrame. r=roc --- layout/base/ActiveLayerTracker.cpp | 2 +- layout/base/FrameLayerBuilder.cpp | 3 +- layout/base/nsDisplayList.cpp | 16 ++++----- layout/base/nsLayoutUtils.cpp | 8 ++--- layout/base/nsPresShell.cpp | 4 +-- layout/generic/nsFrame.cpp | 52 +++++++++++++++--------------- layout/generic/nsIFrame.h | 8 ++--- layout/style/AnimationCommon.cpp | 6 ++-- 8 files changed, 50 insertions(+), 49 deletions(-) diff --git a/layout/base/ActiveLayerTracker.cpp b/layout/base/ActiveLayerTracker.cpp index adee328e119a..9a77f2ac350b 100644 --- a/layout/base/ActiveLayerTracker.cpp +++ b/layout/base/ActiveLayerTracker.cpp @@ -337,7 +337,7 @@ ActiveLayerTracker::IsStyleAnimated(nsDisplayListBuilder* aBuilder, return true; } } - if (aProperty == eCSSProperty_transform && aFrame->Preserves3D()) { + if (aProperty == eCSSProperty_transform && aFrame->Combines3DTransformWithAncestors()) { return IsStyleAnimated(aBuilder, aFrame->GetParent(), aProperty); } return nsLayoutUtils::HasCurrentAnimationsForProperties(aFrame, &aProperty, 1); diff --git a/layout/base/FrameLayerBuilder.cpp b/layout/base/FrameLayerBuilder.cpp index bd8a25a2271c..ecc78701d524 100644 --- a/layout/base/FrameLayerBuilder.cpp +++ b/layout/base/FrameLayerBuilder.cpp @@ -3942,7 +3942,8 @@ ContainerState::ProcessDisplayItems(nsDisplayList* aList) // 3D-transformed layers don't necessarily draw in the order in which // they're added to their parent container layer. bool mayDrawOutOfOrder = itemType == nsDisplayItem::TYPE_TRANSFORM && - (item->Frame()->Preserves3D() || item->Frame()->Preserves3DChildren()); + (item->Frame()->Combines3DTransformWithAncestors() || + item->Frame()->Extend3DContext()); // Let mPaintedLayerDataTree know about this item, so that // FindPaintedLayerFor and FindOpaqueBackgroundColor are aware of this diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp index 3d5f75a6bb0e..1665965f7865 100644 --- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -934,7 +934,7 @@ nsDisplayListBuilder::MarkPreserve3DFramesForDisplayList(nsIFrame* aDirtyFrame, nsFrameList::Enumerator childFrames(lists.CurrentList()); for (; !childFrames.AtEnd(); childFrames.Next()) { nsIFrame *child = childFrames.get(); - if (child->Preserves3D()) { + if (child->Combines3DTransformWithAncestors()) { mFramesMarkedForDisplay.AppendElement(child); nsRect dirty = aDirtyRect - child->GetOffsetTo(aDirtyFrame); @@ -1838,7 +1838,7 @@ void nsDisplayList::HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect, // so we can sort them later, otherwise we add them directly to the output list. nsTArray *writeFrames = aOutFrames; if (item->GetType() == nsDisplayItem::TYPE_TRANSFORM && - item->Frame()->Preserves3D()) { + item->Frame()->Combines3DTransformWithAncestors()) { if (outFrames.Length()) { nsDisplayTransform *transform = static_cast(item); nsPoint point = aRect.TopLeft(); @@ -3564,7 +3564,7 @@ nsDisplayWrapList::nsDisplayWrapList(nsDisplayListBuilder* aBuilder, // inside this list afterwards (see WrapPreserve3DList in nsFrame.cpp). // In this case we will always be outside of the transform, so share // our parents reference frame. - if (aFrame->Preserves3DChildren()) { + if (aFrame->Extend3DContext()) { mReferenceFrame = aBuilder->FindReferenceFrameFor(GetTransformRootFrame(aFrame)); mToReferenceFrame = aFrame->GetOffsetToCrossDoc(mReferenceFrame); @@ -3610,7 +3610,7 @@ nsDisplayWrapList::nsDisplayWrapList(nsDisplayListBuilder* aBuilder, return; } - if (aFrame->Preserves3DChildren()) { + if (aFrame->Extend3DContext()) { mReferenceFrame = aBuilder->FindReferenceFrameFor(GetTransformRootFrame(aFrame)); mToReferenceFrame = aFrame->GetOffsetToCrossDoc(mReferenceFrame); @@ -5051,11 +5051,11 @@ nsDisplayTransform::GetResultingTransformMatrixInternal(const FrameTransformProp } } - if (frame && frame->Preserves3D()) { + if (frame && frame->Combines3DTransformWithAncestors()) { // Include the transform set on our parent NS_ASSERTION(frame->GetParent() && frame->GetParent()->IsTransformed() && - frame->GetParent()->Preserves3DChildren(), + frame->GetParent()->Extend3DContext(), "Preserve3D mismatch!"); FrameTransformProperties props(frame->GetParent(), aAppUnitsPerPixel, @@ -5256,7 +5256,7 @@ already_AddRefed nsDisplayTransform::BuildLayer(nsDisplayListBuilder *aBu // Add the preserve-3d flag for this layer, BuildContainerLayerFor clears all flags, // so we never need to explicitely unset this flag. - if (mFrame->Preserves3D() || mFrame->Preserves3DChildren()) { + if (mFrame->Combines3DTransformWithAncestors() || mFrame->Extend3DContext()) { container->SetContentFlags(container->GetContentFlags() | Layer::CONTENT_EXTEND_3D_CONTEXT); } else { container->SetContentFlags(container->GetContentFlags() & ~Layer::CONTENT_EXTEND_3D_CONTEXT); @@ -5282,7 +5282,7 @@ nsDisplayTransform::GetLayerState(nsDisplayListBuilder* aBuilder, const ContainerLayerParameters& aParameters) { // If the transform is 3d, or the layer takes part in preserve-3d sorting // then we *always* want this to be an active layer. - if (!GetTransform().Is2D() || mFrame->Preserves3D()) { + if (!GetTransform().Is2D() || mFrame->Combines3DTransformWithAncestors()) { return LAYER_ACTIVE_FORCE; } // Here we check if the *post-transform* bounds of this item are big enough diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index b26888878ea0..d638db4bd9a4 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -2379,7 +2379,7 @@ nsLayoutUtils::GetTransformToAncestor(nsIFrame *aFrame, const nsIFrame *aAncesto } ctm = aFrame->GetTransformMatrix(aAncestor, &parent); while (parent && parent != aAncestor) { - if (!parent->Preserves3DChildren()) { + if (!parent->Extend3DContext()) { ctm.ProjectTo2D(); } ctm = ctm * parent->GetTransformMatrix(aAncestor, &parent); @@ -2416,7 +2416,7 @@ GetTransformToAncestorExcludingAnimated(nsIFrame* aFrame, if (ActiveLayerTracker::IsScaleSubjectToAnimation(parent)) { return Matrix4x4(); } - if (!parent->Preserves3DChildren()) { + if (!parent->Extend3DContext()) { ctm.ProjectTo2D(); } ctm = ctm * parent->GetTransformMatrix(aAncestor, &parent); @@ -2643,7 +2643,7 @@ nsLayoutUtils::GetLayerTransformForFrame(nsIFrame* aFrame, { // FIXME/bug 796690: we can sometimes compute a transform in these // cases, it just increases complexity considerably. Punt for now. - if (aFrame->Preserves3DChildren() || aFrame->HasTransformGetter()) { + if (aFrame->Extend3DContext() || aFrame->HasTransformGetter()) { return false; } @@ -6644,7 +6644,7 @@ nsLayoutUtils::GetReferenceFrame(nsIFrame* aFrame) nsLayoutUtils::GetTransformRootFrame(nsIFrame* aFrame) { nsIFrame *parent = nsLayoutUtils::GetCrossDocParentFrame(aFrame); - while (parent && parent->Preserves3DChildren()) { + while (parent && parent->Extend3DContext()) { parent = nsLayoutUtils::GetCrossDocParentFrame(parent); } return parent; diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp index c24709a4dd86..4592300c81fd 100644 --- a/layout/base/nsPresShell.cpp +++ b/layout/base/nsPresShell.cpp @@ -5723,7 +5723,7 @@ PresShell::MarkImagesInSubtreeVisible(nsIFrame* aFrame, const nsRect& aRect) rect = scrollFrame->ExpandRectToNearlyVisible(rect); } - bool preserves3DChildren = aFrame->Preserves3DChildren(); + bool preserves3DChildren = aFrame->Extend3DContext(); // we assume all images in popups are visible elsewhere, so we skip them here const nsIFrame::ChildListIDs skip(nsIFrame::kPopupList | @@ -5741,7 +5741,7 @@ PresShell::MarkImagesInSubtreeVisible(nsIFrame* aFrame, const nsRect& aRect) } if (child->IsTransformed()) { // for children of a preserve3d element we just pass down the same dirty rect - if (!preserves3DChildren || !child->Preserves3D()) { + if (!preserves3DChildren || !child->Combines3DTransformWithAncestors()) { const nsRect overflow = child->GetVisualOverflowRectRelativeToSelf(); nsRect out; if (nsDisplayTransform::UntransformRect(r, overflow, child, nsPoint(0,0), &out)) { diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index 2504a7f5267a..6bef7b2b0dbf 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -1120,7 +1120,7 @@ nsIFrame::IsSVGTransformed(gfx::Matrix *aOwnTransforms, } bool -nsIFrame::Preserves3DChildren() const +nsIFrame::Extend3DContext() const { const nsStyleDisplay* disp = StyleDisplay(); if (disp->mTransformStyle != NS_STYLE_TRANSFORM_STYLE_PRESERVE_3D || @@ -1140,9 +1140,9 @@ nsIFrame::Preserves3DChildren() const } bool -nsIFrame::Preserves3D() const +nsIFrame::Combines3DTransformWithAncestors() const { - if (!GetParent() || !GetParent()->Preserves3DChildren()) { + if (!GetParent() || !GetParent()->Extend3DContext()) { return false; } return StyleDisplay()->HasTransform(this) || StyleDisplay()->BackfaceIsHidden(); @@ -1804,7 +1804,7 @@ WrapPreserve3DListInternal(nsIFrame* aFrame, nsDisplayListBuilder *aBuilder, // nsDisplayTransform. if (childFrame->GetParent() && - (childFrame->GetParent()->Preserves3DChildren() || childFrame == aFrame)) { + (childFrame->GetParent()->Extend3DContext() || childFrame == aFrame)) { switch (item->GetType()) { case nsDisplayItem::TYPE_TRANSFORM: { if (!aTemp->IsEmpty()) { @@ -2064,7 +2064,7 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder, nsDisplayTransform::ShouldPrerenderTransformedContent(aBuilder, this)) { dirtyRect = overflow; } else { - if (overflow.IsEmpty() && !Preserves3DChildren()) { + if (overflow.IsEmpty() && !Extend3DContext()) { return; } @@ -2134,7 +2134,7 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder, // Preserve3DChildren() also guarantees that applyAbsPosClipping and usingSVGEffects are false // We only modify the preserve-3d rect if we are the top of a preserve-3d heirarchy - if (Preserves3DChildren()) { + if (Extend3DContext()) { aBuilder->MarkPreserve3DFramesForDisplayList(this, aDirtyRect); } @@ -2265,7 +2265,7 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder, buildingDisplayList.SetReferenceFrameAndCurrentOffset(outerReferenceFrame, GetOffsetToCrossDoc(outerReferenceFrame)); - if (Preserves3DChildren()) { + if (Extend3DContext()) { WrapPreserve3DList(this, aBuilder, &resultList); } else { resultList.AppendNewToTop( @@ -2400,7 +2400,7 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder, } pseudoStackingContext = true; } - if (child->Preserves3D()) { + if (child->Combines3DTransformWithAncestors()) { nsRect* savedDirty = static_cast (child->Properties().Get(nsDisplayListBuilder::Preserve3DDirtyRectProperty())); if (savedDirty) { @@ -5857,10 +5857,10 @@ nsIFrame::ListGeneric(nsACString& aTo, const char* aPrefix, uint32_t aFlags) con if (ChildrenHavePerspective()) { aTo += nsPrintfCString(" perspective"); } - if (Preserves3DChildren()) { + if (Extend3DContext()) { aTo += nsPrintfCString(" preserves-3d-children"); } - if (Preserves3D()) { + if (Combines3DTransformWithAncestors()) { aTo += nsPrintfCString(" preserves-3d"); } if (mContent) { @@ -7514,14 +7514,14 @@ UnionBorderBoxes(nsIFrame* aFrame, bool aApplyTransform, for (nsFrameList::Enumerator e(children); !e.AtEnd(); e.Next()) { nsIFrame* child = e.get(); // Note that passing |true| for aApplyTransform when - // child->Preserves3D() is incorrect if our aApplyTransform is - // false... but the opposite would be as well. This is because - // elements within a preserve-3d scene are always transformed up - // to the top of the scene. This means we don't have a - // mechanism for getting a transform up to an intermediate point - // within the scene. We choose to over-transform rather than - // under-transform because this is consistent with other - // overflow areas. + // child->Combines3DTransformWithAncestors() is incorrect if our + // aApplyTransform is false... but the opposite would be as + // well. This is because elements within a preserve-3d scene + // are always transformed up to the top of the scene. This + // means we don't have a mechanism for getting a transform up to + // an intermediate point within the scene. We choose to + // over-transform rather than under-transform because this is + // consistent with other overflow areas. nsRect childRect = UnionBorderBoxes(child, true) + child->GetPosition(); @@ -7536,7 +7536,7 @@ UnionBorderBoxes(nsIFrame* aFrame, bool aApplyTransform, // union. This doesn't match the way we handle overflow areas // with 2-D transforms, though it does match the way we handle // overflow areas in preserve-3d 3-D scenes. - if (doTransform && !child->Preserves3D()) { + if (doTransform && !child->Combines3DTransformWithAncestors()) { childRect = nsDisplayTransform::TransformRect(childRect, aFrame, nsPoint(0, 0), &bounds); } @@ -7605,7 +7605,7 @@ ComputeAndIncludeOutlineArea(nsIFrame* aFrame, nsOverflowAreas& aOverflowAreas, if (parent == aFrame) { break; } - if (parent->IsTransformed() && !f->Preserves3D()) { + if (parent->IsTransformed() && !f->Combines3DTransformWithAncestors()) { r = nsDisplayTransform::TransformRect(r, parent, nsPoint(0, 0)); } } @@ -7653,7 +7653,7 @@ nsIFrame::FinishAndStoreOverflow(nsOverflowAreas& aOverflowAreas, nsRect bounds(nsPoint(0, 0), aNewSize); // Store the passed in overflow area if we are a preserve-3d frame or we have // a transform, and it's not just the frame bounds. - if (Preserves3D() || IsTransformed()) { + if (Combines3DTransformWithAncestors() || IsTransformed()) { if (!aOverflowAreas.VisualOverflow().IsEqualEdges(bounds) || !aOverflowAreas.ScrollableOverflow().IsEqualEdges(bounds)) { nsOverflowAreas* initial = @@ -7766,7 +7766,7 @@ nsIFrame::FinishAndStoreOverflow(nsOverflowAreas& aOverflowAreas, nsRect& o = aOverflowAreas.Overflow(otype); o = nsDisplayTransform::TransformRect(o, this, nsPoint(0, 0), &newBounds); } - if (Preserves3DChildren()) { + if (Extend3DContext()) { ComputePreserve3DChildrenOverflow(aOverflowAreas, newBounds); } else if (sizeChanged && ChildrenHavePerspective()) { RecomputePerspectiveChildrenOverflow(this, &newBounds); @@ -7856,9 +7856,9 @@ RecomputePreserve3DChildrenOverflow(nsIFrame* aFrame, const nsRect* aBounds) if (!FrameMaintainsOverflow(child)) { continue; // frame does not maintain overflow rects } - if (child->Preserves3DChildren()) { + if (child->Extend3DContext()) { RecomputePreserve3DChildrenOverflow(child, nullptr); - } else if (child->Preserves3D()) { + } else if (child->Combines3DTransformWithAncestors()) { nsOverflowAreas* overflow = static_cast(child->Properties().Get(nsIFrame::InitialOverflowProperty())); nsRect bounds(nsPoint(0, 0), child->GetSize()); @@ -7904,7 +7904,7 @@ nsIFrame::ComputePreserve3DChildrenOverflow(nsOverflowAreas& aOverflowAreas, con // If we're the top frame in a preserve 3d chain then we need to recalculate the overflow // areas of all our children since they will have used our size/offset which was invalid at // the time. - if (!Preserves3D()) { + if (!Combines3DTransformWithAncestors()) { RecomputePreserve3DChildrenOverflow(this, &aBounds); } @@ -7920,7 +7920,7 @@ nsIFrame::ComputePreserve3DChildrenOverflow(nsOverflowAreas& aOverflowAreas, con nsRect scrollable = child->GetScrollableOverflowRect(); visual.MoveBy(offset); scrollable.MoveBy(offset); - if (child->Preserves3D()) { + if (child->Combines3DTransformWithAncestors()) { childVisual = childVisual.Union(visual); childScrollable = childScrollable.Union(scrollable); } else { diff --git a/layout/generic/nsIFrame.h b/layout/generic/nsIFrame.h index fcaa420aa2df..a1748e5cff88 100644 --- a/layout/generic/nsIFrame.h +++ b/layout/generic/nsIFrame.h @@ -1247,18 +1247,18 @@ public: Matrix *aFromParentTransforms = nullptr) const; /** - * Returns whether this frame will attempt to preserve the 3d transforms of its + * Returns whether this frame will attempt to extend the 3d transforms of its * children. This requires transform-style: preserve-3d, as well as no clipping * or svg effects. */ - bool Preserves3DChildren() const; + bool Extend3DContext() const; /** - * Returns whether this frame has a parent that Preserves3DChildren() and has + * Returns whether this frame has a parent that Extend3DContext() and has * its own transform (or hidden backface) to be combined with the parent's * transform. */ - bool Preserves3D() const; + bool Combines3DTransformWithAncestors() const; bool HasPerspective() const; diff --git a/layout/style/AnimationCommon.cpp b/layout/style/AnimationCommon.cpp index 68c51560d0fa..2d9df4ee2baa 100644 --- a/layout/style/AnimationCommon.cpp +++ b/layout/style/AnimationCommon.cpp @@ -537,8 +537,8 @@ AnimationCollection::CanAnimatePropertyOnCompositor( return false; } if (aProperty == eCSSProperty_transform) { - if (frame->Preserves3D() || - frame->Preserves3DChildren()) { + if (frame->Combines3DTransformWithAncestors() || + frame->Extend3DContext()) { if (shouldLog) { nsCString message; message.AppendLiteral("Gecko bug: Async animation of 'preserve-3d' transforms is not supported. See bug 779598"); @@ -548,7 +548,7 @@ AnimationCollection::CanAnimatePropertyOnCompositor( } // Note that testing BackfaceIsHidden() is not a sufficient test for // what we need for animating backface-visibility correctly if we - // remove the above test for Preserves3DChildren(); that would require + // remove the above test for Extend3DContext(); that would require // looking at backface-visibility on descendants as well. if (frame->StyleDisplay()->BackfaceIsHidden()) { if (shouldLog) { From 76109f93c44bba2f36bece5364a58e8c154c0eae Mon Sep 17 00:00:00 2001 From: "Thinker K.F. Li" Date: Thu, 17 Sep 2015 03:31:00 +0200 Subject: [PATCH 038/113] Bug 1097464 - Part 6 - Handle preserves-3d by compositor. r=roc Remove WrapPreserve3DList() and replaced it by creating a nsDisplayTransform item for each transformed frame. - Add an additional item for each top frame extending 3D context to separate consequence contexts. - Effective transform of a layer is the accumulation of ancestors in the same 3D context. - The layers creating new context and extended by children need a temporary buffer if it's effective transform is not 2D. - Clip rects are accumulated along the context chain. - Visible rects of items are computed from dirty regions of the frame creating the context and accumulated transforms. - Bounds of items are computed from accumulated transforms and accumulated bounds of the descent frames. - Backface hidden is handled by compositor and BasicLayerManager. --- gfx/layers/LayerSorter.cpp | 9 +- gfx/layers/Layers.cpp | 101 ++++++- gfx/layers/Layers.h | 47 ++- gfx/layers/basic/BasicContainerLayer.cpp | 44 ++- gfx/layers/basic/BasicLayerManager.cpp | 69 ++++- gfx/layers/client/ClientContainerLayer.h | 2 +- .../composite/ContainerLayerComposite.cpp | 20 +- layout/base/FrameLayerBuilder.cpp | 124 ++++++-- layout/base/nsDisplayList.cpp | 274 +++++++++++++----- layout/base/nsDisplayList.h | 228 ++++++++++++++- layout/base/nsLayoutUtils.cpp | 12 +- layout/base/nsLayoutUtils.h | 16 +- layout/generic/nsFrame.cpp | 195 +++++-------- layout/generic/nsIFrame.h | 8 + 14 files changed, 858 insertions(+), 291 deletions(-) diff --git a/gfx/layers/LayerSorter.cpp b/gfx/layers/LayerSorter.cpp index 08dd91a794ab..4ed5d2228a13 100644 --- a/gfx/layers/LayerSorter.cpp +++ b/gfx/layers/LayerSorter.cpp @@ -78,8 +78,13 @@ static LayerSortOrder CompareDepth(Layer* aOne, Layer* aTwo) { gfxRect ourRect = aOne->GetEffectiveVisibleRegion().GetBounds(); gfxRect otherRect = aTwo->GetEffectiveVisibleRegion().GetBounds(); - Matrix4x4 ourTransform = aOne->GetTransform(); - Matrix4x4 otherTransform = aTwo->GetTransform(); + MOZ_ASSERT(aOne->GetParent() && aOne->GetParent()->Extend3DContext() && + aTwo->GetParent() && aTwo->GetParent()->Extend3DContext()); + // Effective transform of leaves may had been projected to 2D. + Matrix4x4 ourTransform = + aOne->GetLocalTransform() * aOne->GetParent()->GetEffectiveTransform(); + Matrix4x4 otherTransform = + aTwo->GetLocalTransform() * aTwo->GetParent()->GetEffectiveTransform(); // Transform both rectangles and project into 2d space. gfxQuad ourTransformedRect = ourRect.TransformToQuad(ourTransform); diff --git a/gfx/layers/Layers.cpp b/gfx/layers/Layers.cpp index cbfd315e2702..1631c8f81994 100644 --- a/gfx/layers/Layers.cpp +++ b/gfx/layers/Layers.cpp @@ -744,7 +744,22 @@ RenderTargetIntRect Layer::CalculateScissorRect(const RenderTargetIntRect& aCurrentScissorRect) { ContainerLayer* container = GetParent(); - NS_ASSERTION(container, "This can't be called on the root!"); + ContainerLayer* containerChild = nullptr; + NS_ASSERTION(GetParent(), "This can't be called on the root!"); + + // Find the layer creating the 3D context. + while (container->Extend3DContext()) { + containerChild = container; + container = container->GetParent(); + MOZ_ASSERT(container); + } + + // Find the nearest layer with a clip, or this layer. + // ContainerState::SetupScrollingMetadata() may install a clip on + // the layer. + Layer *clipLayer = + containerChild && containerChild->GetEffectiveClipRect() ? + containerChild : this; // Establish initial clip rect: it's either the one passed in, or // if the parent has an intermediate surface, it's the extents of that surface. @@ -755,7 +770,7 @@ Layer::CalculateScissorRect(const RenderTargetIntRect& aCurrentScissorRect) currentClip = aCurrentScissorRect; } - if (!GetEffectiveClipRect()) { + if (!clipLayer->GetEffectiveClipRect()) { return currentClip; } @@ -767,7 +782,7 @@ Layer::CalculateScissorRect(const RenderTargetIntRect& aCurrentScissorRect) } const RenderTargetIntRect clipRect = - ViewAs(*GetEffectiveClipRect(), + ViewAs(*clipLayer->GetEffectiveClipRect(), PixelCastJustification::RenderTargetIsParentLayerForRoot); if (clipRect.IsEmpty()) { // We might have a non-translation transform in the container so we can't @@ -1225,6 +1240,22 @@ ContainerLayer::FillSpecificAttributes(SpecificLayerAttributes& aAttrs) reinterpret_cast(mHMDInfo.get())); } +bool +ContainerLayer::Creates3DContextWithExtendingChildren() +{ + if (Extend3DContext()) { + return false; + } + for (Layer* child = GetFirstChild(); + child; + child = child->GetNextSibling()) { + if (child->Extend3DContext()) { + return true; + } + } + return false; +} + bool ContainerLayer::HasMultipleChildren() { @@ -1243,6 +1274,22 @@ ContainerLayer::HasMultipleChildren() return false; } +/** + * Collect all leaf descendants of the current 3D context. + */ +void +ContainerLayer::Collect3DContextLeaves(nsTArray& aToSort) +{ + for (Layer* l = GetFirstChild(); l; l = l->GetNextSibling()) { + ContainerLayer* container = l->AsContainerLayer(); + if (container && container->Extend3DContext()) { + container->Collect3DContextLeaves(aToSort); + } else { + aToSort.AppendElement(l); + } + } +} + void ContainerLayer::SortChildrenBy3DZOrder(nsTArray& aArray) { @@ -1250,8 +1297,8 @@ ContainerLayer::SortChildrenBy3DZOrder(nsTArray& aArray) for (Layer* l = GetFirstChild(); l; l = l->GetNextSibling()) { ContainerLayer* container = l->AsContainerLayer(); - if (container && container->GetContentFlags() & CONTENT_EXTEND_3D_CONTEXT) { - toSort.AppendElement(l); + if (container && container->Extend3DContext()) { + container->Collect3DContextLeaves(toSort); } else { if (toSort.Length() > 0) { SortLayersBy3DZOrder(toSort); @@ -1277,21 +1324,25 @@ ContainerLayer::DefaultComputeEffectiveTransforms(const Matrix4x4& aTransformToS { Matrix residual; Matrix4x4 idealTransform = GetLocalTransform() * aTransformToSurface; - idealTransform.ProjectTo2D(); - mEffectiveTransform = SnapTransformTranslation(idealTransform, &residual); + + // Keep 3D transforms for leaves to keep z-order sorting correct. + if (!Extend3DContext() && !Is3DContextLeaf()) { + idealTransform.ProjectTo2D(); + } bool useIntermediateSurface; if (HasMaskLayers() || GetForceIsolatedGroup()) { useIntermediateSurface = true; #ifdef MOZ_DUMP_PAINTING - } else if (gfxUtils::sDumpPaintingIntermediate) { + } else if (gfxUtils::sDumpPaintingIntermediate && !Extend3DContext()) { useIntermediateSurface = true; #endif } else { float opacity = GetEffectiveOpacity(); CompositionOp blendMode = GetEffectiveMixBlendMode(); - if ((opacity != 1.0f || blendMode != CompositionOp::OP_OVER) && HasMultipleChildren()) { + if (((opacity != 1.0f || blendMode != CompositionOp::OP_OVER) && HasMultipleChildren()) || + (!idealTransform.Is2D() && Creates3DContextWithExtendingChildren())) { useIntermediateSurface = true; } else { useIntermediateSurface = false; @@ -1299,7 +1350,7 @@ ContainerLayer::DefaultComputeEffectiveTransforms(const Matrix4x4& aTransformToS bool checkClipRect = false; bool checkMaskLayers = false; - if (!mEffectiveTransform.Is2D(&contTransform)) { + if (!idealTransform.Is2D(&contTransform)) { // In 3D case, always check if we should use IntermediateSurface. checkClipRect = true; checkMaskLayers = true; @@ -1340,6 +1391,19 @@ ContainerLayer::DefaultComputeEffectiveTransforms(const Matrix4x4& aTransformToS } } + if (useIntermediateSurface) { + mEffectiveTransform = SnapTransformTranslation(idealTransform, &residual); + } else { + mEffectiveTransform = idealTransform; + } + + // For layers extending 3d context, its ideal transform should be + // applied on children. + if (!Extend3DContext()) { + // Without this projection, non-container children would get a 3D + // transform while 2D is expected. + idealTransform.ProjectTo2D(); + } mUseIntermediateSurface = useIntermediateSurface && !GetEffectiveVisibleRegion().IsEmpty(); if (useIntermediateSurface) { ComputeEffectiveTransformsForChildren(Matrix4x4::From2D(residual)); @@ -1952,6 +2016,23 @@ Layer::DumpPacket(layerscope::LayersPacket* aPacket, const void* aParent) } } +bool +Layer::IsBackfaceHidden() +{ + if (GetContentFlags() & CONTENT_BACKFACE_HIDDEN) { + Layer* container = AsContainerLayer() ? this : GetParent(); + if (container) { + // The effective transform can include non-preserve-3d parent + // transforms, since we don't always require an intermediate. + if (container->Extend3DContext() || container->Is3DContextLeaf()) { + return container->GetEffectiveTransform().IsBackfaceVisible(); + } + return container->GetBaseTransform().IsBackfaceVisible(); + } + } + return false; +} + void PaintedLayer::PrintInfo(std::stringstream& aStream, const char* aPrefix) { diff --git a/gfx/layers/Layers.h b/gfx/layers/Layers.h index 7723cc91c373..32325bf537cf 100644 --- a/gfx/layers/Layers.h +++ b/gfx/layers/Layers.h @@ -804,7 +804,13 @@ public: * This is for internal layout/FrameLayerBuilder usage only until flattening * code is obsoleted. See bug 633097 */ - CONTENT_DISABLE_FLATTENING = 0x40 + CONTENT_DISABLE_FLATTENING = 0x40, + + /** + * This layer is hidden if the backface of the layer is visible + * to user. + */ + CONTENT_BACKFACE_HIDDEN = 0x80 }; /** * CONSTRUCTION PHASE ONLY @@ -1463,6 +1469,26 @@ public: const Maybe& GetEffectiveClipRect(); const nsIntRegion& GetEffectiveVisibleRegion(); + bool Extend3DContext() { + return GetContentFlags() & CONTENT_EXTEND_3D_CONTEXT; + } + bool Is3DContextLeaf() { + return !Extend3DContext() && GetParent() && + reinterpret_cast(GetParent())->Extend3DContext(); + } + /** + * It is true if the user can see the back of the layer and the + * backface is hidden. The compositor should skip the layer if the + * result is true. + */ + bool IsBackfaceHidden(); + bool IsVisible() { + // For containers extending 3D context, visible region + // is meaningless, since they are just intermediate result of + // content. + return !GetEffectiveVisibleRegion().IsEmpty() || Extend3DContext(); + } + /** * Returns the product of the opacities of this layer and all ancestors up * to and excluding the nearest ancestor that has UseIntermediateSurface() set. @@ -1861,6 +1887,17 @@ public: "Residual transform can only be a translation"); if (!gfx::ThebesPoint(residual.GetTranslation()).WithinEpsilonOf(mResidualTranslation, 1e-3f)) { mResidualTranslation = gfx::ThebesPoint(residual.GetTranslation()); + DebugOnly transformedOrig = + idealTransform * mozilla::gfx::Point(); +#ifdef DEBUG + DebugOnly transformed = + idealTransform * mozilla::gfx::Point(mResidualTranslation.x, + mResidualTranslation.y) - + *&transformedOrig; +#endif + NS_ASSERTION(-0.5 <= (&transformed)->x && (&transformed)->x < 0.5 && + -0.5 <= (&transformed)->y && (&transformed)->y < 0.5, + "Residual translation out of range"); mValidRegion.SetEmpty(); } ComputeEffectiveTransformForMaskLayers(aTransformToSurface); @@ -2104,6 +2141,8 @@ protected: void DidInsertChild(Layer* aLayer); void DidRemoveChild(Layer* aLayer); + void Collect3DContextLeaves(nsTArray& aToSort); + ContainerLayer(LayerManager* aManager, void* aImplData); /** @@ -2129,6 +2168,12 @@ protected: virtual void DumpPacket(layerscope::LayersPacket* aPacket, const void* aParent) override; + /** + * True for if the container start a new 3D context extended by one + * or more children. + */ + bool Creates3DContextWithExtendingChildren(); + Layer* mFirstChild; Layer* mLastChild; float mPreXScale; diff --git a/gfx/layers/basic/BasicContainerLayer.cpp b/gfx/layers/basic/BasicContainerLayer.cpp index 7e2abf3a8e2e..7530af5a6a47 100644 --- a/gfx/layers/basic/BasicContainerLayer.cpp +++ b/gfx/layers/basic/BasicContainerLayer.cpp @@ -39,22 +39,32 @@ BasicContainerLayer::ComputeEffectiveTransforms(const Matrix4x4& aTransformToSur // containers. Matrix residual; Matrix4x4 idealTransform = GetLocalTransform() * aTransformToSurface; - idealTransform.ProjectTo2D(); + if (!Extend3DContext() && !Is3DContextLeaf()) { + // For 3D transform leaked from extended parent layer. + idealTransform.ProjectTo2D(); + } if (!idealTransform.CanDraw2D()) { + if (!Extend3DContext() || + (!idealTransform.Is2D() && Creates3DContextWithExtendingChildren())) { + if (!Creates3DContextWithExtendingChildren()) { + idealTransform.ProjectTo2D(); + } + mEffectiveTransform = idealTransform; + ComputeEffectiveTransformsForChildren(Matrix4x4()); + ComputeEffectiveTransformForMaskLayers(Matrix4x4()); + mUseIntermediateSurface = true; + return; + } + mEffectiveTransform = idealTransform; - ComputeEffectiveTransformsForChildren(Matrix4x4()); - ComputeEffectiveTransformForMaskLayers(Matrix4x4()); - mUseIntermediateSurface = true; + ComputeEffectiveTransformsForChildren(idealTransform); + ComputeEffectiveTransformForMaskLayers(idealTransform); + mUseIntermediateSurface = false; return; } - mEffectiveTransform = SnapTransformTranslation(idealTransform, &residual); - // We always pass the ideal matrix down to our children, so there is no - // need to apply any compensation using the residual from SnapTransformTranslation. - ComputeEffectiveTransformsForChildren(idealTransform); - - ComputeEffectiveTransformForMaskLayers(aTransformToSurface); + // With 2D transform or extended 3D context. Layer* child = GetFirstChild(); bool hasSingleBlendingChild = false; @@ -74,6 +84,20 @@ BasicContainerLayer::ComputeEffectiveTransforms(const Matrix4x4& aTransformToSur GetForceIsolatedGroup() || (GetMixBlendMode() != CompositionOp::OP_OVER && HasMultipleChildren()) || (GetEffectiveOpacity() != 1.0 && (HasMultipleChildren() || hasSingleBlendingChild)); + + if (!Extend3DContext()) { + idealTransform.ProjectTo2D(); + } + mEffectiveTransform = + !mUseIntermediateSurface ? + idealTransform : SnapTransformTranslation(idealTransform, &residual); + Matrix4x4 childTransformToSurface = + (!mUseIntermediateSurface || + (mUseIntermediateSurface && !Extend3DContext() /* 2D */)) ? + idealTransform : Matrix4x4::From2D(residual); + ComputeEffectiveTransformsForChildren(childTransformToSurface); + + ComputeEffectiveTransformForMaskLayers(aTransformToSurface); } bool diff --git a/gfx/layers/basic/BasicLayerManager.cpp b/gfx/layers/basic/BasicLayerManager.cpp index 0341da8bff88..129fdcdabe20 100644 --- a/gfx/layers/basic/BasicLayerManager.cpp +++ b/gfx/layers/basic/BasicLayerManager.cpp @@ -811,7 +811,15 @@ BasicLayerManager::PaintSelfOrChildren(PaintLayerContext& aPaintContext, nsAutoTArray children; container->SortChildrenBy3DZOrder(children); for (uint32_t i = 0; i < children.Length(); i++) { - PaintLayer(aGroupTarget, children.ElementAt(i), aPaintContext.mCallback, + Layer* layer = children.ElementAt(i); + if (layer->IsBackfaceHidden()) { + continue; + } + if (!layer->AsContainerLayer() && !layer->IsVisible()) { + continue; + } + + PaintLayer(aGroupTarget, layer, aPaintContext.mCallback, aPaintContext.mCallbackData); if (mTransactionIncomplete) break; @@ -845,6 +853,41 @@ BasicLayerManager::FlushGroup(PaintLayerContext& aPaintContext, bool aNeedsClipT } } +/** + * Install the clip applied to the layer on the given gfxContext. The + * given gfxContext is the buffer that the layer will be painted to. + */ +static void +InstallLayerClipPreserves3D(gfxContext* aTarget, Layer* aLayer) +{ + const Maybe &clipRect = aLayer->GetEffectiveClipRect(); + + if (!clipRect) { + return; + } + + Layer* parent = aLayer->GetParent(); + Matrix4x4 transform3d = + parent && parent->Extend3DContext() ? + parent->GetEffectiveTransform() : + Matrix4x4(); + Matrix transform; + if (!transform3d.CanDraw2D(&transform)) { + MOZ_CRASH("We should not have a 3D transform that CanDraw2D() is false!"); + return; + } + gfxMatrix oldTransform = aTarget->CurrentMatrix(); + transform *= ToMatrix(oldTransform); + aTarget->SetMatrix(ThebesMatrix(transform)); + + aTarget->NewPath(); + aTarget->SnappedRectangle(gfxRect(clipRect->x, clipRect->y, + clipRect->width, clipRect->height)); + aTarget->Clip(); + + aTarget->SetMatrix(oldTransform); +} + void BasicLayerManager::PaintLayer(gfxContext* aTarget, Layer* aLayer, @@ -884,17 +927,24 @@ BasicLayerManager::PaintLayer(gfxContext* aTarget, gfxMatrix transform; // Will return an identity matrix for 3d transforms, and is handled separately below. bool is2D = paintLayerContext.Setup2DTransform(); - MOZ_ASSERT(is2D || needsGroup || !container, "Must PushGroup for 3d transforms!"); + MOZ_ASSERT(is2D || needsGroup || !container || + container->Extend3DContext() || + container->Is3DContextLeaf(), + "Must PushGroup for 3d transforms!"); + Layer* parent = aLayer->GetParent(); + bool inPreserves3DChain = parent && parent->Extend3DContext(); bool needsSaveRestore = - needsGroup || clipRect || needsClipToVisibleRegion || !is2D; + needsGroup || clipRect || needsClipToVisibleRegion || !is2D || + inPreserves3DChain; if (needsSaveRestore) { contextSR.SetContext(aTarget); - if (clipRect) { - aTarget->NewPath(); - aTarget->SnappedRectangle(gfxRect(clipRect->x, clipRect->y, clipRect->width, clipRect->height)); - aTarget->Clip(); + // The clips on ancestors on the preserved3d chain should be + // installed on the aTarget before painting the layer. + InstallLayerClipPreserves3D(aTarget, aLayer); + for (Layer* l = parent; l && l->Extend3DContext(); l = l->GetParent()) { + InstallLayerClipPreserves3D(aTarget, l); } } @@ -929,6 +979,11 @@ BasicLayerManager::PaintLayer(gfxContext* aTarget, PaintSelfOrChildren(paintLayerContext, aTarget); } } else { + if (!needsGroup && container) { + PaintSelfOrChildren(paintLayerContext, aTarget); + return; + } + const IntRect& bounds = visibleRegion.GetBounds(); RefPtr untransformedDT = gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(IntSize(bounds.width, bounds.height), diff --git a/gfx/layers/client/ClientContainerLayer.h b/gfx/layers/client/ClientContainerLayer.h index ac67566e9aaf..30d6669d98b7 100644 --- a/gfx/layers/client/ClientContainerLayer.h +++ b/gfx/layers/client/ClientContainerLayer.h @@ -58,7 +58,7 @@ public: for (uint32_t i = 0; i < children.Length(); i++) { Layer* child = children.ElementAt(i); - if (child->GetEffectiveVisibleRegion().IsEmpty()) { + if (!child->IsVisible()) { continue; } diff --git a/gfx/layers/composite/ContainerLayerComposite.cpp b/gfx/layers/composite/ContainerLayerComposite.cpp index c4d6f5161cd0..b65e6ea06b50 100755 --- a/gfx/layers/composite/ContainerLayerComposite.cpp +++ b/gfx/layers/composite/ContainerLayerComposite.cpp @@ -196,14 +196,18 @@ ContainerRenderVR(ContainerT* aContainer, Layer* layer = layerToRender->GetLayer(); uint32_t contentFlags = layer->GetContentFlags(); - if (layer->GetEffectiveVisibleRegion().IsEmpty() && - !layer->AsContainerLayer()) { + if (layer->IsBackfaceHidden()) { continue; } - // We flip between pre-rendered and Gecko-rendered VR based on whether - // the child layer of this VR container layer has PRESERVE_3D or not. - if ((contentFlags & Layer::CONTENT_PRESERVE_3D) == 0) { + if (!layer->IsVisible() && !layer->AsContainerLayer()) { + continue; + } + + // We flip between pre-rendered and Gecko-rendered VR based on + // whether the child layer of this VR container layer has + // CONTENT_EXTEND_3D_CONTEXT or not. + if ((contentFlags & Layer::CONTENT_EXTEND_3D_CONTEXT) == 0) { // This layer is native VR DUMP("%p Switching to pre-rendered VR\n", aContainer); @@ -352,10 +356,14 @@ ContainerPrepare(ContainerT* aContainer, RenderTargetIntRect clipRect = layerToRender->GetLayer()-> CalculateScissorRect(aClipRect); + if (layerToRender->GetLayer()->IsBackfaceHidden()) { + continue; + } + // We don't want to skip container layers because otherwise their mPrepared // may be null which is not allowed. if (!layerToRender->GetLayer()->AsContainerLayer()) { - if (layerToRender->GetLayer()->GetEffectiveVisibleRegion().IsEmpty()) { + if (!layerToRender->GetLayer()->IsVisible()) { CULLING_LOG("Sublayer %p has no effective visible region\n", layerToRender->GetLayer()); continue; } diff --git a/layout/base/FrameLayerBuilder.cpp b/layout/base/FrameLayerBuilder.cpp index ecc78701d524..53b8091b2d7c 100644 --- a/layout/base/FrameLayerBuilder.cpp +++ b/layout/base/FrameLayerBuilder.cpp @@ -401,6 +401,7 @@ public: mHideAllLayersBelow(false), mOpaqueForAnimatedGeometryRootParent(false), mDisableFlattening(false), + mBackfaceHidden(false), mImage(nullptr), mCommonClipCount(-1), mNewChildLayersIndex(-1) @@ -588,6 +589,12 @@ public: * Set if there is content in the layer that must avoid being flattened. */ bool mDisableFlattening; + /** + * Set if the backface of this region is hidden to the user. + * Content that backface is hidden should not be draw on the layer + * with visible backface. + */ + bool mBackfaceHidden; /** * Stores the pointer to the nsDisplayImage if we want to * convert this to an ImageLayer. @@ -647,6 +654,7 @@ struct NewLayerEntry { , mHideAllLayersBelow(false) , mOpaqueForAnimatedGeometryRootParent(false) , mPropagateComponentAlphaFlattening(true) + , mUntransformedVisibleRegion(false) , mIsCaret(false) {} // mLayer is null if the previous entry is for a PaintedLayer that hasn't @@ -685,6 +693,9 @@ struct NewLayerEntry { // If true, then the content flags for this layer should contribute // to our decision to flatten component alpha layers, false otherwise. bool mPropagateComponentAlphaFlattening; + // mVisibleRegion is relative to the associated frame before + // transform. + bool mUntransformedVisibleRegion; bool mIsCaret; }; @@ -740,6 +751,7 @@ public: */ template PaintedLayerData* FindPaintedLayerFor(const nsIntRect& aVisibleRect, + bool aBackfaceHidden, NewPaintedLayerCallbackType aNewPaintedLayerCallback); /** @@ -915,6 +927,7 @@ public: PaintedLayerData* FindPaintedLayerFor(const nsIFrame* aAnimatedGeometryRoot, const nsIntRect& aVisibleRect, bool aForceOwnLayer, + bool aBackfaceidden, NewPaintedLayerCallbackType aNewPaintedLayerCallback); /** @@ -1119,14 +1132,18 @@ public: } /** - * Sets aOuterVisibleRegion as aLayer's visible region. aOuterVisibleRegion - * is in the coordinate space of the container reference frame. - * aLayerContentsVisibleRect, if non-null, is in the layer's own - * coordinate system. + * Sets aOuterVisibleRegion as aLayer's visible region. + * @param aOuterVisibleRegion + * is in the coordinate space of the container reference frame. + * @param aLayerContentsVisibleRect, if non-null, is in the layer's own + * coordinate system. + * @param aOuterUntransformed is true if the given aOuterVisibleRegion + * is already untransformed with the matrix of the layer. */ void SetOuterVisibleRegionForLayer(Layer* aLayer, const nsIntRegion& aOuterVisibleRegion, - const nsIntRect* aLayerContentsVisibleRect = nullptr) const; + const nsIntRect* aLayerContentsVisibleRect = nullptr, + bool aOuterUntransformed = false) const; /** * Try to determine whether the PaintedLayer aData has a single opaque color @@ -2370,11 +2387,17 @@ AppUnitsPerDevPixel(nsDisplayItem* aItem) */ static void SetOuterVisibleRegion(Layer* aLayer, nsIntRegion* aOuterVisibleRegion, - const nsIntRect* aLayerContentsVisibleRect = nullptr) + const nsIntRect* aLayerContentsVisibleRect = nullptr, + bool aOuterUntransformed = false) { Matrix4x4 transform = aLayer->GetTransform(); Matrix transform2D; - if (transform.Is2D(&transform2D) && !transform2D.HasNonIntegerTranslation()) { + if (aOuterUntransformed) { + if (aLayerContentsVisibleRect) { + aOuterVisibleRegion->And(*aOuterVisibleRegion, + *aLayerContentsVisibleRect); + } + } else if (transform.Is2D(&transform2D) && !transform2D.HasNonIntegerTranslation()) { aOuterVisibleRegion->MoveBy(-int(transform2D._31), -int(transform2D._32)); if (aLayerContentsVisibleRect) { aOuterVisibleRegion->And(*aOuterVisibleRegion, *aLayerContentsVisibleRect); @@ -2415,11 +2438,15 @@ SetOuterVisibleRegion(Layer* aLayer, nsIntRegion* aOuterVisibleRegion, void ContainerState::SetOuterVisibleRegionForLayer(Layer* aLayer, const nsIntRegion& aOuterVisibleRegion, - const nsIntRect* aLayerContentsVisibleRect) const + const nsIntRect* aLayerContentsVisibleRect, + bool aOuterUntransformed) const { nsIntRegion visRegion = aOuterVisibleRegion; - visRegion.MoveBy(mParameters.mOffset); - SetOuterVisibleRegion(aLayer, &visRegion, aLayerContentsVisibleRect); + if (!aOuterUntransformed) { + visRegion.MoveBy(mParameters.mOffset); + } + SetOuterVisibleRegion(aLayer, &visRegion, aLayerContentsVisibleRect, + aOuterUntransformed); } nscolor @@ -2611,6 +2638,7 @@ PaintedLayerDataNode::AddChildNodeFor(const nsIFrame* aAnimatedGeometryRoot) template PaintedLayerData* PaintedLayerDataNode::FindPaintedLayerFor(const nsIntRect& aVisibleRect, + bool aBackfaceHidden, NewPaintedLayerCallbackType aNewPaintedLayerCallback) { if (!mPaintedLayerDataStack.IsEmpty()) { @@ -2625,7 +2653,9 @@ PaintedLayerDataNode::FindPaintedLayerFor(const nsIntRect& aVisibleRect, break; } MOZ_ASSERT(!data.mExclusiveToOneItem); - lowestUsableLayer = &data; + if (data.mBackfaceHidden == aBackfaceHidden) { + lowestUsableLayer = &data; + } nsIntRegion visibleRegion = data.mVisibleRegion; // Also check whether the event-regions intersect the visible rect, // unless we're in an inactive layer, in which case the event-regions @@ -2797,6 +2827,7 @@ PaintedLayerData* PaintedLayerDataTree::FindPaintedLayerFor(const nsIFrame* aAnimatedGeometryRoot, const nsIntRect& aVisibleRect, bool aForceOwnLayer, + bool aBackfaceHidden, NewPaintedLayerCallbackType aNewPaintedLayerCallback) { const nsIntRect* bounds = aForceOwnLayer ? nullptr : &aVisibleRect; @@ -2806,7 +2837,8 @@ PaintedLayerDataTree::FindPaintedLayerFor(const nsIFrame* aAnimatedGeometryRoot, node->SetAllDrawingAbove(); } PaintedLayerData* data = - node->FindPaintedLayerFor(aVisibleRect, aNewPaintedLayerCallback); + node->FindPaintedLayerFor(aVisibleRect, aBackfaceHidden, + aNewPaintedLayerCallback); data->mExclusiveToOneItem = aForceOwnLayer; return data; } @@ -3073,6 +3105,18 @@ ContainerState::PrepareColorLayer(PaintedLayerData* aData) return colorLayer.forget(); } +static void +SetBackfaceHiddenForLayer(bool aBackfaceHidden, Layer* aLayer) +{ + if (aBackfaceHidden) { + aLayer->SetContentFlags(aLayer->GetContentFlags() | + Layer::CONTENT_BACKFACE_HIDDEN); + } else { + aLayer->SetContentFlags(aLayer->GetContentFlags() & + ~Layer::CONTENT_BACKFACE_HIDDEN); + } +} + template void ContainerState::FinishPaintedLayerData(PaintedLayerData& aData, FindOpaqueBackgroundColorCallbackType aFindOpaqueBackgroundColor) { @@ -3320,6 +3364,11 @@ void ContainerState::FinishPaintedLayerData(PaintedLayerData& aData, FindOpaqueB layer->SetEventRegions(regions); } + + SetBackfaceHiddenForLayer(data->mBackfaceHidden, data->mLayer); + if (layer != data->mLayer) { + SetBackfaceHiddenForLayer(data->mBackfaceHidden, layer); + } } static bool @@ -3526,6 +3575,7 @@ ContainerState::NewPaintedLayerData(nsDisplayItem* aItem, FindFixedPosFrameForLayerData(aAnimatedGeometryRoot, aShouldFixToViewport); data.mReferenceFrame = aItem->ReferenceFrame(); data.mSingleItemFixedToViewport = aShouldFixToViewport; + data.mBackfaceHidden = aItem->Frame()->BackfaceIsHidden(); data.mIsCaret = aItem->GetType() == nsDisplayItem::TYPE_CARET; data.mNewChildLayersIndex = mNewChildLayers.Length(); @@ -4003,6 +4053,14 @@ ContainerState::ProcessDisplayItems(nsDisplayList* aList) NS_ASSERTION(!ownLayer->AsPaintedLayer(), "Should never have created a dedicated Painted layer!"); + if (item->BackfaceIsHidden()) { + ownLayer->SetContentFlags(ownLayer->GetContentFlags() | + Layer::CONTENT_BACKFACE_HIDDEN); + } else { + ownLayer->SetContentFlags(ownLayer->GetContentFlags() & + ~Layer::CONTENT_BACKFACE_HIDDEN); + } + const nsIFrame* fixedPosFrame = FindFixedPosFrameForLayerData(animatedGeometryRoot, shouldFixToViewport); SetFixedPositionLayerData(ownLayer, fixedPosFrame, !shouldFixToViewport); @@ -4067,14 +4125,32 @@ ContainerState::ProcessDisplayItems(nsDisplayList* aList) "Transform items must set layerContentsVisibleRect!"); if (mLayerBuilder->IsBuildingRetainedLayers()) { newLayerEntry->mLayerContentsVisibleRect = layerContentsVisibleRect; - newLayerEntry->mVisibleRegion = itemVisibleRect; + if (itemType == nsDisplayItem::TYPE_TRANSFORM && + (item->Frame()->Extend3DContext() || + item->Frame()->Combines3DTransformWithAncestors())) { + // Give untransformed visible region as outer visible region + // to avoid failure caused by singular transforms. + newLayerEntry->mUntransformedVisibleRegion = true; + newLayerEntry->mVisibleRegion = + item->GetVisibleRectForChildren().ToOutsidePixels(mAppUnitsPerDevPixel); + } else { + newLayerEntry->mVisibleRegion = itemVisibleRect; + } newLayerEntry->mOpaqueRegion = ComputeOpaqueRect(item, animatedGeometryRoot, fixedPosFrame, itemClip, aList, &newLayerEntry->mHideAllLayersBelow, &newLayerEntry->mOpaqueForAnimatedGeometryRootParent); } else { - SetOuterVisibleRegionForLayer(ownLayer, itemVisibleRect, - layerContentsVisibleRect.width >= 0 ? &layerContentsVisibleRect : nullptr); + bool useChildrenVisible = + itemType == nsDisplayItem::TYPE_TRANSFORM && + item->Frame()->IsPreserve3DLeaf(); + const nsIntRegion &visible = useChildrenVisible ? + item->GetVisibleRectForChildren().ToOutsidePixels(mAppUnitsPerDevPixel): + itemVisibleRect; + + SetOuterVisibleRegionForLayer(ownLayer, visible, + layerContentsVisibleRect.width >= 0 ? &layerContentsVisibleRect : nullptr, + useChildrenVisible); } if (itemType == nsDisplayItem::TYPE_SCROLL_INFO_LAYER) { nsDisplayScrollInfoLayer* scrollItem = static_cast(item); @@ -4101,7 +4177,9 @@ ContainerState::ProcessDisplayItems(nsDisplayList* aList) bool forceOwnLayer = shouldFixToViewport || IsCaretWithCustomClip(item, itemType); PaintedLayerData* paintedLayerData = mPaintedLayerDataTree.FindPaintedLayerFor(animatedGeometryRoot, itemVisibleRect, - forceOwnLayer, [&]() { + forceOwnLayer, + item->Frame()->BackfaceIsHidden(), + [&]() { return NewPaintedLayerData(item, itemVisibleRect, animatedGeometryRoot, animatedGeometryRootForScrollMetadata, topLeft, shouldFixToViewport); @@ -4733,8 +4811,10 @@ ContainerState::PostprocessRetainedLayers(nsIntRegion* aOpaqueRegionForContainer } } - SetOuterVisibleRegionForLayer(e->mLayer, e->mVisibleRegion, - e->mLayerContentsVisibleRect.width >= 0 ? &e->mLayerContentsVisibleRect : nullptr); + SetOuterVisibleRegionForLayer(e->mLayer, + e->mVisibleRegion, + e->mLayerContentsVisibleRect.width >= 0 ? &e->mLayerContentsVisibleRect : nullptr, + e->mUntransformedVisibleRegion); PaintedLayer* p = e->mLayer->AsPaintedLayer(); if (p) { @@ -4959,7 +5039,7 @@ ChooseScaleAndSetTransform(FrameLayerBuilder* aLayerBuilder, bool canDraw2D = transform.CanDraw2D(&transform2d); gfxSize scale; // XXX Should we do something for 3D transforms? - if (canDraw2D) { + if (canDraw2D && !aContainerFrame->Combines3DTransformWithAncestors()) { // If the container's transform is animated off main thread, fix a suitable scale size // for animation if (aContainerItem && @@ -5050,8 +5130,10 @@ ChooseScaleAndSetTransform(FrameLayerBuilder* aLayerBuilder, aOutgoingScale.mInActiveTransformedSubtree = true; } } - if (aLayerBuilder->IsBuildingRetainedLayers() && - (!canDraw2D || transform2d.HasNonIntegerTranslation())) { + if ((aLayerBuilder->IsBuildingRetainedLayers() && + (!canDraw2D || transform2d.HasNonIntegerTranslation())) || + aContainerFrame->Extend3DContext() || + aContainerFrame->Combines3DTransformWithAncestors()) { aOutgoingScale.mDisableSubpixelAntialiasingInDescendants = true; } return true; diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp index 1665965f7865..6b1517bcceda 100644 --- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -104,12 +104,6 @@ SpammyLayoutWarningsEnabled() } #endif -static inline nsIFrame* -GetTransformRootFrame(nsIFrame* aFrame) -{ - return nsLayoutUtils::GetTransformRootFrame(aFrame); -} - static inline CSSAngle MakeCSSAngle(const nsCSSValue& aValue) { @@ -580,10 +574,7 @@ nsDisplayListBuilder::AddAnimationsAndTransitionsToLayer(Layer* aLayer, if (aItem) { origin = aItem->ToReferenceFrame(); } else { - // transform display items used a reference frame computed from - // their GetTransformRootFrame(). - nsIFrame* referenceFrame = - nsLayoutUtils::GetReferenceFrame(GetTransformRootFrame(aFrame)); + nsIFrame* referenceFrame = nsLayoutUtils::GetReferenceFrame(aFrame); origin = aFrame->GetOffsetToCrossDoc(referenceFrame); } @@ -924,6 +915,17 @@ nsDisplayListBuilder::MarkFramesForDisplayList(nsIFrame* aDirtyFrame, } } +/** + * Mark all preserve-3d children with + * NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO to make sure + * nsFrame::BuildDisplayListForChild() would visit them. Also compute + * dirty rect for preserve-3d children. + * + * @param aDirtyFrame is the frame to mark children extending context. + * @param aDirtyRect is the same as the dirty rect of the root of the + * current 3D context, but be translated relative to + * the aDirtyFrame. + */ void nsDisplayListBuilder::MarkPreserve3DFramesForDisplayList(nsIFrame* aDirtyFrame, const nsRect& aDirtyRect) { @@ -937,7 +939,6 @@ nsDisplayListBuilder::MarkPreserve3DFramesForDisplayList(nsIFrame* aDirtyFrame, if (child->Combines3DTransformWithAncestors()) { mFramesMarkedForDisplay.AppendElement(child); nsRect dirty = aDirtyRect - child->GetOffsetTo(aDirtyFrame); - child->Properties().Set(nsDisplayListBuilder::Preserve3DDirtyRectProperty(), new nsRect(dirty)); @@ -1830,7 +1831,10 @@ void nsDisplayList::HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect, bool snap; nsRect r = item->GetBounds(aBuilder, &snap).Intersect(aRect); - if (item->GetClip().MayIntersect(r)) { + bool alwaysIntersect = + item->Frame()->Combines3DTransformWithAncestors() && + item->GetType() == nsDisplayItem::TYPE_TRANSFORM; + if (alwaysIntersect || item->GetClip().MayIntersect(r)) { nsAutoTArray outFrames; item->HitTest(aBuilder, aRect, aState, &outFrames); @@ -3560,34 +3564,21 @@ nsDisplayWrapList::nsDisplayWrapList(nsDisplayListBuilder* aBuilder, return; } - // If the frame is a preserve-3d parent, then we will create transforms - // inside this list afterwards (see WrapPreserve3DList in nsFrame.cpp). - // In this case we will always be outside of the transform, so share - // our parents reference frame. - if (aFrame->Extend3DContext()) { - mReferenceFrame = - aBuilder->FindReferenceFrameFor(GetTransformRootFrame(aFrame)); - mToReferenceFrame = aFrame->GetOffsetToCrossDoc(mReferenceFrame); - } else { - // If we're a transformed frame, then we need to find out if we're inside - // the nsDisplayTransform or outside of it. Frames inside the transform - // need mReferenceFrame == mFrame, outside needs the next ancestor - // reference frame. - // If we're inside the transform, then the nsDisplayItem constructor - // will have done the right thing. - // If we're outside the transform, then we should have only one child - // (since nsDisplayTransform wraps all actual content), and that child - // will have the correct reference frame set (since nsDisplayTransform - // handles this explictly). - // - // Preserve-3d can cause us to have multiple nsDisplayTransform - // children. - nsDisplayItem *i = mList.GetBottom(); - if (i && (!i->GetAbove() || i->GetType() == TYPE_TRANSFORM) && - i->Frame() == mFrame) { - mReferenceFrame = i->ReferenceFrame(); - mToReferenceFrame = i->ToReferenceFrame(); - } + // If we're a transformed frame, then we need to find out if we're inside + // the nsDisplayTransform or outside of it. Frames inside the transform + // need mReferenceFrame == mFrame, outside needs the next ancestor + // reference frame. + // If we're inside the transform, then the nsDisplayItem constructor + // will have done the right thing. + // If we're outside the transform, then we should have only one child + // (since nsDisplayTransform wraps all actual content), and that child + // will have the correct reference frame set (since nsDisplayTransform + // handles this explictly). + nsDisplayItem *i = mList.GetBottom(); + if (i && (!i->GetAbove() || i->GetType() == TYPE_TRANSFORM) && + i->Frame() == mFrame) { + mReferenceFrame = i->ReferenceFrame(); + mToReferenceFrame = i->ToReferenceFrame(); } mVisibleRect = aBuilder->GetDirtyRect() + aBuilder->GetCurrentFrameOffsetToReferenceFrame(); @@ -3610,16 +3601,10 @@ nsDisplayWrapList::nsDisplayWrapList(nsDisplayListBuilder* aBuilder, return; } - if (aFrame->Extend3DContext()) { - mReferenceFrame = - aBuilder->FindReferenceFrameFor(GetTransformRootFrame(aFrame)); - mToReferenceFrame = aFrame->GetOffsetToCrossDoc(mReferenceFrame); - } else { - // See the previous nsDisplayWrapList constructor - if (aItem->Frame() == aFrame) { - mReferenceFrame = aItem->ReferenceFrame(); - mToReferenceFrame = aItem->ToReferenceFrame(); - } + // See the previous nsDisplayWrapList constructor + if (aItem->Frame() == aFrame) { + mReferenceFrame = aItem->ReferenceFrame(); + mToReferenceFrame = aItem->ToReferenceFrame(); } mVisibleRect = aBuilder->GetDirtyRect() + aBuilder->GetCurrentFrameOffsetToReferenceFrame(); @@ -4658,24 +4643,27 @@ nsDisplayTransform::nsDisplayTransform(nsDisplayListBuilder* aBuilder, nsIFrame *aFrame, nsDisplayList *aList, const nsRect& aChildrenVisibleRect, ComputeTransformFunction aTransformGetter, - uint32_t aIndex) + uint32_t aIndex) : nsDisplayItem(aBuilder, aFrame) , mStoredList(aBuilder, aFrame, aList) , mTransformGetter(aTransformGetter) , mChildrenVisibleRect(aChildrenVisibleRect) , mIndex(aIndex) + , mNoExtendContext(false) + , mHasPresetTransform(false) + , mTransformPreserves3DInited(false) { MOZ_COUNT_CTOR(nsDisplayTransform); MOZ_ASSERT(aFrame, "Must have a frame!"); - MOZ_ASSERT(!aFrame->IsTransformed(), "Can't specify a transform getter for a transformed frame!"); Init(aBuilder); } void nsDisplayTransform::SetReferenceFrameToAncestor(nsDisplayListBuilder* aBuilder) { + nsIFrame *outerFrame = nsLayoutUtils::GetCrossDocParentFrame(mFrame); mReferenceFrame = - aBuilder->FindReferenceFrameFor(GetTransformRootFrame(mFrame)); + aBuilder->FindReferenceFrameFor(outerFrame); mToReferenceFrame = mFrame->GetOffsetToCrossDoc(mReferenceFrame); mVisibleRect = aBuilder->GetDirtyRect() + mToReferenceFrame; } @@ -4708,6 +4696,9 @@ nsDisplayTransform::nsDisplayTransform(nsDisplayListBuilder* aBuilder, , mTransformGetter(nullptr) , mChildrenVisibleRect(aChildrenVisibleRect) , mIndex(aIndex) + , mNoExtendContext(false) + , mHasPresetTransform(false) + , mTransformPreserves3DInited(false) { MOZ_COUNT_CTOR(nsDisplayTransform); MOZ_ASSERT(aFrame, "Must have a frame!"); @@ -4724,6 +4715,9 @@ nsDisplayTransform::nsDisplayTransform(nsDisplayListBuilder* aBuilder, , mTransformGetter(nullptr) , mChildrenVisibleRect(aChildrenVisibleRect) , mIndex(aIndex) + , mNoExtendContext(false) + , mHasPresetTransform(false) + , mTransformPreserves3DInited(false) { MOZ_COUNT_CTOR(nsDisplayTransform); MOZ_ASSERT(aFrame, "Must have a frame!"); @@ -4731,6 +4725,26 @@ nsDisplayTransform::nsDisplayTransform(nsDisplayListBuilder* aBuilder, Init(aBuilder); } +nsDisplayTransform::nsDisplayTransform(nsDisplayListBuilder* aBuilder, + nsIFrame *aFrame, nsDisplayList *aList, + const nsRect& aChildrenVisibleRect, + const Matrix4x4& aTransform, + uint32_t aIndex) + : nsDisplayItem(aBuilder, aFrame) + , mStoredList(aBuilder, aFrame, aList) + , mTransform(aTransform) + , mTransformGetter(nullptr) + , mChildrenVisibleRect(aChildrenVisibleRect) + , mIndex(aIndex) + , mNoExtendContext(false) + , mHasPresetTransform(true) + , mTransformPreserves3DInited(false) +{ + MOZ_COUNT_CTOR(nsDisplayTransform); + MOZ_ASSERT(aFrame, "Must have a frame!"); + Init(aBuilder); +} + /* Returns the delta specified by the -transform-origin property. * This is a positive delta, meaning that it indicates the direction to move * to get from (0, 0) of the frame to the transform origin. This function is @@ -4742,7 +4756,9 @@ nsDisplayTransform::GetDeltaToTransformOrigin(const nsIFrame* aFrame, const nsRect* aBoundsOverride) { NS_PRECONDITION(aFrame, "Can't get delta for a null frame!"); - NS_PRECONDITION(aFrame->IsTransformed() || aFrame->StyleDisplay()->BackfaceIsHidden(), + NS_PRECONDITION(aFrame->IsTransformed() || + aFrame->StyleDisplay()->BackfaceIsHidden() || + aFrame->Combines3DTransformWithAncestors(), "Shouldn't get a delta for an untransformed frame!"); if (!aFrame->IsTransformed()) { @@ -4817,7 +4833,9 @@ nsDisplayTransform::GetDeltaToPerspectiveOrigin(const nsIFrame* aFrame, float aAppUnitsPerPixel) { NS_PRECONDITION(aFrame, "Can't get delta for a null frame!"); - NS_PRECONDITION(aFrame->IsTransformed() || aFrame->StyleDisplay()->BackfaceIsHidden(), + NS_PRECONDITION(aFrame->IsTransformed() || + aFrame->StyleDisplay()->BackfaceIsHidden() || + aFrame->Combines3DTransformWithAncestors(), "Shouldn't get a delta for an untransformed frame!"); if (!aFrame->IsTransformed()) { @@ -4910,7 +4928,7 @@ nsDisplayTransform::GetResultingTransformMatrix(const FrameTransformProperties& nsIFrame** aOutAncestor) { return GetResultingTransformMatrixInternal(aProperties, aOrigin, aAppUnitsPerPixel, - aBoundsOverride, aOutAncestor, false); + aBoundsOverride, aOutAncestor, false, false); } Matrix4x4 @@ -4927,7 +4945,24 @@ nsDisplayTransform::GetResultingTransformMatrix(const nsIFrame* aFrame, return GetResultingTransformMatrixInternal(props, aOrigin, aAppUnitsPerPixel, aBoundsOverride, aOutAncestor, - aOffsetByOrigin); + aOffsetByOrigin, false); +} + +Matrix4x4 +nsDisplayTransform::GetResultingTransformMatrixP3D(const nsIFrame* aFrame, + const nsPoint& aOrigin, + float aAppUnitsPerPixel, + const nsRect* aBoundsOverride, + nsIFrame** aOutAncestor, + bool aOffsetByOrigin) +{ + FrameTransformProperties props(aFrame, + aAppUnitsPerPixel, + aBoundsOverride); + + return GetResultingTransformMatrixInternal(props, aOrigin, aAppUnitsPerPixel, + aBoundsOverride, aOutAncestor, + aOffsetByOrigin, true); } Matrix4x4 @@ -4936,7 +4971,8 @@ nsDisplayTransform::GetResultingTransformMatrixInternal(const FrameTransformProp float aAppUnitsPerPixel, const nsRect* aBoundsOverride, nsIFrame** aOutAncestor, - bool aOffsetByOrigin) + bool aOffsetByOrigin, + bool aDoPreserves3D) { const nsIFrame *frame = aProperties.mFrame; @@ -5051,7 +5087,7 @@ nsDisplayTransform::GetResultingTransformMatrixInternal(const FrameTransformProp } } - if (frame && frame->Combines3DTransformWithAncestors()) { + if (aDoPreserves3D && frame && frame->Combines3DTransformWithAncestors()) { // Include the transform set on our parent NS_ASSERTION(frame->GetParent() && frame->GetParent()->IsTransformed() && @@ -5069,7 +5105,8 @@ nsDisplayTransform::GetResultingTransformMatrixInternal(const FrameTransformProp GetResultingTransformMatrixInternal(props, aOrigin - frame->GetPosition(), aAppUnitsPerPixel, nullptr, - aOutAncestor, !frame->IsTransformed()); + aOutAncestor, !frame->IsTransformed(), + aDoPreserves3D); result = result * parent; } @@ -5209,7 +5246,10 @@ nsDisplayTransform::GetTransform() if (mTransformGetter) { mTransform = mTransformGetter(mFrame, scale); mTransform.ChangeBasis(newOrigin.x, newOrigin.y, newOrigin.z); - } else { + } else if (!mHasPresetTransform) { + bool isReference = + mFrame->IsTransformed() || + mFrame->Combines3DTransformWithAncestors() || mFrame->Extend3DContext(); /** * Passing true as the final argument means that we want to shift the * coordinates to be relative to our reference frame instead of relative @@ -5217,32 +5257,56 @@ nsDisplayTransform::GetTransform() * When we have preserve-3d, our reference frame is already guaranteed * to be an ancestor of the preserve-3d chain, so we only need to do * this once. + * For preserve-3d leaf, itself is a refrence frame. */ mTransform = GetResultingTransformMatrix(mFrame, ToReferenceFrame(), scale, nullptr, nullptr, - mFrame->IsTransformed()); + isReference); } } return mTransform; } +const Matrix4x4& +nsDisplayTransform::GetAccumulatedPreserved3DTransform() +{ + // XXX: should go back to fix mTransformGetter. + if (!mTransformPreserves3DInited) { + mTransformPreserves3DInited = true; + if (!mFrame->Combines3DTransformWithAncestors()) { + mTransformPreserves3D = GetTransform(); + return mTransformPreserves3D; + } + float scale = mFrame->PresContext()->AppUnitsPerDevPixel(); + bool isReference = + mFrame->IsTransformed() || + mFrame->Combines3DTransformWithAncestors() || mFrame->Extend3DContext(); + mTransformPreserves3D = + GetResultingTransformMatrixP3D(mFrame, ToReferenceFrame(), scale, + nullptr, nullptr, isReference); + } + return mTransformPreserves3D; +} + bool nsDisplayTransform::ShouldBuildLayerEvenIfInvisible(nsDisplayListBuilder* aBuilder) { - return ShouldPrerender(aBuilder); + // The visible rect of a Preserves-3D frame is just an intermediate + // result. It should always build a layer to make sure it is + // rendering correctly. + return ShouldPrerender(aBuilder) || mFrame->Combines3DTransformWithAncestors(); } already_AddRefed nsDisplayTransform::BuildLayer(nsDisplayListBuilder *aBuilder, LayerManager *aManager, const ContainerLayerParameters& aContainerParameters) { + /* For frames without transform, it would not be removed for + * backface hidden here. But, it would be removed by the init + * function of nsDisplayTransform. + */ const Matrix4x4& newTransformMatrix = GetTransform(); - if (mFrame->StyleDisplay()->mBackfaceVisibility == NS_STYLE_BACKFACE_VISIBILITY_HIDDEN && - newTransformMatrix.IsBackfaceVisible()) { - return nullptr; - } - uint32_t flags = ShouldPrerender(aBuilder) ? FrameLayerBuilder::CONTAINER_NOT_CLIPPED_BY_ANCESTORS : 0; flags |= FrameLayerBuilder::CONTAINER_ALLOW_PULL_BACKGROUND_COLOR; @@ -5256,7 +5320,7 @@ already_AddRefed nsDisplayTransform::BuildLayer(nsDisplayListBuilder *aBu // Add the preserve-3d flag for this layer, BuildContainerLayerFor clears all flags, // so we never need to explicitely unset this flag. - if (mFrame->Combines3DTransformWithAncestors() || mFrame->Extend3DContext()) { + if (mFrame->Extend3DContext() && !mNoExtendContext) { container->SetContentFlags(container->GetContentFlags() | Layer::CONTENT_EXTEND_3D_CONTEXT); } else { container->SetContentFlags(container->GetContentFlags() & ~Layer::CONTENT_EXTEND_3D_CONTEXT); @@ -5349,7 +5413,7 @@ void nsDisplayTransform::HitTest(nsDisplayListBuilder *aBuilder, float factor = mFrame->PresContext()->AppUnitsPerDevPixel(); Matrix4x4 matrix = GetTransform(); - if (!IsFrameVisible(mFrame, matrix)) { + if (!IsFrameVisible(mFrame, GetAccumulatedPreserved3DTransform())) { return; } @@ -5426,7 +5490,8 @@ nsDisplayTransform::GetHitDepthAtPoint(nsDisplayListBuilder* aBuilder, const nsP float factor = mFrame->PresContext()->AppUnitsPerDevPixel(); Matrix4x4 matrix = GetTransform(); - NS_ASSERTION(IsFrameVisible(mFrame, matrix), "We can't have hit a frame that isn't visible!"); + NS_ASSERTION(IsFrameVisible(mFrame, GetAccumulatedPreserved3DTransform()), + "We can't have hit a frame that isn't visible!"); Matrix4x4 inverse = matrix; inverse.Invert(); @@ -5445,15 +5510,59 @@ nsDisplayTransform::GetHitDepthAtPoint(nsDisplayListBuilder* aBuilder, const nsP */ nsRect nsDisplayTransform::GetBounds(nsDisplayListBuilder *aBuilder, bool* aSnap) { + /* For some cases, the transform would make an empty bounds, but it + * may be turned back again to get a non-empty bounds. We should + * not depend on transforming bounds level by level. + * + * Here, it applies accumulated transforms on the leaf frames of the + * 3d rendering context, and track and accmulate bounds at + * nsDisplayListBuilder. + */ + nsDisplayListBuilder::AutoAccumulateTransform accTransform(aBuilder); + Maybe accRect; + bool startPreserves3D = + mFrame->Extend3DContext() && !mFrame->Combines3DTransformWithAncestors(); + + if (!mFrame->Combines3DTransformWithAncestors()) { + accTransform.StartRoot(); + } + + accTransform.Accumulate(GetTransform()); + if (startPreserves3D) { + accRect.emplace(aBuilder); + } + + /* For Preserves3D, it is bounds of only children as leaf frames. + * For non-leaf frames, their bounds are accumulated and kept at + * nsDisplayListBuilder. + */ nsRect untransformedBounds = MaybePrerender() ? mFrame->GetVisualOverflowRectRelativeToSelf() : mStoredList.GetBounds(aBuilder, aSnap); *aSnap = false; // GetTransform always operates in dev pixels. float factor = mFrame->PresContext()->AppUnitsPerDevPixel(); - return nsLayoutUtils::MatrixTransformRect(untransformedBounds, - GetTransform(), - factor); + nsRect rect = + nsLayoutUtils::MatrixTransformRect(untransformedBounds, + accTransform.GetCurrentTransform(), + factor); + + if (mFrame->Combines3DTransformWithAncestors()) { + if (!mFrame->Extend3DContext() && + !aBuilder->GetAccumulatedRectLevels()) { + // For preserve-3d, only leaf frames and frames start + // preserve-3d chain have non-empty bounds. + return rect; + } + aBuilder->AccumulateRect(rect); + return nsRect(); + } + + if (startPreserves3D) { + rect.UnionRect(rect, aBuilder->GetAccumulatedRect()); + } + + return rect; } /* The transform is opaque iff the transform consists solely of scales and @@ -5579,14 +5688,18 @@ nsDisplayTransform::TryMerge(nsDisplayListBuilder *aBuilder, nsRect nsDisplayTransform::TransformRect(const nsRect &aUntransformedBounds, const nsIFrame* aFrame, const nsPoint &aOrigin, - const nsRect* aBoundsOverride) + const nsRect* aBoundsOverride, + bool aPreserves3D) { NS_PRECONDITION(aFrame, "Can't take the transform based on a null frame!"); float factor = aFrame->PresContext()->AppUnitsPerDevPixel(); return nsLayoutUtils::MatrixTransformRect (aUntransformedBounds, - GetResultingTransformMatrix(aFrame, aOrigin, factor, aBoundsOverride), + (aPreserves3D ? + GetResultingTransformMatrixP3D(aFrame, aOrigin, factor, + aBoundsOverride) : + GetResultingTransformMatrix(aFrame, aOrigin, factor, aBoundsOverride)), factor); } @@ -5600,7 +5713,7 @@ nsRect nsDisplayTransform::TransformRectOut(const nsRect &aUntransformedBounds, float factor = aFrame->PresContext()->AppUnitsPerDevPixel(); return nsLayoutUtils::MatrixTransformRectOut (aUntransformedBounds, - GetResultingTransformMatrix(aFrame, aOrigin, factor, aBoundsOverride), + GetResultingTransformMatrixP3D(aFrame, aOrigin, factor, aBoundsOverride), factor); } @@ -5608,13 +5721,16 @@ bool nsDisplayTransform::UntransformRect(const nsRect &aTransformedBounds, const nsRect &aChildBounds, const nsIFrame* aFrame, const nsPoint &aOrigin, - nsRect *aOutRect) + nsRect *aOutRect, + bool aPreserves3D) { NS_PRECONDITION(aFrame, "Can't take the transform based on a null frame!"); float factor = aFrame->PresContext()->AppUnitsPerDevPixel(); - Matrix4x4 transform = GetResultingTransformMatrix(aFrame, aOrigin, factor, nullptr); + Matrix4x4 transform = aPreserves3D ? + GetResultingTransformMatrixP3D(aFrame, aOrigin, factor, nullptr) : + GetResultingTransformMatrix(aFrame, aOrigin, factor, nullptr); if (transform.IsSingular()) { return false; } diff --git a/layout/base/nsDisplayList.h b/layout/base/nsDisplayList.h index 5722e00989a9..7c48e42dc7ce 100644 --- a/layout/base/nsDisplayList.h +++ b/layout/base/nsDisplayList.h @@ -116,6 +116,42 @@ typedef mozilla::EnumSet BlendModeSet; * for faster/more convenient access. */ class nsDisplayListBuilder { + /** + * This manages status of a 3d context to collect visible rects of + * descendants and passing a dirty rect. + * + * Since some transforms maybe singular, passing visible rects or + * the dirty rect level by level from parent to children may get a + * wrong result, being different from the result of appling with + * effective transform directly. + * + * nsFrame::BuildDisplayListForStackingContext() uses + * AutoPreserves3DContext to install an instance on the builder. + * + * \see AutoAccumulateTransform, AutoAccumulateRect, + * AutoPreserves3DContext, Accumulate, GetCurrentTransform, + * StartRoot. + */ + class Preserves3DContext { + public: + typedef mozilla::gfx::Matrix4x4 Matrix4x4; + + Preserves3DContext() {} + Preserves3DContext(const Preserves3DContext &aOther) + : mAccumulatedTransform() + , mAccumulatedRect() + , mAccumulatedRectLevels(0) + , mDirtyRect(aOther.mDirtyRect) {} + + // Accmulate transforms of ancestors on the preserves-3d chain. + Matrix4x4 mAccumulatedTransform; + // Accmulate visible rect of descendants in the preserves-3d context. + nsRect mAccumulatedRect; + // How far this frame is from the root of the current 3d context. + int mAccumulatedRectLevels; + nsRect mDirtyRect; + }; + public: typedef mozilla::FramePropertyDescriptor FramePropertyDescriptor; typedef mozilla::FrameLayerBuilder FrameLayerBuilder; @@ -125,6 +161,7 @@ public: typedef mozilla::layers::Layer Layer; typedef mozilla::layers::FrameMetrics FrameMetrics; typedef mozilla::layers::FrameMetrics::ViewID ViewID; + typedef mozilla::gfx::Matrix4x4 Matrix4x4; /** * @param aReferenceFrame the frame at the root of the subtree; its origin @@ -726,6 +763,86 @@ public: nsDisplayListBuilder* mBuilder; }; + /** + * A helper class to track current effective transform for items. + * + * For frames that is Combines3DTransformWithAncestors(), we need to + * apply all transforms of ancestors on the same preserves3D chain + * on the bounds of current frame to the coordination of the 3D + * context root. The 3D context root computes it's bounds from + * these transformed bounds. + */ + class AutoAccumulateTransform; + friend class AutoAccumulateTransform; + class AutoAccumulateTransform { + public: + typedef mozilla::gfx::Matrix4x4 Matrix4x4; + + explicit AutoAccumulateTransform(nsDisplayListBuilder* aBuilder) + : mBuilder(aBuilder) + , mSavedTransform(aBuilder->mPreserves3DCtx.mAccumulatedTransform) {} + + ~AutoAccumulateTransform() { + mBuilder->mPreserves3DCtx.mAccumulatedTransform = mSavedTransform; + } + + void Accumulate(const Matrix4x4& aTransform) { + mBuilder->mPreserves3DCtx.mAccumulatedTransform = + aTransform * mBuilder->mPreserves3DCtx.mAccumulatedTransform; + } + + const Matrix4x4& GetCurrentTransform() { + return mBuilder->mPreserves3DCtx.mAccumulatedTransform; + } + + void StartRoot() { + mBuilder->mPreserves3DCtx.mAccumulatedTransform = Matrix4x4(); + } + + private: + nsDisplayListBuilder* mBuilder; + Matrix4x4 mSavedTransform; + }; + + /** + * A helper class to collect bounds rects of descendants. + * + * For a 3D context root, it's bounds is computed from the bounds of + * descendants. If we transform bounds frame by frame applying + * transforms, the bounds may turn to empty for any singular + * transform on the path, but it is not empty for the accumulated + * transform. + */ + class AutoAccumulateRect; + friend class AutoAccumulateRect; + class AutoAccumulateRect { + public: + explicit AutoAccumulateRect(nsDisplayListBuilder* aBuilder) + : mBuilder(aBuilder) + , mSavedRect(aBuilder->mPreserves3DCtx.mAccumulatedRect) { + aBuilder->mPreserves3DCtx.mAccumulatedRect = nsRect(); + aBuilder->mPreserves3DCtx.mAccumulatedRectLevels++; + } + ~AutoAccumulateRect() { + mBuilder->mPreserves3DCtx.mAccumulatedRect = mSavedRect; + mBuilder->mPreserves3DCtx.mAccumulatedRectLevels--; + } + + private: + nsDisplayListBuilder* mBuilder; + nsRect mSavedRect; + }; + + void AccumulateRect(const nsRect& aRect) { + mPreserves3DCtx.mAccumulatedRect.UnionRect(mPreserves3DCtx.mAccumulatedRect, aRect); + } + const nsRect& GetAccumulatedRect() { + return mPreserves3DCtx.mAccumulatedRect; + } + int GetAccumulatedRectLevels() { + return mPreserves3DCtx.mAccumulatedRectLevels; + } + // Helpers for tables nsDisplayTableItem* GetCurrentTableItem() { return mCurrentTableItem; } void SetCurrentTableItem(nsDisplayTableItem* aTableItem) { mCurrentTableItem = aTableItem; } @@ -880,6 +997,46 @@ public: */ nsRect GetDirtyRectForScrolledContents(const nsIFrame* aScrollableFrame) const; + /** + * A helper class to install/restore nsDisplayListBuilder::mPreserves3DCtx. + * + * mPreserves3DCtx is used by class AutoAccumulateTransform & + * AutoAccumulateRect to passing data between frames in the 3D + * context. If a frame create a new 3D context, it should restore + * the value of mPreserves3DCtx before returning back to the parent. + * This class do it for the users. + */ + class AutoPreserves3DContext; + friend class AutoPreserves3DContext; + class AutoPreserves3DContext { + public: + explicit AutoPreserves3DContext(nsDisplayListBuilder* aBuilder) + : mBuilder(aBuilder) + , mSavedCtx(aBuilder->mPreserves3DCtx) {} + ~AutoPreserves3DContext() { + mBuilder->mPreserves3DCtx = mSavedCtx; + } + + private: + nsDisplayListBuilder* mBuilder; + Preserves3DContext mSavedCtx; + }; + + const nsRect GetPreserves3DDirtyRect(const nsIFrame *aFrame) const { + nsRect dirty = mPreserves3DCtx.mDirtyRect; + // Translate the dirty rect to make it positioned relative to the + // origin of aFrame. + const nsIFrame *rootPreserves3D = aFrame; + while (rootPreserves3D && rootPreserves3D->Combines3DTransformWithAncestors()) { + dirty.MoveBy(-rootPreserves3D->GetPosition()); + rootPreserves3D = rootPreserves3D->GetParent(); + } + return dirty; + } + void SetPreserves3DDirtyRect(const nsRect &aDirtyRect) { + mPreserves3DCtx.mDirtyRect = aDirtyRect; + } + private: void MarkOutOfFlowFrameForDisplay(nsIFrame* aDirtyFrame, nsIFrame* aFrame, const nsRect& aDirtyRect); @@ -983,6 +1140,7 @@ private: ViewID mCurrentScrollbarTarget; uint32_t mCurrentScrollbarFlags; BlendModeSet mContainedBlendModes; + Preserves3DContext mPreserves3DCtx; bool mBuildCaret; bool mIgnoreSuppression; bool mHadToIgnoreSuppression; @@ -1557,6 +1715,10 @@ public: } } + bool BackfaceIsHidden() { + return mFrame->StyleDisplay()->BackfaceIsHidden(); + } + protected: friend class nsDisplayList; @@ -3424,6 +3586,30 @@ class nsDisplayTransform: public nsDisplayItem { typedef mozilla::gfx::Matrix4x4 Matrix4x4; typedef mozilla::gfx::Point3D Point3D; + + /* + * Avoid doing UpdateBounds() during construction. + */ + class StoreList : public nsDisplayWrapList { + public: + StoreList(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, + nsDisplayList* aList) : + nsDisplayWrapList(aBuilder, aFrame, aList) {} + StoreList(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, + nsDisplayItem* aItem) : + nsDisplayWrapList(aBuilder, aFrame, aItem) {} + virtual ~StoreList() {} + + virtual void UpdateBounds(nsDisplayListBuilder* aBuilder) override {} + virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, + bool* aSnap) override { + // The bounds should not be computed until now, because we don't + // get accmulated transform before. + nsDisplayWrapList::UpdateBounds(aBuilder); + return nsDisplayWrapList::GetBounds(aBuilder, aSnap); + } + }; + public: /** * Returns a matrix (in pixels) for the current frame. The matrix should be relative to @@ -3446,6 +3632,9 @@ public: nsDisplayTransform(nsDisplayListBuilder* aBuilder, nsIFrame *aFrame, nsDisplayList *aList, const nsRect& aChildrenVisibleRect, ComputeTransformFunction aTransformGetter, uint32_t aIndex = 0); + nsDisplayTransform(nsDisplayListBuilder* aBuilder, nsIFrame *aFrame, + nsDisplayList *aList, const nsRect& aChildrenVisibleRect, + const Matrix4x4& aTransform, uint32_t aIndex = 0); #ifdef NS_BUILD_REFCNT_LOGGING virtual ~nsDisplayTransform() @@ -3512,6 +3701,11 @@ public: }; const Matrix4x4& GetTransform(); + /** + * Return the transform that is aggregation of all transform on the + * preserves3d chain. + */ + const Matrix4x4& GetAccumulatedPreserved3DTransform(); float GetHitDepthAtPoint(nsDisplayListBuilder* aBuilder, const nsPoint& aPoint); @@ -3536,7 +3730,8 @@ public: static nsRect TransformRect(const nsRect &aUntransformedBounds, const nsIFrame* aFrame, const nsPoint &aOrigin, - const nsRect* aBoundsOverride = nullptr); + const nsRect* aBoundsOverride = nullptr, + bool aPreserves3D = true); static nsRect TransformRectOut(const nsRect &aUntransformedBounds, const nsIFrame* aFrame, @@ -3550,7 +3745,8 @@ public: const nsRect &aChildBounds, const nsIFrame* aFrame, const nsPoint &aOrigin, - nsRect *aOutRect); + nsRect *aOutRect, + bool aPreserves3D = true); bool UntransformVisibleRect(nsDisplayListBuilder* aBuilder, nsRect* aOutRect); @@ -3620,6 +3816,12 @@ public: float aAppUnitsPerPixel, const nsRect* aBoundsOverride = nullptr, nsIFrame** aOutAncestor = nullptr); + static Matrix4x4 GetResultingTransformMatrixP3D(const nsIFrame* aFrame, + const nsPoint& aOrigin, + float aAppUnitsPerPixel, + const nsRect* aBoundsOverride = nullptr, + nsIFrame** aOutAncestor = nullptr, + bool aOffsetByOrigin = false); /** * Return true when we should try to prerender the entire contents of the * transformed frame even when it's not completely visible (yet). @@ -3642,6 +3844,10 @@ public: virtual void WriteDebugInfo(std::stringstream& aStream) override; + // Force the layer created for this item not to extend 3D context. + // See nsIFrame::BuildDisplayListForStackingContext() + void SetNoExtendContext() { mNoExtendContext = true; } + private: void SetReferenceFrameToAncestor(nsDisplayListBuilder* aBuilder); void Init(nsDisplayListBuilder* aBuilder); @@ -3651,16 +3857,30 @@ private: float aAppUnitsPerPixel, const nsRect* aBoundsOverride, nsIFrame** aOutAncestor, - bool aOffsetByOrigin); + bool aOffsetByOrigin, + bool aDoPreserves3D); - nsDisplayWrapList mStoredList; + StoreList mStoredList; Matrix4x4 mTransform; + // Accumulated transform of ancestors on the preserves-3d chain. + Matrix4x4 mTransformPreserves3D; ComputeTransformFunction mTransformGetter; nsRect mChildrenVisibleRect; uint32_t mIndex; // We wont know if we pre-render until the layer building phase where we can // check layers will-change budget. bool mMaybePrerender; + // Be forced not to extend 3D context. Since we don't create a + // transform item, a container layer, for every frames in a + // preserves3d context, the transform items of a child preserves3d + // context may extend the parent context not intented if the root of + // the child preserves3d context doesn't create a transform item. + // With this flags, we force the item not extending 3D context. + bool mNoExtendContext; + // mTransform have been presetted by the constructor. + bool mHasPresetTransform; + // True if mTransformPreserves3D have been initialized. + bool mTransformPreserves3DInited; }; /** diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index d638db4bd9a4..7df94ff6502c 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -6629,7 +6629,7 @@ nsLayoutUtils::GetReferenceFrame(nsIFrame* aFrame) { nsIFrame *f = aFrame; for (;;) { - if (f->IsTransformed() || IsPopup(f)) { + if (f->IsTransformed() || f->IsPreserve3DLeaf() || IsPopup(f)) { return f; } nsIFrame* parent = GetCrossDocParentFrame(f); @@ -6640,16 +6640,6 @@ nsLayoutUtils::GetReferenceFrame(nsIFrame* aFrame) } } -/* static */ nsIFrame* -nsLayoutUtils::GetTransformRootFrame(nsIFrame* aFrame) -{ - nsIFrame *parent = nsLayoutUtils::GetCrossDocParentFrame(aFrame); - while (parent && parent->Extend3DContext()) { - parent = nsLayoutUtils::GetCrossDocParentFrame(parent); - } - return parent; -} - /* static */ uint32_t nsLayoutUtils::GetTextRunFlagsForStyle(nsStyleContext* aStyleContext, const nsStyleFont* aStyleFont, diff --git a/layout/base/nsLayoutUtils.h b/layout/base/nsLayoutUtils.h index 03b7287f4928..9f04f45c894a 100644 --- a/layout/base/nsLayoutUtils.h +++ b/layout/base/nsLayoutUtils.h @@ -1960,10 +1960,8 @@ public: /** * Get the reference frame that would be used when constructing a - * display item for this frame. (Note, however, that - * nsDisplayTransform use the reference frame appropriate for their - * GetTransformRootFrame(), rather than using their own frame as a - * reference frame.) + * display item for this frame. Rather than using their own frame + * as a reference frame.) * * This duplicates some of the logic of GetDisplayRootFrame above and * of nsDisplayListBuilder::FindReferenceFrameFor. @@ -1973,16 +1971,6 @@ public: */ static nsIFrame* GetReferenceFrame(nsIFrame* aFrame); - /** - * Get the parent of this frame, except if that parent is part of a - * preserve-3d hierarchy, get the parent of the root of the - * preserve-3d hierarchy. - * - * (This is used as the starting point for reference frame computation - * for nsDisplayTransform display items.) - */ - static nsIFrame* GetTransformRootFrame(nsIFrame* aFrame); - /** * Get textrun construction flags determined by a given style; in particular * some combination of: diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index 6bef7b2b0dbf..b16ba9ca154b 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -1786,126 +1786,12 @@ DisplayDebugBorders(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, } #endif -static nsresult -WrapPreserve3DListInternal(nsIFrame* aFrame, nsDisplayListBuilder *aBuilder, - nsDisplayList *aList, nsDisplayList *aOutput, - uint32_t& aIndex, nsDisplayList* aTemp) -{ - if (aIndex > nsDisplayTransform::INDEX_MAX) { - return NS_OK; - } - - nsresult rv = NS_OK; - while (nsDisplayItem *item = aList->RemoveBottom()) { - nsIFrame *childFrame = item->Frame(); - - // We accumulate sequential items that aren't transforms into the 'temp' list - // and then flush this list into aOutput by wrapping the whole lot with a single - // nsDisplayTransform. - - if (childFrame->GetParent() && - (childFrame->GetParent()->Extend3DContext() || childFrame == aFrame)) { - switch (item->GetType()) { - case nsDisplayItem::TYPE_TRANSFORM: { - if (!aTemp->IsEmpty()) { - // Flush current aTemp contents - aOutput->AppendToTop(new (aBuilder) nsDisplayTransform(aBuilder, - aFrame, aTemp, aTemp->GetVisibleRect(), aIndex++)); - } - // Override item's clipping with our current clip state (if any). Since we're - // bubbling up a preserve-3d transformed child to a preserve-3d parent, - // we can be sure the child doesn't have clip state of its own. - NS_ASSERTION(!item->GetClip().HasClip(), "Unexpected clip on item"); - const DisplayItemClip* clip = aBuilder->ClipState().GetCurrentCombinedClip(aBuilder); - if (clip) { - item->SetClip(aBuilder, *clip); - } - aOutput->AppendToTop(item); - break; - } - case nsDisplayItem::TYPE_WRAP_LIST: { - nsDisplayWrapList *list = static_cast(item); - rv = WrapPreserve3DListInternal(aFrame, aBuilder, - list->GetChildren(), aOutput, aIndex, aTemp); - list->~nsDisplayWrapList(); - break; - } - case nsDisplayItem::TYPE_OPACITY: { - if (!aTemp->IsEmpty()) { - // Flush current aTemp contents - aOutput->AppendToTop(new (aBuilder) nsDisplayTransform(aBuilder, - aFrame, aTemp, aTemp->GetVisibleRect(), aIndex++)); - } - nsDisplayOpacity *opacity = static_cast(item); - nsDisplayList output; - // Call GetChildren, not GetSameCoordinateSystemChildren, because - // the preserve-3d children of 'opacity' are temporarily not in the - // same coordinate system as the opacity --- until this wrapping is done. - rv = WrapPreserve3DListInternal(aFrame, aBuilder, - opacity->GetChildren(), &output, aIndex, aTemp); - if (!aTemp->IsEmpty()) { - output.AppendToTop(new (aBuilder) nsDisplayTransform(aBuilder, - aFrame, aTemp, aTemp->GetVisibleRect(), aIndex++)); - } - - opacity->SetVisibleRect(output.GetVisibleRect()); - opacity->SetReferenceFrame(output.GetBottom()->ReferenceFrame()); - opacity->GetChildren()->AppendToTop(&output); - opacity->UpdateBounds(aBuilder); - aOutput->AppendToTop(item); - break; - } - default: { - if (childFrame->StyleDisplay()->BackfaceIsHidden()) { - if (!aTemp->IsEmpty()) { - aOutput->AppendToTop(new (aBuilder) nsDisplayTransform(aBuilder, - aFrame, aTemp, aTemp->GetVisibleRect(), aIndex++)); - } - - aOutput->AppendToTop(new (aBuilder) nsDisplayTransform(aBuilder, - childFrame, item, item->GetVisibleRect(), aIndex++)); - } else { - aTemp->AppendToTop(item); - } - break; - } - } - } else { - aTemp->AppendToTop(item); - } - - if (NS_FAILED(rv) || !item || aIndex > nsDisplayTransform::INDEX_MAX) - return rv; - } - - return NS_OK; -} - static bool IsScrollFrameActive(nsDisplayListBuilder* aBuilder, nsIScrollableFrame* aScrollableFrame) { return aScrollableFrame && aScrollableFrame->IsScrollingActive(aBuilder); } -static nsresult -WrapPreserve3DList(nsIFrame* aFrame, nsDisplayListBuilder* aBuilder, - nsDisplayList *aList) -{ - uint32_t index = 0; - nsDisplayList temp; - nsDisplayList output; - nsresult rv = WrapPreserve3DListInternal(aFrame, aBuilder, aList, &output, - index, &temp); - - if (!temp.IsEmpty()) { - output.AppendToTop(new (aBuilder) nsDisplayTransform(aBuilder, aFrame, - &temp, temp.GetVisibleRect(), index++)); - } - - aList->AppendToTop(&output); - return rv; -} - class AutoSaveRestoreBlendMode { nsDisplayListBuilder& mBuilder; @@ -2047,6 +1933,19 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder, aBuilder->AddToWillChangeBudget(this, GetSize()); } + Maybe autoPreserves3DContext; + if (Extend3DContext() && !Combines3DTransformWithAncestors()) { + // Start a new preserves3d context to keep informations on + // nsDisplayListBuilder. + autoPreserves3DContext.emplace(aBuilder); + // Save dirty rect on the builder to avoid being distorted for + // multiple transforms along the chain. + aBuilder->SetPreserves3DDirtyRect(aDirtyRect); + } + + // For preserves3d, use the dirty rect already installed on the + // builder, since aDirtyRect maybe distorted for transforms along + // the chain. nsRect dirtyRect = aDirtyRect; bool inTransform = aBuilder->IsInTransform(); @@ -2061,16 +1960,18 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder, if (isTransformed) { const nsRect overflow = GetVisualOverflowRectRelativeToSelf(); if (aBuilder->IsForPainting() && - nsDisplayTransform::ShouldPrerenderTransformedContent(aBuilder, this)) { + (nsDisplayTransform::ShouldPrerenderTransformedContent(aBuilder, + this) || + Extend3DContext() || Combines3DTransformWithAncestors())) { dirtyRect = overflow; } else { - if (overflow.IsEmpty() && !Extend3DContext()) { + if (overflow.IsEmpty()) { return; } nsRect untransformedDirtyRect; if (nsDisplayTransform::UntransformRect(dirtyRect, overflow, this, - nsPoint(0,0), &untransformedDirtyRect)) { + nsPoint(0,0), &untransformedDirtyRect, false)) { dirtyRect = untransformedDirtyRect; } else { NS_WARNING("Unable to untransform dirty rect!"); @@ -2132,10 +2033,11 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder, MarkAbsoluteFramesForDisplayList(aBuilder, dirtyRect); - // Preserve3DChildren() also guarantees that applyAbsPosClipping and usingSVGEffects are false + // Extend3DContext() also guarantees that applyAbsPosClipping and usingSVGEffects are false // We only modify the preserve-3d rect if we are the top of a preserve-3d heirarchy if (Extend3DContext()) { - aBuilder->MarkPreserve3DFramesForDisplayList(this, aDirtyRect); + nsRect dirty = aBuilder->GetPreserves3DDirtyRect(this); + aBuilder->MarkPreserve3DFramesForDisplayList(this, dirty); } if (aBuilder->IsBuildingLayerEventRegions()) { @@ -2260,16 +2162,59 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder, buildingDisplayList.SetDirtyRect(dirtyRectOutsideTransform); // Revert to the outer reference frame and offset because all display // items we create from now on are outside the transform. + nsPoint toOuterReferenceFrame; const nsIFrame* outerReferenceFrame = - aBuilder->FindReferenceFrameFor(nsLayoutUtils::GetTransformRootFrame(this)); + aBuilder->FindReferenceFrameFor(GetParent(), &toOuterReferenceFrame); buildingDisplayList.SetReferenceFrameAndCurrentOffset(outerReferenceFrame, GetOffsetToCrossDoc(outerReferenceFrame)); - if (Extend3DContext()) { - WrapPreserve3DList(this, aBuilder, &resultList); - } else { - resultList.AppendNewToTop( - new (aBuilder) nsDisplayTransform(aBuilder, this, &resultList, dirtyRect)); + nsDisplayTransform *transformItem = + new (aBuilder) nsDisplayTransform(aBuilder, this, &resultList, dirtyRect); + resultList.AppendNewToTop(transformItem); + + /* + * Create an additional transform item as a separator layer + * between current and parent's 3D context if necessary. + * + * Separator layers avoid improperly exteding 3D context by + * children. + */ + { + bool needAdditionalTransform = false; + if (Extend3DContext()) { + if (outerReferenceFrame->Extend3DContext()) { + for (nsIFrame *f = nsLayoutUtils::GetCrossDocParentFrame(this); + f && f != outerReferenceFrame && !f->IsTransformed(); + f = nsLayoutUtils::GetCrossDocParentFrame(f)) { + if (!f->Extend3DContext()) { + // The first one with transform in it's 3D context chain, + // and it is different 3D context with the outer reference + // frame. + needAdditionalTransform = true; + break; + } + } + } + } else if (outerReferenceFrame->Extend3DContext() && + outerReferenceFrame != nsLayoutUtils::GetCrossDocParentFrame(this)) { + // The content should be transformed and drawn on a buffer, + // then tranformed and drawn again for outerReferenceFrame. + // So, a separator layer is required. + needAdditionalTransform = true; + } + if (needAdditionalTransform) { + nsRect sepDirty = dirtyRectOutsideTransform; + // The separator item is with ID transform and is out of this + // frame, so it is in the coordination of the outer reference + // frame. Here translate the dirty rect back. + sepDirty.MoveBy(toOuterReferenceFrame); + nsDisplayTransform *sepIdItem = + new (aBuilder) nsDisplayTransform(aBuilder, this, &resultList, + sepDirty, + Matrix4x4(), 1); + sepIdItem->SetNoExtendContext(); + resultList.AppendNewToTop(sepIdItem); + } } } diff --git a/layout/generic/nsIFrame.h b/layout/generic/nsIFrame.h index a1748e5cff88..bfc31e40e655 100644 --- a/layout/generic/nsIFrame.h +++ b/layout/generic/nsIFrame.h @@ -1260,6 +1260,10 @@ public: */ bool Combines3DTransformWithAncestors() const; + bool IsPreserve3DLeaf() const { + return Combines3DTransformWithAncestors() && !Extend3DContext(); + } + bool HasPerspective() const; bool ChildrenHavePerspective() const; @@ -3030,6 +3034,10 @@ NS_PTR_TO_INT32(frame->Properties().Get(nsIFrame::ParagraphDepthProperty())) */ virtual mozilla::dom::Element* GetPseudoElement(nsCSSPseudoElements::Type aType); + bool BackfaceIsHidden() { + return StyleDisplay()->BackfaceIsHidden(); + } + protected: // Members nsRect mRect; From 2e884ff4776723e106422d662074a13506d3fc5e Mon Sep 17 00:00:00 2001 From: hchang Date: Wed, 16 Sep 2015 19:42:00 +0200 Subject: [PATCH 039/113] Bug 1163254 - Add signedPkg to OriginAttributes. r=bholley --- caps/BasePrincipal.cpp | 10 ++++++++++ caps/BasePrincipal.h | 7 ++++++- caps/tests/unit/test_origin.js | 16 ++++++++++++++++ dom/base/StructuredCloneHelper.cpp | 17 +++++++++++++++-- dom/cache/DBSchema.cpp | 3 ++- dom/webidl/ChromeUtils.webidl | 4 ++-- dom/workers/ServiceWorkerRegistrar.cpp | 3 ++- dom/workers/test/gtest/TestReadWrite.cpp | 2 +- ipc/glue/BackgroundUtils.cpp | 7 ++++++- ipc/glue/PBackgroundSharedTypes.ipdlh | 1 + 10 files changed, 61 insertions(+), 9 deletions(-) diff --git a/caps/BasePrincipal.cpp b/caps/BasePrincipal.cpp index f6d58c8268ed..a864c85a234d 100644 --- a/caps/BasePrincipal.cpp +++ b/caps/BasePrincipal.cpp @@ -62,6 +62,10 @@ OriginAttributes::CreateSuffix(nsACString& aStr) const params->Set(NS_LITERAL_STRING("userContextId"), value); } + if (!mSignedPkg.IsEmpty()) { + params->Set(NS_LITERAL_STRING("signedPkg"), mSignedPkg); + } + aStr.Truncate(); params->Serialize(value); @@ -132,6 +136,12 @@ public: return true; } + if (aName.EqualsLiteral("signedPkg")) { + MOZ_RELEASE_ASSERT(mOriginAttributes->mSignedPkg.IsEmpty()); + mOriginAttributes->mSignedPkg.Assign(aValue); + return true; + } + // No other attributes are supported. return false; } diff --git a/caps/BasePrincipal.h b/caps/BasePrincipal.h index 927c8d0fe3c6..01ed3927fa8a 100644 --- a/caps/BasePrincipal.h +++ b/caps/BasePrincipal.h @@ -36,7 +36,8 @@ public: return mAppId == aOther.mAppId && mInBrowser == aOther.mInBrowser && mAddonId == aOther.mAddonId && - mUserContextId == aOther.mUserContextId; + mUserContextId == aOther.mUserContextId && + mSignedPkg == aOther.mSignedPkg; } bool operator!=(const OriginAttributes& aOther) const { @@ -88,6 +89,10 @@ public: return false; } + if (mSignedPkg.WasPassed() && mSignedPkg.Value() != aAttrs.mSignedPkg) { + return false; + } + return true; } }; diff --git a/caps/tests/unit/test_origin.js b/caps/tests/unit/test_origin.js index 8ec957428d12..7b9a0a5769bc 100644 --- a/caps/tests/unit/test_origin.js +++ b/caps/tests/unit/test_origin.js @@ -122,6 +122,19 @@ function run_test() { checkOriginAttributes(nullPrin_userContextApp, {appId: 24, userContextId: 42}, '^appId=24&userContextId=42'); do_check_eq(exampleOrg_userContextApp.origin, 'http://example.org^appId=24&userContextId=42'); + // Just signedPkg + var exampleOrg_signedPkg = ssm.createCodebasePrincipal(makeURI('http://example.org'), {signedPkg: 'whatever'}); + checkOriginAttributes(exampleOrg_signedPkg, { signedPkg: 'id' }, '^signedPkg=whatever'); + do_check_eq(exampleOrg_signedPkg.origin, 'http://example.org^signedPkg=whatever'); + + // signedPkg and browser + var exampleOrg_signedPkg_browser = ssm.createCodebasePrincipal(makeURI('http://example.org'), {signedPkg: 'whatever', inBrowser: true}); + checkOriginAttributes(exampleOrg_signedPkg_browser, { signedPkg: 'whatever', inBrowser: true }, '^inBrowser=1&signedPkg=whatever'); + do_check_eq(exampleOrg_signedPkg_browser.origin, 'http://example.org^inBrowser=1&signedPkg=whatever'); + + // Just signedPkg (but different value from 'exampleOrg_signedPkg_app') + var exampleOrg_signedPkg_another = ssm.createCodebasePrincipal(makeURI('http://example.org'), {signedPkg: 'whatup'}); + // Check that all of the above are cross-origin. checkCrossOrigin(exampleOrg_app, exampleOrg); checkCrossOrigin(exampleOrg_app, nullPrin_app); @@ -135,4 +148,7 @@ function run_test() { checkCrossOrigin(exampleOrg_userContextAddon, exampleOrg); checkCrossOrigin(exampleOrg_userContext, exampleOrg_userContextAddon); checkCrossOrigin(exampleOrg_userContext, exampleOrg_userContextApp); + checkCrossOrigin(exampleOrg_signedPkg, exampleOrg); + checkCrossOrigin(exampleOrg_signedPkg, exampleOrg_signedPkg_browser); + checkCrossOrigin(exampleOrg_signedPkg, exampleOrg_signedPkg_another); } diff --git a/dom/base/StructuredCloneHelper.cpp b/dom/base/StructuredCloneHelper.cpp index 833d0ac4c952..2646a61e06a1 100644 --- a/dom/base/StructuredCloneHelper.cpp +++ b/dom/base/StructuredCloneHelper.cpp @@ -432,14 +432,25 @@ StructuredCloneHelper::ReadFullySerializableObjects(JSContext* aCx, return nullptr; } + uint32_t signedPkgLength, dummy; + if (!JS_ReadUint32Pair(aReader, &signedPkgLength, &dummy)) { + return nullptr; + } + nsAutoCString spec; spec.SetLength(specLength); if (!JS_ReadBytes(aReader, spec.BeginWriting(), specLength)) { return nullptr; } + nsAutoCString signedPkg; + spec.SetLength(signedPkgLength); + if (!JS_ReadBytes(aReader, signedPkg.BeginWriting(), signedPkgLength)) { + return nullptr; + } + info = mozilla::ipc::ContentPrincipalInfo(appId, isInBrowserElement, - spec); + spec, signedPkg); } nsresult rv; @@ -570,7 +581,9 @@ StructuredCloneHelper::WriteFullySerializableObjects(JSContext* aCx, cInfo.appId()) && JS_WriteUint32Pair(aWriter, cInfo.isInBrowserElement(), cInfo.spec().Length()) && - JS_WriteBytes(aWriter, cInfo.spec().get(), cInfo.spec().Length()); + JS_WriteUint32Pair(aWriter, cInfo.signedPkg().Length(), 0) && + JS_WriteBytes(aWriter, cInfo.spec().get(), cInfo.spec().Length()) && + JS_WriteBytes(aWriter, cInfo.signedPkg().get(), cInfo.signedPkg().Length()); } } diff --git a/dom/cache/DBSchema.cpp b/dom/cache/DBSchema.cpp index 52a93333425d..e532adee167d 100644 --- a/dom/cache/DBSchema.cpp +++ b/dom/cache/DBSchema.cpp @@ -1908,8 +1908,9 @@ ReadResponse(mozIStorageConnection* aConn, EntryId aEntryId, return NS_ERROR_FAILURE; } + nsCString signedPkg = NS_ConvertUTF16toUTF8(attrs.mSignedPkg); aSavedResponseOut->mValue.principalInfo() = - mozilla::ipc::ContentPrincipalInfo(attrs.mAppId, attrs.mInBrowser, originNoSuffix); + mozilla::ipc::ContentPrincipalInfo(attrs.mAppId, attrs.mInBrowser, originNoSuffix, signedPkg); } int32_t redirected; diff --git a/dom/webidl/ChromeUtils.webidl b/dom/webidl/ChromeUtils.webidl index 6b24e58a7c4e..8c43ffb7129d 100644 --- a/dom/webidl/ChromeUtils.webidl +++ b/dom/webidl/ChromeUtils.webidl @@ -41,18 +41,18 @@ interface ChromeUtils : ThreadSafeChromeUtils { * (2) Update the methods on mozilla::OriginAttributes, including equality, * serialization, and deserialization. * (3) Update the methods on mozilla::OriginAttributesPattern, including matching. - * (4) Bump the CIDs (_not_ IIDs) of all the principal implementations that - * use OriginAttributes in their nsISerializable implementations. */ dictionary OriginAttributesDictionary { unsigned long appId = 0; unsigned long userContextId = 0; boolean inBrowser = false; DOMString addonId = ""; + DOMString signedPkg = ""; }; dictionary OriginAttributesPatternDictionary { unsigned long appId; unsigned long userContextId; boolean inBrowser; DOMString addonId; + DOMString signedPkg; }; diff --git a/dom/workers/ServiceWorkerRegistrar.cpp b/dom/workers/ServiceWorkerRegistrar.cpp index 4db7de3525c7..138349d56223 100644 --- a/dom/workers/ServiceWorkerRegistrar.cpp +++ b/dom/workers/ServiceWorkerRegistrar.cpp @@ -332,8 +332,9 @@ ServiceWorkerRegistrar::ReadData() } GET_LINE(line); + nsCString signedPkg = NS_ConvertUTF16toUTF8(attrs.mSignedPkg); entry->principal() = - mozilla::ipc::ContentPrincipalInfo(attrs.mAppId, attrs.mInBrowser, line); + mozilla::ipc::ContentPrincipalInfo(attrs.mAppId, attrs.mInBrowser, line, signedPkg); GET_LINE(entry->scope()); GET_LINE(entry->scriptSpec()); diff --git a/dom/workers/test/gtest/TestReadWrite.cpp b/dom/workers/test/gtest/TestReadWrite.cpp index bf85a6031ea2..8c1514b043a4 100644 --- a/dom/workers/test/gtest/TestReadWrite.cpp +++ b/dom/workers/test/gtest/TestReadWrite.cpp @@ -221,7 +221,7 @@ TEST(ServiceWorkerRegistrar, TestWriteData) nsAutoCString spec; spec.AppendPrintf("spec write %d", i); - d->principal() = mozilla::ipc::ContentPrincipalInfo(i, i % 2, spec); + d->principal() = mozilla::ipc::ContentPrincipalInfo(i, i % 2, spec, EmptyCString()); d->scope().AppendPrintf("scope write %d", i); d->scriptSpec().AppendPrintf("scriptSpec write %d", i); d->currentWorkerURL().AppendPrintf("currentWorkerURL write %d", i); diff --git a/ipc/glue/BackgroundUtils.cpp b/ipc/glue/BackgroundUtils.cpp index 517bfab3bde0..0aaf7fc8f647 100644 --- a/ipc/glue/BackgroundUtils.cpp +++ b/ipc/glue/BackgroundUtils.cpp @@ -82,6 +82,7 @@ PrincipalInfoToPrincipal(const PrincipalInfo& aPrincipalInfo, } else { // TODO: Bug 1167100 - User nsIPrincipal.originAttribute in ContentPrincipalInfo OriginAttributes attrs(info.appId(), info.isInBrowserElement()); + attrs.mSignedPkg = NS_ConvertUTF8toUTF16(info.signedPkg()); principal = BasePrincipal::CreateCodebasePrincipal(uri, attrs); rv = principal ? NS_OK : NS_ERROR_FAILURE; } @@ -202,6 +203,10 @@ PrincipalToPrincipalInfo(nsIPrincipal* aPrincipal, return rv; } + const mozilla::OriginAttributes& attr = + mozilla::BasePrincipal::Cast(aPrincipal)->OriginAttributesRef(); + nsCString signedPkg = NS_ConvertUTF16toUTF8(attr.mSignedPkg); + bool isUnknownAppId; rv = aPrincipal->GetUnknownAppId(&isUnknownAppId); if (NS_WARN_IF(NS_FAILED(rv))) { @@ -224,7 +229,7 @@ PrincipalToPrincipalInfo(nsIPrincipal* aPrincipal, return rv; } - *aPrincipalInfo = ContentPrincipalInfo(appId, isInBrowserElement, spec); + *aPrincipalInfo = ContentPrincipalInfo(appId, isInBrowserElement, spec, signedPkg); return NS_OK; } diff --git a/ipc/glue/PBackgroundSharedTypes.ipdlh b/ipc/glue/PBackgroundSharedTypes.ipdlh index c0fe2939ca39..546c3cd8f6b7 100644 --- a/ipc/glue/PBackgroundSharedTypes.ipdlh +++ b/ipc/glue/PBackgroundSharedTypes.ipdlh @@ -12,6 +12,7 @@ struct ContentPrincipalInfo uint32_t appId; bool isInBrowserElement; nsCString spec; + nsCString signedPkg; }; struct SystemPrincipalInfo From 1e387b4675dab58267aa27a01d3d9b8b69eeaa54 Mon Sep 17 00:00:00 2001 From: Marcos Caceres Date: Wed, 16 Sep 2015 06:55:00 +0200 Subject: [PATCH 040/113] Bug 1169633 - [Browser API] getWebManifest(). r=kanru, r=bholley --- .../BrowserElementChildPreload.js | 29 ++++++- dom/browser-element/BrowserElementParent.js | 5 +- dom/browser-element/mochitest/async.js | 78 +++++++++++++++++++ .../browserElement_getWebManifest.js | 63 +++++++++++++++ .../mochitest/file_illegal_web_manifest.html | 6 ++ .../mochitest/file_web_manifest.html | 6 ++ .../mochitest/file_web_manifest.json | 1 + .../mochitest/mochitest-oop.ini | 1 + dom/browser-element/mochitest/mochitest.ini | 6 ++ ..._browserElement_inproc_getWebManifest.html | 17 ++++ ...est_browserElement_oop_getWebManifest.html | 16 ++++ dom/browser-element/nsIBrowserElementAPI.idl | 6 +- dom/html/nsBrowserElement.cpp | 17 ++++ dom/html/nsBrowserElement.h | 2 + dom/webidl/BrowserElement.webidl | 4 + 15 files changed, 253 insertions(+), 4 deletions(-) create mode 100644 dom/browser-element/mochitest/async.js create mode 100644 dom/browser-element/mochitest/browserElement_getWebManifest.js create mode 100644 dom/browser-element/mochitest/file_illegal_web_manifest.html create mode 100644 dom/browser-element/mochitest/file_web_manifest.html create mode 100644 dom/browser-element/mochitest/file_web_manifest.json create mode 100644 dom/browser-element/mochitest/test_browserElement_inproc_getWebManifest.html create mode 100644 dom/browser-element/mochitest/test_browserElement_oop_getWebManifest.html diff --git a/dom/browser-element/BrowserElementChildPreload.js b/dom/browser-element/BrowserElementChildPreload.js index 27a9082f9ef1..9c2390713e62 100644 --- a/dom/browser-element/BrowserElementChildPreload.js +++ b/dom/browser-element/BrowserElementChildPreload.js @@ -12,10 +12,15 @@ var { classes: Cc, interfaces: Ci, results: Cr, utils: Cu } = Components; Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://gre/modules/BrowserElementPromptService.jsm"); +Cu.import("resource://gre/modules/Task.jsm"); XPCOMUtils.defineLazyServiceGetter(this, "acs", "@mozilla.org/audiochannel/service;1", "nsIAudioChannelService"); +XPCOMUtils.defineLazyModuleGetter(this, "ManifestFinder", + "resource://gre/modules/ManifestFinder.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "ManifestObtainer", + "resource://gre/modules/ManifestObtainer.jsm"); var kLongestReturnedString = 128; @@ -251,7 +256,8 @@ BrowserElementChild.prototype = { "set-audio-channel-volume": this._recvSetAudioChannelVolume, "get-audio-channel-muted": this._recvGetAudioChannelMuted, "set-audio-channel-muted": this._recvSetAudioChannelMuted, - "get-is-audio-channel-active": this._recvIsAudioChannelActive + "get-is-audio-channel-active": this._recvIsAudioChannelActive, + "get-web-manifest": this._recvGetWebManifest, } addMessageListener("browser-element-api:call", function(aMessage) { @@ -1478,6 +1484,27 @@ BrowserElementChild.prototype = { }); }, + _recvGetWebManifest: Task.async(function* (data) { + debug(`Received GetWebManifest message: (${data.json.id})`); + let manifest = null; + let hasManifest = ManifestFinder.contentHasManifestLink(content); + if (hasManifest) { + try { + manifest = yield ManifestObtainer.contentObtainManifest(content); + } catch (e) { + sendAsyncMsg('got-web-manifest', { + id: data.json.id, + errorMsg: `Error fetching web manifest: ${e}.`, + }); + return; + } + } + sendAsyncMsg('got-web-manifest', { + id: data.json.id, + successRv: manifest + }); + }), + _initFinder: function() { if (!this._finder) { try { diff --git a/dom/browser-element/BrowserElementParent.js b/dom/browser-element/BrowserElementParent.js index 7b9e60f80620..a61d26ad0d67 100644 --- a/dom/browser-element/BrowserElementParent.js +++ b/dom/browser-element/BrowserElementParent.js @@ -210,7 +210,8 @@ BrowserElementParent.prototype = { "got-set-audio-channel-volume": this._gotDOMRequestResult, "got-audio-channel-muted": this._gotDOMRequestResult, "got-set-audio-channel-muted": this._gotDOMRequestResult, - "got-is-audio-channel-active": this._gotDOMRequestResult + "got-is-audio-channel-active": this._gotDOMRequestResult, + "got-web-manifest": this._gotDOMRequestResult, }; let mmSecuritySensitiveCalls = { @@ -1033,6 +1034,8 @@ BrowserElementParent.prototype = { {audioChannel: aAudioChannel}); }, + getWebManifest: defineDOMRequestMethod('get-web-manifest'), + /** * Called when the visibility of the window which owns this iframe changes. */ diff --git a/dom/browser-element/mochitest/async.js b/dom/browser-element/mochitest/async.js new file mode 100644 index 000000000000..d0007fa0964a --- /dev/null +++ b/dom/browser-element/mochitest/async.js @@ -0,0 +1,78 @@ +/* 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/. */ + +/* + * This is an approximate implementation of ES7's async-await pattern. + * see: https://github.com/tc39/ecmascript-asyncawait + * + * It allows for simple creation of async function and "tasks". + * + * For example: + * + * var myThinger = { + * doAsynThing: async(function*(url){ + * var result = yield fetch(url); + * return process(result); + * }); + * } + * + * And Task-like things can be created as follows: + * + * var myTask = async(function*{ + * var result = yield fetch(url); + * return result; + * }); + * //returns a promise + * + * myTask().then(doSomethingElse); + * + */ + +(function(exports) { + "use strict"; + function async(func, self) { + return function asyncFunction() { + const functionArgs = Array.from(arguments); + return new Promise(function(resolve, reject) { + var gen; + if (typeof func !== "function") { + reject(new TypeError("Expected a Function.")); + } + //not a generator, wrap it. + if (func.constructor.name !== "GeneratorFunction") { + gen = (function*() { + return func.apply(self, functionArgs); + }()); + } else { + gen = func.apply(self, functionArgs); + } + try { + step(gen.next(undefined)); + } catch (err) { + reject(err); + } + + function step({value, done}) { + if (done) { + return resolve(value); + } + if (value instanceof Promise) { + return value.then( + result => step(gen.next(result)), + error => { + try { + step(gen.throw(error)); + } catch (err) { + throw err; + } + } + ).catch(err => reject(err)); + } + step(gen.next(value)); + } + }); + }; + } + exports.async = async; +}(this || self)); diff --git a/dom/browser-element/mochitest/browserElement_getWebManifest.js b/dom/browser-element/mochitest/browserElement_getWebManifest.js new file mode 100644 index 000000000000..31b06d0b82c3 --- /dev/null +++ b/dom/browser-element/mochitest/browserElement_getWebManifest.js @@ -0,0 +1,63 @@ +/* Any copyright is dedicated to the public domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ +/*globals async, ok, is, SimpleTest, browserElementTestHelpers*/ + +// Bug 1169633 - getWebManifest tests +'use strict'; +SimpleTest.waitForExplicitFinish(); +browserElementTestHelpers.setEnabledPref(true); +browserElementTestHelpers.addPermission(); + +// request to load a manifest from a page that doesn't have a manifest. +// The expected result to be null. +var test1 = async(function* () { + var manifest = yield requestManifest('file_empty.html'); + is(manifest, null, 'it should be null.'); +}); + +// request to load a manifest from a page that has a manifest. +// The expected manifest to have a property name whose value is 'pass'. +var test2 = async(function* () { + var manifest = yield requestManifest('file_web_manifest.html'); + is(manifest && manifest.name, 'pass', 'it should return a manifest with name pass.'); +}); + +// Cause an exception by attempting to fetch a file URL, +// expect onerror to be called. +var test3 = async(function* () { + var gotError = false; + try { + yield requestManifest('file_illegal_web_manifest.html'); + } catch (err) { + gotError = true; + } + ok(gotError, 'onerror was called on the DOMRequest.'); +}); + +// Run the tests +Promise + .all([test1(), test2(), test3()]) + .then(SimpleTest.finish); + +function requestManifest(url) { + var iframe = document.createElement('iframe'); + iframe.setAttribute('mozbrowser', 'true'); + iframe.src = url; + document.body.appendChild(iframe); + return new Promise((resolve, reject) => { + iframe.addEventListener('mozbrowserloadend', function loadend() { + iframe.removeEventListener('mozbrowserloadend', loadend); + SimpleTest.executeSoon(() => { + var req = iframe.getWebManifest(); + req.onsuccess = () => { + document.body.removeChild(iframe); + resolve(req.result); + }; + req.onerror = () => { + document.body.removeChild(iframe); + reject(new Error(req.error)); + }; + }); + }); + }); +} diff --git a/dom/browser-element/mochitest/file_illegal_web_manifest.html b/dom/browser-element/mochitest/file_illegal_web_manifest.html new file mode 100644 index 000000000000..b4e06918950c --- /dev/null +++ b/dom/browser-element/mochitest/file_illegal_web_manifest.html @@ -0,0 +1,6 @@ + + + + + +

Support Page for Web Manifest Tests

diff --git a/dom/browser-element/mochitest/file_web_manifest.html b/dom/browser-element/mochitest/file_web_manifest.html new file mode 100644 index 000000000000..783da0f47d04 --- /dev/null +++ b/dom/browser-element/mochitest/file_web_manifest.html @@ -0,0 +1,6 @@ + + + + + +

Support Page for Web Manifest Tests

diff --git a/dom/browser-element/mochitest/file_web_manifest.json b/dom/browser-element/mochitest/file_web_manifest.json new file mode 100644 index 000000000000..57d0c3d42ef4 --- /dev/null +++ b/dom/browser-element/mochitest/file_web_manifest.json @@ -0,0 +1 @@ +{"name": "pass"} diff --git a/dom/browser-element/mochitest/mochitest-oop.ini b/dom/browser-element/mochitest/mochitest-oop.ini index 4e9fb0a2f2fa..53942381dd3d 100644 --- a/dom/browser-element/mochitest/mochitest-oop.ini +++ b/dom/browser-element/mochitest/mochitest-oop.ini @@ -114,3 +114,4 @@ disabled = bug 924771 [test_browserElement_oop_GetContentDimensions.html] [test_browserElement_oop_AudioChannel.html] [test_browserElement_oop_SetNFCFocus.html] +[test_browserElement_oop_getWebManifest.html] diff --git a/dom/browser-element/mochitest/mochitest.ini b/dom/browser-element/mochitest/mochitest.ini index 80e978921a31..9bfd6c33a40d 100644 --- a/dom/browser-element/mochitest/mochitest.ini +++ b/dom/browser-element/mochitest/mochitest.ini @@ -3,6 +3,7 @@ skip-if = buildapp == 'mulet' || (buildapp == 'b2g' && (toolkit != 'gonk' || deb support-files = ../../../browser/base/content/test/general/audio.ogg ../../../dom/media/test/short-video.ogv + async.js browserElementTestHelpers.js browserElement_Alert.js browserElement_AlertInFrame.js @@ -37,6 +38,7 @@ support-files = browserElement_FrameWrongURI.js browserElement_GetScreenshot.js browserElement_GetScreenshotDppx.js + browserElement_getWebManifest.js browserElement_Iconchange.js browserElement_LoadEvents.js browserElement_Manifestchange.js @@ -128,10 +130,14 @@ support-files = file_wyciwyg.html file_audio.html iframe_file_audio.html + file_web_manifest.html + file_web_manifest.json + file_illegal_web_manifest.html # Note: browserElementTestHelpers.js looks at the test's filename to determine # whether the test should be OOP. "_oop_" signals OOP, "_inproc_" signals in # process. Default is OOP. +[test_browserElement_inproc_getWebManifest.html] [test_browserElement_NoAttr.html] [test_browserElement_NoPref.html] [test_browserElement_NoPermission.html] diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_getWebManifest.html b/dom/browser-element/mochitest/test_browserElement_inproc_getWebManifest.html new file mode 100644 index 000000000000..2c52a3d396cf --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_inproc_getWebManifest.html @@ -0,0 +1,17 @@ + + + + Test for Bug 1169633 + + + + + + + + + diff --git a/dom/browser-element/mochitest/test_browserElement_oop_getWebManifest.html b/dom/browser-element/mochitest/test_browserElement_oop_getWebManifest.html new file mode 100644 index 000000000000..9a1d72cc4914 --- /dev/null +++ b/dom/browser-element/mochitest/test_browserElement_oop_getWebManifest.html @@ -0,0 +1,16 @@ + + + + Test for Bug 1169633 + + + + + + + + + diff --git a/dom/browser-element/nsIBrowserElementAPI.idl b/dom/browser-element/nsIBrowserElementAPI.idl index bb7a9d5a90ab..28ddce0e3912 100644 --- a/dom/browser-element/nsIBrowserElementAPI.idl +++ b/dom/browser-element/nsIBrowserElementAPI.idl @@ -9,7 +9,7 @@ interface nsIDOMDOMRequest; interface nsIFrameLoader; -[scriptable, function, uuid(c0c2dd9b-41ef-42dd-a4c1-e456619c1941)] +[scriptable, function, uuid(00d0e19d-bd67-491f-8e85-b9905224d3bb)] interface nsIBrowserElementNextPaintListener : nsISupports { void recvNextPaint(); @@ -26,7 +26,7 @@ interface nsIBrowserElementNextPaintListener : nsISupports * Interface to the BrowserElementParent implementation. All methods * but setFrameLoader throw when the remote process is dead. */ -[scriptable, uuid(56bd3e12-4a8b-422a-89fc-6dc25aa30aa2)] +[scriptable, uuid(1e098c3a-7d65-452d-a2b2-9ffd1b6e04bb)] interface nsIBrowserElementAPI : nsISupports { const long FIND_CASE_SENSITIVE = 0; @@ -100,4 +100,6 @@ interface nsIBrowserElementAPI : nsISupports void setNFCFocus(in boolean isFocus); nsIDOMDOMRequest executeScript(in DOMString script, in jsval options); + + nsIDOMDOMRequest getWebManifest(); }; diff --git a/dom/html/nsBrowserElement.cpp b/dom/html/nsBrowserElement.cpp index 49993758e5fa..1e7469dc2f7b 100644 --- a/dom/html/nsBrowserElement.cpp +++ b/dom/html/nsBrowserElement.cpp @@ -747,4 +747,21 @@ nsBrowserElement::ExecuteScript(const nsAString& aScript, return req.forget().downcast(); } +already_AddRefed +nsBrowserElement::GetWebManifest(ErrorResult& aRv) +{ + NS_ENSURE_TRUE(IsBrowserElementOrThrow(aRv), nullptr); + + nsCOMPtr req; + nsresult rv = mBrowserElementAPI->GetWebManifest(getter_AddRefs(req)); + + if (NS_WARN_IF(NS_FAILED(rv))) { + aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); + return nullptr; + } + + return req.forget().downcast(); +} + + } // namespace mozilla diff --git a/dom/html/nsBrowserElement.h b/dom/html/nsBrowserElement.h index f5819ca2cd9e..af4053bde289 100644 --- a/dom/html/nsBrowserElement.h +++ b/dom/html/nsBrowserElement.h @@ -112,6 +112,8 @@ public: const dom::BrowserElementExecuteScriptOptions& aOptions, ErrorResult& aRv); + already_AddRefed GetWebManifest(ErrorResult& aRv); + void SetNFCFocus(bool isFocus, ErrorResult& aRv); diff --git a/dom/webidl/BrowserElement.webidl b/dom/webidl/BrowserElement.webidl index 72f88426170c..2ee6c505cf3c 100644 --- a/dom/webidl/BrowserElement.webidl +++ b/dom/webidl/BrowserElement.webidl @@ -174,5 +174,9 @@ interface BrowserElementPrivileged { CheckAllPermissions="browser browser:universalxss"] DOMRequest executeScript(DOMString script, optional BrowserElementExecuteScriptOptions options); + [Throws, + Pref="dom.mozBrowserFramesEnabled", + CheckAllPermissions="browser"] + DOMRequest getWebManifest(); }; From b95e1faf4ef161e3a471e7eee1c1d2fef945d2c9 Mon Sep 17 00:00:00 2001 From: Mike Conley Date: Tue, 15 Sep 2015 16:33:36 -0400 Subject: [PATCH 041/113] Bug 1189554 - Make Saved Passwords dialog resizable on Windows again. r=smaug We were accidentally overwriting chromeFlags with CHROME_DEFAULT, which we should only do if the caller has provided a features string when opening a dialog. --HG-- extra : transplant_source : %A8Q%A4%2C%A8%04%03%A98%F1%93%7C%A9%D3%956%F8g%40w --- embedding/components/windowwatcher/nsWindowWatcher.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embedding/components/windowwatcher/nsWindowWatcher.cpp b/embedding/components/windowwatcher/nsWindowWatcher.cpp index 0f96f1ae4ae8..dd1c18cb1c0e 100644 --- a/embedding/components/windowwatcher/nsWindowWatcher.cpp +++ b/embedding/components/windowwatcher/nsWindowWatcher.cpp @@ -1610,7 +1610,7 @@ nsWindowWatcher::CalculateChromeFlags(nsIDOMWindow* aParent, } } - if (aDialog && !presenceFlag) { + if (aDialog && aFeaturesSpecified && !presenceFlag) { chromeFlags = nsIWebBrowserChrome::CHROME_DEFAULT; } From 0ad2686c67882af6365eba5d5a54b2e9dbe9ccd2 Mon Sep 17 00:00:00 2001 From: Dylan Roeh Date: Tue, 15 Sep 2015 11:54:56 -0500 Subject: [PATCH 042/113] Bug 1189881 - Move GeckoJavaSampler::getProfilerTime out of AndroidJNI.cpp. r=jchen --- mobile/android/base/GeckoJavaSampler.java | 4 +--- tools/profiler/core/platform.cpp | 26 +++++++++++++++++++++++ widget/android/AndroidJNI.cpp | 15 +++---------- widget/android/GeneratedJNINatives.h | 15 +++++++++++++ widget/android/GeneratedJNIWrappers.cpp | 3 +++ widget/android/GeneratedJNIWrappers.h | 17 +++++++++++++++ widget/android/moz.build | 1 + 7 files changed, 66 insertions(+), 15 deletions(-) diff --git a/mobile/android/base/GeckoJavaSampler.java b/mobile/android/base/GeckoJavaSampler.java index cb0d60d06c20..8d7ac3553af7 100644 --- a/mobile/android/base/GeckoJavaSampler.java +++ b/mobile/android/base/GeckoJavaSampler.java @@ -22,6 +22,7 @@ public class GeckoJavaSampler { // Use the same timer primitive as the profiler // to get a perfect sample syncing. + @WrapForJNI private static native double getProfilerTime(); private static class Sample { @@ -208,6 +209,3 @@ public class GeckoJavaSampler { } } } - - - diff --git a/tools/profiler/core/platform.cpp b/tools/profiler/core/platform.cpp index 50ff84f67e0a..5fbbddaf5f17 100644 --- a/tools/profiler/core/platform.cpp +++ b/tools/profiler/core/platform.cpp @@ -35,6 +35,10 @@ #include "AndroidBridge.h" #endif +#ifdef SPS_OS_android +#include "GeneratedJNINatives.h" +#endif + #ifndef SPS_STANDALONE #if defined(SPS_PLAT_amd64_linux) || defined(SPS_PLAT_x86_linux) # define USE_LUL_STACKWALK @@ -43,6 +47,22 @@ #endif #endif +#ifdef SPS_OS_android +class GeckoJavaSampler : public widget::GeckoJavaSampler::Natives +{ +private: + GeckoJavaSampler(); + +public: + static double GetProfilerTime() { + if (!profiler_is_active()) { + return 0.0; + } + return profiler_time(); + }; +}; +#endif + mozilla::ThreadLocal tlsPseudoStack; mozilla::ThreadLocal tlsTicker; mozilla::ThreadLocal tlsStackTop; @@ -473,6 +493,12 @@ void mozilla_sampler_init(void* stackTop) set_stderr_callback(mozilla_sampler_log); #endif +#ifdef SPS_OS_android + if (mozilla::jni::IsAvailable()) { + GeckoJavaSampler::Init(); + } +#endif + // We can't open pref so we use an environment variable // to know if we should trigger the profiler on startup // NOTE: Default diff --git a/widget/android/AndroidJNI.cpp b/widget/android/AndroidJNI.cpp index 6b75536a0c69..db2686ba3cdf 100644 --- a/widget/android/AndroidJNI.cpp +++ b/widget/android/AndroidJNI.cpp @@ -680,7 +680,7 @@ Java_org_mozilla_gecko_GeckoAppShell_notifyFilePickerResult(JNIEnv* jenv, jclass { class NotifyFilePickerResultRunnable : public nsRunnable { public: - NotifyFilePickerResultRunnable(nsString& fileDir, long callback) : + NotifyFilePickerResultRunnable(nsString& fileDir, long callback) : mFileDir(fileDir), mCallback(callback) {} NS_IMETHODIMP Run() { @@ -694,7 +694,7 @@ Java_org_mozilla_gecko_GeckoAppShell_notifyFilePickerResult(JNIEnv* jenv, jclass long mCallback; }; nsString path = nsJNIString(filePath, jenv); - + nsCOMPtr runnable = new NotifyFilePickerResultRunnable(path, (long)callback); NS_DispatchToMainThread(runnable); @@ -767,7 +767,7 @@ Java_org_mozilla_gecko_GeckoAppShell_getSurfaceBits(JNIEnv* jenv, jclass, jobjec for (int i = 0; i < srcHeight; i++) { memcpy(bitsCopy + ((dstHeight - i - 1) * dstWidth * bpp), bits + (i * srcStride * bpp), srcStride * bpp); } - + if (!jSurfaceBitsClass) { jSurfaceBitsClass = (jclass)jenv->NewGlobalRef(jenv->FindClass("org/mozilla/gecko/SurfaceBits")); jSurfaceBitsCtor = jenv->GetMethodID(jSurfaceBitsClass, "", "()V"); @@ -852,15 +852,6 @@ Java_org_mozilla_gecko_GeckoAppShell_dispatchMemoryPressure(JNIEnv* jenv, jclass NS_DispatchMemoryPressure(MemPressure_New); } -NS_EXPORT jdouble JNICALL -Java_org_mozilla_gecko_GeckoJavaSampler_getProfilerTime(JNIEnv *jenv, jclass jc) -{ - if (!profiler_is_active()) { - return 0.0; - } - return profiler_time(); -} - NS_EXPORT void JNICALL Java_org_mozilla_gecko_gfx_NativePanZoomController_abortAnimation(JNIEnv* env, jobject instance) { diff --git a/widget/android/GeneratedJNINatives.h b/widget/android/GeneratedJNINatives.h index ed062caab8c2..3e04a51888bc 100644 --- a/widget/android/GeneratedJNINatives.h +++ b/widget/android/GeneratedJNINatives.h @@ -36,6 +36,21 @@ public: template constexpr JNINativeMethod ANRReporter::Natives::methods[]; +template +class GeckoJavaSampler::Natives : public mozilla::jni::NativeImpl +{ +public: + static constexpr JNINativeMethod methods[] = { + + mozilla::jni::MakeNativeMethod( + mozilla::jni::NativeStub + ::template Wrap<&Impl::GetProfilerTime>) + }; +}; + +template +constexpr JNINativeMethod GeckoJavaSampler::Natives::methods[]; + template class GeckoThread::Natives : public mozilla::jni::NativeImpl { diff --git a/widget/android/GeneratedJNIWrappers.cpp b/widget/android/GeneratedJNIWrappers.cpp index 9ddd80864443..363d5de0baa2 100644 --- a/widget/android/GeneratedJNIWrappers.cpp +++ b/widget/android/GeneratedJNIWrappers.cpp @@ -715,6 +715,9 @@ auto GeckoJavaSampler::GetFrameNameJavaProfilingWrapper(int32_t a0, int32_t a1, return mozilla::jni::Method::Call(nullptr, nullptr, a0, a1, a2); } +constexpr char GeckoJavaSampler::GetProfilerTime_t::name[]; +constexpr char GeckoJavaSampler::GetProfilerTime_t::signature[]; + constexpr char GeckoJavaSampler::GetSampleTimeJavaProfiling_t::name[]; constexpr char GeckoJavaSampler::GetSampleTimeJavaProfiling_t::signature[]; diff --git a/widget/android/GeneratedJNIWrappers.h b/widget/android/GeneratedJNIWrappers.h index a36ff9666db2..f222acce0580 100644 --- a/widget/android/GeneratedJNIWrappers.h +++ b/widget/android/GeneratedJNIWrappers.h @@ -1694,6 +1694,21 @@ public: static auto GetFrameNameJavaProfilingWrapper(int32_t, int32_t, int32_t) -> mozilla::jni::String::LocalRef; +public: + struct GetProfilerTime_t { + typedef GeckoJavaSampler Owner; + typedef double ReturnType; + typedef double SetterType; + typedef mozilla::jni::Args<> Args; + static constexpr char name[] = "getProfilerTime"; + static constexpr char signature[] = + "()D"; + static const bool isStatic = true; + static const bool isMultithreaded = false; + static const mozilla::jni::ExceptionMode exceptionMode = + mozilla::jni::ExceptionMode::ABORT; + }; + public: struct GetSampleTimeJavaProfiling_t { typedef GeckoJavaSampler Owner; @@ -1801,6 +1816,8 @@ public: static auto UnpauseJavaProfiling() -> void; +public: + template class Natives; }; class GeckoThread : public mozilla::jni::Class diff --git a/widget/android/moz.build b/widget/android/moz.build index 03dd17ea37b0..402e69ab957c 100644 --- a/widget/android/moz.build +++ b/widget/android/moz.build @@ -19,6 +19,7 @@ EXPORTS += [ 'AndroidBridge.h', 'AndroidJavaWrappers.h', 'AndroidJNIWrapper.h', + 'GeneratedJNINatives.h', 'GeneratedJNIWrappers.h', ] From a7a276263d31f703108fee8d077e71cb5f4ffa2a Mon Sep 17 00:00:00 2001 From: Jamie Nicol Date: Tue, 15 Sep 2015 14:41:42 +0100 Subject: [PATCH 043/113] Bug 1200729 - Recompute FrameLayerBuilder item visibility if dirty region changes. r=mwoodrow Make the FrameLayerBuilder remember for what region it has calculated display item visibility, then recompute the visibility whenever the dirty region it is passed to DrawPaintedLayer changes. This means that the caller does not have to know the entire dirty region that will be drawn for the transaction, but we can still optimise cases where it knows some of the dirty region in advance. This fixes a regression where MultiTiledContentClient's low-res display port would not be painted if a smaller region of its high-res buffer had already been painted that transaction, since the FrameLayerBuilder had decided that most of the larger low-res region was invisible. --- embedding/browser/nsWebBrowser.cpp | 2 +- gfx/layers/Layers.h | 13 +++---- gfx/layers/basic/BasicPaintedLayer.cpp | 2 +- gfx/layers/basic/BasicPaintedLayer.h | 2 +- gfx/layers/client/ClientPaintedLayer.cpp | 2 +- .../client/SingleTiledContentClient.cpp | 2 +- gfx/layers/client/TiledContentClient.cpp | 4 +-- layout/base/FrameLayerBuilder.cpp | 36 +++++++++---------- layout/base/FrameLayerBuilder.h | 8 ++--- 9 files changed, 35 insertions(+), 36 deletions(-) diff --git a/embedding/browser/nsWebBrowser.cpp b/embedding/browser/nsWebBrowser.cpp index 884bfb3952bc..973da7d868b1 100644 --- a/embedding/browser/nsWebBrowser.cpp +++ b/embedding/browser/nsWebBrowser.cpp @@ -1688,7 +1688,7 @@ static void DrawPaintedLayer(PaintedLayer* aLayer, gfxContext* aContext, const nsIntRegion& aRegionToDraw, - const nsIntRegion* aDirtyRegion, + const nsIntRegion& aDirtyRegion, DrawRegionClip aClip, const nsIntRegion& aRegionToInvalidate, void* aCallbackData) diff --git a/gfx/layers/Layers.h b/gfx/layers/Layers.h index 32325bf537cf..533c22615eb3 100644 --- a/gfx/layers/Layers.h +++ b/gfx/layers/Layers.h @@ -259,11 +259,12 @@ public: * The callee must draw all of aRegionToDraw. * This region is relative to 0,0 in the PaintedLayer. * - * aDirtyRegion, if non-null, contains the total region that is due to be - * painted during the transaction, even though only aRegionToDraw should - * be drawn during this call. The sum of every aRegionToDraw over the - * course of the transaction must equal aDirtyRegion. aDirtyRegion can be - * null if the total dirty region is unknown. + * aDirtyRegion should contain the total region that is be due to be painted + * during the transaction, even though only aRegionToDraw should be drawn + * during this call. aRegionToDraw must be entirely contained within + * aDirtyRegion. If the total dirty region is unknown it is okay to pass a + * subregion of the total dirty region, e.g. just aRegionToDraw, though it + * may not be as efficient. * * aRegionToInvalidate contains a region whose contents have been * changed by the layer manager and which must therefore be invalidated. @@ -285,7 +286,7 @@ public: typedef void (* DrawPaintedLayerCallback)(PaintedLayer* aLayer, gfxContext* aContext, const nsIntRegion& aRegionToDraw, - const nsIntRegion* aDirtyRegion, + const nsIntRegion& aDirtyRegion, DrawRegionClip aClip, const nsIntRegion& aRegionToInvalidate, void* aCallbackData); diff --git a/gfx/layers/basic/BasicPaintedLayer.cpp b/gfx/layers/basic/BasicPaintedLayer.cpp index 36314977a0c3..74b5bc48ef3e 100644 --- a/gfx/layers/basic/BasicPaintedLayer.cpp +++ b/gfx/layers/basic/BasicPaintedLayer.cpp @@ -91,7 +91,7 @@ BasicPaintedLayer::PaintThebes(gfxContext* aContext, groupContext = aContext; } SetAntialiasingFlags(this, groupContext->GetDrawTarget()); - aCallback(this, groupContext, toDraw, &toDraw, + aCallback(this, groupContext, toDraw, toDraw, DrawRegionClip::NONE, nsIntRegion(), aCallbackData); if (needsGroup) { aContext->PopGroupToSource(); diff --git a/gfx/layers/basic/BasicPaintedLayer.h b/gfx/layers/basic/BasicPaintedLayer.h index 7b29de719d74..ae5d896121ba 100644 --- a/gfx/layers/basic/BasicPaintedLayer.h +++ b/gfx/layers/basic/BasicPaintedLayer.h @@ -112,7 +112,7 @@ protected: BasicManager()->SetTransactionIncomplete(); return; } - aCallback(this, aContext, aExtendedRegionToDraw, &aExtendedRegionToDraw, + aCallback(this, aContext, aExtendedRegionToDraw, aExtendedRegionToDraw, aClip, aRegionToInvalidate, aCallbackData); // Everything that's visible has been validated. Do this instead of just // OR-ing with aRegionToDraw, since that can lead to a very complex region diff --git a/gfx/layers/client/ClientPaintedLayer.cpp b/gfx/layers/client/ClientPaintedLayer.cpp index d67f5ab447af..ac4e60e62a41 100644 --- a/gfx/layers/client/ClientPaintedLayer.cpp +++ b/gfx/layers/client/ClientPaintedLayer.cpp @@ -87,7 +87,7 @@ ClientPaintedLayer::PaintThebes() ClientManager()->GetPaintedLayerCallback()(this, ctx, iter.mDrawRegion, - nullptr, + iter.mDrawRegion, state.mClip, state.mRegionToInvalidate, ClientManager()->GetPaintedLayerCallbackData()); diff --git a/gfx/layers/client/SingleTiledContentClient.cpp b/gfx/layers/client/SingleTiledContentClient.cpp index 7e1ad060a02b..c7a1360ea875 100644 --- a/gfx/layers/client/SingleTiledContentClient.cpp +++ b/gfx/layers/client/SingleTiledContentClient.cpp @@ -181,7 +181,7 @@ ClientSingleTiledLayerBuffer::PaintThebes(const nsIntRegion& aNewValidRegion, nsRefPtr ctx = new gfxContext(dt); ctx->SetMatrix(ctx->CurrentMatrix().Translate(-mTilingOrigin.x, -mTilingOrigin.y)); - aCallback(mPaintedLayer, ctx, paintRegion, &paintRegion, DrawRegionClip::DRAW, nsIntRegion(), aCallbackData); + aCallback(mPaintedLayer, ctx, paintRegion, paintRegion, DrawRegionClip::DRAW, nsIntRegion(), aCallbackData); } // Mark the area we just drew into the back buffer as invalid in the front buffer as they're diff --git a/gfx/layers/client/TiledContentClient.cpp b/gfx/layers/client/TiledContentClient.cpp index b547ed1f08c4..a4c64793c788 100644 --- a/gfx/layers/client/TiledContentClient.cpp +++ b/gfx/layers/client/TiledContentClient.cpp @@ -964,7 +964,7 @@ ClientMultiTiledLayerBuffer::PaintThebes(const nsIntRegion& aNewValidRegion, PROFILER_LABEL("ClientMultiTiledLayerBuffer", "PaintThebesSingleBufferDraw", js::ProfileEntry::Category::GRAPHICS); - mCallback(mPaintedLayer, ctxt, aPaintRegion, &aDirtyRegion, + mCallback(mPaintedLayer, ctxt, aPaintRegion, aDirtyRegion, DrawRegionClip::NONE, nsIntRegion(), mCallbackData); } @@ -1171,7 +1171,7 @@ void ClientMultiTiledLayerBuffer::Update(const nsIntRegion& newValidRegion, ctx->SetMatrix( ctx->CurrentMatrix().Scale(mResolution, mResolution).Translate(ThebesPoint(-mTilingOrigin))); - mCallback(mPaintedLayer, ctx, aPaintRegion, &aDirtyRegion, + mCallback(mPaintedLayer, ctx, aPaintRegion, aDirtyRegion, DrawRegionClip::DRAW, nsIntRegion(), mCallbackData); mMoz2DTiles.clear(); // Reset: diff --git a/layout/base/FrameLayerBuilder.cpp b/layout/base/FrameLayerBuilder.cpp index 53b8091b2d7c..78ff5618c4e9 100644 --- a/layout/base/FrameLayerBuilder.cpp +++ b/layout/base/FrameLayerBuilder.cpp @@ -1420,8 +1420,7 @@ public: mXScale(1.f), mYScale(1.f), mAppUnitsPerDevPixel(0), mTranslation(0, 0), - mAnimatedGeometryRootPosition(0, 0), - mNeedsRecomputeVisibility(false) {} + mAnimatedGeometryRootPosition(0, 0) {} /** * Record the number of clips in the PaintedLayer's mask layer. @@ -1493,10 +1492,12 @@ public: nsRefPtr mColorLayer; nsRefPtr mImageLayer; - // True if the display items for this layer have changed and we need a call - // to RecomputeVisibilityForItems before painting them. This can be false - // during the latter iterations of progressive painting. - bool mNeedsRecomputeVisibility; + // The region for which display item visibility for this layer has already + // been calculated. Used to reduce the number of calls to + // RecomputeVisibilityForItems if it is known in advance that a larger + // region will be painted during a transaction than in a single call to + // DrawPaintedLayer, for example when progressive paint is enabled. + nsIntRegion mVisibilityComputedRegion; }; /* @@ -2339,7 +2340,7 @@ ContainerState::PreparePaintedLayerForUse(PaintedLayer* aLayer, ComputeAndSetIgnoreInvalidationRect(aLayer, aData, aAnimatedGeometryRoot, mBuilder, pixOffset); - aData->mNeedsRecomputeVisibility = true; + aData->mVisibilityComputedRegion.SetEmpty(); // FIXME: Temporary workaround for bug 681192 and bug 724786. #ifndef MOZ_WIDGET_ANDROID @@ -5716,7 +5717,7 @@ static void DrawForcedBackgroundColor(DrawTarget& aDrawTarget, FrameLayerBuilder::DrawPaintedLayer(PaintedLayer* aLayer, gfxContext* aContext, const nsIntRegion& aRegionToDraw, - const nsIntRegion* aDirtyRegion, + const nsIntRegion& aDirtyRegion, DrawRegionClip aClip, const nsIntRegion& aRegionToInvalidate, void* aCallbackData) @@ -5769,21 +5770,18 @@ FrameLayerBuilder::DrawPaintedLayer(PaintedLayer* aLayer, nsIntPoint offset = GetTranslationForPaintedLayer(aLayer); nsPresContext* presContext = entry->mContainerLayerFrame->PresContext(); - if (userData->mNeedsRecomputeVisibility && + if (!userData->mVisibilityComputedRegion.Contains(aDirtyRegion) && !layerBuilder->GetContainingPaintedLayerData()) { - // Recompute visibility of items in our PaintedLayer. Note that this - // recomputes visibility for all descendants of our display items too, - // so there's no need to do this for the items in inactive PaintedLayers. - // If aDirtyRegion is non-null then recompute the visibility of the entire - // aDirtyRegion at once, rather of aRegionToDraw separately on each call. + // Recompute visibility of items in our PaintedLayer, if required. Note + // that this recomputes visibility for all descendants of our display + // items too, so there's no need to do this for the items in inactive + // PaintedLayers. If aDirtyRegion has not changed since the previous call + // then we can skip this. int32_t appUnitsPerDevPixel = presContext->AppUnitsPerDevPixel(); - RecomputeVisibilityForItems(entry->mItems, builder, - aDirtyRegion ? *aDirtyRegion : aRegionToDraw, + RecomputeVisibilityForItems(entry->mItems, builder, aDirtyRegion, offset, appUnitsPerDevPixel, userData->mXScale, userData->mYScale); - if (aDirtyRegion) { - userData->mNeedsRecomputeVisibility = false; - } + userData->mVisibilityComputedRegion = aDirtyRegion; } nsRenderingContext rc(aContext); diff --git a/layout/base/FrameLayerBuilder.h b/layout/base/FrameLayerBuilder.h index 169f5e1755b8..330959e26752 100644 --- a/layout/base/FrameLayerBuilder.h +++ b/layout/base/FrameLayerBuilder.h @@ -282,14 +282,14 @@ public: * must be the nsDisplayListBuilder containing this FrameLayerBuilder. * This function can be called multiple times in a row to draw * different regions. This will occur when, for example, progressive paint is - * enabled. In these cases aDirtyRegion can optionally be used to specify the - * total region that will be drawn during the transaction, possibly allowing - * the callback to make optimizations. + * enabled. In these cases aDirtyRegion can be used to specify a larger region + * than aRegionToDraw that will be drawn during the transaction, possibly + * allowing the callback to make optimizations. */ static void DrawPaintedLayer(PaintedLayer* aLayer, gfxContext* aContext, const nsIntRegion& aRegionToDraw, - const nsIntRegion* aDirtyRegion, + const nsIntRegion& aDirtyRegion, mozilla::layers::DrawRegionClip aClip, const nsIntRegion& aRegionToInvalidate, void* aCallbackData); From 930f7b97f3a2bdb7a00827f44d12d05c91ec5e32 Mon Sep 17 00:00:00 2001 From: Chris Lord Date: Wed, 16 Sep 2015 01:49:00 +0200 Subject: [PATCH 044/113] Bug 1201098 - Consume fling and overscroll velocity per-axis. r=botond --- gfx/layers/apz/src/APZCTreeManager.cpp | 75 +++++++++----- gfx/layers/apz/src/APZCTreeManager.h | 24 ++--- gfx/layers/apz/src/AsyncPanZoomController.cpp | 99 +++++++++++-------- gfx/layers/apz/src/AsyncPanZoomController.h | 30 +++--- gfx/layers/apz/src/OverscrollHandoffState.cpp | 15 +-- 5 files changed, 138 insertions(+), 105 deletions(-) diff --git a/gfx/layers/apz/src/APZCTreeManager.cpp b/gfx/layers/apz/src/APZCTreeManager.cpp index 434f748845a7..17fff4af98d2 100644 --- a/gfx/layers/apz/src/APZCTreeManager.cpp +++ b/gfx/layers/apz/src/APZCTreeManager.cpp @@ -1227,6 +1227,10 @@ TransformDisplacement(APZCTreeManager* aTreeManager, AsyncPanZoomController* aTarget, ParentLayerPoint& aStartPoint, ParentLayerPoint& aEndPoint) { + if (aSource == aTarget) { + return true; + } + // Convert start and end points to Screen coordinates. Matrix4x4 untransformToApzc = aTreeManager->GetScreenToApzcTransform(aSource).Inverse(); ScreenPoint screenStart = TransformTo(untransformToApzc, aStartPoint); @@ -1246,10 +1250,10 @@ TransformDisplacement(APZCTreeManager* aTreeManager, return true; } -bool +void APZCTreeManager::DispatchScroll(AsyncPanZoomController* aPrev, - ParentLayerPoint aStartPoint, - ParentLayerPoint aEndPoint, + ParentLayerPoint& aStartPoint, + ParentLayerPoint& aEndPoint, OverscrollHandoffState& aOverscrollHandoffState) { const OverscrollHandoffChain& overscrollHandoffChain = aOverscrollHandoffState.mChain; @@ -1259,34 +1263,39 @@ APZCTreeManager::DispatchScroll(AsyncPanZoomController* aPrev, // nothing more to scroll, so we ignore the rest of the pan gesture. if (overscrollHandoffChainIndex >= overscrollHandoffChain.Length()) { // Nothing more to scroll - ignore the rest of the pan gesture. - return false; + return; } next = overscrollHandoffChain.GetApzcAtIndex(overscrollHandoffChainIndex); if (next == nullptr || next->IsDestroyed()) { - return false; + return; } // Convert the start and end points from |aPrev|'s coordinate space to - // |next|'s coordinate space. Since |aPrev| may be the same as |next| - // (if |aPrev| is the APZC that is initiating the scroll and there is no - // scroll grabbing to grab the scroll from it), don't bother doing the - // transformations in that case. - if (next != aPrev) { - if (!TransformDisplacement(this, aPrev, next, aStartPoint, aEndPoint)) { - return false; - } + // |next|'s coordinate space. + if (!TransformDisplacement(this, aPrev, next, aStartPoint, aEndPoint)) { + return; } // Scroll |next|. If this causes overscroll, it will call DispatchScroll() // again with an incremented index. - return next->AttemptScroll(aStartPoint, aEndPoint, aOverscrollHandoffState); + if (!next->AttemptScroll(aStartPoint, aEndPoint, aOverscrollHandoffState)) { + // Transform |aStartPoint| and |aEndPoint| (which now represent the + // portion of the displacement that wasn't consumed by APZCs later + // in the handoff chain) back into |aPrev|'s coordinate space. This + // allows the caller (which is |aPrev|) to interpret the unconsumed + // displacement in its own coordinate space, and make use of it + // (e.g. by going into overscroll). + if (!TransformDisplacement(this, next, aPrev, aStartPoint, aEndPoint)) { + NS_WARNING("Failed to untransform scroll points during dispatch"); + } + } } -bool +void APZCTreeManager::DispatchFling(AsyncPanZoomController* aPrev, - ParentLayerPoint aVelocity, + ParentLayerPoint& aVelocity, nsRefPtr aOverscrollHandoffChain, bool aHandoff) { @@ -1303,7 +1312,7 @@ APZCTreeManager::DispatchFling(AsyncPanZoomController* aPrev, // rather than (0, 0). ParentLayerPoint startPoint; // (0, 0) ParentLayerPoint endPoint; - ParentLayerPoint transformedVelocity = aVelocity; + ParentLayerPoint usedTransformedVelocity = aVelocity; if (aHandoff) { startIndex = aOverscrollHandoffChain->IndexOf(aPrev) + 1; @@ -1311,7 +1320,7 @@ APZCTreeManager::DispatchFling(AsyncPanZoomController* aPrev, // IndexOf will return aOverscrollHandoffChain->Length() if // |aPrev| is not found. if (startIndex >= aOverscrollHandoffChainLength) { - return false; + return; } } else { startIndex = 0; @@ -1322,10 +1331,10 @@ APZCTreeManager::DispatchFling(AsyncPanZoomController* aPrev, // Make sure the apcz about to be handled can be handled if (current == nullptr || current->IsDestroyed()) { - return false; + return; } - endPoint = startPoint + transformedVelocity; + endPoint = startPoint + usedTransformedVelocity; // Only transform when current apcz can be transformed with previous if (startIndex > 0) { @@ -1334,20 +1343,34 @@ APZCTreeManager::DispatchFling(AsyncPanZoomController* aPrev, current, startPoint, endPoint)) { - return false; + return; } } - transformedVelocity = endPoint - startPoint; + ParentLayerPoint transformedVelocity = endPoint - startPoint; + usedTransformedVelocity = transformedVelocity; - if (current->AttemptFling(transformedVelocity, + if (current->AttemptFling(usedTransformedVelocity, aOverscrollHandoffChain, aHandoff)) { - return true; + if (IsZero(usedTransformedVelocity)) { + aVelocity = ParentLayerPoint(); + return; + } + + // Subtract the proportion of used velocity from aVelocity + if (!FuzzyEqualsAdditive(transformedVelocity.x, + usedTransformedVelocity.x, COORDINATE_EPSILON)) { + aVelocity.x = aVelocity.x * + (usedTransformedVelocity.x / transformedVelocity.x); + } + if (!FuzzyEqualsAdditive(transformedVelocity.y, + usedTransformedVelocity.y, COORDINATE_EPSILON)) { + aVelocity.y = aVelocity.y * + (usedTransformedVelocity.y / transformedVelocity.y); + } } } - - return false; } bool diff --git a/gfx/layers/apz/src/APZCTreeManager.h b/gfx/layers/apz/src/APZCTreeManager.h index 63b7545ce308..b58c6ab72bf8 100644 --- a/gfx/layers/apz/src/APZCTreeManager.h +++ b/gfx/layers/apz/src/APZCTreeManager.h @@ -327,9 +327,10 @@ public: * |aOverscrollHandoffChainIndex| is the next position in the overscroll * handoff chain that should be scrolled. * - * Returns true iff. some APZC accepted the scroll and scrolled. - * This is to allow the sending APZC to go into an overscrolled state if - * no APZC further up in the handoff chain accepted the overscroll. + * aStartPoint and aEndPoint will be modified depending on how much of the + * scroll each APZC consumes. This is to allow the sending APZC to go into + * an overscrolled state if no APZC further up in the handoff chain accepted + * the entire scroll. * * The way this method works is best illustrated with an example. * Consider three nested APZCs, A, B, and C, with C being the innermost one. @@ -352,9 +353,9 @@ public: * Note: this should be used for panning only. For handing off overscroll for * a fling, use DispatchFling(). */ - bool DispatchScroll(AsyncPanZoomController* aApzc, - ParentLayerPoint aStartPoint, - ParentLayerPoint aEndPoint, + void DispatchScroll(AsyncPanZoomController* aApzc, + ParentLayerPoint& aStartPoint, + ParentLayerPoint& aEndPoint, OverscrollHandoffState& aOverscrollHandoffState); /** @@ -374,12 +375,13 @@ public: * start a fling (in this case the fling is given to the * first APZC in the chain) * - * Returns true iff. an APZC accepted the fling. In the case of fling handoff, - * the caller uses this return value to determine whether it should consume - * the excess fling itself by going into an overscroll fling. + * aVelocity will be modified depending on how much of that velocity has + * been consumed by APZCs in the overscroll hand-off chain. The caller can + * use this value to determine whether it should consume the excess velocity + * by going into an overscroll fling. */ - bool DispatchFling(AsyncPanZoomController* aApzc, - ParentLayerPoint aVelocity, + void DispatchFling(AsyncPanZoomController* aApzc, + ParentLayerPoint& aVelocity, nsRefPtr aOverscrollHandoffChain, bool aHandoff); diff --git a/gfx/layers/apz/src/AsyncPanZoomController.cpp b/gfx/layers/apz/src/AsyncPanZoomController.cpp index ffb60de4f552..6b46b0a7e01e 100644 --- a/gfx/layers/apz/src/AsyncPanZoomController.cpp +++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp @@ -1578,9 +1578,9 @@ nsEventStatus AsyncPanZoomController::OnScrollWheel(const ScrollWheelInput& aEve *mInputQueue->CurrentWheelBlock()->GetOverscrollHandoffChain(), distance, ScrollSource::Wheel); - CallDispatchScroll(aEvent.mLocalOrigin, - aEvent.mLocalOrigin - delta, - handoffState); + ParentLayerPoint startPoint = aEvent.mLocalOrigin; + ParentLayerPoint endPoint = aEvent.mLocalOrigin - delta; + CallDispatchScroll(startPoint, endPoint, handoffState); SetState(NOTHING); RequestContentRepaint(); @@ -1726,9 +1726,9 @@ nsEventStatus AsyncPanZoomController::OnPan(const PanGestureInput& aEvent, bool *CurrentPanGestureBlock()->GetOverscrollHandoffChain(), panDistance, ScrollSource::Wheel); - CallDispatchScroll(aEvent.mLocalPanStartPoint, - aEvent.mLocalPanStartPoint + aEvent.mLocalPanDisplacement, - handoffState); + ParentLayerPoint startPoint = aEvent.mLocalPanStartPoint; + ParentLayerPoint endPoint = aEvent.mLocalPanStartPoint + aEvent.mLocalPanDisplacement; + CallDispatchScroll(startPoint, endPoint, handoffState); return nsEventStatus_eConsumeNoDefault; } @@ -2067,8 +2067,8 @@ void AsyncPanZoomController::UpdateWithTouchAtDevicePoint(const MultiTouchInput& mY.UpdateWithTouchAtDevicePoint(point.y, 0, aEvent.mTime); } -bool AsyncPanZoomController::AttemptScroll(const ParentLayerPoint& aStartPoint, - const ParentLayerPoint& aEndPoint, +bool AsyncPanZoomController::AttemptScroll(ParentLayerPoint& aStartPoint, + ParentLayerPoint& aEndPoint, OverscrollHandoffState& aOverscrollHandoffState) { // "start - end" rather than "end - start" because e.g. moving your finger @@ -2099,6 +2099,9 @@ bool AsyncPanZoomController::AttemptScroll(const ParentLayerPoint& aStartPoint, } } + // Adjust the start point to reflect the consumed portion of the scroll. + aStartPoint = aEndPoint + overscroll; + // If we consumed the entire displacement as a normal scroll, great. if (IsZero(overscroll)) { return true; @@ -2111,8 +2114,10 @@ bool AsyncPanZoomController::AttemptScroll(const ParentLayerPoint& aStartPoint, // Note: "+ overscroll" rather than "- overscroll" because "overscroll" // is what's left of "displacement", and "displacement" is "start - end". ++aOverscrollHandoffState.mChainIndex; - if (CallDispatchScroll(aEndPoint + overscroll, aEndPoint, - aOverscrollHandoffState)) { + CallDispatchScroll(aStartPoint, aEndPoint, aOverscrollHandoffState); + + overscroll = aStartPoint - aEndPoint; + if (IsZero(overscroll)) { return true; } } @@ -2121,10 +2126,13 @@ bool AsyncPanZoomController::AttemptScroll(const ParentLayerPoint& aStartPoint, // overscroll, try to accept it ourselves. We only accept it if we // are pannable. APZC_LOG("%p taking overscroll during panning\n", this); - return OverscrollForPanning(overscroll, aOverscrollHandoffState.mPanDistance); + OverscrollForPanning(overscroll, aOverscrollHandoffState.mPanDistance); + aStartPoint = aEndPoint + overscroll; + + return IsZero(overscroll); } -bool AsyncPanZoomController::OverscrollForPanning(ParentLayerPoint aOverscroll, +void AsyncPanZoomController::OverscrollForPanning(ParentLayerPoint& aOverscroll, const ScreenPoint& aPanDistance) { // Only allow entering overscroll along an axis if the pan distance along // that axis is greater than the pan distance along the other axis by a @@ -2138,12 +2146,12 @@ bool AsyncPanZoomController::OverscrollForPanning(ParentLayerPoint aOverscroll, } } - return OverscrollBy(aOverscroll); + OverscrollBy(aOverscroll); } -bool AsyncPanZoomController::OverscrollBy(const ParentLayerPoint& aOverscroll) { +void AsyncPanZoomController::OverscrollBy(ParentLayerPoint& aOverscroll) { if (!gfxPrefs::APZOverscrollEnabled()) { - return false; + return; } ReentrantMonitorAutoEnter lock(mMonitor); @@ -2151,19 +2159,24 @@ bool AsyncPanZoomController::OverscrollBy(const ParentLayerPoint& aOverscroll) { // scroll to begin with. bool xCanScroll = mX.CanScroll(); bool yCanScroll = mY.CanScroll(); - if (xCanScroll) { + + bool xConsumed = FuzzyEqualsAdditive(aOverscroll.x, 0.0f, COORDINATE_EPSILON); + if (xCanScroll && !xConsumed) { mX.OverscrollBy(aOverscroll.x); + aOverscroll.x = 0; + xConsumed = true; } - if (yCanScroll) { + + bool yConsumed = FuzzyEqualsAdditive(aOverscroll.y, 0.0f, COORDINATE_EPSILON); + if (yCanScroll && !yConsumed) { mY.OverscrollBy(aOverscroll.y); + aOverscroll.y = 0; + yConsumed = true; } - if (xCanScroll || yCanScroll) { + + if ((xCanScroll && xConsumed) || (yCanScroll && yConsumed)) { ScheduleComposite(); - return true; } - // TODO(botond): If one of the x- or y-overscroll was not accepted, we - // may want to propagate that one to an APZC earlier in the handoff chain. - return false; } nsRefPtr AsyncPanZoomController::BuildOverscrollHandoffChain() { @@ -2178,14 +2191,22 @@ nsRefPtr AsyncPanZoomController::BuildOverscrollHa return result; } -void AsyncPanZoomController::AcceptFling(const ParentLayerPoint& aVelocity, +void AsyncPanZoomController::AcceptFling(ParentLayerPoint& aVelocity, const nsRefPtr& aOverscrollHandoffChain, bool aHandoff) { + ReentrantMonitorAutoEnter lock(mMonitor); + // We may have a pre-existing velocity for whatever reason (for example, // a previously handed off fling). We don't want to clobber that. APZC_LOG("%p accepting fling with velocity %s\n", this, Stringify(aVelocity).c_str()); - mX.SetVelocity(mX.GetVelocity() + aVelocity.x); - mY.SetVelocity(mY.GetVelocity() + aVelocity.y); + if (mX.CanScroll()) { + mX.SetVelocity(mX.GetVelocity() + aVelocity.x); + aVelocity.x = 0; + } + if (mY.CanScroll()) { + mY.SetVelocity(mY.GetVelocity() + aVelocity.y); + aVelocity.y = 0; + } SetState(FLING); FlingAnimation *fling = new FlingAnimation(*this, aOverscrollHandoffChain, @@ -2227,7 +2248,7 @@ void AsyncPanZoomController::AcceptFling(const ParentLayerPoint& aVelocity, StartAnimation(fling); } -bool AsyncPanZoomController::AttemptFling(ParentLayerPoint aVelocity, +bool AsyncPanZoomController::AttemptFling(ParentLayerPoint& aVelocity, const nsRefPtr& aOverscrollHandoffChain, bool aHandoff) { // If we are pannable, take over the fling ourselves. @@ -2244,14 +2265,12 @@ bool AsyncPanZoomController::AttemptFling(ParentLayerPoint aVelocity, void AsyncPanZoomController::HandleFlingOverscroll(const ParentLayerPoint& aVelocity, const nsRefPtr& aOverscrollHandoffChain) { APZCTreeManager* treeManagerLocal = GetApzcTreeManager(); - if (!(treeManagerLocal && treeManagerLocal->DispatchFling(this, - aVelocity, - aOverscrollHandoffChain, - true /* handoff */))) { - // No one wanted the fling, so we "take it" ourselves by entering an - // overscroll animation starting with the fling's velocity. - if (IsPannable() && gfxPrefs::APZOverscrollEnabled()) { - StartOverscrollAnimation(aVelocity); + ParentLayerPoint velocity = aVelocity; + if (treeManagerLocal) { + treeManagerLocal->DispatchFling(this, velocity, aOverscrollHandoffChain, + true /* handoff */); + if (!IsZero(velocity) && IsPannable() && gfxPrefs::APZOverscrollEnabled()) { + StartOverscrollAnimation(velocity); } } } @@ -2284,19 +2303,19 @@ void AsyncPanZoomController::StartOverscrollAnimation(const ParentLayerPoint& aV StartAnimation(new OverscrollAnimation(*this, aVelocity)); } -bool AsyncPanZoomController::CallDispatchScroll(const ParentLayerPoint& aStartPoint, - const ParentLayerPoint& aEndPoint, +void AsyncPanZoomController::CallDispatchScroll(ParentLayerPoint& aStartPoint, + ParentLayerPoint& aEndPoint, OverscrollHandoffState& aOverscrollHandoffState) { // Make a local copy of the tree manager pointer and check if it's not // null before calling DispatchScroll(). This is necessary because // Destroy(), which nulls out mTreeManager, could be called concurrently. APZCTreeManager* treeManagerLocal = GetApzcTreeManager(); if (!treeManagerLocal) { - return false; + return; } - return treeManagerLocal->DispatchScroll(this, - aStartPoint, aEndPoint, - aOverscrollHandoffState); + treeManagerLocal->DispatchScroll(this, + aStartPoint, aEndPoint, + aOverscrollHandoffState); } void AsyncPanZoomController::TrackTouch(const MultiTouchInput& aEvent) { diff --git a/gfx/layers/apz/src/AsyncPanZoomController.h b/gfx/layers/apz/src/AsyncPanZoomController.h index 9dcaaf93886c..88058a047d52 100644 --- a/gfx/layers/apz/src/AsyncPanZoomController.h +++ b/gfx/layers/apz/src/AsyncPanZoomController.h @@ -855,15 +855,16 @@ private: */ public: /** - * Attempt a fling with the given velocity. If we are not pannable, tehe fling + * Attempt a fling with the given velocity. If we are not pannable, the fling * is handed off to the next APZC in the handoff chain via - * mTreeManager->DspatchFling(). Returns true iff. any APZC (whether this - * one or one further in the handoff chain) accepted the fling. + * mTreeManager->DispatchFling(). Returns true iff. the entire velocity of + * the fling was consumed by this APZC. aVelocity is modified to contain any + * unused, residual velocity. * |aHandoff| should be true iff. the fling was handed off from a previous * APZC, and determines whether acceleration is applied to the * fling. */ - bool AttemptFling(ParentLayerPoint aVelocity, + bool AttemptFling(ParentLayerPoint& aVelocity, const nsRefPtr& aOverscrollHandoffChain, bool aHandoff); @@ -889,7 +890,7 @@ private: void HandleSmoothScrollOverscroll(const ParentLayerPoint& aVelocity); // Helper function used by TakeOverFling() and HandleFlingOverscroll(). - void AcceptFling(const ParentLayerPoint& aVelocity, + void AcceptFling(ParentLayerPoint& aVelocity, const nsRefPtr& aOverscrollHandoffChain, bool aHandoff); @@ -967,9 +968,11 @@ public: * handoff chain, accepted the scroll (possibly entering an overscrolled * state). If this returns false, the caller APZC knows that it should enter * an overscrolled state itself if it can. + * aStartPoint and aEndPoint are modified depending on how much of the + * scroll gesture was consumed by APZCs in the handoff chain. */ - bool AttemptScroll(const ParentLayerPoint& aStartPoint, - const ParentLayerPoint& aEndPoint, + bool AttemptScroll(ParentLayerPoint& aStartPoint, + ParentLayerPoint& aEndPoint, OverscrollHandoffState& aOverscrollHandoffState); void FlushRepaintForOverscrollHandoff(); @@ -1007,8 +1010,8 @@ private: * Guards against the case where the APZC is being concurrently destroyed * (and thus mTreeManager is being nulled out). */ - bool CallDispatchScroll(const ParentLayerPoint& aStartPoint, - const ParentLayerPoint& aEndPoint, + void CallDispatchScroll(ParentLayerPoint& aStartPoint, + ParentLayerPoint& aEndPoint, OverscrollHandoffState& aOverscrollHandoffState); /** @@ -1016,16 +1019,15 @@ private: * around OverscrollBy() that also implements restrictions on entering * overscroll based on the pan angle. */ - bool OverscrollForPanning(ParentLayerPoint aOverscroll, + void OverscrollForPanning(ParentLayerPoint& aOverscroll, const ScreenPoint& aPanDistance); /** * Try to overscroll by 'aOverscroll'. - * If we are pannable, 'aOverscroll' is added to any existing overscroll, - * and the function returns true. - * Otherwise, nothing happens and the function return false. + * If we are pannable on a particular axis, that component of 'aOverscroll' + * is transferred to any existing overscroll. */ - bool OverscrollBy(const ParentLayerPoint& aOverscroll); + void OverscrollBy(ParentLayerPoint& aOverscroll); /* =================================================================== diff --git a/gfx/layers/apz/src/OverscrollHandoffState.cpp b/gfx/layers/apz/src/OverscrollHandoffState.cpp index 0b834dd2ff49..8bcce1d2e167 100644 --- a/gfx/layers/apz/src/OverscrollHandoffState.cpp +++ b/gfx/layers/apz/src/OverscrollHandoffState.cpp @@ -105,25 +105,12 @@ void OverscrollHandoffChain::SnapBackOverscrolledApzc(const AsyncPanZoomController* aStart) const { uint32_t i = IndexOf(aStart); - for (; i < Length(); ++i) { - AsyncPanZoomController* apzc = mChain[i]; - if (!apzc->IsDestroyed() && apzc->SnapBackIfOverscrolled()) { - // At most one APZC from |aStart| onwards can be overscrolled. - break; - } - } - - // In debug builds, verify our assumption that only one APZC from |aStart| - // onwards is overscrolled. -#ifdef DEBUG - ++i; for (; i < Length(); ++i) { AsyncPanZoomController* apzc = mChain[i]; if (!apzc->IsDestroyed()) { - MOZ_ASSERT(!apzc->IsOverscrolled()); + apzc->SnapBackIfOverscrolled(); } } -#endif } bool From 8e7eb5231c7f59396d65c11f2a6f2c402fc5454d Mon Sep 17 00:00:00 2001 From: "Nils Ohlmeier [:drno]" Date: Wed, 16 Sep 2015 13:42:57 -0700 Subject: [PATCH 045/113] Bug 1205421 - fix DNS resolution of STUN server in ice_unittest. r=bwc --HG-- extra : transplant_source : %CA%C8M%F6%8DrK%8D%113%C9%D512C%96%06%B8%86o --- media/mtransport/test/ice_unittest.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/media/mtransport/test/ice_unittest.cpp b/media/mtransport/test/ice_unittest.cpp index f0a2428eff6f..ac337c422c29 100644 --- a/media/mtransport/test/ice_unittest.cpp +++ b/media/mtransport/test/ice_unittest.cpp @@ -3080,12 +3080,14 @@ Resolve(const std::string& fqdn, int address_family) &reinterpret_cast(res->ai_addr)->sin_addr, str_addr, sizeof(str_addr)); + break; case AF_INET6: inet_ntop( AF_INET6, &reinterpret_cast(res->ai_addr)->sin6_addr, str_addr, sizeof(str_addr)); + break; default: std::cerr << "Got unexpected address family in DNS lookup: " << res->ai_family << std::endl; From 07467bcbc8a62c2e546961fd5bcc94b0a6505b04 Mon Sep 17 00:00:00 2001 From: Chris Lord Date: Mon, 14 Sep 2015 07:40:00 +0200 Subject: [PATCH 046/113] Bug 1201101 - Enable axis-locking over multiple APZCs. r=botond --- gfx/layers/apz/src/AsyncPanZoomController.cpp | 14 +++++++++++--- gfx/layers/apz/src/Axis.cpp | 4 ++++ gfx/layers/apz/src/Axis.h | 5 +++++ 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/gfx/layers/apz/src/AsyncPanZoomController.cpp b/gfx/layers/apz/src/AsyncPanZoomController.cpp index 6b46b0a7e01e..67ce4a570dcf 100644 --- a/gfx/layers/apz/src/AsyncPanZoomController.cpp +++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp @@ -1983,11 +1983,19 @@ void AsyncPanZoomController::HandlePanningWithTouchAction(double aAngle) { void AsyncPanZoomController::HandlePanning(double aAngle) { ReentrantMonitorAutoEnter lock(mMonitor); - if (!gfxPrefs::APZCrossSlideEnabled() && (!mX.CanScrollNow() || !mY.CanScrollNow())) { + nsRefPtr overscrollHandoffChain = + GetInputQueue()->CurrentBlock()->GetOverscrollHandoffChain(); + bool canScrollHorizontal = !mX.IsAxisLocked() && + overscrollHandoffChain->CanScrollInDirection(this, Layer::HORIZONTAL); + bool canScrollVertical = !mY.IsAxisLocked() && + overscrollHandoffChain->CanScrollInDirection(this, Layer::VERTICAL); + + if (!gfxPrefs::APZCrossSlideEnabled() && + (!canScrollHorizontal || !canScrollVertical)) { SetState(PANNING); } else if (IsCloseToHorizontal(aAngle, gfxPrefs::APZAxisLockAngle())) { mY.SetAxisLocked(true); - if (mX.CanScrollNow()) { + if (canScrollHorizontal) { SetState(PANNING_LOCKED_X); } else { SetState(CROSS_SLIDING_X); @@ -1995,7 +2003,7 @@ void AsyncPanZoomController::HandlePanning(double aAngle) { } } else if (IsCloseToVertical(aAngle, gfxPrefs::APZAxisLockAngle())) { mX.SetAxisLocked(true); - if (mY.CanScrollNow()) { + if (canScrollVertical) { SetState(PANNING_LOCKED_Y); } else { SetState(CROSS_SLIDING_Y); diff --git a/gfx/layers/apz/src/Axis.cpp b/gfx/layers/apz/src/Axis.cpp index 59ed88092a67..1684016125d4 100644 --- a/gfx/layers/apz/src/Axis.cpp +++ b/gfx/layers/apz/src/Axis.cpp @@ -510,6 +510,10 @@ CSSCoord Axis::ScaleWillOverscrollAmount(float aScale, CSSCoord aFocus) const { return 0; } +bool Axis::IsAxisLocked() const { + return mAxisLocked; +} + float Axis::GetVelocity() const { return mAxisLocked ? 0 : mVelocity; } diff --git a/gfx/layers/apz/src/Axis.h b/gfx/layers/apz/src/Axis.h index cee381d86f50..2294510f7b36 100644 --- a/gfx/layers/apz/src/Axis.h +++ b/gfx/layers/apz/src/Axis.h @@ -223,6 +223,11 @@ public: */ bool ScaleWillOverscrollBothSides(float aScale) const; + /** + * Returns true if movement on this axis is locked. + */ + bool IsAxisLocked() const; + ParentLayerCoord GetOrigin() const; ParentLayerCoord GetCompositionLength() const; ParentLayerCoord GetPageStart() const; From 28d24ea24ff10e9252c6937a5680e289da211429 Mon Sep 17 00:00:00 2001 From: Tim Chien Date: Wed, 16 Sep 2015 22:11:00 +0200 Subject: [PATCH 047/113] Bug 1201407 - Add input-manage-only events for InputMethod API, r=janjongboom, sr=smaug --- dom/inputmethod/Keyboard.jsm | 93 +++++- dom/inputmethod/MozKeyboard.js | 290 +++++++++++++++++- dom/inputmethod/forms.js | 2 + ...putmethod_1043828.html => file_blank.html} | 0 dom/inputmethod/mochitest/mochitest.ini | 5 +- .../mochitest/test_bug1043828.html | 2 +- .../test_focus_blur_manage_events.html | 230 ++++++++++++++ .../mochitest/test_input_registry_events.html | 259 ++++++++++++++++ .../mochitest/test_simple_manage_events.html | 164 ++++++++++ dom/webidl/InputMethod.webidl | 167 +++++++++- 10 files changed, 1185 insertions(+), 27 deletions(-) rename dom/inputmethod/mochitest/{file_inputmethod_1043828.html => file_blank.html} (100%) create mode 100644 dom/inputmethod/mochitest/test_focus_blur_manage_events.html create mode 100644 dom/inputmethod/mochitest/test_input_registry_events.html create mode 100644 dom/inputmethod/mochitest/test_simple_manage_events.html diff --git a/dom/inputmethod/Keyboard.jsm b/dom/inputmethod/Keyboard.jsm index 177c49200b6e..84d8db1c920a 100644 --- a/dom/inputmethod/Keyboard.jsm +++ b/dom/inputmethod/Keyboard.jsm @@ -45,10 +45,12 @@ this.Keyboard = { _keyboardMM: null, // The keyboard app message manager. _keyboardID: -1, // The keyboard app's ID number. -1 = invalid _nextKeyboardID: 0, // The ID number counter. + _systemMMs: [], // The message managers registered to handle system async + // messages. _supportsSwitchingTypes: [], _systemMessageNames: [ 'SetValue', 'RemoveFocus', 'SetSelectedOption', 'SetSelectedOptions', - 'SetSupportsSwitchingTypes' + 'SetSupportsSwitchingTypes', 'RegisterSync', 'Unregister' ], _messageNames: [ @@ -57,7 +59,7 @@ this.Keyboard = { 'SwitchToNextInputMethod', 'HideInputMethod', 'GetText', 'SendKey', 'GetContext', 'SetComposition', 'EndComposition', - 'Register', 'Unregister' + 'RegisterSync', 'Unregister' ], get formMM() { @@ -89,6 +91,20 @@ this.Keyboard = { } catch(e) { } }, + sendToSystem: function(name, data) { + if (!this._systemMMs.length) { + dump("Keyboard.jsm: Attempt to send message " + name + + " to system but no message manager registered.\n"); + + return; + } + + this._systemMMs.forEach((mm, i) => { + data.inputManageId = i; + mm.sendAsyncMessage(name, data); + }); + }, + init: function keyboardInit() { Services.obs.addObserver(this, 'inprocess-browser-shown', false); Services.obs.addObserver(this, 'remote-browser-shown', false); @@ -124,10 +140,14 @@ this.Keyboard = { // keyboard app that the focus has been lost. this.sendToKeyboard('Keyboard:Blur', {}); // Notify system app to hide keyboard. + this.sendToSystem('System:Blur', {}); + // XXX: To be removed when content migrate away from mozChromeEvents. SystemAppProxy.dispatchEvent({ type: 'inputmethod-contextchange', inputType: 'blur' }); + + this.formMM = null; } } else { // Ignore notifications that aren't from a BrowserOrApp @@ -193,7 +213,7 @@ this.Keyboard = { } if (0 === msg.name.indexOf('Keyboard:') && - ('Keyboard:Register' !== msg.name && this._keyboardID !== kbID) + ('Keyboard:RegisterSync' !== msg.name && this._keyboardID !== kbID) ) { return; } @@ -228,6 +248,24 @@ this.Keyboard = { case 'Keyboard:RemoveFocus': case 'System:RemoveFocus': this.removeFocus(); + break; + case 'System:RegisterSync': { + if (this._systemMMs.length !== 0) { + dump('Keyboard.jsm Warning: There are more than one content page ' + + 'with input-manage permission. There will be undeterministic ' + + 'responses to addInput()/removeInput() if both content pages are ' + + 'trying to respond to the same request event.\n'); + } + + let id = this._systemMMs.length; + this._systemMMs.push(mm); + + return id; + } + + case 'System:Unregister': + this._systemMMs.splice(msg.data.id, 1); + break; case 'System:SetSelectedOption': this.setSelectedOption(msg); @@ -265,7 +303,7 @@ this.Keyboard = { case 'Keyboard:EndComposition': this.endComposition(msg); break; - case 'Keyboard:Register': + case 'Keyboard:RegisterSync': this._keyboardMM = mm; if (kbID) { // keyboard identifies itself, use its kbID @@ -293,10 +331,14 @@ this.Keyboard = { .frameLoader.messageManager; this.formMM = mm; + // Notify the current active input app to gain focus. this.forwardEvent('Keyboard:Focus', msg); - // Chrome event, used also to render value selectors; that's why we need - // the info about choices / min / max here as well... + // Notify System app, used also to render value selectors for now; + // that's why we need the info about choices / min / max here as well... + this.sendToSystem('System:Focus', msg.data); + + // XXX: To be removed when content migrate away from mozChromeEvents. SystemAppProxy.dispatchEvent({ type: 'inputmethod-contextchange', inputType: msg.data.inputType, @@ -322,7 +364,9 @@ this.Keyboard = { this.formMM = null; this.forwardEvent('Keyboard:Blur', msg); + this.sendToSystem('System:Blur', {}); + // XXX: To be removed when content migrate away from mozChromeEvents. SystemAppProxy.dispatchEvent({ type: 'inputmethod-contextchange', inputType: 'blur' @@ -362,12 +406,18 @@ this.Keyboard = { }, showInputMethodPicker: function keyboardShowInputMethodPicker() { + this.sendToSystem('System:ShowAll', {}); + + // XXX: To be removed with mozContentEvent support from shell.js SystemAppProxy.dispatchEvent({ type: "inputmethod-showall" }); }, switchToNextInputMethod: function keyboardSwitchToNextInputMethod() { + this.sendToSystem('System:Next', {}); + + // XXX: To be removed with mozContentEvent support from shell.js SystemAppProxy.dispatchEvent({ type: "inputmethod-next" }); @@ -432,14 +482,17 @@ function InputRegistryGlue() { ppmm.addMessageListener('InputRegistry:Add', this); ppmm.addMessageListener('InputRegistry:Remove', this); + ppmm.addMessageListener('System:InputRegistry:Add:Done', this); + ppmm.addMessageListener('System:InputRegistry:Remove:Done', this); }; InputRegistryGlue.prototype.receiveMessage = function(msg) { let mm = Utils.getMMFromMessage(msg); - if (!Utils.checkPermissionForMM(mm, 'input')) { + let permName = msg.name.startsWith("System:") ? "input-mgmt" : "input"; + if (!Utils.checkPermissionForMM(mm, permName)) { dump("InputRegistryGlue message " + msg.name + - " from a content process with no 'input' privileges."); + " from a content process with no " + permName + " privileges."); return; } @@ -452,6 +505,12 @@ InputRegistryGlue.prototype.receiveMessage = function(msg) { case 'InputRegistry:Remove': this.removeInput(msg, mm); + break; + + case 'System:InputRegistry:Add:Done': + case 'System:InputRegistry:Remove:Done': + this.returnMessage(msg.data); + break; } }; @@ -465,6 +524,14 @@ InputRegistryGlue.prototype.addInput = function(msg, mm) { let manifestURL = appsService.getManifestURLByLocalId(msg.data.appId); + Keyboard.sendToSystem('System:InputRegistry:Add', { + id: msgId, + manifestURL: manifestURL, + inputId: msg.data.inputId, + inputManifest: msg.data.inputManifest + }); + + // XXX: To be removed when content migrate away from mozChromeEvents. SystemAppProxy.dispatchEvent({ type: 'inputregistry-add', id: msgId, @@ -483,6 +550,13 @@ InputRegistryGlue.prototype.removeInput = function(msg, mm) { let manifestURL = appsService.getManifestURLByLocalId(msg.data.appId); + Keyboard.sendToSystem('System:InputRegistry:Remove', { + id: msgId, + manifestURL: manifestURL, + inputId: msg.data.inputId + }); + + // XXX: To be removed when content migrate away from mozChromeEvents. SystemAppProxy.dispatchEvent({ type: 'inputregistry-remove', id: msgId, @@ -493,6 +567,8 @@ InputRegistryGlue.prototype.removeInput = function(msg, mm) { InputRegistryGlue.prototype.returnMessage = function(detail) { if (!this._msgMap.has(detail.id)) { + dump('InputRegistryGlue: Ignoring already handled message response. ' + + 'id=' + detail.id + '\n'); return; } @@ -500,6 +576,7 @@ InputRegistryGlue.prototype.returnMessage = function(detail) { this._msgMap.delete(detail.id); if (Cu.isDeadWrapper(mm)) { + dump('InputRegistryGlue: Message manager has already died.\n'); return; } diff --git a/dom/inputmethod/MozKeyboard.js b/dom/inputmethod/MozKeyboard.js index 7f6c7e7a5d23..1a740b930a7c 100644 --- a/dom/inputmethod/MozKeyboard.js +++ b/dom/inputmethod/MozKeyboard.js @@ -7,6 +7,7 @@ const Cc = Components.classes; const Ci = Components.interfaces; const Cu = Components.utils; +const Cr = Components.results; Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/Services.jsm"); @@ -143,6 +144,54 @@ MozInputMethodManager.prototype = { QueryInterface: XPCOMUtils.generateQI([]), + set oninputcontextfocus(handler) { + this.__DOM_IMPL__.setEventHandler("oninputcontextfocus", handler); + }, + + get oninputcontextfocus() { + return this.__DOM_IMPL__.getEventHandler("oninputcontextfocus"); + }, + + set oninputcontextblur(handler) { + this.__DOM_IMPL__.setEventHandler("oninputcontextblur", handler); + }, + + get oninputcontextblur() { + return this.__DOM_IMPL__.getEventHandler("oninputcontextblur"); + }, + + set onshowallrequest(handler) { + this.__DOM_IMPL__.setEventHandler("onshowallrequest", handler); + }, + + get onshowallrequest() { + return this.__DOM_IMPL__.getEventHandler("onshowallrequest"); + }, + + set onnextrequest(handler) { + this.__DOM_IMPL__.setEventHandler("onnextrequest", handler); + }, + + get onnextrequest() { + return this.__DOM_IMPL__.getEventHandler("onnextrequest"); + }, + + set onaddinputrequest(handler) { + this.__DOM_IMPL__.setEventHandler("onaddinputrequest", handler); + }, + + get onaddinputrequest() { + return this.__DOM_IMPL__.getEventHandler("onaddinputrequest"); + }, + + set onremoveinputrequest(handler) { + this.__DOM_IMPL__.setEventHandler("onremoveinputrequest", handler); + }, + + get onremoveinputrequest() { + return this.__DOM_IMPL__.getEventHandler("onremoveinputrequest"); + }, + showAll: function() { if (!WindowMap.isActive(this._window)) { return; @@ -175,6 +224,169 @@ MozInputMethodManager.prototype = { cpmm.sendAsyncMessage('System:SetSupportsSwitchingTypes', { types: types }); + }, + + handleFocus: function(data) { + let detail = new MozInputContextFocusEventDetail(this._window, data); + let wrappedDetail = + this._window.MozInputContextFocusEventDetail._create(this._window, detail); + let event = new this._window.CustomEvent('inputcontextfocus', + { cancelable: true, detail: wrappedDetail }); + + let handled = !this.__DOM_IMPL__.dispatchEvent(event); + + // A gentle warning if the event is not preventDefault() by the content. + if (!handled) { + dump('MozKeyboard.js: A frame with input-manage permission did not' + + ' handle the inputcontextfocus event dispatched.\n'); + } + }, + + handleBlur: function(data) { + let event = + new this._window.Event('inputcontextblur', { cancelable: true }); + + let handled = !this.__DOM_IMPL__.dispatchEvent(event); + + // A gentle warning if the event is not preventDefault() by the content. + if (!handled) { + dump('MozKeyboard.js: A frame with input-manage permission did not' + + ' handle the inputcontextblur event dispatched.\n'); + } + }, + + dispatchShowAllRequestEvent: function() { + this._fireSimpleEvent('showallrequest'); + }, + + dispatchNextRequestEvent: function() { + this._fireSimpleEvent('nextrequest'); + }, + + _fireSimpleEvent: function(eventType) { + let event = new this._window.Event(eventType); + let handled = !this.__DOM_IMPL__.dispatchEvent(event, { cancelable: true }); + + // A gentle warning if the event is not preventDefault() by the content. + if (!handled) { + dump('MozKeyboard.js: A frame with input-manage permission did not' + + ' handle the ' + eventType + ' event dispatched.\n'); + } + }, + + handleAddInput: function(data) { + let p = this._fireInputRegistryEvent('addinputrequest', data); + if (!p) { + return; + } + + p.then(() => { + cpmm.sendAsyncMessage('System:InputRegistry:Add:Done', { + id: data.id + }); + }, (error) => { + cpmm.sendAsyncMessage('System:InputRegistry:Add:Done', { + id: data.id, + error: error || 'Unknown Error' + }); + }); + }, + + handleRemoveInput: function(data) { + let p = this._fireInputRegistryEvent('removeinputrequest', data); + if (!p) { + return; + } + + p.then(() => { + cpmm.sendAsyncMessage('System:InputRegistry:Remove:Done', { + id: data.id + }); + }, (error) => { + cpmm.sendAsyncMessage('System:InputRegistry:Remove:Done', { + id: data.id, + error: error || 'Unknown Error' + }); + }); + }, + + _fireInputRegistryEvent: function(eventType, data) { + let detail = new MozInputRegistryEventDetail(this._window, data); + let wrappedDetail = + this._window.MozInputRegistryEventDetail._create(this._window, detail); + let event = new this._window.CustomEvent(eventType, + { cancelable: true, detail: wrappedDetail }); + let handled = !this.__DOM_IMPL__.dispatchEvent(event); + + // A gentle warning if the event is not preventDefault() by the content. + if (!handled) { + dump('MozKeyboard.js: A frame with input-manage permission did not' + + ' handle the ' + eventType + ' event dispatched.\n'); + + return null; + } + return detail.takeChainedPromise(); + } +}; + +function MozInputContextFocusEventDetail(win, data) { + this.type = data.type; + this.inputType = data.inputType; + this.value = data.value; + // Exposed as MozInputContextChoicesInfo dictionary defined in WebIDL + this.choices = data.choices; + this.min = data.min; + this.max = data.max; +} +MozInputContextFocusEventDetail.prototype = { + classID: Components.ID("{e0794208-ac50-40e8-b22e-6ee0b4c4e6e8}"), + QueryInterface: XPCOMUtils.generateQI([]), + + type: undefined, + inputType: undefined, + value: '', + choices: null, + min: undefined, + max: undefined +}; + +function MozInputRegistryEventDetail(win, data) { + this._window = win; + + this.manifestURL = data.manifestURL; + this.inputId = data.inputId; + // Exposed as MozInputMethodInputManifest dictionary defined in WebIDL + this.inputManifest = data.inputManifest; + + this._chainedPromise = Promise.resolve(); +} +MozInputRegistryEventDetail.prototype = { + classID: Components.ID("{02130070-9b3e-4f38-bbd9-f0013aa36717}"), + QueryInterface: XPCOMUtils.generateQI([]), + + _window: null, + + manifestURL: undefined, + inputId: undefined, + inputManifest: null, + + waitUntil: function(p) { + // Need an extra protection here since waitUntil will be an no-op + // when chainedPromise is already returned. + if (!this._chainedPromise) { + throw new this._window.DOMException( + 'Must call waitUntil() within the event handling loop.', + 'InvalidStateError'); + } + + this._chainedPromise = this._chainedPromise + .then(function() { return p; }); + }, + + takeChainedPromise: function() { + var p = this._chainedPromise; + this._chainedPromise = null; + return p; } }; @@ -188,10 +400,13 @@ function MozInputMethod() { } MozInputMethod.prototype = { __proto__: DOMRequestIpcHelper.prototype, + _window: null, _inputcontext: null, _wrappedInputContext: null, + _mgmt: null, + _wrappedMgmt: null, _supportsSwitchingTypes: [], - _window: null, + _inputManageId: undefined, classID: Components.ID("{4607330d-e7d2-40a4-9eb8-43967eae0142}"), @@ -204,6 +419,7 @@ MozInputMethod.prototype = { init: function mozInputMethodInit(win) { this._window = win; this._mgmt = new MozInputMethodManager(win); + this._wrappedMgmt = win.MozInputMethodManager._create(win, this._mgmt); this.innerWindowID = win.QueryInterface(Ci.nsIInterfaceRequestor) .getInterface(Ci.nsIDOMWindowUtils) .currentInnerWindowID; @@ -217,11 +433,22 @@ MozInputMethod.prototype = { cpmm.addWeakMessageListener('Keyboard:SupportsSwitchingTypesChange', this); cpmm.addWeakMessageListener('InputRegistry:Result:OK', this); cpmm.addWeakMessageListener('InputRegistry:Result:Error', this); + + if (this._hasInputManagePerm(win)) { + this._inputManageId = cpmm.sendSyncMessage('System:RegisterSync', {})[0]; + cpmm.addWeakMessageListener('System:Focus', this); + cpmm.addWeakMessageListener('System:Blur', this); + cpmm.addWeakMessageListener('System:ShowAll', this); + cpmm.addWeakMessageListener('System:Next', this); + cpmm.addWeakMessageListener('System:InputRegistry:Add', this); + cpmm.addWeakMessageListener('System:InputRegistry:Remove', this); + } }, uninit: function mozInputMethodUninit() { this._window = null; this._mgmt = null; + this._wrappedMgmt = null; cpmm.removeWeakMessageListener('Keyboard:Focus', this); cpmm.removeWeakMessageListener('Keyboard:Blur', this); @@ -231,15 +458,34 @@ MozInputMethod.prototype = { cpmm.removeWeakMessageListener('InputRegistry:Result:OK', this); cpmm.removeWeakMessageListener('InputRegistry:Result:Error', this); this.setActive(false); + + if (typeof this._inputManageId === 'number') { + cpmm.sendAsyncMessage('System:Unregister', { + 'id': this._inputManageId + }); + cpmm.removeWeakMessageListener('System:Focus', this); + cpmm.removeWeakMessageListener('System:Blur', this); + cpmm.removeWeakMessageListener('System:ShowAll', this); + cpmm.removeWeakMessageListener('System:Next', this); + cpmm.removeWeakMessageListener('System:InputRegistry:Add', this); + cpmm.removeWeakMessageListener('System:InputRegistry:Remove', this); + } }, receiveMessage: function mozInputMethodReceiveMsg(msg) { - if (!msg.name.startsWith('InputRegistry') && + if (msg.name.startsWith('Keyboard') && !WindowMap.isActive(this._window)) { return; } let data = msg.data; + + if (msg.name.startsWith('System') && + this._inputManageId !== data.inputManageId) { + return; + } + delete data.inputManageId; + let resolver = ('requestId' in data) ? this.takePromiseResolver(data.requestId) : null; @@ -272,6 +518,30 @@ MozInputMethod.prototype = { resolver.reject(data.error); break; + + case 'System:Focus': + this._mgmt.handleFocus(data); + break; + + case 'System:Blur': + this._mgmt.handleBlur(data); + break; + + case 'System:ShowAll': + this._mgmt.dispatchShowAllRequestEvent(); + break; + + case 'System:Next': + this._mgmt.dispatchNextRequestEvent(); + break; + + case 'System:InputRegistry:Add': + this._mgmt.handleAddInput(data); + break; + + case 'System:InputRegistry:Remove': + this._mgmt.handleRemoveInput(data); + break; } }, @@ -282,7 +552,7 @@ MozInputMethod.prototype = { }, get mgmt() { - return this._mgmt; + return this._wrappedMgmt; }, get inputcontext() { @@ -320,8 +590,7 @@ MozInputMethod.prototype = { this._window.MozInputContext._create(this._window, this._inputcontext); } - let event = new this._window.Event("inputcontextchange", - Cu.cloneInto({}, this._window)); + let event = new this._window.Event("inputcontextchange"); this.__DOM_IMPL__.dispatchEvent(event); }, @@ -344,9 +613,9 @@ MozInputMethod.prototype = { // we have to use a synchronous message var kbID = WindowMap.getKbID(this._window); if (kbID) { - cpmmSendAsyncMessageWithKbID(this, 'Keyboard:Register', {}); + cpmmSendAsyncMessageWithKbID(this, 'Keyboard:RegisterSync', {}); } else { - let res = cpmm.sendSyncMessage('Keyboard:Register', {}); + let res = cpmm.sendSyncMessage('Keyboard:RegisterSync', {}); WindowMap.setKbID(this._window, res[0]); } @@ -405,6 +674,13 @@ MozInputMethod.prototype = { removeFocus: function() { cpmm.sendAsyncMessage('System:RemoveFocus', {}); + }, + + _hasInputManagePerm: function(win) { + let principal = win.document.nodePrincipal; + let perm = Services.perms.testExactPermissionFromPrincipal(principal, + "input-manage"); + return (perm === Ci.nsIPermissionManager.ALLOW_ACTION); } }; diff --git a/dom/inputmethod/forms.js b/dom/inputmethod/forms.js index 0a7d151c0052..0510b08dce63 100644 --- a/dom/inputmethod/forms.js +++ b/dom/inputmethod/forms.js @@ -1135,6 +1135,8 @@ function getJSON(element, focusCounter) { switch (inputTypeLowerCase) { case "datetime": case "datetime-local": + case "month": + case "week": case "range": inputType = inputTypeLowerCase; break; diff --git a/dom/inputmethod/mochitest/file_inputmethod_1043828.html b/dom/inputmethod/mochitest/file_blank.html similarity index 100% rename from dom/inputmethod/mochitest/file_inputmethod_1043828.html rename to dom/inputmethod/mochitest/file_blank.html diff --git a/dom/inputmethod/mochitest/mochitest.ini b/dom/inputmethod/mochitest/mochitest.ini index 3c2614e67fbd..2b7652e602d4 100644 --- a/dom/inputmethod/mochitest/mochitest.ini +++ b/dom/inputmethod/mochitest/mochitest.ini @@ -4,7 +4,7 @@ skip-if = (toolkit == 'android' || toolkit == 'gonk') || e10s support-files = inputmethod_common.js file_inputmethod.html - file_inputmethod_1043828.html + file_blank.html file_test_app.html file_test_sendkey_cancel.html file_test_sms_app.html @@ -22,8 +22,11 @@ support-files = [test_bug1066515.html] [test_bug1175399.html] [test_bug1137557.html] +[test_focus_blur_manage_events.html] +[test_input_registry_events.html] [test_sendkey_cancel.html] [test_setSupportsSwitching.html] +[test_simple_manage_events.html] [test_sync_edit.html] [test_two_inputs.html] [test_two_selects.html] diff --git a/dom/inputmethod/mochitest/test_bug1043828.html b/dom/inputmethod/mochitest/test_bug1043828.html index 5325ab722abd..0dae3e6a9d4e 100644 --- a/dom/inputmethod/mochitest/test_bug1043828.html +++ b/dom/inputmethod/mochitest/test_bug1043828.html @@ -84,7 +84,7 @@ function runTest() { document.body.appendChild(keyboardB); // simulate two different keyboard apps - let imeUrl = basePath + '/file_inputmethod_1043828.html'; + let imeUrl = basePath + '/file_blank.html'; SpecialPowers.pushPermissions([{ type: 'input', diff --git a/dom/inputmethod/mochitest/test_focus_blur_manage_events.html b/dom/inputmethod/mochitest/test_focus_blur_manage_events.html new file mode 100644 index 000000000000..9bea186fbd47 --- /dev/null +++ b/dom/inputmethod/mochitest/test_focus_blur_manage_events.html @@ -0,0 +1,230 @@ + + + + + Test inputcontextfocus and inputcontextblur event + + + + + +Mozilla Bug 1201407 +

+
+
+
+ + + diff --git a/dom/inputmethod/mochitest/test_input_registry_events.html b/dom/inputmethod/mochitest/test_input_registry_events.html new file mode 100644 index 000000000000..bd93ae8b37a8 --- /dev/null +++ b/dom/inputmethod/mochitest/test_input_registry_events.html @@ -0,0 +1,259 @@ + + + + + Test addinputrequest and removeinputrequest event + + + + + +Mozilla Bug 1201407 +

+
+
+
+ + diff --git a/dom/inputmethod/mochitest/test_simple_manage_events.html b/dom/inputmethod/mochitest/test_simple_manage_events.html new file mode 100644 index 000000000000..88bd344e8d81 --- /dev/null +++ b/dom/inputmethod/mochitest/test_simple_manage_events.html @@ -0,0 +1,164 @@ + + + + + Test simple manage notification events on MozInputMethodManager + + + + + +Mozilla Bug 1201407 +

+
+
+
+ + + diff --git a/dom/webidl/InputMethod.webidl b/dom/webidl/InputMethod.webidl index 46e5963eb7a0..7214f27ff0a0 100644 --- a/dom/webidl/InputMethod.webidl +++ b/dom/webidl/InputMethod.webidl @@ -120,7 +120,7 @@ interface MozInputMethod : EventTarget { [JSImplementation="@mozilla.org/b2g-imm;1", Pref="dom.mozInputMethod.enabled", CheckAnyPermissions="input input-manage"] -interface MozInputMethodManager { +interface MozInputMethodManager : EventTarget { /** * Ask the OS to show a list of available inputs for users to switch from. * OS should sliently ignore this request if the app is currently not the @@ -165,6 +165,149 @@ interface MozInputMethodManager { */ [CheckAllPermissions="input-manage"] void setSupportsSwitchingTypes(sequence types); + + /** + * CustomEvent dispatches to System when there is an input to handle. + * If the API consumer failed to handle and call preventDefault(), + * there will be a message printed on the console. + * + * evt.detail is defined by MozInputContextFocusEventDetail. + */ + [CheckAnyPermissions="input-manage"] + attribute EventHandler oninputcontextfocus; + + /** + * Event dispatches to System when there is no longer an input to handle. + * If the API consumer failed to handle and call preventDefault(), + * there will be a message printed on the console. + */ + [CheckAnyPermissions="input-manage"] + attribute EventHandler oninputcontextblur; + + /** + * Event dispatches to System when there is a showAll() call. + * If the API consumer failed to handle and call preventDefault(), + * there will be a message printed on the console. + */ + [CheckAnyPermissions="input-manage"] + attribute EventHandler onshowallrequest; + + /** + * Event dispatches to System when there is a next() call. + * If the API consumer failed to handle and call preventDefault(), + * there will be a message printed on the console. + */ + [CheckAnyPermissions="input-manage"] + attribute EventHandler onnextrequest; + + /** + * Event dispatches to System when there is a addInput() call. + * The API consumer must call preventDefault() to indicate the event is + * consumed, otherwise the request is not considered handled even if + * waitUntil() was called. + * + * evt.detail is defined by MozInputRegistryEventDetail. + */ + [CheckAnyPermissions="input-manage"] + attribute EventHandler onaddinputrequest; + + /** + * Event dispatches to System when there is a removeInput() call. + * The API consumer must call preventDefault() to indicate the event is + * consumed, otherwise the request is not considered handled even if + * waitUntil() was called. + * + * evt.detail is defined by MozInputRegistryEventDetail. + */ + [CheckAnyPermissions="input-manage"] + attribute EventHandler onremoveinputrequest; +}; + +/** + * Detail of the inputcontextfocus event. + */ +[JSImplementation="@mozilla.org/b2g-imm-focus;1", + Pref="dom.mozInputMethod.enabled", + CheckAnyPermissions="input-manage"] +interface MozInputContextFocusEventDetail { + /** + * The type of the focused input. + */ + readonly attribute MozInputMethodInputContextTypes type; + /** + * The input type of the focused input. + */ + readonly attribute MozInputMethodInputContextInputTypes inputType; + + /** + * The following is only needed for rendering and handling "option" input types, + * in System app. + */ + + /** + * Current value of the input/select element. + */ + readonly attribute DOMString? value; + /** + * An object representing all the and Text" + ""; function openSelectPopup(selectPopup, withMouse) @@ -108,6 +108,12 @@ function doSelectTests(contentType, dtd) is((yield getChangeEvents()), 0, "Before closed - number of change events"); + EventUtils.synthesizeKey("a", { accelKey: true }); + let selection = yield ContentTask.spawn(gBrowser.selectedBrowser, {}, function() { + return String(content.getSelection()); + }); + is(selection, isWindows ? "Text" : "", "Select all while popup is open"); + yield hideSelectPopup(selectPopup); is(menulist.selectedIndex, 3, "Item 3 still selected"); diff --git a/layout/xul/nsXULPopupManager.cpp b/layout/xul/nsXULPopupManager.cpp index 04e7d62f0020..d32452277ed9 100644 --- a/layout/xul/nsXULPopupManager.cpp +++ b/layout/xul/nsXULPopupManager.cpp @@ -867,9 +867,13 @@ nsXULPopupManager::ShowPopupCallback(nsIContent* aPopup, // escape key may be used to close the panel. However, the ignorekeys // attribute may be used to disable adding these event listeners for popups // that want to handle their own keyboard events. - if (aPopup->AttrValueIs(kNameSpaceID_None, nsGkAtoms::ignorekeys, - nsGkAtoms::_true, eCaseMatters)) - item->SetIgnoreKeys(true); + nsAutoString ignorekeys; + aPopup->GetAttr(kNameSpaceID_None, nsGkAtoms::ignorekeys, ignorekeys); + if (ignorekeys.EqualsLiteral("true")) { + item->SetIgnoreKeys(eIgnoreKeys_True); + } else if (ignorekeys.EqualsLiteral("handled")) { + item->SetIgnoreKeys(eIgnoreKeys_Handled); + } if (ismenu) { // if the menu is on a menubar, use the menubar's listener instead @@ -1835,8 +1839,9 @@ nsXULPopupManager::UpdateKeyboardListeners() bool isForMenu = false; nsMenuChainItem* item = GetTopVisibleMenu(); if (item) { - if (!item->IgnoreKeys()) + if (item->IgnoreKeys() != eIgnoreKeys_True) { newTarget = item->Content()->GetComposedDoc(); + } isForMenu = item->PopupType() == ePopupTypeMenu; } else if (mActiveMenuBar) { @@ -2002,6 +2007,14 @@ bool nsXULPopupManager::HandleShortcutNavigation(nsIDOMKeyEvent* aKeyEvent, nsMenuPopupFrame* aFrame) { + // On Windows, don't check shortcuts when the accelerator key is down. +#ifdef XP_WIN + WidgetInputEvent* evt = aKeyEvent->GetInternalNSEvent()->AsInputEvent(); + if (evt && evt->IsAccel()) { + return false; + } +#endif + nsMenuChainItem* item = GetTopVisibleMenu(); if (!aFrame && item) aFrame = item->Frame(); @@ -2470,6 +2483,11 @@ nsXULPopupManager::KeyUp(nsIDOMKeyEvent* aKeyEvent) nsMenuChainItem* item = GetTopVisibleMenu(); if (!item || item->PopupType() != ePopupTypeMenu) return NS_OK; + + if (item->IgnoreKeys() == eIgnoreKeys_Handled) { + aKeyEvent->StopCrossProcessForwarding(); + return NS_OK; + } } aKeyEvent->StopPropagation(); @@ -2525,13 +2543,18 @@ nsXULPopupManager::KeyDown(nsIDOMKeyEvent* aKeyEvent) else if (mActiveMenuBar) mActiveMenuBar->MenuClosed(); } + aKeyEvent->StopPropagation(); aKeyEvent->PreventDefault(); } } // Since a menu was open, stop propagation of the event to keep other event // listeners from becoming confused. - aKeyEvent->StopPropagation(); + + if (!item || item->IgnoreKeys() != eIgnoreKeys_Handled) { + aKeyEvent->StopPropagation(); + } + aKeyEvent->StopCrossProcessForwarding(); return NS_OK; } @@ -2551,10 +2574,17 @@ nsXULPopupManager::KeyPress(nsIDOMKeyEvent* aKeyEvent) NS_ENSURE_TRUE(keyEvent, NS_ERROR_UNEXPECTED); // if a menu is open or a menubar is active, it consumes the key event bool consume = (mPopups || mActiveMenuBar); - HandleShortcutNavigation(keyEvent, nullptr); - if (consume) { + + // When ignorekeys="handled" is used, we don't call preventDefault on the key + // event, which allows another listener to handle keys that the popup hasn't + // already handled. For instance, this allows global shortcuts to still apply + // while a menu is open. + bool onlyHandled = item && item->IgnoreKeys() == eIgnoreKeys_Handled; + bool handled = HandleShortcutNavigation(keyEvent, nullptr); + + aKeyEvent->StopCrossProcessForwarding(); + if (handled || (consume && !onlyHandled)) { aKeyEvent->StopPropagation(); - aKeyEvent->StopCrossProcessForwarding(); aKeyEvent->PreventDefault(); } diff --git a/layout/xul/nsXULPopupManager.h b/layout/xul/nsXULPopupManager.h index d76364f449c7..1e02ef6e5859 100644 --- a/layout/xul/nsXULPopupManager.h +++ b/layout/xul/nsXULPopupManager.h @@ -99,6 +99,12 @@ enum nsNavigationDirection { eNavigationDirection_After }; +enum nsIgnoreKeys { + eIgnoreKeys_False, + eIgnoreKeys_True, + eIgnoreKeys_Handled, +}; + #define NS_DIRECTION_IS_INLINE(dir) (dir == eNavigationDirection_Start || \ dir == eNavigationDirection_End) #define NS_DIRECTION_IS_BLOCK(dir) (dir == eNavigationDirection_Before || \ @@ -129,7 +135,7 @@ private: nsPopupType mPopupType; // the popup type of the frame bool mIsContext; // true for context menus bool mOnMenuBar; // true if the menu is on a menu bar - bool mIgnoreKeys; // true if keyboard listeners should not be used + nsIgnoreKeys mIgnoreKeys; // indicates how keyboard listeners should be used nsMenuChainItem* mParent; nsMenuChainItem* mChild; @@ -140,7 +146,7 @@ public: mPopupType(aPopupType), mIsContext(aIsContext), mOnMenuBar(false), - mIgnoreKeys(false), + mIgnoreKeys(eIgnoreKeys_False), mParent(nullptr), mChild(nullptr) { @@ -158,9 +164,9 @@ public: nsPopupType PopupType() { return mPopupType; } bool IsMenu() { return mPopupType == ePopupTypeMenu; } bool IsContextMenu() { return mIsContext; } - bool IgnoreKeys() { return mIgnoreKeys; } + nsIgnoreKeys IgnoreKeys() { return mIgnoreKeys; } + void SetIgnoreKeys(nsIgnoreKeys aIgnoreKeys) { mIgnoreKeys = aIgnoreKeys; } bool IsOnMenuBar() { return mOnMenuBar; } - void SetIgnoreKeys(bool aIgnoreKeys) { mIgnoreKeys = aIgnoreKeys; } void SetOnMenuBar(bool aOnMenuBar) { mOnMenuBar = aOnMenuBar; } nsMenuChainItem* GetParent() { return mParent; } nsMenuChainItem* GetChild() { return mChild; } diff --git a/toolkit/content/tests/chrome/test_popup_keys.xul b/toolkit/content/tests/chrome/test_popup_keys.xul index 7008f0bb3fc7..4338b4b0c487 100644 --- a/toolkit/content/tests/chrome/test_popup_keys.xul +++ b/toolkit/content/tests/chrome/test_popup_keys.xul @@ -3,8 +3,8 @@ @@ -18,7 +18,7 @@ should not be highlighted. --> - + @@ -32,42 +32,82 @@ SimpleTest.waitForExplicitFinish(); var gIgnoreKeys = false; var gIgnoreAttrChange = false; +var gKeyPressCount = 0; + +let {Task} = Components.utils.import("resource://gre/modules/Task.jsm", {}); + +function waitForEvent(target, eventName) { + return new Promise(resolve => { + target.addEventListener(eventName, function eventOccurred(event) { + target.removeEventListener(eventName, eventOccurred, false); + resolve(); + }, false); + }); +} function runTests() { - var popup = $("popup"); - popup.enableKeyboardNavigator(false); - is(popup.getAttribute("ignorekeys"), "true", "keys disabled"); - popup.enableKeyboardNavigator(true); - is(popup.hasAttribute("ignorekeys"), false, "keys enabled"); - popup.openPopup(null, "after_start"); -} - -function popupShown() -{ - synthesizeKey("VK_DOWN", { }); - if (gIgnoreKeys) { + Task.async(function* () { var popup = $("popup"); - setTimeout(function() { popup.hidePopup() }, 1000); - } -} + popup.enableKeyboardNavigator(false); + is(popup.getAttribute("ignorekeys"), "true", "keys disabled"); + popup.enableKeyboardNavigator(true); + is(popup.hasAttribute("ignorekeys"), false, "keys enabled"); + + let popupShownPromise = waitForEvent(popup, "popupshown"); + popup.openPopup(null, "after_start"); + yield popupShownPromise; + + let popupHiddenPromise = waitForEvent(popup, "popuphidden"); + synthesizeKey("VK_DOWN", { }); + yield popupHiddenPromise; + + is(gKeyPressCount, 0, "keypresses with ignorekeys='false'"); -function popupHidden() -{ - if (gIgnoreKeys) { - SimpleTest.finish(); - } - else { - // try the test again with ignorekeys set gIgnoreKeys = true; - var popup = $("popup"); popup.setAttribute("ignorekeys", "true"); // clear this first to avoid confusion gIgnoreAttrChange = true; $("i1").removeAttribute("_moz-menuactive") gIgnoreAttrChange = false; + + popupShownPromise = waitForEvent(popup, "popupshown"); popup.openPopup(null, "after_start"); - } + yield popupShownPromise; + + synthesizeKey("VK_DOWN", { }); + + yield new Promise(resolve => setTimeout(() => resolve(), 1000)); + popupHiddenPromise = waitForEvent(popup, "popuphidden"); + popup.hidePopup(); + yield popupHiddenPromise; + + is(gKeyPressCount, 1, "keypresses with ignorekeys='true'"); + + popup.setAttribute("ignorekeys", "handled"); + // clear this first to avoid confusion + gIgnoreAttrChange = true; + $("i1").removeAttribute("_moz-menuactive") + gIgnoreAttrChange = false; + + popupShownPromise = waitForEvent(popup, "popupshown"); + popup.openPopup(null, "after_start"); + yield popupShownPromise; + + // When ignorekeys="handled", T should be handled but accel+T should propagate. + synthesizeKey("t", { }); + is(gKeyPressCount, 1, "keypresses after t pressed with ignorekeys='handled'"); + + let isWindows = navigator.platform.indexOf("Win") >= 0; + synthesizeKey("t", { accelKey: true }); + is(gKeyPressCount, isWindows ? 2 : 1, "keypresses after accel+t pressed with ignorekeys='handled'"); + + popupHiddenPromise = waitForEvent(popup, "popuphidden"); + popup.hidePopup(); + yield popupHiddenPromise; + + SimpleTest.finish(); + })(); } function attrModified(event) From d2ca40bafa737b34195e6fe4ab37f4cdd415ff43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Pag=C3=A8s?= Date: Tue, 15 Sep 2015 07:16:42 +0200 Subject: [PATCH 082/113] Bug 1204628 - Talos' setup.py does not install psutil into virtualenv.r=jmaher --HG-- extra : commitid : 8hcj1zngmWS extra : rebase_source : 9378511894288f08f2048a15f29d0443768836aa --- testing/talos/requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/testing/talos/requirements.txt b/testing/talos/requirements.txt index 3f94c4b51b7a..c19cb0bb9040 100644 --- a/testing/talos/requirements.txt +++ b/testing/talos/requirements.txt @@ -5,3 +5,4 @@ mozinfo>=0.8 mozprocess>=0.22 mozversion>=1.3 mozprofile>=0.25 +psutil>=3.1.1 From d0e6ae8cc1e2e04e436116372060eadd7a904475 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Wed, 16 Sep 2015 23:02:17 -0700 Subject: [PATCH 083/113] Bumping gaia.json for 1 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/35ecf3d9f9cf Author: spark-bot Desc: update directory, add mozspeechcollect --- b2g/config/gaia.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 0a7b39fde9da..ce4c0d4743f7 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,9 +1,9 @@ { "git": { - "git_revision": "aede8622d780ec71f766a3ecccbff74c04aaba4e", + "git_revision": "eb62d50351fd6a9b560fe369387d8138b9b3a2d3", "remote": "https://git.mozilla.org/releases/gaia.git", "branch": "" }, - "revision": "dbd3a4ea9042cae987147f2d05f41d2a7ebaccbc", + "revision": "35ecf3d9f9cf69f77085c89d368561be713f78f0", "repo_path": "integration/gaia-central" } From 83f841e7093039920e2a565cbf73d89458a26ba1 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Wed, 16 Sep 2015 23:05:01 -0700 Subject: [PATCH 084/113] Bumping manifests a=b2g-bump --- b2g/config/aries/sources.xml | 2 +- b2g/config/dolphin/sources.xml | 2 +- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator-l/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame-kk/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/nexus-5-l/sources.xml | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/b2g/config/aries/sources.xml b/b2g/config/aries/sources.xml index 1ffdf1650434..05130fdc8580 100644 --- a/b2g/config/aries/sources.xml +++ b/b2g/config/aries/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index 9379420fe47a..2b046830b2b2 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index 827501b0c4fc..ff8a53a04359 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index 892fc6fd80dd..cedd4de25c29 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index fa095dff005b..5fa203eeda42 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator-l/sources.xml b/b2g/config/emulator-l/sources.xml index 92fe63b5bc98..11ebf2d1137b 100644 --- a/b2g/config/emulator-l/sources.xml +++ b/b2g/config/emulator-l/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index 827501b0c4fc..ff8a53a04359 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame-kk/sources.xml b/b2g/config/flame-kk/sources.xml index 84eb0cf9907e..82858d3451da 100644 --- a/b2g/config/flame-kk/sources.xml +++ b/b2g/config/flame-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index 185a7dd18c71..65838033f811 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/nexus-5-l/sources.xml b/b2g/config/nexus-5-l/sources.xml index 57c4df19634c..dfe5f3bfbedd 100644 --- a/b2g/config/nexus-5-l/sources.xml +++ b/b2g/config/nexus-5-l/sources.xml @@ -15,7 +15,7 @@ - + From d27129032ae7ee199e4eeaa09d827338672c6e3f Mon Sep 17 00:00:00 2001 From: Cervantes Yu Date: Thu, 17 Sep 2015 14:36:06 +0800 Subject: [PATCH 085/113] Bug 1204837: Make ClosingService thread Nuwa-friedly. r=khuey --- netwerk/base/ClosingService.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/netwerk/base/ClosingService.cpp b/netwerk/base/ClosingService.cpp index ef7f26c9fe4c..284d2ca3b156 100644 --- a/netwerk/base/ClosingService.cpp +++ b/netwerk/base/ClosingService.cpp @@ -6,6 +6,9 @@ #include "ClosingService.h" #include "nsIOService.h" +#ifdef MOZ_NUWA_PROCESS +#include "ipc/Nuwa.h" +#endif class ClosingLayerSecret { @@ -200,6 +203,13 @@ ClosingService::ShutdownInternal() void ClosingService::ThreadFunc() { + PR_SetCurrentThreadName("Closing Service"); +#ifdef MOZ_NUWA_PROCESS + if (IsNuwaProcess()) { + NuwaMarkCurrentThread(nullptr, nullptr); + } +#endif + for (;;) { PRFileDesc *fd; { From f47edecb4b1043163880f69ba614ed71e910ff98 Mon Sep 17 00:00:00 2001 From: Cervantes Yu Date: Thu, 17 Sep 2015 14:40:23 +0800 Subject: [PATCH 086/113] Bug 1204405: Don't access prefs off main thread in testing ProcessLink::Open(). r=khuey --- ipc/glue/MessageLink.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ipc/glue/MessageLink.cpp b/ipc/glue/MessageLink.cpp index 7b302219126b..14edb93b00a8 100644 --- a/ipc/glue/MessageLink.cpp +++ b/ipc/glue/MessageLink.cpp @@ -13,7 +13,7 @@ #ifdef MOZ_NUWA_PROCESS #include "ipc/Nuwa.h" #include "mozilla/Preferences.h" -#include "mozilla/dom/PContent.h" +#include "mozilla/dom/ContentParent.h" #include "mozilla/dom/PNuwa.h" #include "mozilla/hal_sandbox/PHal.h" #if defined(DEBUG) || defined(ENABLE_TESTS) @@ -144,7 +144,7 @@ ProcessLink::Open(mozilla::ipc::Transport* aTransport, MessageLoop *aIOLoop, Sid } #ifdef MOZ_NUWA_PROCESS - if (IsNuwaProcess() && + if (IsNuwaProcess() && NS_IsMainThread() && Preferences::GetBool("dom.ipc.processPrelaunch.testMode")) { // The pref value is turned on in a deadlock test against the Nuwa // process. The sleep here makes it easy to trigger the deadlock From 86fcc7a88d9d010ec83530255d67e582e8553970 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Thu, 17 Sep 2015 10:08:47 +0200 Subject: [PATCH 087/113] Bug 1205253: Move |BluetoothDaemonCoreModule| into separate compilation unit, r=btian This patch moves |BluetoothDaemonCoreModule| into its own compilation unit. The notifications handlers are not set via getter/setter methods o fthis class. No further code changes are made. --- .../BluetoothDaemonCoreInterface.cpp | 1194 +++++++++++++++++ .../bluedroid/BluetoothDaemonCoreInterface.h | 308 +++++ .../bluedroid/BluetoothDaemonInterface.cpp | 1188 +--------------- dom/bluetooth/moz.build | 1 + 4 files changed, 1516 insertions(+), 1175 deletions(-) create mode 100644 dom/bluetooth/bluedroid/BluetoothDaemonCoreInterface.cpp create mode 100644 dom/bluetooth/bluedroid/BluetoothDaemonCoreInterface.h diff --git a/dom/bluetooth/bluedroid/BluetoothDaemonCoreInterface.cpp b/dom/bluetooth/bluedroid/BluetoothDaemonCoreInterface.cpp new file mode 100644 index 000000000000..cec4110fa4a2 --- /dev/null +++ b/dom/bluetooth/bluedroid/BluetoothDaemonCoreInterface.cpp @@ -0,0 +1,1194 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#include "BluetoothDaemonCoreInterface.h" +#include "mozilla/unused.h" + +BEGIN_BLUETOOTH_NAMESPACE + +using namespace mozilla::ipc; + +// +// Core module +// + +const int BluetoothDaemonCoreModule::MAX_NUM_CLIENTS = 1; + +BluetoothNotificationHandler* BluetoothDaemonCoreModule::sNotificationHandler; + +void +BluetoothDaemonCoreModule::SetNotificationHandler( + BluetoothNotificationHandler* aNotificationHandler) +{ + sNotificationHandler = aNotificationHandler; +} + +BluetoothNotificationHandler* +BluetoothDaemonCoreModule::GetNotificationHandler() +{ + return sNotificationHandler; +} + +void +BluetoothDaemonCoreModule::HandleSvc(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, + DaemonSocketResultHandler* aRes) +{ + static void (BluetoothDaemonCoreModule::* const HandleOp[])( + const DaemonSocketPDUHeader&, DaemonSocketPDU&, + DaemonSocketResultHandler*) = { + [0] = &BluetoothDaemonCoreModule::HandleRsp, + [1] = &BluetoothDaemonCoreModule::HandleNtf + }; + + MOZ_ASSERT(!NS_IsMainThread()); + + (this->*(HandleOp[!!(aHeader.mOpcode & 0x80)]))(aHeader, aPDU, aRes); +} + +// Commands +// + +nsresult +BluetoothDaemonCoreModule::EnableCmd(BluetoothResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x01, 0)); + + nsresult rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return rv; +} + +nsresult +BluetoothDaemonCoreModule::DisableCmd(BluetoothResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x02, 0)); + + nsresult rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return rv; +} + +nsresult +BluetoothDaemonCoreModule::GetAdapterPropertiesCmd( + BluetoothResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x03, 0)); + + nsresult rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return rv; +} + +nsresult +BluetoothDaemonCoreModule::GetAdapterPropertyCmd(const nsAString& aName, + BluetoothResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x04, 0)); + + nsresult rv = PackPDU( + PackConversion(aName), *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return rv; +} + +nsresult +BluetoothDaemonCoreModule::SetAdapterPropertyCmd( + const BluetoothNamedValue& aProperty, BluetoothResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x05, 0)); + + nsresult rv = PackPDU(aProperty, *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return rv; +} + +nsresult +BluetoothDaemonCoreModule::GetRemoteDevicePropertiesCmd( + const nsAString& aRemoteAddr, BluetoothResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x06, 0)); + + nsresult rv = PackPDU( + PackConversion(aRemoteAddr), *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return rv; +} + +nsresult +BluetoothDaemonCoreModule::GetRemoteDevicePropertyCmd( + const nsAString& aRemoteAddr, + const nsAString& aName, + BluetoothResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x07, 0)); + + nsresult rv = PackPDU( + PackConversion(aRemoteAddr), + PackConversion(aName), *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return rv; +} + +nsresult +BluetoothDaemonCoreModule::SetRemoteDevicePropertyCmd( + const nsAString& aRemoteAddr, + const BluetoothNamedValue& aProperty, + BluetoothResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x08, 0)); + + nsresult rv = PackPDU( + PackConversion(aRemoteAddr), + aProperty, *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return rv; +} + +nsresult +BluetoothDaemonCoreModule::GetRemoteServiceRecordCmd( + const nsAString& aRemoteAddr, const uint8_t aUuid[16], + BluetoothResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x09, 0)); + + nsresult rv = PackPDU( + PackConversion(aRemoteAddr), + PackArray(aUuid, 16), *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return rv; +} + +nsresult +BluetoothDaemonCoreModule::GetRemoteServicesCmd( + const nsAString& aRemoteAddr, BluetoothResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x0a, 0)); + + nsresult rv = PackPDU( + PackConversion(aRemoteAddr), *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return rv; +} + +nsresult +BluetoothDaemonCoreModule::StartDiscoveryCmd(BluetoothResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x0b, 0)); + + nsresult rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return rv; +} + +nsresult +BluetoothDaemonCoreModule::CancelDiscoveryCmd(BluetoothResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x0c, 0)); + + nsresult rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return rv; +} + +nsresult +BluetoothDaemonCoreModule::CreateBondCmd(const nsAString& aBdAddr, + BluetoothTransport aTransport, + BluetoothResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x0d, 0)); + +#if ANDROID_VERSION >= 21 + nsresult rv = PackPDU( + PackConversion(aBdAddr), aTransport, *pdu); +#else + nsresult rv = PackPDU( + PackConversion(aBdAddr), *pdu); +#endif + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return rv; +} + +nsresult +BluetoothDaemonCoreModule::RemoveBondCmd(const nsAString& aBdAddr, + BluetoothResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x0e, 0)); + + nsresult rv = PackPDU( + PackConversion(aBdAddr), *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return rv; +} + +nsresult +BluetoothDaemonCoreModule::CancelBondCmd(const nsAString& aBdAddr, + BluetoothResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x0f, 0)); + + nsresult rv = PackPDU( + PackConversion(aBdAddr), *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return rv; +} + +nsresult +BluetoothDaemonCoreModule::PinReplyCmd(const nsAString& aBdAddr, bool aAccept, + const nsAString& aPinCode, + BluetoothResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x10, 0)); + + nsresult rv = PackPDU( + PackConversion(aBdAddr), + aAccept, + PackConversion(aPinCode), *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return rv; +} + +nsresult +BluetoothDaemonCoreModule::SspReplyCmd(const nsAString& aBdAddr, + BluetoothSspVariant aVariant, + bool aAccept, uint32_t aPasskey, + BluetoothResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x11, 0)); + + nsresult rv = PackPDU( + PackConversion(aBdAddr), + aVariant, aAccept, aPasskey, *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return rv; +} + +nsresult +BluetoothDaemonCoreModule::DutModeConfigureCmd(bool aEnable, + BluetoothResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x12, 0)); + + nsresult rv = PackPDU(aEnable, *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return rv; +} + +nsresult +BluetoothDaemonCoreModule::DutModeSendCmd(uint16_t aOpcode, + uint8_t* aBuf, uint8_t aLen, + BluetoothResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x13, 0)); + + nsresult rv = PackPDU(aOpcode, aLen, PackArray(aBuf, aLen), + *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return rv; +} + +nsresult +BluetoothDaemonCoreModule::LeTestModeCmd(uint16_t aOpcode, + uint8_t* aBuf, uint8_t aLen, + BluetoothResultHandler* aRes) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x14, 0)); + + nsresult rv = PackPDU(aOpcode, aLen, PackArray(aBuf, aLen), + *pdu); + if (NS_FAILED(rv)) { + return rv; + } + rv = Send(pdu, aRes); + if (NS_FAILED(rv)) { + return rv; + } + unused << pdu.forget(); + return rv; +} + +// Responses +// + +void +BluetoothDaemonCoreModule::ErrorRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, + BluetoothResultHandler* aRes) +{ + ErrorRunnable::Dispatch( + aRes, &BluetoothResultHandler::OnError, UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonCoreModule::EnableRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, + BluetoothResultHandler* aRes) +{ + ResultRunnable::Dispatch( + aRes, &BluetoothResultHandler::Enable, UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonCoreModule::DisableRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, + BluetoothResultHandler* aRes) +{ + ResultRunnable::Dispatch( + aRes, &BluetoothResultHandler::Disable, UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonCoreModule::GetAdapterPropertiesRsp( + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, + BluetoothResultHandler* aRes) +{ + ResultRunnable::Dispatch( + aRes, &BluetoothResultHandler::GetAdapterProperties, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonCoreModule::GetAdapterPropertyRsp( + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, + BluetoothResultHandler* aRes) +{ + ResultRunnable::Dispatch( + aRes, &BluetoothResultHandler::GetAdapterProperty, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonCoreModule::SetAdapterPropertyRsp( + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, + BluetoothResultHandler* aRes) +{ + ResultRunnable::Dispatch( + aRes, &BluetoothResultHandler::SetAdapterProperty, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonCoreModule::GetRemoteDevicePropertiesRsp( + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, + BluetoothResultHandler* aRes) +{ + ResultRunnable::Dispatch( + aRes, &BluetoothResultHandler::GetRemoteDeviceProperties, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonCoreModule::GetRemoteDevicePropertyRsp( + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, + BluetoothResultHandler* aRes) +{ + ResultRunnable::Dispatch( + aRes, &BluetoothResultHandler::GetRemoteDeviceProperty, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonCoreModule::SetRemoteDevicePropertyRsp( + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, + BluetoothResultHandler* aRes) +{ + ResultRunnable::Dispatch( + aRes, &BluetoothResultHandler::SetRemoteDeviceProperty, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonCoreModule::GetRemoteServiceRecordRsp( + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, + BluetoothResultHandler* aRes) +{ + ResultRunnable::Dispatch( + aRes, &BluetoothResultHandler::GetRemoteServiceRecord, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonCoreModule::GetRemoteServicesRsp( + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, + BluetoothResultHandler* aRes) +{ + ResultRunnable::Dispatch( + aRes, &BluetoothResultHandler::GetRemoteServices, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonCoreModule::StartDiscoveryRsp( + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, + BluetoothResultHandler* aRes) +{ + ResultRunnable::Dispatch( + aRes, &BluetoothResultHandler::StartDiscovery, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonCoreModule::CancelDiscoveryRsp( + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, + BluetoothResultHandler* aRes) +{ + ResultRunnable::Dispatch( + aRes, &BluetoothResultHandler::CancelDiscovery, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonCoreModule::CreateBondRsp( + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, + BluetoothResultHandler* aRes) +{ + ResultRunnable::Dispatch( + aRes, &BluetoothResultHandler::CreateBond, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonCoreModule::RemoveBondRsp( + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, + BluetoothResultHandler* aRes) +{ + ResultRunnable::Dispatch( + aRes, &BluetoothResultHandler::RemoveBond, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonCoreModule::CancelBondRsp( + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, + BluetoothResultHandler* aRes) +{ + ResultRunnable::Dispatch( + aRes, &BluetoothResultHandler::CancelBond, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonCoreModule::PinReplyRsp( + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, + BluetoothResultHandler* aRes) +{ + ResultRunnable::Dispatch( + aRes, &BluetoothResultHandler::PinReply, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonCoreModule::SspReplyRsp( + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, + BluetoothResultHandler* aRes) +{ + ResultRunnable::Dispatch( + aRes, &BluetoothResultHandler::SspReply, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonCoreModule::DutModeConfigureRsp( + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, + BluetoothResultHandler* aRes) +{ + ResultRunnable::Dispatch( + aRes, &BluetoothResultHandler::DutModeConfigure, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonCoreModule::DutModeSendRsp( + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, + BluetoothResultHandler* aRes) +{ + ResultRunnable::Dispatch( + aRes, &BluetoothResultHandler::DutModeSend, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonCoreModule::LeTestModeRsp( + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, + BluetoothResultHandler* aRes) +{ + ResultRunnable::Dispatch( + aRes, &BluetoothResultHandler::LeTestMode, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonCoreModule::HandleRsp( + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, + DaemonSocketResultHandler* aRes) +{ + static void (BluetoothDaemonCoreModule::* const HandleRsp[])( + const DaemonSocketPDUHeader&, + DaemonSocketPDU&, + BluetoothResultHandler*) = { + [0x00] = &BluetoothDaemonCoreModule::ErrorRsp, + [0x01] = &BluetoothDaemonCoreModule::EnableRsp, + [0x02] = &BluetoothDaemonCoreModule::DisableRsp, + [0x03] = &BluetoothDaemonCoreModule::GetAdapterPropertiesRsp, + [0x04] = &BluetoothDaemonCoreModule::GetAdapterPropertyRsp, + [0x05] = &BluetoothDaemonCoreModule::SetAdapterPropertyRsp, + [0x06] = &BluetoothDaemonCoreModule::GetRemoteDevicePropertiesRsp, + [0x07] = &BluetoothDaemonCoreModule::GetRemoteDevicePropertyRsp, + [0x08] = &BluetoothDaemonCoreModule::SetRemoteDevicePropertyRsp, + [0x09] = &BluetoothDaemonCoreModule::GetRemoteServiceRecordRsp, + [0x0a] = &BluetoothDaemonCoreModule::GetRemoteServicesRsp, + [0x0b] = &BluetoothDaemonCoreModule::StartDiscoveryRsp, + [0x0c] = &BluetoothDaemonCoreModule::CancelDiscoveryRsp, + [0x0d] = &BluetoothDaemonCoreModule::CreateBondRsp, + [0x0e] = &BluetoothDaemonCoreModule::RemoveBondRsp, + [0x0f] = &BluetoothDaemonCoreModule::CancelBondRsp, + [0x10] = &BluetoothDaemonCoreModule::PinReplyRsp, + [0x11] = &BluetoothDaemonCoreModule::SspReplyRsp, + [0x12] = &BluetoothDaemonCoreModule::DutModeConfigureRsp, + [0x13] = &BluetoothDaemonCoreModule::DutModeSendRsp, + [0x14] = &BluetoothDaemonCoreModule::LeTestModeRsp, + }; + + MOZ_ASSERT(!NS_IsMainThread()); + + if (NS_WARN_IF(!(aHeader.mOpcode < MOZ_ARRAY_LENGTH(HandleRsp))) || + NS_WARN_IF(!HandleRsp[aHeader.mOpcode])) { + return; + } + + nsRefPtr res = + static_cast(aRes); + + if (!res) { + return; // Return early if no result handler has been set for response + } + + (this->*(HandleRsp[aHeader.mOpcode]))(aHeader, aPDU, res); +} + +// Notifications +// + +class BluetoothDaemonCoreModule::NotificationHandlerWrapper final +{ +public: + typedef BluetoothNotificationHandler ObjectType; + + static ObjectType* GetInstance() + { + MOZ_ASSERT(NS_IsMainThread()); + + return sNotificationHandler; + } +}; + +void +BluetoothDaemonCoreModule::AdapterStateChangedNtf( + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) +{ + AdapterStateChangedNotification::Dispatch( + &BluetoothNotificationHandler::AdapterStateChangedNotification, + UnpackPDUInitOp(aPDU)); +} + +// Init operator class for AdapterPropertiesNotification +class BluetoothDaemonCoreModule::AdapterPropertiesInitOp final + : private PDUInitOp +{ +public: + AdapterPropertiesInitOp(DaemonSocketPDU& aPDU) + : PDUInitOp(aPDU) + { } + + nsresult + operator () (BluetoothStatus& aArg1, int& aArg2, + nsAutoArrayPtr& aArg3) const + { + DaemonSocketPDU& pdu = GetPDU(); + + /* Read status */ + nsresult rv = UnpackPDU(pdu, aArg1); + if (NS_FAILED(rv)) { + return rv; + } + + /* Read number of properties */ + uint8_t numProperties; + rv = UnpackPDU(pdu, numProperties); + if (NS_FAILED(rv)) { + return rv; + } + aArg2 = numProperties; + + /* Read properties array */ + UnpackArray properties(aArg3, aArg2); + rv = UnpackPDU(pdu, properties); + if (NS_FAILED(rv)) { + return rv; + } + WarnAboutTrailingData(); + return NS_OK; + } +}; + +void +BluetoothDaemonCoreModule::AdapterPropertiesNtf( + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) +{ + AdapterPropertiesNotification::Dispatch( + &BluetoothNotificationHandler::AdapterPropertiesNotification, + AdapterPropertiesInitOp(aPDU)); +} + +// Init operator class for RemoteDevicePropertiesNotification +class BluetoothDaemonCoreModule::RemoteDevicePropertiesInitOp final + : private PDUInitOp +{ +public: + RemoteDevicePropertiesInitOp(DaemonSocketPDU& aPDU) + : PDUInitOp(aPDU) + { } + + nsresult + operator () (BluetoothStatus& aArg1, nsString& aArg2, int& aArg3, + nsAutoArrayPtr& aArg4) const + { + DaemonSocketPDU& pdu = GetPDU(); + + /* Read status */ + nsresult rv = UnpackPDU(pdu, aArg1); + if (NS_FAILED(rv)) { + return rv; + } + + /* Read address */ + rv = UnpackPDU( + pdu, UnpackConversion(aArg2)); + if (NS_FAILED(rv)) { + return rv; + } + + /* Read number of properties */ + uint8_t numProperties; + rv = UnpackPDU(pdu, numProperties); + if (NS_FAILED(rv)) { + return rv; + } + aArg3 = numProperties; + + /* Read properties array */ + UnpackArray properties(aArg4, aArg3); + rv = UnpackPDU(pdu, properties); + if (NS_FAILED(rv)) { + return rv; + } + WarnAboutTrailingData(); + return NS_OK; + } +}; + +void +BluetoothDaemonCoreModule::RemoteDevicePropertiesNtf( + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) +{ + RemoteDevicePropertiesNotification::Dispatch( + &BluetoothNotificationHandler::RemoteDevicePropertiesNotification, + RemoteDevicePropertiesInitOp(aPDU)); +} + +// Init operator class for DeviceFoundNotification +class BluetoothDaemonCoreModule::DeviceFoundInitOp final + : private PDUInitOp +{ +public: + DeviceFoundInitOp(DaemonSocketPDU& aPDU) + : PDUInitOp(aPDU) + { } + + nsresult + operator () (int& aArg1, nsAutoArrayPtr& aArg2) const + { + DaemonSocketPDU& pdu = GetPDU(); + + /* Read number of properties */ + uint8_t numProperties; + nsresult rv = UnpackPDU(pdu, numProperties); + if (NS_FAILED(rv)) { + return rv; + } + aArg1 = numProperties; + + /* Read properties array */ + UnpackArray properties(aArg2, aArg1); + rv = UnpackPDU(pdu, properties); + if (NS_FAILED(rv)) { + return rv; + } + WarnAboutTrailingData(); + return NS_OK; + } +}; + +void +BluetoothDaemonCoreModule::DeviceFoundNtf( + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) +{ + DeviceFoundNotification::Dispatch( + &BluetoothNotificationHandler::DeviceFoundNotification, + DeviceFoundInitOp(aPDU)); +} + +void +BluetoothDaemonCoreModule::DiscoveryStateChangedNtf( + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) +{ + DiscoveryStateChangedNotification::Dispatch( + &BluetoothNotificationHandler::DiscoveryStateChangedNotification, + UnpackPDUInitOp(aPDU)); +} + +// Init operator class for PinRequestNotification +class BluetoothDaemonCoreModule::PinRequestInitOp final + : private PDUInitOp +{ +public: + PinRequestInitOp(DaemonSocketPDU& aPDU) + : PDUInitOp(aPDU) + { } + + nsresult + operator () (nsString& aArg1, nsString& aArg2, uint32_t& aArg3) const + { + DaemonSocketPDU& pdu = GetPDU(); + + /* Read remote address */ + nsresult rv = UnpackPDU( + pdu, UnpackConversion(aArg1)); + if (NS_FAILED(rv)) { + return rv; + } + + /* Read remote name */ + rv = UnpackPDU( + pdu, UnpackConversion(aArg2)); + if (NS_FAILED(rv)) { + return rv; + } + + /* Read CoD */ + rv = UnpackPDU(pdu, aArg3); + if (NS_FAILED(rv)) { + return rv; + } + WarnAboutTrailingData(); + return NS_OK; + } +}; + +void +BluetoothDaemonCoreModule::PinRequestNtf( + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) +{ + PinRequestNotification::Dispatch( + &BluetoothNotificationHandler::PinRequestNotification, + PinRequestInitOp(aPDU)); +} + +// Init operator class for SspRequestNotification +class BluetoothDaemonCoreModule::SspRequestInitOp final + : private PDUInitOp +{ +public: + SspRequestInitOp(DaemonSocketPDU& aPDU) + : PDUInitOp(aPDU) + { } + + nsresult + operator () (nsString& aArg1, nsString& aArg2, uint32_t& aArg3, + BluetoothSspVariant& aArg4, uint32_t& aArg5) const + { + DaemonSocketPDU& pdu = GetPDU(); + + /* Read remote address */ + nsresult rv = UnpackPDU( + pdu, UnpackConversion(aArg1)); + if (NS_FAILED(rv)) { + return rv; + } + + /* Read remote name */ + rv = UnpackPDU( + pdu, UnpackConversion(aArg2)); + if (NS_FAILED(rv)) { + return rv; + } + + /* Read CoD */ + rv = UnpackPDU(pdu, aArg3); + if (NS_FAILED(rv)) { + return rv; + } + + /* Read pairing variant */ + rv = UnpackPDU(pdu, aArg4); + if (NS_FAILED(rv)) { + return rv; + } + + /* Read passkey */ + rv = UnpackPDU(pdu, aArg5); + if (NS_FAILED(rv)) { + return rv; + } + WarnAboutTrailingData(); + return NS_OK; + } +}; + +void +BluetoothDaemonCoreModule::SspRequestNtf( + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) +{ + SspRequestNotification::Dispatch( + &BluetoothNotificationHandler::SspRequestNotification, + SspRequestInitOp(aPDU)); +} + +// Init operator class for BondStateChangedNotification +class BluetoothDaemonCoreModule::BondStateChangedInitOp final + : private PDUInitOp +{ +public: + BondStateChangedInitOp(DaemonSocketPDU& aPDU) + : PDUInitOp(aPDU) + { } + + nsresult + operator () (BluetoothStatus& aArg1, nsString& aArg2, + BluetoothBondState& aArg3) const + { + DaemonSocketPDU& pdu = GetPDU(); + + /* Read status */ + nsresult rv = UnpackPDU(pdu, aArg1); + if (NS_FAILED(rv)) { + return rv; + } + + /* Read remote address */ + rv = UnpackPDU( + pdu, UnpackConversion(aArg2)); + if (NS_FAILED(rv)) { + return rv; + } + + /* Read bond state */ + rv = UnpackPDU(pdu, aArg3); + if (NS_FAILED(rv)) { + return rv; + } + WarnAboutTrailingData(); + return NS_OK; + } +}; + +void +BluetoothDaemonCoreModule::BondStateChangedNtf( + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) +{ + BondStateChangedNotification::Dispatch( + &BluetoothNotificationHandler::BondStateChangedNotification, + BondStateChangedInitOp(aPDU)); +} + +// Init operator class for AclStateChangedNotification +class BluetoothDaemonCoreModule::AclStateChangedInitOp final + : private PDUInitOp +{ +public: + AclStateChangedInitOp(DaemonSocketPDU& aPDU) + : PDUInitOp(aPDU) + { } + + nsresult + operator () (BluetoothStatus& aArg1, nsString& aArg2, bool& aArg3) const + { + DaemonSocketPDU& pdu = GetPDU(); + + /* Read status */ + nsresult rv = UnpackPDU(pdu, aArg1); + if (NS_FAILED(rv)) { + return rv; + } + + /* Read remote address */ + rv = UnpackPDU( + pdu, UnpackConversion(aArg2)); + if (NS_FAILED(rv)) { + return rv; + } + + /* Read ACL state */ + rv = UnpackPDU( + pdu, UnpackConversion(aArg3)); + if (NS_FAILED(rv)) { + return rv; + } + WarnAboutTrailingData(); + return NS_OK; + } +}; + +void +BluetoothDaemonCoreModule::AclStateChangedNtf( + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) +{ + AclStateChangedNotification::Dispatch( + &BluetoothNotificationHandler::AclStateChangedNotification, + AclStateChangedInitOp(aPDU)); +} + +// Init operator class for DutModeRecvNotification +class BluetoothDaemonCoreModule::DutModeRecvInitOp final + : private PDUInitOp +{ +public: + DutModeRecvInitOp(DaemonSocketPDU& aPDU) + : PDUInitOp(aPDU) + { } + + nsresult + operator () (uint16_t& aArg1, nsAutoArrayPtr& aArg2, + uint8_t& aArg3) const + { + DaemonSocketPDU& pdu = GetPDU(); + + /* Read opcode */ + nsresult rv = UnpackPDU(pdu, aArg1); + if (NS_FAILED(rv)) { + return rv; + } + + /* Read length */ + rv = UnpackPDU(pdu, aArg3); + if (NS_FAILED(rv)) { + return rv; + } + + /* Read data */ + rv = UnpackPDU(pdu, UnpackArray(aArg2, aArg3)); + if (NS_FAILED(rv)) { + return rv; + } + WarnAboutTrailingData(); + return NS_OK; + } +}; + +void +BluetoothDaemonCoreModule::DutModeRecvNtf( + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) +{ + DutModeRecvNotification::Dispatch( + &BluetoothNotificationHandler::DutModeRecvNotification, + DutModeRecvInitOp(aPDU)); +} + +void +BluetoothDaemonCoreModule::LeTestModeNtf( + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU) +{ + LeTestModeNotification::Dispatch( + &BluetoothNotificationHandler::LeTestModeNotification, + UnpackPDUInitOp(aPDU)); +} + +void +BluetoothDaemonCoreModule::HandleNtf( + const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, + DaemonSocketResultHandler* aRes) +{ + static void (BluetoothDaemonCoreModule::* const HandleNtf[])( + const DaemonSocketPDUHeader&, DaemonSocketPDU&) = { + [0] = &BluetoothDaemonCoreModule::AdapterStateChangedNtf, + [1] = &BluetoothDaemonCoreModule::AdapterPropertiesNtf, + [2] = &BluetoothDaemonCoreModule::RemoteDevicePropertiesNtf, + [3] = &BluetoothDaemonCoreModule::DeviceFoundNtf, + [4] = &BluetoothDaemonCoreModule::DiscoveryStateChangedNtf, + [5] = &BluetoothDaemonCoreModule::PinRequestNtf, + [6] = &BluetoothDaemonCoreModule::SspRequestNtf, + [7] = &BluetoothDaemonCoreModule::BondStateChangedNtf, + [8] = &BluetoothDaemonCoreModule::AclStateChangedNtf, + [9] = &BluetoothDaemonCoreModule::DutModeRecvNtf, + [10] = &BluetoothDaemonCoreModule::LeTestModeNtf + }; + + MOZ_ASSERT(!NS_IsMainThread()); + + uint8_t index = aHeader.mOpcode - 0x81; + + if (NS_WARN_IF(!(index < MOZ_ARRAY_LENGTH(HandleNtf))) || + NS_WARN_IF(!HandleNtf[index])) { + return; + } + + (this->*(HandleNtf[index]))(aHeader, aPDU); +} + +END_BLUETOOTH_NAMESPACE diff --git a/dom/bluetooth/bluedroid/BluetoothDaemonCoreInterface.h b/dom/bluetooth/bluedroid/BluetoothDaemonCoreInterface.h new file mode 100644 index 000000000000..a79502297181 --- /dev/null +++ b/dom/bluetooth/bluedroid/BluetoothDaemonCoreInterface.h @@ -0,0 +1,308 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#ifndef mozilla_dom_bluetooth_bluedroid_BluetoothDaemonCoreInterface_h +#define mozilla_dom_bluetooth_bluedroid_BluetoothDaemonCoreInterface_h + +#include "BluetoothDaemonHelpers.h" +#include "BluetoothInterface.h" +#include "mozilla/ipc/DaemonRunnables.h" + +BEGIN_BLUETOOTH_NAMESPACE + +using mozilla::ipc::DaemonSocketPDU; +using mozilla::ipc::DaemonSocketPDUHeader; +using mozilla::ipc::DaemonSocketResultHandler; + +class BluetoothDaemonCoreModule +{ +public: + + static const int MAX_NUM_CLIENTS; + + virtual nsresult Send(DaemonSocketPDU* aPDU, + DaemonSocketResultHandler* aRes) = 0; + + void SetNotificationHandler( + BluetoothNotificationHandler* aNotificationHandler); + + BluetoothNotificationHandler* GetNotificationHandler(); + + // + // Commands + // + + nsresult EnableCmd(BluetoothResultHandler* aRes); + + nsresult DisableCmd(BluetoothResultHandler* aRes); + + nsresult GetAdapterPropertiesCmd(BluetoothResultHandler* aRes); + + nsresult GetAdapterPropertyCmd(const nsAString& aName, + BluetoothResultHandler* aRes); + + nsresult SetAdapterPropertyCmd(const BluetoothNamedValue& aProperty, + BluetoothResultHandler* aRes); + + nsresult GetRemoteDevicePropertiesCmd(const nsAString& aRemoteAddr, + BluetoothResultHandler* aRes); + + nsresult GetRemoteDevicePropertyCmd(const nsAString& aRemoteAddr, + const nsAString& aName, + BluetoothResultHandler* aRes); + + nsresult SetRemoteDevicePropertyCmd(const nsAString& aRemoteAddr, + const BluetoothNamedValue& aProperty, + BluetoothResultHandler* aRes); + + nsresult GetRemoteServiceRecordCmd(const nsAString& aRemoteAddr, + const uint8_t aUuid[16], + BluetoothResultHandler* aRes); + + nsresult GetRemoteServicesCmd(const nsAString& aRemoteAddr, + BluetoothResultHandler* aRes); + + nsresult StartDiscoveryCmd(BluetoothResultHandler* aRes); + + nsresult CancelDiscoveryCmd(BluetoothResultHandler* aRes); + + nsresult CreateBondCmd(const nsAString& aBdAddr, + BluetoothTransport aTransport, + BluetoothResultHandler* aRes); + + nsresult RemoveBondCmd(const nsAString& aBdAddr, + BluetoothResultHandler* aRes); + + nsresult CancelBondCmd(const nsAString& aBdAddr, + BluetoothResultHandler* aRes); + + nsresult PinReplyCmd(const nsAString& aBdAddr, bool aAccept, + const nsAString& aPinCode, + BluetoothResultHandler* aRes); + + nsresult SspReplyCmd(const nsAString& aBdAddr, BluetoothSspVariant aVariant, + bool aAccept, uint32_t aPasskey, + BluetoothResultHandler* aRes); + + nsresult DutModeConfigureCmd(bool aEnable, BluetoothResultHandler* aRes); + + nsresult DutModeSendCmd(uint16_t aOpcode, uint8_t* aBuf, uint8_t aLen, + BluetoothResultHandler* aRes); + + nsresult LeTestModeCmd(uint16_t aOpcode, uint8_t* aBuf, uint8_t aLen, + BluetoothResultHandler* aRes); + +protected: + void HandleSvc(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, DaemonSocketResultHandler* aRes); + +private: + + // + // Responses + // + + typedef mozilla::ipc::DaemonResultRunnable0< + BluetoothResultHandler, void> + ResultRunnable; + + typedef mozilla::ipc::DaemonResultRunnable1< + BluetoothResultHandler, void, BluetoothStatus, BluetoothStatus> + ErrorRunnable; + + void ErrorRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, + BluetoothResultHandler* aRes); + + void EnableRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, + BluetoothResultHandler* aRes); + + void DisableRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, + BluetoothResultHandler* aRes); + + void GetAdapterPropertiesRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, + BluetoothResultHandler* aRes); + + void GetAdapterPropertyRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, + BluetoothResultHandler* aRes); + + void SetAdapterPropertyRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, + BluetoothResultHandler* aRes); + + void GetRemoteDevicePropertiesRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, + BluetoothResultHandler* aRes); + + void + GetRemoteDevicePropertyRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, + BluetoothResultHandler* aRes); + + void SetRemoteDevicePropertyRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, + BluetoothResultHandler* aRes); + void GetRemoteServiceRecordRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, + BluetoothResultHandler* aRes); + void GetRemoteServicesRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, + BluetoothResultHandler* aRes); + + void StartDiscoveryRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, + BluetoothResultHandler* aRes); + void CancelDiscoveryRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, + BluetoothResultHandler* aRes); + + void CreateBondRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, + BluetoothResultHandler* aRes); + void RemoveBondRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, + BluetoothResultHandler* aRes); + void CancelBondRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, + BluetoothResultHandler* aRes); + + void PinReplyRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, + BluetoothResultHandler* aRes); + void SspReplyRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, + BluetoothResultHandler* aRes); + + void DutModeConfigureRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, + BluetoothResultHandler* aRes); + + void DutModeSendRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, + BluetoothResultHandler* aRes); + + void LeTestModeRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, + BluetoothResultHandler* aRes); + + void HandleRsp(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, DaemonSocketResultHandler* aRes); + + // + // Notifications + // + + class NotificationHandlerWrapper; + + typedef mozilla::ipc::DaemonNotificationRunnable1< + NotificationHandlerWrapper, void, bool> + AdapterStateChangedNotification; + + typedef mozilla::ipc::DaemonNotificationRunnable3< + NotificationHandlerWrapper, void, BluetoothStatus, int, + nsAutoArrayPtr, BluetoothStatus, int, + const BluetoothProperty*> + AdapterPropertiesNotification; + + typedef mozilla::ipc::DaemonNotificationRunnable4< + NotificationHandlerWrapper, void, BluetoothStatus, nsString, int, + nsAutoArrayPtr, BluetoothStatus, const nsAString&, + int, const BluetoothProperty*> + RemoteDevicePropertiesNotification; + + typedef mozilla::ipc::DaemonNotificationRunnable2< + NotificationHandlerWrapper, void, int, nsAutoArrayPtr, + int, const BluetoothProperty*> + DeviceFoundNotification; + + typedef mozilla::ipc::DaemonNotificationRunnable1< + NotificationHandlerWrapper, void, bool> + DiscoveryStateChangedNotification; + + typedef mozilla::ipc::DaemonNotificationRunnable3< + NotificationHandlerWrapper, void, nsString, nsString, uint32_t, + const nsAString&, const nsAString&> + PinRequestNotification; + + typedef mozilla::ipc::DaemonNotificationRunnable5< + NotificationHandlerWrapper, void, nsString, nsString, uint32_t, + BluetoothSspVariant, uint32_t, const nsAString&, const nsAString&> + SspRequestNotification; + + typedef mozilla::ipc::DaemonNotificationRunnable3< + NotificationHandlerWrapper, void, BluetoothStatus, nsString, + BluetoothBondState, BluetoothStatus, const nsAString&> + BondStateChangedNotification; + + typedef mozilla::ipc::DaemonNotificationRunnable3< + NotificationHandlerWrapper, void, BluetoothStatus, nsString, bool, + BluetoothStatus, const nsAString&> + AclStateChangedNotification; + + typedef mozilla::ipc::DaemonNotificationRunnable3< + NotificationHandlerWrapper, void, uint16_t, nsAutoArrayPtr, + uint8_t, uint16_t, const uint8_t*> + DutModeRecvNotification; + + typedef mozilla::ipc::DaemonNotificationRunnable2< + NotificationHandlerWrapper, void, BluetoothStatus, uint16_t> + LeTestModeNotification; + + class AclStateChangedInitOp; + class AdapterPropertiesInitOp; + class BondStateChangedInitOp; + class DeviceFoundInitOp; + class DutModeRecvInitOp; + class PinRequestInitOp; + class RemoteDevicePropertiesInitOp; + class SspRequestInitOp; + + void AdapterStateChangedNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); + + void AdapterPropertiesNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); + + void RemoteDevicePropertiesNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); + + void DeviceFoundNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); + + void DiscoveryStateChangedNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); + + void PinRequestNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); + + void SspRequestNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); + + void BondStateChangedNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); + + void AclStateChangedNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); + + void DutModeRecvNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); + + void LeTestModeNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU); + + void HandleNtf(const DaemonSocketPDUHeader& aHeader, + DaemonSocketPDU& aPDU, DaemonSocketResultHandler* aRes); + + static BluetoothNotificationHandler* sNotificationHandler; +}; + +END_BLUETOOTH_NAMESPACE + +#endif // mozilla_dom_bluetooth_bluedroid_BluetoothDaemonCoreInterface_h diff --git a/dom/bluetooth/bluedroid/BluetoothDaemonInterface.cpp b/dom/bluetooth/bluedroid/BluetoothDaemonInterface.cpp index 0f5069f5e1fa..94733752af1e 100644 --- a/dom/bluetooth/bluedroid/BluetoothDaemonInterface.cpp +++ b/dom/bluetooth/bluedroid/BluetoothDaemonInterface.cpp @@ -10,6 +10,7 @@ #include #include "BluetoothDaemonA2dpInterface.h" #include "BluetoothDaemonAvrcpInterface.h" +#include "BluetoothDaemonCoreInterface.h" #include "BluetoothDaemonGattInterface.h" #include "BluetoothDaemonHandsfreeInterface.h" #include "BluetoothDaemonHelpers.h" @@ -27,1174 +28,6 @@ using namespace mozilla::ipc; static const int sRetryInterval = 100; // ms -// -// Core module -// - -static BluetoothNotificationHandler* sNotificationHandler; - -class BluetoothDaemonCoreModule -{ -public: - - static const int MAX_NUM_CLIENTS; - - virtual nsresult Send(DaemonSocketPDU* aPDU, - DaemonSocketResultHandler* aRes) = 0; - - nsresult EnableCmd(BluetoothResultHandler* aRes) - { - MOZ_ASSERT(NS_IsMainThread()); - - nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x01, 0)); - - nsresult rv = Send(pdu, aRes); - if (NS_FAILED(rv)) { - return rv; - } - unused << pdu.forget(); - return rv; - } - - nsresult DisableCmd(BluetoothResultHandler* aRes) - { - MOZ_ASSERT(NS_IsMainThread()); - - nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x02, 0)); - - nsresult rv = Send(pdu, aRes); - if (NS_FAILED(rv)) { - return rv; - } - unused << pdu.forget(); - return rv; - } - - nsresult GetAdapterPropertiesCmd(BluetoothResultHandler* aRes) - { - MOZ_ASSERT(NS_IsMainThread()); - - nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x03, 0)); - - nsresult rv = Send(pdu, aRes); - if (NS_FAILED(rv)) { - return rv; - } - unused << pdu.forget(); - return rv; - } - - nsresult GetAdapterPropertyCmd(const nsAString& aName, - BluetoothResultHandler* aRes) - { - MOZ_ASSERT(NS_IsMainThread()); - - nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x04, 0)); - - nsresult rv = PackPDU( - PackConversion(aName), *pdu); - if (NS_FAILED(rv)) { - return rv; - } - rv = Send(pdu, aRes); - if (NS_FAILED(rv)) { - return rv; - } - unused << pdu.forget(); - return rv; - } - - nsresult SetAdapterPropertyCmd(const BluetoothNamedValue& aProperty, - BluetoothResultHandler* aRes) - { - MOZ_ASSERT(NS_IsMainThread()); - - nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x05, 0)); - - nsresult rv = PackPDU(aProperty, *pdu); - if (NS_FAILED(rv)) { - return rv; - } - rv = Send(pdu, aRes); - if (NS_FAILED(rv)) { - return rv; - } - unused << pdu.forget(); - return rv; - } - - nsresult GetRemoteDevicePropertiesCmd(const nsAString& aRemoteAddr, - BluetoothResultHandler* aRes) - { - MOZ_ASSERT(NS_IsMainThread()); - - nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x06, 0)); - - nsresult rv = PackPDU( - PackConversion(aRemoteAddr), *pdu); - if (NS_FAILED(rv)) { - return rv; - } - rv = Send(pdu, aRes); - if (NS_FAILED(rv)) { - return rv; - } - unused << pdu.forget(); - return rv; - } - - nsresult GetRemoteDevicePropertyCmd(const nsAString& aRemoteAddr, - const nsAString& aName, - BluetoothResultHandler* aRes) - { - MOZ_ASSERT(NS_IsMainThread()); - - nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x07, 0)); - - nsresult rv = PackPDU( - PackConversion(aRemoteAddr), - PackConversion(aName), *pdu); - if (NS_FAILED(rv)) { - return rv; - } - rv = Send(pdu, aRes); - if (NS_FAILED(rv)) { - return rv; - } - unused << pdu.forget(); - return rv; - } - - nsresult SetRemoteDevicePropertyCmd(const nsAString& aRemoteAddr, - const BluetoothNamedValue& aProperty, - BluetoothResultHandler* aRes) - { - MOZ_ASSERT(NS_IsMainThread()); - - nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x08, 0)); - - nsresult rv = PackPDU( - PackConversion(aRemoteAddr), - aProperty, *pdu); - if (NS_FAILED(rv)) { - return rv; - } - rv = Send(pdu, aRes); - if (NS_FAILED(rv)) { - return rv; - } - unused << pdu.forget(); - return rv; - } - - nsresult GetRemoteServiceRecordCmd(const nsAString& aRemoteAddr, - const uint8_t aUuid[16], - BluetoothResultHandler* aRes) - { - MOZ_ASSERT(NS_IsMainThread()); - - nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x09, 0)); - - nsresult rv = PackPDU( - PackConversion(aRemoteAddr), - PackArray(aUuid, 16), *pdu); - if (NS_FAILED(rv)) { - return rv; - } - rv = Send(pdu, aRes); - if (NS_FAILED(rv)) { - return rv; - } - unused << pdu.forget(); - return rv; - } - - nsresult GetRemoteServicesCmd(const nsAString& aRemoteAddr, - BluetoothResultHandler* aRes) - { - MOZ_ASSERT(NS_IsMainThread()); - - nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x0a, 0)); - - nsresult rv = PackPDU( - PackConversion(aRemoteAddr), *pdu); - if (NS_FAILED(rv)) { - return rv; - } - rv = Send(pdu, aRes); - if (NS_FAILED(rv)) { - return rv; - } - unused << pdu.forget(); - return rv; - } - - nsresult StartDiscoveryCmd(BluetoothResultHandler* aRes) - { - MOZ_ASSERT(NS_IsMainThread()); - - nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x0b, 0)); - - nsresult rv = Send(pdu, aRes); - if (NS_FAILED(rv)) { - return rv; - } - unused << pdu.forget(); - return rv; - } - - nsresult CancelDiscoveryCmd(BluetoothResultHandler* aRes) - { - MOZ_ASSERT(NS_IsMainThread()); - - nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x0c, 0)); - - nsresult rv = Send(pdu, aRes); - if (NS_FAILED(rv)) { - return rv; - } - unused << pdu.forget(); - return rv; - } - - nsresult CreateBondCmd(const nsAString& aBdAddr, - BluetoothTransport aTransport, - BluetoothResultHandler* aRes) - { - MOZ_ASSERT(NS_IsMainThread()); - - nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x0d, 0)); - -#if ANDROID_VERSION >= 21 - nsresult rv = PackPDU( - PackConversion(aBdAddr), aTransport, *pdu); -#else - nsresult rv = PackPDU( - PackConversion(aBdAddr), *pdu); -#endif - if (NS_FAILED(rv)) { - return rv; - } - rv = Send(pdu, aRes); - if (NS_FAILED(rv)) { - return rv; - } - unused << pdu.forget(); - return rv; - } - - nsresult RemoveBondCmd(const nsAString& aBdAddr, - BluetoothResultHandler* aRes) - { - MOZ_ASSERT(NS_IsMainThread()); - - nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x0e, 0)); - - nsresult rv = PackPDU( - PackConversion(aBdAddr), *pdu); - if (NS_FAILED(rv)) { - return rv; - } - rv = Send(pdu, aRes); - if (NS_FAILED(rv)) { - return rv; - } - unused << pdu.forget(); - return rv; - } - - nsresult CancelBondCmd(const nsAString& aBdAddr, - BluetoothResultHandler* aRes) - { - MOZ_ASSERT(NS_IsMainThread()); - - nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x0f, 0)); - - nsresult rv = PackPDU( - PackConversion(aBdAddr), *pdu); - if (NS_FAILED(rv)) { - return rv; - } - rv = Send(pdu, aRes); - if (NS_FAILED(rv)) { - return rv; - } - unused << pdu.forget(); - return rv; - } - - nsresult PinReplyCmd(const nsAString& aBdAddr, bool aAccept, - const nsAString& aPinCode, - BluetoothResultHandler* aRes) - { - MOZ_ASSERT(NS_IsMainThread()); - - nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x10, 0)); - - nsresult rv = PackPDU( - PackConversion(aBdAddr), - aAccept, - PackConversion(aPinCode), *pdu); - if (NS_FAILED(rv)) { - return rv; - } - rv = Send(pdu, aRes); - if (NS_FAILED(rv)) { - return rv; - } - unused << pdu.forget(); - return rv; - } - - nsresult SspReplyCmd(const nsAString& aBdAddr, BluetoothSspVariant aVariant, - bool aAccept, uint32_t aPasskey, - BluetoothResultHandler* aRes) - { - MOZ_ASSERT(NS_IsMainThread()); - - nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x11, 0)); - - nsresult rv = PackPDU( - PackConversion(aBdAddr), - aVariant, aAccept, aPasskey, *pdu); - if (NS_FAILED(rv)) { - return rv; - } - rv = Send(pdu, aRes); - if (NS_FAILED(rv)) { - return rv; - } - unused << pdu.forget(); - return rv; - } - - nsresult DutModeConfigureCmd(bool aEnable, BluetoothResultHandler* aRes) - { - MOZ_ASSERT(NS_IsMainThread()); - - nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x12, 0)); - - nsresult rv = PackPDU(aEnable, *pdu); - if (NS_FAILED(rv)) { - return rv; - } - rv = Send(pdu, aRes); - if (NS_FAILED(rv)) { - return rv; - } - unused << pdu.forget(); - return rv; - } - - nsresult DutModeSendCmd(uint16_t aOpcode, uint8_t* aBuf, uint8_t aLen, - BluetoothResultHandler* aRes) - { - MOZ_ASSERT(NS_IsMainThread()); - - nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x13, 0)); - - nsresult rv = PackPDU(aOpcode, aLen, PackArray(aBuf, aLen), - *pdu); - if (NS_FAILED(rv)) { - return rv; - } - rv = Send(pdu, aRes); - if (NS_FAILED(rv)) { - return rv; - } - unused << pdu.forget(); - return rv; - } - - nsresult LeTestModeCmd(uint16_t aOpcode, uint8_t* aBuf, uint8_t aLen, - BluetoothResultHandler* aRes) - { - MOZ_ASSERT(NS_IsMainThread()); - - nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x14, 0)); - - nsresult rv = PackPDU(aOpcode, aLen, PackArray(aBuf, aLen), - *pdu); - if (NS_FAILED(rv)) { - return rv; - } - rv = Send(pdu, aRes); - if (NS_FAILED(rv)) { - return rv; - } - unused << pdu.forget(); - return rv; - } - -protected: - - void HandleSvc(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU, DaemonSocketResultHandler* aRes) - { - static void (BluetoothDaemonCoreModule::* const HandleOp[])( - const DaemonSocketPDUHeader&, DaemonSocketPDU&, - DaemonSocketResultHandler*) = { - [0] = &BluetoothDaemonCoreModule::HandleRsp, - [1] = &BluetoothDaemonCoreModule::HandleNtf - }; - - MOZ_ASSERT(!NS_IsMainThread()); - - (this->*(HandleOp[!!(aHeader.mOpcode & 0x80)]))(aHeader, aPDU, aRes); - } - -private: - - // Responses - // - - typedef mozilla::ipc::DaemonResultRunnable0< - BluetoothResultHandler, void> - ResultRunnable; - - typedef mozilla::ipc::DaemonResultRunnable1< - BluetoothResultHandler, void, BluetoothStatus, BluetoothStatus> - ErrorRunnable; - - void ErrorRsp(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU, - BluetoothResultHandler* aRes) - { - ErrorRunnable::Dispatch( - aRes, &BluetoothResultHandler::OnError, UnpackPDUInitOp(aPDU)); - } - - void EnableRsp(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU, - BluetoothResultHandler* aRes) - { - ResultRunnable::Dispatch( - aRes, &BluetoothResultHandler::Enable, UnpackPDUInitOp(aPDU)); - } - - void DisableRsp(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU, - BluetoothResultHandler* aRes) - { - ResultRunnable::Dispatch( - aRes, &BluetoothResultHandler::Disable, UnpackPDUInitOp(aPDU)); - } - - void GetAdapterPropertiesRsp(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU, - BluetoothResultHandler* aRes) - { - ResultRunnable::Dispatch( - aRes, &BluetoothResultHandler::GetAdapterProperties, - UnpackPDUInitOp(aPDU)); - } - - void GetAdapterPropertyRsp(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU, - BluetoothResultHandler* aRes) - { - ResultRunnable::Dispatch( - aRes, &BluetoothResultHandler::GetAdapterProperty, - UnpackPDUInitOp(aPDU)); - } - - void SetAdapterPropertyRsp(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU, - BluetoothResultHandler* aRes) - { - ResultRunnable::Dispatch( - aRes, &BluetoothResultHandler::SetAdapterProperty, - UnpackPDUInitOp(aPDU)); - } - - void GetRemoteDevicePropertiesRsp(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU, - BluetoothResultHandler* aRes) - { - ResultRunnable::Dispatch( - aRes, &BluetoothResultHandler::GetRemoteDeviceProperties, - UnpackPDUInitOp(aPDU)); - } - - void - GetRemoteDevicePropertyRsp(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU, - BluetoothResultHandler* aRes) - { - ResultRunnable::Dispatch( - aRes, &BluetoothResultHandler::GetRemoteDeviceProperty, - UnpackPDUInitOp(aPDU)); - } - - void SetRemoteDevicePropertyRsp(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU, - BluetoothResultHandler* aRes) - { - ResultRunnable::Dispatch( - aRes, &BluetoothResultHandler::SetRemoteDeviceProperty, - UnpackPDUInitOp(aPDU)); - } - - void GetRemoteServiceRecordRsp(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU, - BluetoothResultHandler* aRes) - { - ResultRunnable::Dispatch( - aRes, &BluetoothResultHandler::GetRemoteServiceRecord, - UnpackPDUInitOp(aPDU)); - } - - void GetRemoteServicesRsp(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU, - BluetoothResultHandler* aRes) - { - ResultRunnable::Dispatch( - aRes, &BluetoothResultHandler::GetRemoteServices, - UnpackPDUInitOp(aPDU)); - } - - void StartDiscoveryRsp(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU, - BluetoothResultHandler* aRes) - { - ResultRunnable::Dispatch( - aRes, &BluetoothResultHandler::StartDiscovery, - UnpackPDUInitOp(aPDU)); - } - - void CancelDiscoveryRsp(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU, - BluetoothResultHandler* aRes) - { - ResultRunnable::Dispatch( - aRes, &BluetoothResultHandler::CancelDiscovery, - UnpackPDUInitOp(aPDU)); - } - - void CreateBondRsp(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU, - BluetoothResultHandler* aRes) - { - ResultRunnable::Dispatch( - aRes, &BluetoothResultHandler::CreateBond, - UnpackPDUInitOp(aPDU)); - } - - void RemoveBondRsp(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU, - BluetoothResultHandler* aRes) - { - ResultRunnable::Dispatch( - aRes, &BluetoothResultHandler::RemoveBond, - UnpackPDUInitOp(aPDU)); - } - - void CancelBondRsp(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU, - BluetoothResultHandler* aRes) - { - ResultRunnable::Dispatch( - aRes, &BluetoothResultHandler::CancelBond, - UnpackPDUInitOp(aPDU)); - } - - void PinReplyRsp(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU, - BluetoothResultHandler* aRes) - { - ResultRunnable::Dispatch( - aRes, &BluetoothResultHandler::PinReply, - UnpackPDUInitOp(aPDU)); - } - - void SspReplyRsp(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU, - BluetoothResultHandler* aRes) - { - ResultRunnable::Dispatch( - aRes, &BluetoothResultHandler::SspReply, - UnpackPDUInitOp(aPDU)); - } - - void DutModeConfigureRsp(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU, - BluetoothResultHandler* aRes) - { - ResultRunnable::Dispatch( - aRes, &BluetoothResultHandler::DutModeConfigure, - UnpackPDUInitOp(aPDU)); - } - - void DutModeSendRsp(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU, - BluetoothResultHandler* aRes) - { - ResultRunnable::Dispatch( - aRes, &BluetoothResultHandler::DutModeSend, - UnpackPDUInitOp(aPDU)); - } - - void LeTestModeRsp(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU, - BluetoothResultHandler* aRes) - { - ResultRunnable::Dispatch( - aRes, &BluetoothResultHandler::LeTestMode, - UnpackPDUInitOp(aPDU)); - } - - void HandleRsp(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU, DaemonSocketResultHandler* aRes) - { - static void (BluetoothDaemonCoreModule::* const HandleRsp[])( - const DaemonSocketPDUHeader&, - DaemonSocketPDU&, - BluetoothResultHandler*) = { - [0x00] = &BluetoothDaemonCoreModule::ErrorRsp, - [0x01] = &BluetoothDaemonCoreModule::EnableRsp, - [0x02] = &BluetoothDaemonCoreModule::DisableRsp, - [0x03] = &BluetoothDaemonCoreModule::GetAdapterPropertiesRsp, - [0x04] = &BluetoothDaemonCoreModule::GetAdapterPropertyRsp, - [0x05] = &BluetoothDaemonCoreModule::SetAdapterPropertyRsp, - [0x06] = &BluetoothDaemonCoreModule::GetRemoteDevicePropertiesRsp, - [0x07] = &BluetoothDaemonCoreModule::GetRemoteDevicePropertyRsp, - [0x08] = &BluetoothDaemonCoreModule::SetRemoteDevicePropertyRsp, - [0x09] = &BluetoothDaemonCoreModule::GetRemoteServiceRecordRsp, - [0x0a] = &BluetoothDaemonCoreModule::GetRemoteServicesRsp, - [0x0b] = &BluetoothDaemonCoreModule::StartDiscoveryRsp, - [0x0c] = &BluetoothDaemonCoreModule::CancelDiscoveryRsp, - [0x0d] = &BluetoothDaemonCoreModule::CreateBondRsp, - [0x0e] = &BluetoothDaemonCoreModule::RemoveBondRsp, - [0x0f] = &BluetoothDaemonCoreModule::CancelBondRsp, - [0x10] = &BluetoothDaemonCoreModule::PinReplyRsp, - [0x11] = &BluetoothDaemonCoreModule::SspReplyRsp, - [0x12] = &BluetoothDaemonCoreModule::DutModeConfigureRsp, - [0x13] = &BluetoothDaemonCoreModule::DutModeSendRsp, - [0x14] = &BluetoothDaemonCoreModule::LeTestModeRsp, - }; - - MOZ_ASSERT(!NS_IsMainThread()); - - if (NS_WARN_IF(!(aHeader.mOpcode < MOZ_ARRAY_LENGTH(HandleRsp))) || - NS_WARN_IF(!HandleRsp[aHeader.mOpcode])) { - return; - } - - nsRefPtr res = - static_cast(aRes); - - if (!res) { - return; // Return early if no result handler has been set for response - } - - (this->*(HandleRsp[aHeader.mOpcode]))(aHeader, aPDU, res); - } - - // Notifications - // - - class NotificationHandlerWrapper - { - public: - typedef BluetoothNotificationHandler ObjectType; - - static ObjectType* GetInstance() - { - MOZ_ASSERT(NS_IsMainThread()); - - return sNotificationHandler; - } - }; - - typedef mozilla::ipc::DaemonNotificationRunnable1< - NotificationHandlerWrapper, void, bool> - AdapterStateChangedNotification; - - typedef mozilla::ipc::DaemonNotificationRunnable3< - NotificationHandlerWrapper, void, BluetoothStatus, int, - nsAutoArrayPtr, BluetoothStatus, int, - const BluetoothProperty*> - AdapterPropertiesNotification; - - typedef mozilla::ipc::DaemonNotificationRunnable4< - NotificationHandlerWrapper, void, BluetoothStatus, nsString, int, - nsAutoArrayPtr, BluetoothStatus, const nsAString&, - int, const BluetoothProperty*> - RemoteDevicePropertiesNotification; - - typedef mozilla::ipc::DaemonNotificationRunnable2< - NotificationHandlerWrapper, void, int, nsAutoArrayPtr, - int, const BluetoothProperty*> - DeviceFoundNotification; - - typedef mozilla::ipc::DaemonNotificationRunnable1< - NotificationHandlerWrapper, void, bool> - DiscoveryStateChangedNotification; - - typedef mozilla::ipc::DaemonNotificationRunnable3< - NotificationHandlerWrapper, void, nsString, nsString, uint32_t, - const nsAString&, const nsAString&> - PinRequestNotification; - - typedef mozilla::ipc::DaemonNotificationRunnable5< - NotificationHandlerWrapper, void, nsString, nsString, uint32_t, - BluetoothSspVariant, uint32_t, const nsAString&, const nsAString&> - SspRequestNotification; - - typedef mozilla::ipc::DaemonNotificationRunnable3< - NotificationHandlerWrapper, void, BluetoothStatus, nsString, - BluetoothBondState, BluetoothStatus, const nsAString&> - BondStateChangedNotification; - - typedef mozilla::ipc::DaemonNotificationRunnable3< - NotificationHandlerWrapper, void, BluetoothStatus, nsString, bool, - BluetoothStatus, const nsAString&> - AclStateChangedNotification; - - typedef mozilla::ipc::DaemonNotificationRunnable3< - NotificationHandlerWrapper, void, uint16_t, nsAutoArrayPtr, - uint8_t, uint16_t, const uint8_t*> - DutModeRecvNotification; - - typedef mozilla::ipc::DaemonNotificationRunnable2< - NotificationHandlerWrapper, void, BluetoothStatus, uint16_t> - LeTestModeNotification; - - void AdapterStateChangedNtf(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU) - { - AdapterStateChangedNotification::Dispatch( - &BluetoothNotificationHandler::AdapterStateChangedNotification, - UnpackPDUInitOp(aPDU)); - } - - // Init operator class for AdapterPropertiesNotification - class AdapterPropertiesInitOp final : private PDUInitOp - { - public: - AdapterPropertiesInitOp(DaemonSocketPDU& aPDU) - : PDUInitOp(aPDU) - { } - - nsresult - operator () (BluetoothStatus& aArg1, int& aArg2, - nsAutoArrayPtr& aArg3) const - { - DaemonSocketPDU& pdu = GetPDU(); - - /* Read status */ - nsresult rv = UnpackPDU(pdu, aArg1); - if (NS_FAILED(rv)) { - return rv; - } - - /* Read number of properties */ - uint8_t numProperties; - rv = UnpackPDU(pdu, numProperties); - if (NS_FAILED(rv)) { - return rv; - } - aArg2 = numProperties; - - /* Read properties array */ - UnpackArray properties(aArg3, aArg2); - rv = UnpackPDU(pdu, properties); - if (NS_FAILED(rv)) { - return rv; - } - WarnAboutTrailingData(); - return NS_OK; - } - }; - - void AdapterPropertiesNtf(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU) - { - AdapterPropertiesNotification::Dispatch( - &BluetoothNotificationHandler::AdapterPropertiesNotification, - AdapterPropertiesInitOp(aPDU)); - } - - // Init operator class for RemoteDevicePropertiesNotification - class RemoteDevicePropertiesInitOp final : private PDUInitOp - { - public: - RemoteDevicePropertiesInitOp(DaemonSocketPDU& aPDU) - : PDUInitOp(aPDU) - { } - - nsresult - operator () (BluetoothStatus& aArg1, nsString& aArg2, int& aArg3, - nsAutoArrayPtr& aArg4) const - { - DaemonSocketPDU& pdu = GetPDU(); - - /* Read status */ - nsresult rv = UnpackPDU(pdu, aArg1); - if (NS_FAILED(rv)) { - return rv; - } - - /* Read address */ - rv = UnpackPDU( - pdu, UnpackConversion(aArg2)); - if (NS_FAILED(rv)) { - return rv; - } - - /* Read number of properties */ - uint8_t numProperties; - rv = UnpackPDU(pdu, numProperties); - if (NS_FAILED(rv)) { - return rv; - } - aArg3 = numProperties; - - /* Read properties array */ - UnpackArray properties(aArg4, aArg3); - rv = UnpackPDU(pdu, properties); - if (NS_FAILED(rv)) { - return rv; - } - WarnAboutTrailingData(); - return NS_OK; - } - }; - - void RemoteDevicePropertiesNtf(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU) - { - RemoteDevicePropertiesNotification::Dispatch( - &BluetoothNotificationHandler::RemoteDevicePropertiesNotification, - RemoteDevicePropertiesInitOp(aPDU)); - } - - // Init operator class for DeviceFoundNotification - class DeviceFoundInitOp final : private PDUInitOp - { - public: - DeviceFoundInitOp(DaemonSocketPDU& aPDU) - : PDUInitOp(aPDU) - { } - - nsresult - operator () (int& aArg1, nsAutoArrayPtr& aArg2) const - { - DaemonSocketPDU& pdu = GetPDU(); - - /* Read number of properties */ - uint8_t numProperties; - nsresult rv = UnpackPDU(pdu, numProperties); - if (NS_FAILED(rv)) { - return rv; - } - aArg1 = numProperties; - - /* Read properties array */ - UnpackArray properties(aArg2, aArg1); - rv = UnpackPDU(pdu, properties); - if (NS_FAILED(rv)) { - return rv; - } - WarnAboutTrailingData(); - return NS_OK; - } - }; - - void DeviceFoundNtf(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU) - { - DeviceFoundNotification::Dispatch( - &BluetoothNotificationHandler::DeviceFoundNotification, - DeviceFoundInitOp(aPDU)); - } - - void DiscoveryStateChangedNtf(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU) - { - DiscoveryStateChangedNotification::Dispatch( - &BluetoothNotificationHandler::DiscoveryStateChangedNotification, - UnpackPDUInitOp(aPDU)); - } - - // Init operator class for PinRequestNotification - class PinRequestInitOp final : private PDUInitOp - { - public: - PinRequestInitOp(DaemonSocketPDU& aPDU) - : PDUInitOp(aPDU) - { } - - nsresult - operator () (nsString& aArg1, nsString& aArg2, uint32_t& aArg3) const - { - DaemonSocketPDU& pdu = GetPDU(); - - /* Read remote address */ - nsresult rv = UnpackPDU( - pdu, UnpackConversion(aArg1)); - if (NS_FAILED(rv)) { - return rv; - } - - /* Read remote name */ - rv = UnpackPDU( - pdu, UnpackConversion(aArg2)); - if (NS_FAILED(rv)) { - return rv; - } - - /* Read CoD */ - rv = UnpackPDU(pdu, aArg3); - if (NS_FAILED(rv)) { - return rv; - } - WarnAboutTrailingData(); - return NS_OK; - } - }; - - void PinRequestNtf(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU) - { - PinRequestNotification::Dispatch( - &BluetoothNotificationHandler::PinRequestNotification, - PinRequestInitOp(aPDU)); - } - - // Init operator class for SspRequestNotification - class SspRequestInitOp final : private PDUInitOp - { - public: - SspRequestInitOp(DaemonSocketPDU& aPDU) - : PDUInitOp(aPDU) - { } - - nsresult - operator () (nsString& aArg1, nsString& aArg2, uint32_t& aArg3, - BluetoothSspVariant& aArg4, uint32_t& aArg5) const - { - DaemonSocketPDU& pdu = GetPDU(); - - /* Read remote address */ - nsresult rv = UnpackPDU( - pdu, UnpackConversion(aArg1)); - if (NS_FAILED(rv)) { - return rv; - } - - /* Read remote name */ - rv = UnpackPDU( - pdu, UnpackConversion(aArg2)); - if (NS_FAILED(rv)) { - return rv; - } - - /* Read CoD */ - rv = UnpackPDU(pdu, aArg3); - if (NS_FAILED(rv)) { - return rv; - } - - /* Read pairing variant */ - rv = UnpackPDU(pdu, aArg4); - if (NS_FAILED(rv)) { - return rv; - } - - /* Read passkey */ - rv = UnpackPDU(pdu, aArg5); - if (NS_FAILED(rv)) { - return rv; - } - WarnAboutTrailingData(); - return NS_OK; - } - }; - - void SspRequestNtf(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU) - { - SspRequestNotification::Dispatch( - &BluetoothNotificationHandler::SspRequestNotification, - SspRequestInitOp(aPDU)); - } - - // Init operator class for BondStateChangedNotification - class BondStateChangedInitOp final : private PDUInitOp - { - public: - BondStateChangedInitOp(DaemonSocketPDU& aPDU) - : PDUInitOp(aPDU) - { } - - nsresult - operator () (BluetoothStatus& aArg1, nsString& aArg2, - BluetoothBondState& aArg3) const - { - DaemonSocketPDU& pdu = GetPDU(); - - /* Read status */ - nsresult rv = UnpackPDU(pdu, aArg1); - if (NS_FAILED(rv)) { - return rv; - } - - /* Read remote address */ - rv = UnpackPDU( - pdu, UnpackConversion(aArg2)); - if (NS_FAILED(rv)) { - return rv; - } - - /* Read bond state */ - rv = UnpackPDU(pdu, aArg3); - if (NS_FAILED(rv)) { - return rv; - } - WarnAboutTrailingData(); - return NS_OK; - } - }; - - void BondStateChangedNtf(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU) - { - BondStateChangedNotification::Dispatch( - &BluetoothNotificationHandler::BondStateChangedNotification, - BondStateChangedInitOp(aPDU)); - } - - // Init operator class for AclStateChangedNotification - class AclStateChangedInitOp final : private PDUInitOp - { - public: - AclStateChangedInitOp(DaemonSocketPDU& aPDU) - : PDUInitOp(aPDU) - { } - - nsresult - operator () (BluetoothStatus& aArg1, nsString& aArg2, bool& aArg3) const - { - DaemonSocketPDU& pdu = GetPDU(); - - /* Read status */ - nsresult rv = UnpackPDU(pdu, aArg1); - if (NS_FAILED(rv)) { - return rv; - } - - /* Read remote address */ - rv = UnpackPDU( - pdu, UnpackConversion(aArg2)); - if (NS_FAILED(rv)) { - return rv; - } - - /* Read ACL state */ - rv = UnpackPDU( - pdu, UnpackConversion(aArg3)); - if (NS_FAILED(rv)) { - return rv; - } - WarnAboutTrailingData(); - return NS_OK; - } - }; - - void AclStateChangedNtf(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU) - { - AclStateChangedNotification::Dispatch( - &BluetoothNotificationHandler::AclStateChangedNotification, - AclStateChangedInitOp(aPDU)); - } - - // Init operator class for DutModeRecvNotification - class DutModeRecvInitOp final : private PDUInitOp - { - public: - DutModeRecvInitOp(DaemonSocketPDU& aPDU) - : PDUInitOp(aPDU) - { } - - nsresult - operator () (uint16_t& aArg1, nsAutoArrayPtr& aArg2, - uint8_t& aArg3) const - { - DaemonSocketPDU& pdu = GetPDU(); - - /* Read opcode */ - nsresult rv = UnpackPDU(pdu, aArg1); - if (NS_FAILED(rv)) { - return rv; - } - - /* Read length */ - rv = UnpackPDU(pdu, aArg3); - if (NS_FAILED(rv)) { - return rv; - } - - /* Read data */ - rv = UnpackPDU(pdu, UnpackArray(aArg2, aArg3)); - if (NS_FAILED(rv)) { - return rv; - } - WarnAboutTrailingData(); - return NS_OK; - } - }; - - void DutModeRecvNtf(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU) - { - DutModeRecvNotification::Dispatch( - &BluetoothNotificationHandler::DutModeRecvNotification, - DutModeRecvInitOp(aPDU)); - } - - void LeTestModeNtf(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU) - { - LeTestModeNotification::Dispatch( - &BluetoothNotificationHandler::LeTestModeNotification, - UnpackPDUInitOp(aPDU)); - } - - void HandleNtf(const DaemonSocketPDUHeader& aHeader, - DaemonSocketPDU& aPDU, DaemonSocketResultHandler* aRes) - { - static void (BluetoothDaemonCoreModule::* const HandleNtf[])( - const DaemonSocketPDUHeader&, DaemonSocketPDU&) = { - [0] = &BluetoothDaemonCoreModule::AdapterStateChangedNtf, - [1] = &BluetoothDaemonCoreModule::AdapterPropertiesNtf, - [2] = &BluetoothDaemonCoreModule::RemoteDevicePropertiesNtf, - [3] = &BluetoothDaemonCoreModule::DeviceFoundNtf, - [4] = &BluetoothDaemonCoreModule::DiscoveryStateChangedNtf, - [5] = &BluetoothDaemonCoreModule::PinRequestNtf, - [6] = &BluetoothDaemonCoreModule::SspRequestNtf, - [7] = &BluetoothDaemonCoreModule::BondStateChangedNtf, - [8] = &BluetoothDaemonCoreModule::AclStateChangedNtf, - [9] = &BluetoothDaemonCoreModule::DutModeRecvNtf, - [10] = &BluetoothDaemonCoreModule::LeTestModeNtf - }; - - MOZ_ASSERT(!NS_IsMainThread()); - - uint8_t index = aHeader.mOpcode - 0x81; - - if (NS_WARN_IF(!(index < MOZ_ARRAY_LENGTH(HandleNtf))) || - NS_WARN_IF(!HandleNtf[index])) { - return; - } - - (this->*(HandleNtf[index]))(aHeader, aPDU); - } -}; - -const int BluetoothDaemonCoreModule::MAX_NUM_CLIENTS = 1; - // // Protocol handling // @@ -1644,13 +477,13 @@ BluetoothDaemonInterface::Init( // here. unused << NS_WARN_IF(property_set("ctl.stop", "bluetoothd")); - sNotificationHandler = aNotificationHandler; - mResultHandlerQ.AppendElement(aRes); if (!mProtocol) { mProtocol = new BluetoothDaemonProtocol(); } + static_cast(mProtocol)->SetNotificationHandler( + aNotificationHandler); if (!mListenSocket) { mListenSocket = new ListenSocket(this, LISTEN_SOCKET); @@ -1760,8 +593,8 @@ private: void BluetoothDaemonInterface::Cleanup(BluetoothResultHandler* aRes) { - - sNotificationHandler = nullptr; + static_cast(mProtocol)->SetNotificationHandler( + nullptr); // Cleanup, step 1: Unregister Socket module nsresult rv = mProtocol->UnregisterModuleCmd( @@ -2246,17 +1079,22 @@ BluetoothDaemonInterface::OnDisconnect(int aIndex) break; } + BluetoothNotificationHandler* notificationHandler = + static_cast(mProtocol)-> + GetNotificationHandler(); + /* For recovery make sure all sockets disconnected, in order to avoid * the remaining disconnects interfere with the restart procedure. */ - if (sNotificationHandler && mResultHandlerQ.IsEmpty()) { + if (notificationHandler && mResultHandlerQ.IsEmpty()) { if (mListenSocket->GetConnectionStatus() == SOCKET_DISCONNECTED && mCmdChannel->GetConnectionStatus() == SOCKET_DISCONNECTED && mNtfChannel->GetConnectionStatus() == SOCKET_DISCONNECTED) { // Assume daemon crashed during regular service; notify // BluetoothServiceBluedroid to prepare restart-daemon procedure - sNotificationHandler->BackendErrorNotification(true); - sNotificationHandler = nullptr; + notificationHandler->BackendErrorNotification(true); + static_cast(mProtocol)-> + SetNotificationHandler(nullptr); } } } diff --git a/dom/bluetooth/moz.build b/dom/bluetooth/moz.build index 48cc87235ae7..65844c35f74c 100644 --- a/dom/bluetooth/moz.build +++ b/dom/bluetooth/moz.build @@ -74,6 +74,7 @@ if CONFIG['MOZ_B2G_BT']: 'bluedroid/BluetoothAvrcpManager.cpp', 'bluedroid/BluetoothDaemonA2dpInterface.cpp', 'bluedroid/BluetoothDaemonAvrcpInterface.cpp', + 'bluedroid/BluetoothDaemonCoreInterface.cpp', 'bluedroid/BluetoothDaemonGattInterface.cpp', 'bluedroid/BluetoothDaemonHandsfreeInterface.cpp', 'bluedroid/BluetoothDaemonHelpers.cpp', From 9da2d90e28558c14ceae4b96a7245cf822d76289 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Thu, 17 Sep 2015 10:08:47 +0200 Subject: [PATCH 088/113] Bug 1205253: Use enum constants for Bluetooth Core module, r=btian --- .../BluetoothDaemonCoreInterface.cpp | 142 +++++++++++++----- .../bluedroid/BluetoothDaemonCoreInterface.h | 38 +++++ .../bluedroid/BluetoothDaemonInterface.cpp | 3 +- 3 files changed, 141 insertions(+), 42 deletions(-) diff --git a/dom/bluetooth/bluedroid/BluetoothDaemonCoreInterface.cpp b/dom/bluetooth/bluedroid/BluetoothDaemonCoreInterface.cpp index cec4110fa4a2..73acd5cc9c65 100644 --- a/dom/bluetooth/bluedroid/BluetoothDaemonCoreInterface.cpp +++ b/dom/bluetooth/bluedroid/BluetoothDaemonCoreInterface.cpp @@ -57,7 +57,9 @@ BluetoothDaemonCoreModule::EnableCmd(BluetoothResultHandler* aRes) { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x01, 0)); + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_ENABLE, + 0)); nsresult rv = Send(pdu, aRes); if (NS_FAILED(rv)) { @@ -72,7 +74,9 @@ BluetoothDaemonCoreModule::DisableCmd(BluetoothResultHandler* aRes) { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x02, 0)); + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_DISABLE, + 0)); nsresult rv = Send(pdu, aRes); if (NS_FAILED(rv)) { @@ -88,7 +92,9 @@ BluetoothDaemonCoreModule::GetAdapterPropertiesCmd( { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x03, 0)); + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_GET_ADAPTER_PROPERTIES, + 0)); nsresult rv = Send(pdu, aRes); if (NS_FAILED(rv)) { @@ -104,7 +110,9 @@ BluetoothDaemonCoreModule::GetAdapterPropertyCmd(const nsAString& aName, { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x04, 0)); + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_GET_ADAPTER_PROPERTY, + 0)); nsresult rv = PackPDU( PackConversion(aName), *pdu); @@ -125,7 +133,9 @@ BluetoothDaemonCoreModule::SetAdapterPropertyCmd( { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x05, 0)); + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_SET_ADAPTER_PROPERTY, + 0)); nsresult rv = PackPDU(aProperty, *pdu); if (NS_FAILED(rv)) { @@ -145,7 +155,9 @@ BluetoothDaemonCoreModule::GetRemoteDevicePropertiesCmd( { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x06, 0)); + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_GET_REMOTE_DEVICE_PROPERTIES, + 0)); nsresult rv = PackPDU( PackConversion(aRemoteAddr), *pdu); @@ -168,7 +180,9 @@ BluetoothDaemonCoreModule::GetRemoteDevicePropertyCmd( { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x07, 0)); + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_GET_REMOTE_DEVICE_PROPERTY, + 0)); nsresult rv = PackPDU( PackConversion(aRemoteAddr), @@ -192,7 +206,9 @@ BluetoothDaemonCoreModule::SetRemoteDevicePropertyCmd( { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x08, 0)); + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_SET_REMOTE_DEVICE_PROPERTY, + 0)); nsresult rv = PackPDU( PackConversion(aRemoteAddr), @@ -215,7 +231,9 @@ BluetoothDaemonCoreModule::GetRemoteServiceRecordCmd( { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x09, 0)); + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_GET_REMOTE_SERVICE_RECORD, + 0)); nsresult rv = PackPDU( PackConversion(aRemoteAddr), @@ -237,7 +255,8 @@ BluetoothDaemonCoreModule::GetRemoteServicesCmd( { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x0a, 0)); + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_GET_REMOTE_SERVICES, 0)); nsresult rv = PackPDU( PackConversion(aRemoteAddr), *pdu); @@ -257,7 +276,9 @@ BluetoothDaemonCoreModule::StartDiscoveryCmd(BluetoothResultHandler* aRes) { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x0b, 0)); + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_START_DISCOVERY, + 0)); nsresult rv = Send(pdu, aRes); if (NS_FAILED(rv)) { @@ -272,7 +293,9 @@ BluetoothDaemonCoreModule::CancelDiscoveryCmd(BluetoothResultHandler* aRes) { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x0c, 0)); + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_CANCEL_DISCOVERY, + 0)); nsresult rv = Send(pdu, aRes); if (NS_FAILED(rv)) { @@ -289,7 +312,9 @@ BluetoothDaemonCoreModule::CreateBondCmd(const nsAString& aBdAddr, { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x0d, 0)); + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_CREATE_BOND, + 0)); #if ANDROID_VERSION >= 21 nsresult rv = PackPDU( @@ -315,7 +340,9 @@ BluetoothDaemonCoreModule::RemoveBondCmd(const nsAString& aBdAddr, { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x0e, 0)); + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_REMOVE_BOND, + 0)); nsresult rv = PackPDU( PackConversion(aBdAddr), *pdu); @@ -336,7 +363,9 @@ BluetoothDaemonCoreModule::CancelBondCmd(const nsAString& aBdAddr, { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x0f, 0)); + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_CANCEL_BOND, + 0)); nsresult rv = PackPDU( PackConversion(aBdAddr), *pdu); @@ -358,7 +387,9 @@ BluetoothDaemonCoreModule::PinReplyCmd(const nsAString& aBdAddr, bool aAccept, { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x10, 0)); + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_PIN_REPLY, + 0)); nsresult rv = PackPDU( PackConversion(aBdAddr), @@ -383,7 +414,9 @@ BluetoothDaemonCoreModule::SspReplyCmd(const nsAString& aBdAddr, { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x11, 0)); + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_SSP_REPLY, + 0)); nsresult rv = PackPDU( PackConversion(aBdAddr), @@ -405,7 +438,9 @@ BluetoothDaemonCoreModule::DutModeConfigureCmd(bool aEnable, { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x12, 0)); + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_DUT_MODE_CONFIGURE, + 0)); nsresult rv = PackPDU(aEnable, *pdu); if (NS_FAILED(rv)) { @@ -426,7 +461,9 @@ BluetoothDaemonCoreModule::DutModeSendCmd(uint16_t aOpcode, { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x13, 0)); + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_DUT_MODE_SEND, + 0)); nsresult rv = PackPDU(aOpcode, aLen, PackArray(aBuf, aLen), *pdu); @@ -448,7 +485,9 @@ BluetoothDaemonCoreModule::LeTestModeCmd(uint16_t aOpcode, { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu(new DaemonSocketPDU(0x01, 0x14, 0)); + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_LE_TEST_MODE, + 0)); nsresult rv = PackPDU(aOpcode, aLen, PackArray(aBuf, aLen), *pdu); @@ -682,27 +721,48 @@ BluetoothDaemonCoreModule::HandleRsp( const DaemonSocketPDUHeader&, DaemonSocketPDU&, BluetoothResultHandler*) = { - [0x00] = &BluetoothDaemonCoreModule::ErrorRsp, - [0x01] = &BluetoothDaemonCoreModule::EnableRsp, - [0x02] = &BluetoothDaemonCoreModule::DisableRsp, - [0x03] = &BluetoothDaemonCoreModule::GetAdapterPropertiesRsp, - [0x04] = &BluetoothDaemonCoreModule::GetAdapterPropertyRsp, - [0x05] = &BluetoothDaemonCoreModule::SetAdapterPropertyRsp, - [0x06] = &BluetoothDaemonCoreModule::GetRemoteDevicePropertiesRsp, - [0x07] = &BluetoothDaemonCoreModule::GetRemoteDevicePropertyRsp, - [0x08] = &BluetoothDaemonCoreModule::SetRemoteDevicePropertyRsp, - [0x09] = &BluetoothDaemonCoreModule::GetRemoteServiceRecordRsp, - [0x0a] = &BluetoothDaemonCoreModule::GetRemoteServicesRsp, - [0x0b] = &BluetoothDaemonCoreModule::StartDiscoveryRsp, - [0x0c] = &BluetoothDaemonCoreModule::CancelDiscoveryRsp, - [0x0d] = &BluetoothDaemonCoreModule::CreateBondRsp, - [0x0e] = &BluetoothDaemonCoreModule::RemoveBondRsp, - [0x0f] = &BluetoothDaemonCoreModule::CancelBondRsp, - [0x10] = &BluetoothDaemonCoreModule::PinReplyRsp, - [0x11] = &BluetoothDaemonCoreModule::SspReplyRsp, - [0x12] = &BluetoothDaemonCoreModule::DutModeConfigureRsp, - [0x13] = &BluetoothDaemonCoreModule::DutModeSendRsp, - [0x14] = &BluetoothDaemonCoreModule::LeTestModeRsp, + [OPCODE_ERROR] = + &BluetoothDaemonCoreModule::ErrorRsp, + [OPCODE_ENABLE] = + &BluetoothDaemonCoreModule::EnableRsp, + [OPCODE_DISABLE] = + &BluetoothDaemonCoreModule::DisableRsp, + [OPCODE_GET_ADAPTER_PROPERTIES] = + &BluetoothDaemonCoreModule::GetAdapterPropertiesRsp, + [OPCODE_GET_ADAPTER_PROPERTY] = + &BluetoothDaemonCoreModule::GetAdapterPropertyRsp, + [OPCODE_SET_ADAPTER_PROPERTY] = + &BluetoothDaemonCoreModule::SetAdapterPropertyRsp, + [OPCODE_GET_REMOTE_DEVICE_PROPERTIES] = + &BluetoothDaemonCoreModule::GetRemoteDevicePropertiesRsp, + [OPCODE_GET_REMOTE_DEVICE_PROPERTY] = + &BluetoothDaemonCoreModule::GetRemoteDevicePropertyRsp, + [OPCODE_SET_REMOTE_DEVICE_PROPERTY] = + &BluetoothDaemonCoreModule::SetRemoteDevicePropertyRsp, + [OPCODE_GET_REMOTE_SERVICE_RECORD] = + &BluetoothDaemonCoreModule::GetRemoteServiceRecordRsp, + [OPCODE_GET_REMOTE_SERVICES] = + &BluetoothDaemonCoreModule::GetRemoteServicesRsp, + [OPCODE_START_DISCOVERY] = + &BluetoothDaemonCoreModule::StartDiscoveryRsp, + [OPCODE_CANCEL_DISCOVERY] = + &BluetoothDaemonCoreModule::CancelDiscoveryRsp, + [OPCODE_CREATE_BOND] = + &BluetoothDaemonCoreModule::CreateBondRsp, + [OPCODE_REMOVE_BOND] = + &BluetoothDaemonCoreModule::RemoveBondRsp, + [OPCODE_CANCEL_BOND] = + &BluetoothDaemonCoreModule::CancelBondRsp, + [OPCODE_PIN_REPLY] = + &BluetoothDaemonCoreModule::PinReplyRsp, + [OPCODE_SSP_REPLY] = + &BluetoothDaemonCoreModule::SspReplyRsp, + [OPCODE_DUT_MODE_CONFIGURE] = + &BluetoothDaemonCoreModule::DutModeConfigureRsp, + [OPCODE_DUT_MODE_SEND] = + &BluetoothDaemonCoreModule::DutModeSendRsp, + [OPCODE_LE_TEST_MODE] = + &BluetoothDaemonCoreModule::LeTestModeRsp, }; MOZ_ASSERT(!NS_IsMainThread()); diff --git a/dom/bluetooth/bluedroid/BluetoothDaemonCoreInterface.h b/dom/bluetooth/bluedroid/BluetoothDaemonCoreInterface.h index a79502297181..5faf399c2234 100644 --- a/dom/bluetooth/bluedroid/BluetoothDaemonCoreInterface.h +++ b/dom/bluetooth/bluedroid/BluetoothDaemonCoreInterface.h @@ -20,6 +20,44 @@ using mozilla::ipc::DaemonSocketResultHandler; class BluetoothDaemonCoreModule { public: + enum { + SERVICE_ID = 0x01 + }; + + enum { + OPCODE_ERROR = 0x00, + OPCODE_ENABLE = 0x01, + OPCODE_DISABLE = 0x02, + OPCODE_GET_ADAPTER_PROPERTIES = 0x03, + OPCODE_GET_ADAPTER_PROPERTY = 0x04, + OPCODE_SET_ADAPTER_PROPERTY = 0x05, + OPCODE_GET_REMOTE_DEVICE_PROPERTIES = 0x06, + OPCODE_GET_REMOTE_DEVICE_PROPERTY = 0x07, + OPCODE_SET_REMOTE_DEVICE_PROPERTY = 0x08, + OPCODE_GET_REMOTE_SERVICE_RECORD = 0x09, + OPCODE_GET_REMOTE_SERVICES = 0x0a, + OPCODE_START_DISCOVERY = 0x0b, + OPCODE_CANCEL_DISCOVERY = 0x0c, + OPCODE_CREATE_BOND = 0x0d, + OPCODE_REMOVE_BOND = 0x0e, + OPCODE_CANCEL_BOND = 0x0f, + OPCODE_PIN_REPLY = 0x10, + OPCODE_SSP_REPLY = 0x11, + OPCODE_DUT_MODE_CONFIGURE = 0x12, + OPCODE_DUT_MODE_SEND = 0x13, + OPCODE_LE_TEST_MODE = 0x14, + OPCODE_ADAPTER_STATE_CHANGED_NTF = 0x81, + OPCODE_ADAPTER_PROPERTIES_NTF = 0x82, + OPCODE_REMOTE_DEVICE_PROPERTIES_NTF = 0x83, + OPCODE_DEVICE_FOUND_NTF = 0x84, + OPCODE_DISCOVERY_STATE_CHANGED_NTF = 0x85, + OPCODE_PIN_REQUEST_NTF = 0x86, + OPCODE_SSP_REQUEST_NTF = 0x87, + OPCODE_BOND_STATE_CHANGED_NTF = 0x88, + OPCODE_ACL_STATE_CHANGED_NTF = 0x89, + OPCODE_DUT_MODE_RECV_NTF = 0x8a, + OPCODE_LE_TEST_MODE_NTF = 0x8b + }; static const int MAX_NUM_CLIENTS; diff --git a/dom/bluetooth/bluedroid/BluetoothDaemonInterface.cpp b/dom/bluetooth/bluedroid/BluetoothDaemonInterface.cpp index 94733752af1e..f1a1b9f9f019 100644 --- a/dom/bluetooth/bluedroid/BluetoothDaemonInterface.cpp +++ b/dom/bluetooth/bluedroid/BluetoothDaemonInterface.cpp @@ -254,7 +254,8 @@ BluetoothDaemonProtocol::Handle(DaemonSocketPDU& aPDU) DaemonSocketResultHandler*) = { [BluetoothDaemonSetupModule::SERVICE_ID] = &BluetoothDaemonProtocol::HandleSetupSvc, - [0x01] = &BluetoothDaemonProtocol::HandleCoreSvc, + [BluetoothDaemonCoreModule::SERVICE_ID] = + &BluetoothDaemonProtocol::HandleCoreSvc, [0x02] = &BluetoothDaemonProtocol::HandleSocketSvc, [0x03] = nullptr, // HID host [0x04] = nullptr, // PAN From 124089fd9639bdbab34e063413550a027c94bf2b Mon Sep 17 00:00:00 2001 From: "Carsten \"Tomcat\" Book" Date: Thu, 17 Sep 2015 11:59:25 +0200 Subject: [PATCH 089/113] Backed out 1 changesets (bug 1204837) for causing B2G ICS Emulator test failures on a CLOSED TREE Backed out changeset 99c11d836978 (bug 1204837) --- netwerk/base/ClosingService.cpp | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/netwerk/base/ClosingService.cpp b/netwerk/base/ClosingService.cpp index 284d2ca3b156..ef7f26c9fe4c 100644 --- a/netwerk/base/ClosingService.cpp +++ b/netwerk/base/ClosingService.cpp @@ -6,9 +6,6 @@ #include "ClosingService.h" #include "nsIOService.h" -#ifdef MOZ_NUWA_PROCESS -#include "ipc/Nuwa.h" -#endif class ClosingLayerSecret { @@ -203,13 +200,6 @@ ClosingService::ShutdownInternal() void ClosingService::ThreadFunc() { - PR_SetCurrentThreadName("Closing Service"); -#ifdef MOZ_NUWA_PROCESS - if (IsNuwaProcess()) { - NuwaMarkCurrentThread(nullptr, nullptr); - } -#endif - for (;;) { PRFileDesc *fd; { From c9a314a19990fdf3301284281ba396b4d71b2949 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Thu, 17 Sep 2015 04:57:20 -0700 Subject: [PATCH 090/113] Bumping gaia.json for 2 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/8a7cf070544f Author: Timothy Guan-tin Chien Desc: Merge pull request #31850 from janus926/bug-1203945 Bug 1203945 - Overwrite updated app instead of push directly to avoid unlink, r=timdream ======== https://hg.mozilla.org/integration/gaia-central/rev/420cb6b83f5b Author: Ting-Yu Chou Desc: Bug 1203945 - Overwrite updated app instead of push directly to avoid unlink. r=timdream --- b2g/config/gaia.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index ce4c0d4743f7..b20438f24d0d 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,9 +1,9 @@ { "git": { - "git_revision": "eb62d50351fd6a9b560fe369387d8138b9b3a2d3", + "git_revision": "6b36df77d4d47cbaecafe4e3a1d3ea7400f17fc7", "remote": "https://git.mozilla.org/releases/gaia.git", "branch": "" }, - "revision": "35ecf3d9f9cf69f77085c89d368561be713f78f0", + "revision": "8a7cf070544f0470c7b03e5032cd602097352e5b", "repo_path": "integration/gaia-central" } From 812541318e3e7adb6334e6cd920416f2ddd65a95 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Thu, 17 Sep 2015 05:00:03 -0700 Subject: [PATCH 091/113] Bumping manifests a=b2g-bump --- b2g/config/aries/sources.xml | 4 ++-- b2g/config/dolphin/sources.xml | 4 ++-- b2g/config/emulator-ics/sources.xml | 4 ++-- b2g/config/emulator-jb/sources.xml | 4 ++-- b2g/config/emulator-kk/sources.xml | 4 ++-- b2g/config/emulator-l/sources.xml | 4 ++-- b2g/config/emulator/sources.xml | 4 ++-- b2g/config/flame-kk/sources.xml | 4 ++-- b2g/config/nexus-4/sources.xml | 4 ++-- b2g/config/nexus-5-l/sources.xml | 4 ++-- 10 files changed, 20 insertions(+), 20 deletions(-) diff --git a/b2g/config/aries/sources.xml b/b2g/config/aries/sources.xml index 05130fdc8580..a6714f6e008e 100644 --- a/b2g/config/aries/sources.xml +++ b/b2g/config/aries/sources.xml @@ -15,11 +15,11 @@ - + - + diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index 2b046830b2b2..52831ff0fe96 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -15,11 +15,11 @@ - + - + diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index ff8a53a04359..c4e84b036a24 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,12 +19,12 @@ - + - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index cedd4de25c29..e7b4a733abd0 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,9 +17,9 @@ - + - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index 5fa203eeda42..3401a233664e 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,11 +15,11 @@ - + - + diff --git a/b2g/config/emulator-l/sources.xml b/b2g/config/emulator-l/sources.xml index 11ebf2d1137b..b2e96ebd119e 100644 --- a/b2g/config/emulator-l/sources.xml +++ b/b2g/config/emulator-l/sources.xml @@ -15,11 +15,11 @@ - + - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index ff8a53a04359..c4e84b036a24 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,12 +19,12 @@ - + - + diff --git a/b2g/config/flame-kk/sources.xml b/b2g/config/flame-kk/sources.xml index 82858d3451da..07b9b2501267 100644 --- a/b2g/config/flame-kk/sources.xml +++ b/b2g/config/flame-kk/sources.xml @@ -15,11 +15,11 @@ - + - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index 65838033f811..756fd2ee224c 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,9 +17,9 @@ - + - + diff --git a/b2g/config/nexus-5-l/sources.xml b/b2g/config/nexus-5-l/sources.xml index dfe5f3bfbedd..1a954d1e9f4b 100644 --- a/b2g/config/nexus-5-l/sources.xml +++ b/b2g/config/nexus-5-l/sources.xml @@ -15,11 +15,11 @@ - + - + From e28a9f89d76b268a360c66cb2ffbb4d982d09659 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Thu, 17 Sep 2015 05:07:15 -0700 Subject: [PATCH 092/113] Bumping gaia.json for 6 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/cc4385d88fa4 Author: Francisco Jordano Desc: Revert "Bug 1183728 - [Contacts][NGA] Connect #new self-contained view to the app. r=arcturus" This reverts commit 5980aa2ded370136250293b5a177535d4be25ce7. ======== https://hg.mozilla.org/integration/gaia-central/rev/05eb70e37832 Author: Francisco Jordano Desc: Revert "Bug 1183727 - [Contacts][NGA] Create #update view and connect it to #open within Contacts App r=arcturus" This reverts commit a1916008434c874f2705fe854d41234fa14db63c. Conflicts: apps/communications/contacts/views/details/js/details_controller.js ======== https://hg.mozilla.org/integration/gaia-central/rev/883004f00510 Author: Francisco Jordano Desc: Revert "Bug 1197750 - [Contacts] After updating contacts, the old one and new one both exist, but they are same. r=borjasalguero" This reverts commit 51a8344093e0391748530b1fe182a77dad423beb. ======== https://hg.mozilla.org/integration/gaia-central/rev/4d21bb2fe930 Author: Francisco Jordano Desc: Revert "Bug 1202217 - [Contacts][NGA][Detail] Merge contact B to contact A, but the contact B is also displayed. r=arcturus" This reverts commit 1e206e7db8c2f2c7f9c05f239936700af6329cff. ======== https://hg.mozilla.org/integration/gaia-central/rev/143450315bab Author: Francisco Jordano Desc: Revert "Bug 1201052 - After updating a contact the statusbar turns from blue to grey r=arcturus" This reverts commit b8f5afcbbdaed9edc15550b31db0186d57736b7f. ======== https://hg.mozilla.org/integration/gaia-central/rev/0335c8713f93 Author: Francisco Jordano Desc: Revert "Bug 1201419 - [NFC] Unable to share contact via NFC. r=francisco" This reverts commit 6da9b222cb0dce9a7b7bfafff7b41e412ae863cb. --- b2g/config/gaia.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index b20438f24d0d..0c7841ce9a47 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,9 +1,9 @@ { "git": { - "git_revision": "6b36df77d4d47cbaecafe4e3a1d3ea7400f17fc7", + "git_revision": "c06f2402e89923810bc47e2af3689660859999db", "remote": "https://git.mozilla.org/releases/gaia.git", "branch": "" }, - "revision": "8a7cf070544f0470c7b03e5032cd602097352e5b", + "revision": "cc4385d88fa4286ee3b0be019ef51ab7b79b52c3", "repo_path": "integration/gaia-central" } From 05364ae7062d72055defe575a3ca6a3400157fd7 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Thu, 17 Sep 2015 05:09:59 -0700 Subject: [PATCH 093/113] Bumping manifests a=b2g-bump --- b2g/config/aries/sources.xml | 2 +- b2g/config/dolphin/sources.xml | 2 +- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator-l/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame-kk/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/nexus-5-l/sources.xml | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/b2g/config/aries/sources.xml b/b2g/config/aries/sources.xml index a6714f6e008e..c9a4a0fd672a 100644 --- a/b2g/config/aries/sources.xml +++ b/b2g/config/aries/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index 52831ff0fe96..60e4865afb7f 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index c4e84b036a24..b747dda3a6ab 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index e7b4a733abd0..0505bb67422e 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index 3401a233664e..1d04693bb2fc 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator-l/sources.xml b/b2g/config/emulator-l/sources.xml index b2e96ebd119e..2d3917193456 100644 --- a/b2g/config/emulator-l/sources.xml +++ b/b2g/config/emulator-l/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index c4e84b036a24..b747dda3a6ab 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame-kk/sources.xml b/b2g/config/flame-kk/sources.xml index 07b9b2501267..a94556a3b886 100644 --- a/b2g/config/flame-kk/sources.xml +++ b/b2g/config/flame-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index 756fd2ee224c..8144dbb1f6cb 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/nexus-5-l/sources.xml b/b2g/config/nexus-5-l/sources.xml index 1a954d1e9f4b..1817a86a5b48 100644 --- a/b2g/config/nexus-5-l/sources.xml +++ b/b2g/config/nexus-5-l/sources.xml @@ -15,7 +15,7 @@ - + From 63aeeea1b1d7c37952ebb5950c0c9f5c40c5c03a Mon Sep 17 00:00:00 2001 From: Ting-Yu Lin Date: Wed, 16 Sep 2015 17:58:14 +0800 Subject: [PATCH 094/113] Bug 1199161 - Add selectedTextContent to CaretStateChangedEvent. r=kanru, sr=smaug The old SelectionStateChangedEvent dispatched by SelectionChanged had this field, but it has not being ported to CaretStateChangedEvent. We should include selected text in the event so that Gaia could have a chance to enhance user experience. --HG-- extra : rebase_source : 7304b71e251e2ee081192340b8f86f22bf6e03a6 --- dom/browser-element/BrowserElementCopyPaste.js | 3 ++- dom/browser-element/BrowserElementParent.js | 2 ++ dom/webidl/CaretStateChangedEvent.webidl | 2 ++ layout/base/AccessibleCaretManager.cpp | 1 + 4 files changed, 7 insertions(+), 1 deletion(-) diff --git a/dom/browser-element/BrowserElementCopyPaste.js b/dom/browser-element/BrowserElementCopyPaste.js index b829c1365c1f..abf8a5f7ffd0 100644 --- a/dom/browser-element/BrowserElementCopyPaste.js +++ b/dom/browser-element/BrowserElementCopyPaste.js @@ -72,7 +72,8 @@ var CopyPasteAssistent = { collapsed: e.collapsed, caretVisible: e.caretVisible, selectionVisible: e.selectionVisible, - selectionEditable: e.selectionEditable + selectionEditable: e.selectionEditable, + selectedTextContent: e.selectedTextContent }; // Get correct geometry information if we have nested iframe. diff --git a/dom/browser-element/BrowserElementParent.js b/dom/browser-element/BrowserElementParent.js index 7b9e60f80620..36a8a15620fd 100644 --- a/dom/browser-element/BrowserElementParent.js +++ b/dom/browser-element/BrowserElementParent.js @@ -459,6 +459,8 @@ BrowserElementParent.prototype = { // - caretVisible: Indicate the caret visiibility. // - selectionVisible: Indicate current selection is visible or not. // - selectionEditable: Indicate current selection is editable or not. + // - selectedTextContent: Contains current selected text content, which is + // equivalent to the string returned by Selection.toString(). _handleCaretStateChanged: function(data) { let evt = this._createEvent('caretstatechanged', data.json, /* cancelable = */ false); diff --git a/dom/webidl/CaretStateChangedEvent.webidl b/dom/webidl/CaretStateChangedEvent.webidl index d016513ca0ed..e2fdf0864372 100644 --- a/dom/webidl/CaretStateChangedEvent.webidl +++ b/dom/webidl/CaretStateChangedEvent.webidl @@ -20,6 +20,7 @@ dictionary CaretStateChangedEventInit : EventInit { boolean caretVisible = false; boolean selectionVisible = false; boolean selectionEditable = false; + DOMString selectedTextContent = ""; }; [Constructor(DOMString type, optional CaretStateChangedEventInit eventInit), @@ -31,4 +32,5 @@ interface CaretStateChangedEvent : Event { readonly attribute boolean caretVisible; readonly attribute boolean selectionVisible; readonly attribute boolean selectionEditable; + readonly attribute DOMString selectedTextContent; }; diff --git a/layout/base/AccessibleCaretManager.cpp b/layout/base/AccessibleCaretManager.cpp index 0201ab4f42b6..35cd3979fc01 100644 --- a/layout/base/AccessibleCaretManager.cpp +++ b/layout/base/AccessibleCaretManager.cpp @@ -953,6 +953,7 @@ AccessibleCaretManager::DispatchCaretStateChangedEvent(CaretChangedReason aReaso init.mCollapsed = sel->IsCollapsed(); init.mCaretVisible = mFirstCaret->IsLogicallyVisible() || mSecondCaret->IsLogicallyVisible(); + sel->Stringify(init.mSelectedTextContent); nsRefPtr event = CaretStateChangedEvent::Constructor(doc, NS_LITERAL_STRING("mozcaretstatechanged"), init); From ca41727a3803897d02d9a56185e4c13e19f987f8 Mon Sep 17 00:00:00 2001 From: Alexandre Lissy Date: Thu, 17 Sep 2015 05:06:00 +0200 Subject: [PATCH 095/113] Bug 1201556 - Send hashed device id for foxfooders. r=fabrice --HG-- extra : rebase_source : beee55eb2c52519d1c19fb5ebc667ea8b6ec7b42 --- b2g/chrome/content/settings.js | 42 +++++++++++++++++++++++ dom/apps/AppsUtils.jsm | 6 ++-- toolkit/mozapps/update/nsUpdateService.js | 3 ++ 3 files changed, 48 insertions(+), 3 deletions(-) diff --git a/b2g/chrome/content/settings.js b/b2g/chrome/content/settings.js index 746b29fde63e..038f73b3d92a 100644 --- a/b2g/chrome/content/settings.js +++ b/b2g/chrome/content/settings.js @@ -537,6 +537,48 @@ SettingsListener.observe("theme.selected", setPAC(); })(); +#ifdef MOZ_B2G_RIL +XPCOMUtils.defineLazyModuleGetter(this, "AppsUtils", + "resource://gre/modules/AppsUtils.jsm"); + +// ======================= Dogfooders FOTA ========================== +SettingsListener.observe('debug.performance_data.dogfooding', false, + isDogfooder => { + if (!isDogfooder) { + dump('AUS:Settings: Not a dogfooder!\n'); + return; + } + + if (!('mozTelephony' in navigator)) { + dump('AUS:Settings: There is no mozTelephony!\n'); + return; + } + + if (!('mozMobileConnections' in navigator)) { + dump('AUS:Settings: There is no mozMobileConnections!\n'); + return; + } + + let conn = navigator.mozMobileConnections[0]; + conn.addEventListener('radiostatechange', function onradiostatechange() { + if (conn.radioState !== 'enabled') { + return; + } + + conn.removeEventListener('radiostatechange', onradiostatechange); + navigator.mozTelephony.dial('*#06#').then(call => { + return call.result.then(res => { + if (res.success && res.statusMessage + && (res.serviceCode === 'scImei')) { + Services.prefs.setCharPref("app.update.imei_hash", + AppsUtils.computeHash(res.statusMessage, "SHA512")); + } + }); + }); + }); + }); +#endif + // =================== Various simple mapping ====================== var settingsToObserve = { 'accessibility.screenreader_quicknav_modes': { diff --git a/dom/apps/AppsUtils.jsm b/dom/apps/AppsUtils.jsm index b2f9b6bc3dac..722555d80dce 100644 --- a/dom/apps/AppsUtils.jsm +++ b/dom/apps/AppsUtils.jsm @@ -757,8 +757,8 @@ this.AppsUtils = { return deferred.promise; }, - // Returns the MD5 hash of a string. - computeHash: function(aString) { + // Returns the hash of a string, with MD5 as a default hashing function. + computeHash: function(aString, aAlgorithm = "MD5") { let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"] .createInstance(Ci.nsIScriptableUnicodeConverter); converter.charset = "UTF-8"; @@ -768,7 +768,7 @@ this.AppsUtils = { let hasher = Cc["@mozilla.org/security/hash;1"] .createInstance(Ci.nsICryptoHash); - hasher.init(hasher.MD5); + hasher.initWithString(aAlgorithm); hasher.update(data, data.length); // We're passing false to get the binary hash and not base64. let hash = hasher.finish(false); diff --git a/toolkit/mozapps/update/nsUpdateService.js b/toolkit/mozapps/update/nsUpdateService.js index 7df8fea3348f..5446c67dca58 100644 --- a/toolkit/mozapps/update/nsUpdateService.js +++ b/toolkit/mozapps/update/nsUpdateService.js @@ -31,6 +31,7 @@ const PREF_APP_UPDATE_CERT_ERRORS = "app.update.cert.errors"; const PREF_APP_UPDATE_CERT_MAXERRORS = "app.update.cert.maxErrors"; const PREF_APP_UPDATE_CERT_REQUIREBUILTIN = "app.update.cert.requireBuiltIn"; const PREF_APP_UPDATE_CUSTOM = "app.update.custom"; +const PREF_APP_UPDATE_IMEI_HASH = "app.update.imei_hash"; const PREF_APP_UPDATE_ENABLED = "app.update.enabled"; const PREF_APP_UPDATE_IDLETIME = "app.update.idletime"; const PREF_APP_UPDATE_INCOMPATIBLE_MODE = "app.update.incompatible.mode"; @@ -3546,6 +3547,8 @@ Checker.prototype = { } url = url.replace(/%B2G_VERSION%/g, getPref("getCharPref", PREF_APP_B2G_VERSION, null)); + url = url.replace(/%IMEI%/g, + getPref("getCharPref", PREF_APP_UPDATE_IMEI_HASH, "default")); } if (force) { From 8a7a6b2e912646c3ccb9a09bbb5d517abdadac5e Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Thu, 17 Sep 2015 05:20:16 -0700 Subject: [PATCH 096/113] Bumping gaia.json for 6 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/03aef0327279 Author: Carsten Book Desc: Merge pull request #31866 from Cwiiis/bug1203993-new-homescreen-performance-markers Bug 1203993 - Add performance markers to new homescreen. r=gmarty ======== https://hg.mozilla.org/integration/gaia-central/rev/70467879cfe5 Author: Chris Lord Desc: Bug 1203993 - Add performance markers to new homescreen. r=gmarty ======== https://hg.mozilla.org/integration/gaia-central/rev/ca622cbf8bda Author: Carsten Book Desc: Merge pull request #31804 from etiennesegonzac/bug-1190308 Bug 1190308 - Cancel the activity picker when the lockscreen is locked. r=albertopq ======== https://hg.mozilla.org/integration/gaia-central/rev/810a396d0cf1 Author: Etienne Segonzac Desc: Bug 1190308 - Cancel the activity picker when the lockscreen is locked. r=albertopq ======== https://hg.mozilla.org/integration/gaia-central/rev/0e627cee1af9 Author: Carsten Book Desc: Merge pull request #31835 from etiennesegonzac/bug-1185709 Bug 1185709 - Turn on the proximity sensor right away for outgoing calls. r=timdream ======== https://hg.mozilla.org/integration/gaia-central/rev/24e672ba05d4 Author: Etienne Segonzac Desc: Bug 1185709 - Turn on the proximity sensor right away for outgoing calls. r=timdream --- b2g/config/gaia.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 0c7841ce9a47..89cdc46a37b9 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,9 +1,9 @@ { "git": { - "git_revision": "c06f2402e89923810bc47e2af3689660859999db", + "git_revision": "0d18a51dabfe28c0d993366a3436a07247a5e3b1", "remote": "https://git.mozilla.org/releases/gaia.git", "branch": "" }, - "revision": "cc4385d88fa4286ee3b0be019ef51ab7b79b52c3", + "revision": "03aef03272796a60645c4e55dc32cc05cecae032", "repo_path": "integration/gaia-central" } From 85444cf326d2cb754e7ddafbdfe080589859b887 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Thu, 17 Sep 2015 05:23:04 -0700 Subject: [PATCH 097/113] Bumping manifests a=b2g-bump --- b2g/config/aries/sources.xml | 2 +- b2g/config/dolphin/sources.xml | 2 +- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator-l/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame-kk/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/nexus-5-l/sources.xml | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/b2g/config/aries/sources.xml b/b2g/config/aries/sources.xml index c9a4a0fd672a..a5619f23267d 100644 --- a/b2g/config/aries/sources.xml +++ b/b2g/config/aries/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index 60e4865afb7f..ce11a2d0df0a 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index b747dda3a6ab..7614f3a06ecf 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index 0505bb67422e..31b12cc4c9b6 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index 1d04693bb2fc..54e85c3c6caa 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator-l/sources.xml b/b2g/config/emulator-l/sources.xml index 2d3917193456..13d1e3e8a07f 100644 --- a/b2g/config/emulator-l/sources.xml +++ b/b2g/config/emulator-l/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index b747dda3a6ab..7614f3a06ecf 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame-kk/sources.xml b/b2g/config/flame-kk/sources.xml index a94556a3b886..97e14993c9e7 100644 --- a/b2g/config/flame-kk/sources.xml +++ b/b2g/config/flame-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index 8144dbb1f6cb..2d454b42f75f 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/nexus-5-l/sources.xml b/b2g/config/nexus-5-l/sources.xml index 1817a86a5b48..120a92c2d8fd 100644 --- a/b2g/config/nexus-5-l/sources.xml +++ b/b2g/config/nexus-5-l/sources.xml @@ -15,7 +15,7 @@ - + From 5befe35395abd7e2f1fb242b93279bc6045feee6 Mon Sep 17 00:00:00 2001 From: Wander Lairson Costa Date: Thu, 17 Sep 2015 14:24:24 +0200 Subject: [PATCH 098/113] Bug 1205574: Fix cache name typo in try white list. r=garndt s/tc-vcs-public-source/tc-vcs-public-sources/. --HG-- extra : commitid : L6XcYBV1cr2 extra : rebase_source : 4452869e3d23bca5b6590df3b481420c2200860b --- testing/taskcluster/mach_commands.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/taskcluster/mach_commands.py b/testing/taskcluster/mach_commands.py index 0466447f2cee..0eaabb0e5e3a 100644 --- a/testing/taskcluster/mach_commands.py +++ b/testing/taskcluster/mach_commands.py @@ -196,7 +196,7 @@ def remove_caches_from_task(task): """ whitelist = [ "tc-vcs", - "tc-vcs-public-source", + "tc-vcs-public-sources", "tooltool-cache", ] try: From 4afaf44ef65229f02efc277b2d020a7842564ff9 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Thu, 17 Sep 2015 14:46:18 +0200 Subject: [PATCH 099/113] Bug 1205577: Use enum constants for Bluetooth Socket module, r=btian --- .../bluedroid/BluetoothDaemonInterface.cpp | 3 ++- .../bluedroid/BluetoothDaemonSocketInterface.cpp | 14 +++++++++----- .../bluedroid/BluetoothDaemonSocketInterface.h | 10 ++++++++++ 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/dom/bluetooth/bluedroid/BluetoothDaemonInterface.cpp b/dom/bluetooth/bluedroid/BluetoothDaemonInterface.cpp index f1a1b9f9f019..a9933d475fa4 100644 --- a/dom/bluetooth/bluedroid/BluetoothDaemonInterface.cpp +++ b/dom/bluetooth/bluedroid/BluetoothDaemonInterface.cpp @@ -256,7 +256,8 @@ BluetoothDaemonProtocol::Handle(DaemonSocketPDU& aPDU) &BluetoothDaemonProtocol::HandleSetupSvc, [BluetoothDaemonCoreModule::SERVICE_ID] = &BluetoothDaemonProtocol::HandleCoreSvc, - [0x02] = &BluetoothDaemonProtocol::HandleSocketSvc, + [BluetoothDaemonSocketModule::SERVICE_ID] = + &BluetoothDaemonProtocol::HandleSocketSvc, [0x03] = nullptr, // HID host [0x04] = nullptr, // PAN [BluetoothDaemonHandsfreeModule::SERVICE_ID] = diff --git a/dom/bluetooth/bluedroid/BluetoothDaemonSocketInterface.cpp b/dom/bluetooth/bluedroid/BluetoothDaemonSocketInterface.cpp index 15afca216c57..397fcfd7c4a4 100644 --- a/dom/bluetooth/bluedroid/BluetoothDaemonSocketInterface.cpp +++ b/dom/bluetooth/bluedroid/BluetoothDaemonSocketInterface.cpp @@ -32,7 +32,9 @@ BluetoothDaemonSocketModule::ListenCmd(BluetoothSocketType aType, { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu(new DaemonSocketPDU(0x02, 0x01, 0)); + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_LISTEN, + 0)); nsresult rv = PackPDU( aType, @@ -61,7 +63,9 @@ BluetoothDaemonSocketModule::ConnectCmd(const nsAString& aBdAddr, { MOZ_ASSERT(NS_IsMainThread()); - nsAutoPtr pdu(new DaemonSocketPDU(0x02, 0x02, 0)); + nsAutoPtr pdu( + new DaemonSocketPDU(SERVICE_ID, OPCODE_CONNECT, + 0)); nsresult rv = PackPDU( PackConversion(aBdAddr), @@ -166,9 +170,9 @@ BluetoothDaemonSocketModule::HandleSvc(const DaemonSocketPDUHeader& aHeader, const DaemonSocketPDUHeader&, DaemonSocketPDU&, BluetoothSocketResultHandler*) = { - [0x00] = &BluetoothDaemonSocketModule::ErrorRsp, - [0x01] = &BluetoothDaemonSocketModule::ListenRsp, - [0x02] = &BluetoothDaemonSocketModule::ConnectRsp + [OPCODE_ERROR] = &BluetoothDaemonSocketModule::ErrorRsp, + [OPCODE_LISTEN] = &BluetoothDaemonSocketModule::ListenRsp, + [OPCODE_CONNECT] = &BluetoothDaemonSocketModule::ConnectRsp }; if (NS_WARN_IF(MOZ_ARRAY_LENGTH(HandleRsp) <= aHeader.mOpcode) || diff --git a/dom/bluetooth/bluedroid/BluetoothDaemonSocketInterface.h b/dom/bluetooth/bluedroid/BluetoothDaemonSocketInterface.h index 506883bbd43b..79c23b5bd7a3 100644 --- a/dom/bluetooth/bluedroid/BluetoothDaemonSocketInterface.h +++ b/dom/bluetooth/bluedroid/BluetoothDaemonSocketInterface.h @@ -20,6 +20,16 @@ using mozilla::ipc::DaemonSocketResultHandler; class BluetoothDaemonSocketModule { public: + enum { + SERVICE_ID = 0x02 + }; + + enum { + OPCODE_ERROR = 0x00, + OPCODE_LISTEN = 0x01, + OPCODE_CONNECT = 0x02 + }; + static const int MAX_NUM_CLIENTS; virtual nsresult Send(DaemonSocketPDU* aPDU, From 674506782032b4e705e8571e3e05fe00bc853ad1 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Thu, 17 Sep 2015 07:00:19 -0700 Subject: [PATCH 100/113] Bumping gaia.json for 2 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/b060f13f81d6 Author: No-Jun Park Desc: Merge pull request #31875 from npark-mozilla/1205450 Bug 1205450 - Imagecompare: test_combo_effects_edit_picture.py fails because of missing import ======== https://hg.mozilla.org/integration/gaia-central/rev/559ac72f6a33 Author: No-Jun Park Desc: Bug 1205450 - Imagecompare: test_combo_effects_edit_picture.py fails because of missing import --- b2g/config/gaia.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 89cdc46a37b9..1a1bff44347c 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,9 +1,9 @@ { "git": { - "git_revision": "0d18a51dabfe28c0d993366a3436a07247a5e3b1", + "git_revision": "71d8d7c95600cd72b7b06f6c79e71d98aa4e9394", "remote": "https://git.mozilla.org/releases/gaia.git", "branch": "" }, - "revision": "03aef03272796a60645c4e55dc32cc05cecae032", + "revision": "b060f13f81d6827dbf27ba2dc5183c5fecced1a2", "repo_path": "integration/gaia-central" } From 63de22ec254af52899db3f850a4ad0735032dba6 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Thu, 17 Sep 2015 07:03:05 -0700 Subject: [PATCH 101/113] Bumping manifests a=b2g-bump --- b2g/config/aries/sources.xml | 2 +- b2g/config/dolphin/sources.xml | 2 +- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator-l/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame-kk/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/nexus-5-l/sources.xml | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/b2g/config/aries/sources.xml b/b2g/config/aries/sources.xml index a5619f23267d..340a568aaa38 100644 --- a/b2g/config/aries/sources.xml +++ b/b2g/config/aries/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index ce11a2d0df0a..b4b4e9ab0d6c 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index 7614f3a06ecf..87d64afb992a 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index 31b12cc4c9b6..83594c1df6ca 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index 54e85c3c6caa..a43b3020d3ce 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator-l/sources.xml b/b2g/config/emulator-l/sources.xml index 13d1e3e8a07f..c468065cc068 100644 --- a/b2g/config/emulator-l/sources.xml +++ b/b2g/config/emulator-l/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index 7614f3a06ecf..87d64afb992a 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame-kk/sources.xml b/b2g/config/flame-kk/sources.xml index 97e14993c9e7..d6d2fea9faeb 100644 --- a/b2g/config/flame-kk/sources.xml +++ b/b2g/config/flame-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index 2d454b42f75f..3fe12cced2ec 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/nexus-5-l/sources.xml b/b2g/config/nexus-5-l/sources.xml index 120a92c2d8fd..f637719a08b3 100644 --- a/b2g/config/nexus-5-l/sources.xml +++ b/b2g/config/nexus-5-l/sources.xml @@ -15,7 +15,7 @@ - + From c49b2345ee8df4d1aa6fc0bf3c962e6c63b341e0 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Thu, 17 Sep 2015 07:40:35 -0700 Subject: [PATCH 102/113] Bumping gaia.json for 2 gaia revision(s) a=gaia-bump MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ======== https://hg.mozilla.org/integration/gaia-central/rev/307646c3fd09 Author: Francisco Jordano Desc: Merge pull request #31443 from arcturus/bug-1191606 Bug 1191606 - [Contacts][Import] Contact thumbnails are improperly cr… ======== https://hg.mozilla.org/integration/gaia-central/rev/1afdaf993b2f Author: Francisco Jordano Desc: Bug 1191606 - [Contacts][Import] Contact thumbnails are improperly cropped to the upper left portion of the image on the import screen. r=borjasalguero --- b2g/config/gaia.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 1a1bff44347c..10493ef70471 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,9 +1,9 @@ { "git": { - "git_revision": "71d8d7c95600cd72b7b06f6c79e71d98aa4e9394", + "git_revision": "7196b004d27eb540e04b6512ae89e4639e26fccf", "remote": "https://git.mozilla.org/releases/gaia.git", "branch": "" }, - "revision": "b060f13f81d6827dbf27ba2dc5183c5fecced1a2", + "revision": "307646c3fd09cbc2ee1f15a063c7fcd9cb01c8ab", "repo_path": "integration/gaia-central" } From 33b6f0e3b0bed509b86fcd9f41d39f3ab579ad07 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Thu, 17 Sep 2015 07:43:52 -0700 Subject: [PATCH 103/113] Bumping manifests a=b2g-bump --- b2g/config/aries/sources.xml | 2 +- b2g/config/dolphin/sources.xml | 2 +- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator-l/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame-kk/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/nexus-5-l/sources.xml | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/b2g/config/aries/sources.xml b/b2g/config/aries/sources.xml index 340a568aaa38..b6dd1ce458c6 100644 --- a/b2g/config/aries/sources.xml +++ b/b2g/config/aries/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index b4b4e9ab0d6c..539171f102d5 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index 87d64afb992a..80c130b08145 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index 83594c1df6ca..c1679840d409 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index a43b3020d3ce..507afee23186 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator-l/sources.xml b/b2g/config/emulator-l/sources.xml index c468065cc068..888c133be83c 100644 --- a/b2g/config/emulator-l/sources.xml +++ b/b2g/config/emulator-l/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index 87d64afb992a..80c130b08145 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame-kk/sources.xml b/b2g/config/flame-kk/sources.xml index d6d2fea9faeb..3a9615c38d7b 100644 --- a/b2g/config/flame-kk/sources.xml +++ b/b2g/config/flame-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index 3fe12cced2ec..a7a6cba101ec 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/nexus-5-l/sources.xml b/b2g/config/nexus-5-l/sources.xml index f637719a08b3..ed5320f49447 100644 --- a/b2g/config/nexus-5-l/sources.xml +++ b/b2g/config/nexus-5-l/sources.xml @@ -15,7 +15,7 @@ - + From eacdd5b17ec5f5a28d06b7b5905bdb0b949a454d Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Thu, 17 Sep 2015 08:02:16 -0700 Subject: [PATCH 104/113] Bumping gaia.json for 2 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/8c84d1a41ed9 Author: Martijn Desc: Merge pull request #31841 from mwargers/1203060 Bug 1203060 - Make the launch code also work for the browser app ======== https://hg.mozilla.org/integration/gaia-central/rev/70c7e69eb938 Author: Martijn Wargers Desc: Bug 1203060 - Make the launch code also work for the browser app --- b2g/config/gaia.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 10493ef70471..e1573f11fe66 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,9 +1,9 @@ { "git": { - "git_revision": "7196b004d27eb540e04b6512ae89e4639e26fccf", + "git_revision": "60011f2947e31a92f064502784d7e1b8fc26898c", "remote": "https://git.mozilla.org/releases/gaia.git", "branch": "" }, - "revision": "307646c3fd09cbc2ee1f15a063c7fcd9cb01c8ab", + "revision": "8c84d1a41ed97cafe0a334eb501bd08043c1d593", "repo_path": "integration/gaia-central" } From 91a4f160b3da17c6a541fb8fc56aaddfaf190083 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Thu, 17 Sep 2015 08:05:00 -0700 Subject: [PATCH 105/113] Bumping manifests a=b2g-bump --- b2g/config/aries/sources.xml | 2 +- b2g/config/dolphin/sources.xml | 2 +- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator-l/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame-kk/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/nexus-5-l/sources.xml | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/b2g/config/aries/sources.xml b/b2g/config/aries/sources.xml index b6dd1ce458c6..dbe34532178f 100644 --- a/b2g/config/aries/sources.xml +++ b/b2g/config/aries/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index 539171f102d5..a50b8cd66869 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index 80c130b08145..e060df6ce9a6 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index c1679840d409..c6c34df12de1 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index 507afee23186..4dfe5b9e5683 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator-l/sources.xml b/b2g/config/emulator-l/sources.xml index 888c133be83c..441eb0aae111 100644 --- a/b2g/config/emulator-l/sources.xml +++ b/b2g/config/emulator-l/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index 80c130b08145..e060df6ce9a6 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame-kk/sources.xml b/b2g/config/flame-kk/sources.xml index 3a9615c38d7b..8afc8ba52a6a 100644 --- a/b2g/config/flame-kk/sources.xml +++ b/b2g/config/flame-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index a7a6cba101ec..f9f5f08bf209 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/nexus-5-l/sources.xml b/b2g/config/nexus-5-l/sources.xml index ed5320f49447..5993e72a75ef 100644 --- a/b2g/config/nexus-5-l/sources.xml +++ b/b2g/config/nexus-5-l/sources.xml @@ -15,7 +15,7 @@ - + From e7f3e1b2a3cef6dd04f68ac1076993e44ea54293 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Thu, 17 Sep 2015 08:22:25 -0700 Subject: [PATCH 106/113] Bumping gaia.json for 2 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/0e712c8d330e Author: No-Jun Park Desc: Merge pull request #31887 from npark-mozilla/1205609 Bug 1205609 - [v2.5][Gaia::UI Tests]test_settings_passcode.py:"AttributeError: ======== https://hg.mozilla.org/integration/gaia-central/rev/a9ec901e0e6b Author: No-Jun Park Desc: Bug 1205609 - [v2.5][Gaia::UI Tests]test_settings_passcode.py:"AttributeError: 'ScreenLock' object has no attribute '_screen_lock_section_locator' --- b2g/config/gaia.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index e1573f11fe66..3358a73f9405 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,9 +1,9 @@ { "git": { - "git_revision": "60011f2947e31a92f064502784d7e1b8fc26898c", + "git_revision": "2082894c8e974b0c371e4dec298e0ad0f3ac56b1", "remote": "https://git.mozilla.org/releases/gaia.git", "branch": "" }, - "revision": "8c84d1a41ed97cafe0a334eb501bd08043c1d593", + "revision": "0e712c8d330e10908f99194a9638e62a07c5c483", "repo_path": "integration/gaia-central" } From 5d037b8b6ea7e2a4ae9c3fa205d4e6e1e140f52d Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Thu, 17 Sep 2015 08:25:12 -0700 Subject: [PATCH 107/113] Bumping manifests a=b2g-bump --- b2g/config/aries/sources.xml | 2 +- b2g/config/dolphin/sources.xml | 2 +- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator-l/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame-kk/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/nexus-5-l/sources.xml | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/b2g/config/aries/sources.xml b/b2g/config/aries/sources.xml index dbe34532178f..686fb3c8446d 100644 --- a/b2g/config/aries/sources.xml +++ b/b2g/config/aries/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index a50b8cd66869..7885aefffcb9 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index e060df6ce9a6..4c9e3ec86dd9 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index c6c34df12de1..4f750f723152 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index 4dfe5b9e5683..b4d110c0b4bb 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator-l/sources.xml b/b2g/config/emulator-l/sources.xml index 441eb0aae111..6c3790092575 100644 --- a/b2g/config/emulator-l/sources.xml +++ b/b2g/config/emulator-l/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index e060df6ce9a6..4c9e3ec86dd9 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame-kk/sources.xml b/b2g/config/flame-kk/sources.xml index 8afc8ba52a6a..0096068244ad 100644 --- a/b2g/config/flame-kk/sources.xml +++ b/b2g/config/flame-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index f9f5f08bf209..eefc6b17bd65 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/nexus-5-l/sources.xml b/b2g/config/nexus-5-l/sources.xml index 5993e72a75ef..9b5668ab3b13 100644 --- a/b2g/config/nexus-5-l/sources.xml +++ b/b2g/config/nexus-5-l/sources.xml @@ -15,7 +15,7 @@ - + From 9355c18c57d04fd71470a2461e4dae8b5d822245 Mon Sep 17 00:00:00 2001 From: Andreas Tolfsen Date: Thu, 17 Sep 2015 17:12:29 +0100 Subject: [PATCH 108/113] Backed out changeset 820865a790e4 (bug 1202663) CLOSED TREE --HG-- extra : commitid : D1PsvakkyZm --- testing/marionette/driver.js | 7 +- testing/marionette/listener.js | 114 +++++++++++++++++---------------- 2 files changed, 63 insertions(+), 58 deletions(-) diff --git a/testing/marionette/driver.js b/testing/marionette/driver.js index f43530a21e22..4d61b4f8da4e 100644 --- a/testing/marionette/driver.js +++ b/testing/marionette/driver.js @@ -2562,8 +2562,6 @@ GeckoDriver.prototype.clearImportedScripts = function(cmd, resp) { * PNG image encoded as base64 encoded string. */ GeckoDriver.prototype.takeScreenshot = function(cmd, resp) { - let {id, highlights, full} = cmd.parameters; - switch (this.context) { case Context.CHROME: let win = this.getCurrentWindow(); @@ -2606,7 +2604,10 @@ GeckoDriver.prototype.takeScreenshot = function(cmd, resp) { break; case Context.CONTENT: - return this.listener.takeScreenshot(id, highlights, full); + resp.body.value = yield this.listener.takeScreenshot({ + id: cmd.parameters.id, + highlights: cmd.parameters.highlights, + full: cmd.parameters.full}); break; } }; diff --git a/testing/marionette/listener.js b/testing/marionette/listener.js index 5c25c898b604..8447780b3a31 100644 --- a/testing/marionette/listener.js +++ b/testing/marionette/listener.js @@ -196,29 +196,26 @@ function removeMessageListenerId(messageName, handler) { removeMessageListener(messageName + listenerId, handler); } -let getTitleFn = dispatch(getTitle); -let getElementSizeFn = dispatch(getElementSize); -let getPageSourceFn = dispatch(getPageSource); -let getActiveElementFn = dispatch(getActiveElement); -let clickElementFn = dispatch(clickElement); -let goBackFn = dispatch(goBack); -let getElementAttributeFn = dispatch(getElementAttribute); -let getElementTextFn = dispatch(getElementText); -let getElementTagNameFn = dispatch(getElementTagName); -let getElementRectFn = dispatch(getElementRect); -let isElementEnabledFn = dispatch(isElementEnabled); -let getCurrentUrlFn = dispatch(getCurrentUrl); -let findElementContentFn = dispatch(findElementContent); -let findElementsContentFn = dispatch(findElementsContent); -let isElementSelectedFn = dispatch(isElementSelected); -let getElementLocationFn = dispatch(getElementLocation); -let clearElementFn = dispatch(clearElement); -let isElementDisplayedFn = dispatch(isElementDisplayed); -let getElementValueOfCssPropertyFn = dispatch(getElementValueOfCssProperty); -let switchToShadowRootFn = dispatch(switchToShadowRoot); -let getCookiesFn = dispatch(getCookies); -let singleTapFn = dispatch(singleTap); -let takeScreenshotFn = dispatch(takeScreenshot); +var getTitleFn = dispatch(getTitle); +var getPageSourceFn = dispatch(getPageSource); +var getActiveElementFn = dispatch(getActiveElement); +var clickElementFn = dispatch(clickElement); +var goBackFn = dispatch(goBack); +var getElementAttributeFn = dispatch(getElementAttribute); +var getElementTextFn = dispatch(getElementText); +var getElementTagNameFn = dispatch(getElementTagName); +var getElementRectFn = dispatch(getElementRect); +var isElementEnabledFn = dispatch(isElementEnabled); +var getCurrentUrlFn = dispatch(getCurrentUrl); +var findElementContentFn = dispatch(findElementContent); +var findElementsContentFn = dispatch(findElementsContent); +var isElementSelectedFn = dispatch(isElementSelected); +var clearElementFn = dispatch(clearElement); +var isElementDisplayedFn = dispatch(isElementDisplayed); +var getElementValueOfCssPropertyFn = dispatch(getElementValueOfCssProperty); +var switchToShadowRootFn = dispatch(switchToShadowRoot); +var getCookiesFn = dispatch(getCookies); +var singleTapFn = dispatch(singleTap); /** * Start all message listeners @@ -263,7 +260,7 @@ function startListeners() { addMessageListenerId("Marionette:importScript", importScript); addMessageListenerId("Marionette:getAppCacheStatus", getAppCacheStatus); addMessageListenerId("Marionette:setTestName", setTestName); - addMessageListenerId("Marionette:takeScreenshot", takeScreenshotFn); + addMessageListenerId("Marionette:takeScreenshot", takeScreenshot); addMessageListenerId("Marionette:addCookie", addCookie); addMessageListenerId("Marionette:getCookies", getCookiesFn); addMessageListenerId("Marionette:deleteAllCookies", deleteAllCookies); @@ -367,7 +364,7 @@ function deleteSession(msg) { removeMessageListenerId("Marionette:importScript", importScript); removeMessageListenerId("Marionette:getAppCacheStatus", getAppCacheStatus); removeMessageListenerId("Marionette:setTestName", setTestName); - removeMessageListenerId("Marionette:takeScreenshot", takeScreenshotFn); + removeMessageListenerId("Marionette:takeScreenshot", takeScreenshot); removeMessageListenerId("Marionette:addCookie", addCookie); removeMessageListenerId("Marionette:getCookies", getCookiesFn); removeMessageListenerId("Marionette:deleteAllCookies", deleteAllCookies); @@ -1997,35 +1994,44 @@ function importScript(msg) { * msg.json.highlights, a red box will be painted around * them to highlight their position. */ -function takeScreenshot(id, highlights, full) { +function takeScreenshot(msg) { let node = null; - if (id) { - node = elementManager.getKnownElement(id, curContainer) - } else { + if (msg.json.id) { + try { + node = elementManager.getKnownElement(msg.json.id, curContainer) + } + catch (e) { + sendResponse(e.message, e.code, e.stack, msg.json.command_id); + return; + } + } + else { node = curContainer.frame; } + let highlights = msg.json.highlights; - let document = curContainer.frame.document; - let rect, win, width, height, left, top; - + var document = curContainer.frame.document; + var rect, win, width, height, left, top; // node can be either a window or an arbitrary DOM node if (node == curContainer.frame) { // node is a window win = node; - if (full) { + if (msg.json.full) { // the full window width = document.body.scrollWidth; height = document.body.scrollHeight; top = 0; left = 0; - } else { + } + else { // only the viewport width = document.documentElement.clientWidth; height = document.documentElement.clientHeight; left = curContainer.frame.pageXOffset; top = curContainer.frame.pageYOffset; } - } else { + } + else { // node is an arbitrary DOM node win = node.ownerDocument.defaultView; rect = node.getBoundingClientRect(); @@ -2035,16 +2041,15 @@ function takeScreenshot(id, highlights, full) { left = rect.left; } - let canvas = document.createElementNS( - "http://www.w3.org/1999/xhtml", "canvas"); + var canvas = document.createElementNS("http://www.w3.org/1999/xhtml", + "canvas"); canvas.width = width; canvas.height = height; - let ctx = canvas.getContext("2d"); - - // draws the DOM contents of the window to the canvas + var ctx = canvas.getContext("2d"); + // Draws the DOM contents of the window to the canvas ctx.drawWindow(win, left, top, width, height, "rgb(255,255,255)"); - // this section is for drawing a red rectangle around each element + // This section is for drawing a red rectangle around each element // passed in via the highlights array if (highlights) { ctx.lineWidth = "2"; @@ -2052,26 +2057,25 @@ function takeScreenshot(id, highlights, full) { ctx.save(); for (var i = 0; i < highlights.length; ++i) { - let elem = elementManager.getKnownElement(highlights[i], curContainer); + var elem = elementManager.getKnownElement(highlights[i], curContainer); rect = elem.getBoundingClientRect(); - let offsetY = -top; - let offsetX = -left; + var offsetY = -top; + var offsetX = -left; - // draw the rectangle - ctx.strokeRect( - rect.left + offsetX, - rect.top + offsetY, - rect.width, - rect.height); + // Draw the rectangle + ctx.strokeRect(rect.left + offsetX, + rect.top + offsetY, + rect.width, + rect.height); } } - // return the Base64 encoded string back to the client - // so that it can save the file to disk if it is required - let dataUrl = canvas.toDataURL("image/png", ""); - let encoded = dataUrl.substring(dataUrl.indexOf(",") + 1); - return encoded; + // Return the Base64 encoded string back to the client so that it + // can save the file to disk if it is required + var dataUrl = canvas.toDataURL("image/png", ""); + var data = dataUrl.substring(dataUrl.indexOf(",") + 1); + sendResponse({value: data}, msg.json.command_id); } // Call register self when we get loaded From e9df0ab2233e0dd55ef6b4f2702e1792e50275b4 Mon Sep 17 00:00:00 2001 From: Wes Kocher Date: Thu, 17 Sep 2015 11:39:14 -0700 Subject: [PATCH 109/113] Backed out changeset 4717107189fe (bug 1204800) for device build bustage CLOSED TREE --- b2g/config/aries/releng-aries.tt | 14 +++++++------- b2g/config/flame-kk/releng-flame-kk.tt | 14 +++++++------- b2g/config/flame/releng-flame.tt | 5 +++++ .../taskcluster/scripts/phone-builder/pre-build.sh | 3 --- .../tasks/builds/b2g_aries_spark_debug.yml | 1 - .../tasks/builds/b2g_aries_spark_eng.yml | 1 - .../tasks/builds/b2g_aries_spark_opt.yml | 1 - .../tasks/builds/b2g_flame_kk_debug.yml | 1 - .../taskcluster/tasks/builds/b2g_flame_kk_eng.yml | 1 - .../taskcluster/tasks/builds/b2g_flame_kk_opt.yml | 1 - .../tasks/builds/b2g_phone_eng_base.yml | 4 ---- testing/taskcluster/tasks/phone_build.yml | 2 -- 12 files changed, 19 insertions(+), 29 deletions(-) diff --git a/b2g/config/aries/releng-aries.tt b/b2g/config/aries/releng-aries.tt index 55f67c82c1fe..74b32b01f17b 100644 --- a/b2g/config/aries/releng-aries.tt +++ b/b2g/config/aries/releng-aries.tt @@ -1,16 +1,16 @@ [ { +"size": 135359412, +"digest": "45e677c9606cc4eec44ef4761df47ff431df1ffad17a5c6d21ce700a1c47f79e87a4aa9f30ae47ff060bd64f5b775d995780d88211f9a759ffa0d076beb4816b", +"algorithm": "sha512", +"filename": "backup-aries.tar.xz", +"comment": "v18D" +}, +{ "size": 80458572, "digest": "e5101f9dee1e462f6cbd3897ea57eede41d23981825c7b20d91d23ab461875d54d3dfc24999aa58a31e8b01f49fb3140e05ffe5af2957ef1d1afb89fd0dfe1ad", "algorithm": "sha512", "filename": "gcc.tar.xz", "unpack": "True" -}, -{ -"size": 12057960, -"digest": "6105d6432943141cffb40020dc5ba3a793650bdeb3af9bd5e56d3796c5f03df9962a73e521646cd71fbfb5e266c1e74716ad722fb6055589dfb7d35175bca89e", -"algorithm": "sha512", -"filename": "gtk3.tar.xz", -"unpack": true } ] diff --git a/b2g/config/flame-kk/releng-flame-kk.tt b/b2g/config/flame-kk/releng-flame-kk.tt index 55f67c82c1fe..d0e0c584aa85 100644 --- a/b2g/config/flame-kk/releng-flame-kk.tt +++ b/b2g/config/flame-kk/releng-flame-kk.tt @@ -1,16 +1,16 @@ [ { +"size": 135359412, +"digest": "45e677c9606cc4eec44ef4761df47ff431df1ffad17a5c6d21ce700a1c47f79e87a4aa9f30ae47ff060bd64f5b775d995780d88211f9a759ffa0d076beb4816b", +"algorithm": "sha512", +"filename": "backup-flame.tar.xz", +"comment": "v18D" +}, +{ "size": 80458572, "digest": "e5101f9dee1e462f6cbd3897ea57eede41d23981825c7b20d91d23ab461875d54d3dfc24999aa58a31e8b01f49fb3140e05ffe5af2957ef1d1afb89fd0dfe1ad", "algorithm": "sha512", "filename": "gcc.tar.xz", "unpack": "True" -}, -{ -"size": 12057960, -"digest": "6105d6432943141cffb40020dc5ba3a793650bdeb3af9bd5e56d3796c5f03df9962a73e521646cd71fbfb5e266c1e74716ad722fb6055589dfb7d35175bca89e", -"algorithm": "sha512", -"filename": "gtk3.tar.xz", -"unpack": true } ] diff --git a/b2g/config/flame/releng-flame.tt b/b2g/config/flame/releng-flame.tt index 1af12208b9da..65f9871b6796 100644 --- a/b2g/config/flame/releng-flame.tt +++ b/b2g/config/flame/releng-flame.tt @@ -1,4 +1,9 @@ [ +{"size": 149922032, +"digest": "8d1a71552ffee561e93b5b3f1bb47866592ab958f908007c75561156430eb1b85a265bfc4dc2038e58dda0264daa9854877a84ef3b591c9ac2f1ab97c098e61e", +"filename": "backup-flame.tar.xz", +"algorithm": "sha512" +}, { "size": 80458572, "digest": "e5101f9dee1e462f6cbd3897ea57eede41d23981825c7b20d91d23ab461875d54d3dfc24999aa58a31e8b01f49fb3140e05ffe5af2957ef1d1afb89fd0dfe1ad", diff --git a/testing/taskcluster/scripts/phone-builder/pre-build.sh b/testing/taskcluster/scripts/phone-builder/pre-build.sh index 47357131ef39..99f0718a87cb 100755 --- a/testing/taskcluster/scripts/phone-builder/pre-build.sh +++ b/testing/taskcluster/scripts/phone-builder/pre-build.sh @@ -26,9 +26,6 @@ tc-vcs repo-checkout $WORKSPACE/B2G https://git.mozilla.org/b2g/B2G.git $MANIFES rm -f $WORKSPACE/B2G/gecko ln -s $WORKSPACE/gecko $WORKSPACE/B2G/gecko -### Install package dependencies -. ../builder/install-packages.sh $WORKSPACE/gecko - debug_flag="" if [ 0$B2G_DEBUG -ne 0 ]; then debug_flag='--debug' diff --git a/testing/taskcluster/tasks/builds/b2g_aries_spark_debug.yml b/testing/taskcluster/tasks/builds/b2g_aries_spark_debug.yml index b3e946cc5fc7..0c751a811aa1 100644 --- a/testing/taskcluster/tasks/builds/b2g_aries_spark_debug.yml +++ b/testing/taskcluster/tasks/builds/b2g_aries_spark_debug.yml @@ -22,7 +22,6 @@ task: GAIA_OPTIMIZE: '1' B2G_SYSTEM_APPS: '1' MOZHARNESS_CONFIG: b2g/taskcluster-spark.py - TOOLTOOL_MANIFEST: 'b2g/config/aries/releng-aries.tt' command: - > checkout-gecko workspace && diff --git a/testing/taskcluster/tasks/builds/b2g_aries_spark_eng.yml b/testing/taskcluster/tasks/builds/b2g_aries_spark_eng.yml index f138a3475740..7c3e71fc05c4 100644 --- a/testing/taskcluster/tasks/builds/b2g_aries_spark_eng.yml +++ b/testing/taskcluster/tasks/builds/b2g_aries_spark_eng.yml @@ -17,7 +17,6 @@ task: env: TARGET: 'aries' MOZHARNESS_CONFIG: b2g/taskcluster-spark.py - TOOLTOOL_MANIFEST: 'b2g/config/aries/releng-aries.tt' extra: treeherderEnv: - production diff --git a/testing/taskcluster/tasks/builds/b2g_aries_spark_opt.yml b/testing/taskcluster/tasks/builds/b2g_aries_spark_opt.yml index c2aa962fa5c5..9207c05a7e62 100644 --- a/testing/taskcluster/tasks/builds/b2g_aries_spark_opt.yml +++ b/testing/taskcluster/tasks/builds/b2g_aries_spark_opt.yml @@ -22,7 +22,6 @@ task: GAIA_OPTIMIZE: '1' B2G_SYSTEM_APPS: '1' MOZHARNESS_CONFIG: b2g/taskcluster-spark.py - TOOLTOOL_MANIFEST: 'b2g/config/aries/releng-aries.tt' command: - > checkout-gecko workspace && diff --git a/testing/taskcluster/tasks/builds/b2g_flame_kk_debug.yml b/testing/taskcluster/tasks/builds/b2g_flame_kk_debug.yml index 61c9ce96308b..42fc7744d197 100644 --- a/testing/taskcluster/tasks/builds/b2g_flame_kk_debug.yml +++ b/testing/taskcluster/tasks/builds/b2g_flame_kk_debug.yml @@ -19,7 +19,6 @@ task: TARGET: 'flame-kk' DEBUG: 0 VARIANT: userdebug - TOOLTOOL_MANIFEST: 'b2g/config/flame-kk/releng-flame-kk.tt' command: - > checkout-gecko workspace && diff --git a/testing/taskcluster/tasks/builds/b2g_flame_kk_eng.yml b/testing/taskcluster/tasks/builds/b2g_flame_kk_eng.yml index 1b1c7452c173..7d8f1cfe8cff 100644 --- a/testing/taskcluster/tasks/builds/b2g_flame_kk_eng.yml +++ b/testing/taskcluster/tasks/builds/b2g_flame_kk_eng.yml @@ -16,7 +16,6 @@ task: build-flame-kk-eng-objdir-gecko-{{project}}: /home/worker/objdir-gecko env: TARGET: 'flame-kk' - TOOLTOOL_MANIFEST: 'b2g/config/flame-kk/releng-flame-kk.tt' extra: treeherderEnv: - production diff --git a/testing/taskcluster/tasks/builds/b2g_flame_kk_opt.yml b/testing/taskcluster/tasks/builds/b2g_flame_kk_opt.yml index 0e06f93d1733..e007d5bbcc63 100644 --- a/testing/taskcluster/tasks/builds/b2g_flame_kk_opt.yml +++ b/testing/taskcluster/tasks/builds/b2g_flame_kk_opt.yml @@ -18,7 +18,6 @@ task: env: TARGET: 'flame-kk' DEBUG: 0 - TOOLTOOL_MANIFEST: 'b2g/config/flame-kk/releng-flame-kk.tt' command: - > checkout-gecko workspace && diff --git a/testing/taskcluster/tasks/builds/b2g_phone_eng_base.yml b/testing/taskcluster/tasks/builds/b2g_phone_eng_base.yml index 768a4f643c64..20268158e66d 100644 --- a/testing/taskcluster/tasks/builds/b2g_phone_eng_base.yml +++ b/testing/taskcluster/tasks/builds/b2g_phone_eng_base.yml @@ -1,13 +1,9 @@ $inherits: from: 'tasks/builds/b2g_phone_base.yml' task: - scopes: - - 'docker-worker:cache:tooltool-cache' workerType: flame-kk payload: - cache: - tooltool-cache: '/home/worker/tooltool-cache' env: DEBUG: 0 VARIANT: eng diff --git a/testing/taskcluster/tasks/phone_build.yml b/testing/taskcluster/tasks/phone_build.yml index 08b9f518b7b1..9ef39d34611c 100644 --- a/testing/taskcluster/tasks/phone_build.yml +++ b/testing/taskcluster/tasks/phone_build.yml @@ -54,8 +54,6 @@ task: GECKO_HEAD_REPOSITORY: '{{head_repository}}' GECKO_HEAD_REV: '{{head_rev}}' GECKO_HEAD_REF: '{{head_ref}}' - TOOLTOOL_REPO: 'https://git.mozilla.org/build/tooltool.git' - TOOLTOOL_REV: 'master' extra: build_product: 'b2g' From 4612e85891fb6657181be1cceba28cc135a185e9 Mon Sep 17 00:00:00 2001 From: Wes Kocher Date: Thu, 17 Sep 2015 11:40:19 -0700 Subject: [PATCH 110/113] Backed out changeset 4c9d2dab60f3 (bug 1181038) for w(4) failures CLOSED TREE --- .../performance-timeline.https.html.ini | 2 +- .../performance-timeline.https.html | 2 +- .../service-worker/resources/dummy.txt | 1 - .../resources/performance-timeline-worker.js | 53 ------------------- 4 files changed, 2 insertions(+), 56 deletions(-) delete mode 100644 testing/web-platform/mozilla/tests/service-workers/service-worker/resources/dummy.txt delete mode 100644 testing/web-platform/mozilla/tests/service-workers/service-worker/resources/performance-timeline-worker.js diff --git a/testing/web-platform/mozilla/meta/service-workers/service-worker/performance-timeline.https.html.ini b/testing/web-platform/mozilla/meta/service-workers/service-worker/performance-timeline.https.html.ini index e37f8696f699..064ae22b3f5b 100644 --- a/testing/web-platform/mozilla/meta/service-workers/service-worker/performance-timeline.https.html.ini +++ b/testing/web-platform/mozilla/meta/service-workers/service-worker/performance-timeline.https.html.ini @@ -1,5 +1,5 @@ [performance-timeline.https.html] type: testharness - [Resource Timing] + [Test Performance Timeline API in Service Worker] expected: FAIL diff --git a/testing/web-platform/mozilla/tests/service-workers/service-worker/performance-timeline.https.html b/testing/web-platform/mozilla/tests/service-workers/service-worker/performance-timeline.https.html index 182076baa984..63e893ad56e8 100644 --- a/testing/web-platform/mozilla/tests/service-workers/service-worker/performance-timeline.https.html +++ b/testing/web-platform/mozilla/tests/service-workers/service-worker/performance-timeline.https.html @@ -5,7 +5,7 @@ diff --git a/testing/web-platform/mozilla/tests/service-workers/service-worker/resources/dummy.txt b/testing/web-platform/mozilla/tests/service-workers/service-worker/resources/dummy.txt deleted file mode 100644 index 802992c4220d..000000000000 --- a/testing/web-platform/mozilla/tests/service-workers/service-worker/resources/dummy.txt +++ /dev/null @@ -1 +0,0 @@ -Hello world diff --git a/testing/web-platform/mozilla/tests/service-workers/service-worker/resources/performance-timeline-worker.js b/testing/web-platform/mozilla/tests/service-workers/service-worker/resources/performance-timeline-worker.js deleted file mode 100644 index c1182c937096..000000000000 --- a/testing/web-platform/mozilla/tests/service-workers/service-worker/resources/performance-timeline-worker.js +++ /dev/null @@ -1,53 +0,0 @@ -importScripts('/resources/testharness.js'); - -promise_test(function(test) { - var durationMsec = 100; - return new Promise(function(resolve) { - performance.mark('startMark'); - setTimeout(resolve, durationMsec); - }).then(function() { - performance.mark('endMark'); - performance.measure('measure', 'startMark', 'endMark'); - var startMark = performance.getEntriesByName('startMark')[0]; - var endMark = performance.getEntriesByName('endMark')[0]; - var measure = performance.getEntriesByType('measure')[0]; - assert_equals(measure.startTime, startMark.startTime); - assert_approx_equals(endMark.startTime - startMark.startTime, - measure.duration, 0.001); - assert_greater_than(measure.duration, durationMsec); - assert_equals(performance.getEntriesByType('mark').length, 2); - assert_equals(performance.getEntriesByType('measure').length, 1); - performance.clearMarks('startMark'); - performance.clearMeasures('measure'); - assert_equals(performance.getEntriesByType('mark').length, 1); - assert_equals(performance.getEntriesByType('measure').length, 0); - }); - }, 'User Timing'); - -promise_test(function(test) { - return fetch('dummy.txt') - .then(function(resp) { - return resp.text(); - }) - .then(function(text) { - var expectedResources = ['testharness.js', 'dummy.txt']; - assert_equals(performance.getEntriesByType('resource').length, expectedResources.length); - for (var i = 0; i < expectedResources.length; i++) { - var entry = performance.getEntriesByType('resource')[i]; - assert_true(entry.name.endsWith(expectedResources[i])); - assert_equals(entry.workerStart, 0); - assert_greater_than(entry.startTime, 0); - assert_greater_than(entry.responseEnd, entry.startTime); - } - return new Promise(function(resolve) { - performance.onresourcetimingbufferfull = resolve; - performance.setResourceTimingBufferSize(expectedResources.length); - }); - }) - .then(function() { - performance.clearResourceTimings(); - assert_equals(performance.getEntriesByType('resource').length, 0); - }) - }, 'Resource Timing'); - -done(); From 40cee6104dbd4879850f2b034aacd98589ad565a Mon Sep 17 00:00:00 2001 From: Wes Kocher Date: Thu, 17 Sep 2015 11:41:27 -0700 Subject: [PATCH 111/113] Backed out changeset 156b6847bbb4 (bug 1186857) for w(4) bustage CLOSED TREE --- .../service-worker/unregister-then-register.https.html.ini | 5 +++++ .../service-worker/unregister-then-register.https.html | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 testing/web-platform/mozilla/meta/service-workers/service-worker/unregister-then-register.https.html.ini diff --git a/testing/web-platform/mozilla/meta/service-workers/service-worker/unregister-then-register.https.html.ini b/testing/web-platform/mozilla/meta/service-workers/service-worker/unregister-then-register.https.html.ini new file mode 100644 index 000000000000..40d1a05994ba --- /dev/null +++ b/testing/web-platform/mozilla/meta/service-workers/service-worker/unregister-then-register.https.html.ini @@ -0,0 +1,5 @@ +[unregister-then-register.https.html] + type: testharness + [Unregister then register resolves to the original value if the registration is in use.] + expected: FAIL + diff --git a/testing/web-platform/mozilla/tests/service-workers/service-worker/unregister-then-register.https.html b/testing/web-platform/mozilla/tests/service-workers/service-worker/unregister-then-register.https.html index 1d1a1ecf0a8c..b6a55eaf9876 100644 --- a/testing/web-platform/mozilla/tests/service-workers/service-worker/unregister-then-register.https.html +++ b/testing/web-platform/mozilla/tests/service-workers/service-worker/unregister-then-register.https.html @@ -48,8 +48,8 @@ async_test(function(t) { return navigator.serviceWorker.register(worker_url, { scope: scope }); }) .then(function(new_registration) { - assert_equals(registration.scope, new_registration.scope, - 'new registration should resolve to the same scope'); + assert_equals(registration, new_registration, + 'register should resolve to the same value'); service_worker_unregister_and_done(t, scope); }) .catch(unreached_rejection(t)); From 5d45d1a728affea8578565ee823c6dd3f801da13 Mon Sep 17 00:00:00 2001 From: Wes Kocher Date: Thu, 17 Sep 2015 13:06:41 -0700 Subject: [PATCH 112/113] Backed out 3 changesets (bug 1161276) for test_mediarecorder_bitrate.html failures CLOSED TREE Backed out changeset 9187f4d2518f (bug 1161276) Backed out changeset 4e8f28b17300 (bug 1161276) Backed out changeset cf05881e89ed (bug 1161276) --- dom/media/MediaRecorder.cpp | 39 +----- dom/media/MediaRecorder.h | 7 - dom/media/encoder/MediaEncoder.cpp | 13 +- dom/media/encoder/MediaEncoder.h | 7 +- dom/media/encoder/OpusTrackEncoder.cpp | 5 - dom/media/encoder/TrackEncoder.h | 16 --- dom/media/encoder/VP8TrackEncoder.cpp | 6 +- dom/media/encoder/VorbisTrackEncoder.cpp | 5 +- dom/media/test/manifest.js | 5 - dom/media/test/mochitest.ini | 2 - .../test/test_mediarecorder_bitrate.html | 131 ------------------ dom/webidl/MediaRecorder.webidl | 3 - 12 files changed, 10 insertions(+), 229 deletions(-) delete mode 100644 dom/media/test/test_mediarecorder_bitrate.html diff --git a/dom/media/MediaRecorder.cpp b/dom/media/MediaRecorder.cpp index ec6258d53464..967816946002 100644 --- a/dom/media/MediaRecorder.cpp +++ b/dom/media/MediaRecorder.cpp @@ -595,17 +595,9 @@ private: // Make sure the application has permission to assign AUDIO_3GPP if (mRecorder->mMimeType.EqualsLiteral(AUDIO_3GPP) && Check3gppPermission()) { - mEncoder = MediaEncoder::CreateEncoder(NS_LITERAL_STRING(AUDIO_3GPP), - mRecorder->GetAudioBitrate(), - mRecorder->GetVideoBitrate(), - mRecorder->GetBitrate(), - aTrackTypes); + mEncoder = MediaEncoder::CreateEncoder(NS_LITERAL_STRING(AUDIO_3GPP), aTrackTypes); } else { - mEncoder = MediaEncoder::CreateEncoder(NS_LITERAL_STRING(""), - mRecorder->GetAudioBitrate(), - mRecorder->GetVideoBitrate(), - mRecorder->GetBitrate(), - aTrackTypes); + mEncoder = MediaEncoder::CreateEncoder(NS_LITERAL_STRING(""), aTrackTypes); } if (!mEncoder) { @@ -973,7 +965,7 @@ MediaRecorder::Constructor(const GlobalObject& aGlobal, } nsRefPtr object = new MediaRecorder(aStream, ownerWindow); - object->SetOptions(aInitDict); + object->SetMimeType(aInitDict.mMimeType); return object.forget(); } @@ -1009,33 +1001,10 @@ MediaRecorder::Constructor(const GlobalObject& aGlobal, nsRefPtr object = new MediaRecorder(aSrcAudioNode, aSrcOutput, ownerWindow); - object->SetOptions(aInitDict); + object->SetMimeType(aInitDict.mMimeType); return object.forget(); } -void -MediaRecorder::SetOptions(const MediaRecorderOptions& aInitDict) -{ - SetMimeType(aInitDict.mMimeType); - mAudioBitsPerSecond = aInitDict.mAudioBitsPerSecond.WasPassed() ? - aInitDict.mAudioBitsPerSecond.Value() : 0; - mVideoBitsPerSecond = aInitDict.mVideoBitsPerSecond.WasPassed() ? - aInitDict.mVideoBitsPerSecond.Value() : 0; - mBitsPerSecond = aInitDict.mBitsPerSecond.WasPassed() ? - aInitDict.mBitsPerSecond.Value() : 0; - // We're not handling dynamic changes yet. Eventually we'll handle - // setting audio, video and/or total -- and anything that isn't set, - // we'll derive. Calculated versions require querying bitrates after - // the encoder is Init()ed. This happens only after data is - // available and thus requires dynamic changes. - // - // Until dynamic changes are supported, I prefer to be safe and err - // slightly high - if (aInitDict.mBitsPerSecond.WasPassed() && !aInitDict.mVideoBitsPerSecond.WasPassed()) { - mVideoBitsPerSecond = mBitsPerSecond; - } -} - nsresult MediaRecorder::CreateAndDispatchBlobEvent(already_AddRefed&& aBlob) { diff --git a/dom/media/MediaRecorder.h b/dom/media/MediaRecorder.h index ca1f3877417a..3aeb8aa00cb6 100644 --- a/dom/media/MediaRecorder.h +++ b/dom/media/MediaRecorder.h @@ -104,9 +104,6 @@ public: NS_DECL_NSIDOCUMENTACTIVITY - uint32_t GetAudioBitrate() { return mAudioBitsPerSecond; } - uint32_t GetVideoBitrate() { return mVideoBitsPerSecond; } - uint32_t GetBitrate() { return mBitsPerSecond; } protected: virtual ~MediaRecorder(); @@ -121,7 +118,6 @@ protected: bool CheckPrincipal(); // Set encoded MIME type. void SetMimeType(const nsString &aMimeType); - void SetOptions(const MediaRecorderOptions& aInitDict); MediaRecorder(const MediaRecorder& x) = delete; // prevent bad usage // Remove session pointer. @@ -148,9 +144,6 @@ protected: // It specifies the container format as well as the audio and video capture formats. nsString mMimeType; - uint32_t mAudioBitsPerSecond; - uint32_t mVideoBitsPerSecond; - uint32_t mBitsPerSecond; private: // Register MediaRecorder into Document to listen the activity changes. void RegisterActivityObserver(); diff --git a/dom/media/encoder/MediaEncoder.cpp b/dom/media/encoder/MediaEncoder.cpp index 0c734f4f0467..e9e10a492835 100644 --- a/dom/media/encoder/MediaEncoder.cpp +++ b/dom/media/encoder/MediaEncoder.cpp @@ -73,9 +73,7 @@ MediaEncoder::NotifyEvent(MediaStreamGraph* aGraph, /* static */ already_AddRefed -MediaEncoder::CreateEncoder(const nsAString& aMIMEType, uint32_t aAudioBitrate, - uint32_t aVideoBitrate, uint32_t aBitrate, - uint8_t aTrackTypes) +MediaEncoder::CreateEncoder(const nsAString& aMIMEType, uint8_t aTrackTypes) { if (!gMediaEncoderLog) { gMediaEncoderLog = PR_NewLogModule("MediaEncoder"); @@ -146,15 +144,8 @@ MediaEncoder::CreateEncoder(const nsAString& aMIMEType, uint32_t aAudioBitrate, LOG(LogLevel::Debug, ("Create encoder result:a[%d] v[%d] w[%d] mimeType = %s.", audioEncoder != nullptr, videoEncoder != nullptr, writer != nullptr, mimeType.get())); - if (videoEncoder && aVideoBitrate != 0) { - videoEncoder->SetBitrate(aVideoBitrate); - } - if (audioEncoder && aAudioBitrate != 0) { - audioEncoder->SetBitrate(aAudioBitrate); - } encoder = new MediaEncoder(writer.forget(), audioEncoder.forget(), - videoEncoder.forget(), mimeType, aAudioBitrate, - aVideoBitrate, aBitrate); + videoEncoder.forget(), mimeType); return encoder.forget(); } diff --git a/dom/media/encoder/MediaEncoder.h b/dom/media/encoder/MediaEncoder.h index 94a3d6dc621e..c947840aec00 100644 --- a/dom/media/encoder/MediaEncoder.h +++ b/dom/media/encoder/MediaEncoder.h @@ -62,10 +62,7 @@ public : MediaEncoder(ContainerWriter* aWriter, AudioTrackEncoder* aAudioEncoder, VideoTrackEncoder* aVideoEncoder, - const nsAString& aMIMEType, - uint32_t aAudioBitrate, - uint32_t aVideoBitrate, - uint32_t aBitrate) + const nsAString& aMIMEType) : mWriter(aWriter) , mAudioEncoder(aAudioEncoder) , mVideoEncoder(aVideoEncoder) @@ -99,8 +96,6 @@ public : * Ogg+Opus if it is empty. */ static already_AddRefed CreateEncoder(const nsAString& aMIMEType, - uint32_t aAudioBitrate, uint32_t aVideoBitrate, - uint32_t aBitrate, uint8_t aTrackTypes = ContainerWriter::CREATE_AUDIO_TRACK); /** * Encodes the raw track data and returns the final container data. Assuming diff --git a/dom/media/encoder/OpusTrackEncoder.cpp b/dom/media/encoder/OpusTrackEncoder.cpp index 053cf658f69c..ec6f2352e167 100644 --- a/dom/media/encoder/OpusTrackEncoder.cpp +++ b/dom/media/encoder/OpusTrackEncoder.cpp @@ -187,13 +187,8 @@ OpusTrackEncoder::Init(int aChannels, int aSamplingRate) mEncoder = opus_encoder_create(GetOutputSampleRate(), mChannels, OPUS_APPLICATION_AUDIO, &error); - mInitialized = (error == OPUS_OK); - if (mAudioBitrate) { - opus_encoder_ctl(mEncoder, OPUS_SET_BITRATE(static_cast(mAudioBitrate))); - } - mReentrantMonitor.NotifyAll(); return error == OPUS_OK ? NS_OK : NS_ERROR_FAILURE; diff --git a/dom/media/encoder/TrackEncoder.h b/dom/media/encoder/TrackEncoder.h index ac01a8ce61aa..20612c551984 100644 --- a/dom/media/encoder/TrackEncoder.h +++ b/dom/media/encoder/TrackEncoder.h @@ -84,8 +84,6 @@ public: mReentrantMonitor.NotifyAll(); } - virtual void SetBitrate(const uint32_t aBitrate) {} - protected: /** * Notifies track encoder that we have reached the end of source stream, and @@ -143,7 +141,6 @@ public: : TrackEncoder() , mChannels(0) , mSamplingRate(0) - , mAudioBitrate(0) {} virtual void NotifyQueuedTrackChanges(MediaStreamGraph* aGraph, TrackID aID, @@ -194,10 +191,6 @@ public: */ size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; - virtual void SetBitrate(const uint32_t aBitrate) override - { - mAudioBitrate = aBitrate; - } protected: /** * Number of samples per channel in a pcm buffer. This is also the value of @@ -246,8 +239,6 @@ protected: * A segment queue of audio track data, protected by mReentrantMonitor. */ AudioSegment mRawSegment; - - uint32_t mAudioBitrate; }; class VideoTrackEncoder : public TrackEncoder @@ -261,7 +252,6 @@ public: , mDisplayHeight(0) , mTrackRate(0) , mTotalFrameDuration(0) - , mVideoBitrate(0) {} /** @@ -277,10 +267,6 @@ public: */ size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; - virtual void SetBitrate(const uint32_t aBitrate) override - { - mVideoBitrate = aBitrate; - } protected: /** * Initialized the video encoder. In order to collect the value of width and @@ -346,8 +332,6 @@ protected: * A segment queue of audio track data, protected by mReentrantMonitor. */ VideoSegment mRawSegment; - - uint32_t mVideoBitrate; }; } // namespace mozilla diff --git a/dom/media/encoder/VP8TrackEncoder.cpp b/dom/media/encoder/VP8TrackEncoder.cpp index 75120524c5ef..f6efac6a523b 100644 --- a/dom/media/encoder/VP8TrackEncoder.cpp +++ b/dom/media/encoder/VP8TrackEncoder.cpp @@ -20,7 +20,7 @@ PRLogModuleInfo* gVP8TrackEncoderLog; (msg, ##__VA_ARGS__)) // Debug logging macro with object pointer and class name. -#define DEFAULT_BITRATE_BPS 2500000 +#define DEFAULT_BITRATE 2500 // in kbit/s #define DEFAULT_ENCODE_FRAMERATE 30 using namespace mozilla::layers; @@ -87,9 +87,7 @@ VP8TrackEncoder::Init(int32_t aWidth, int32_t aHeight, int32_t aDisplayWidth, config.g_h = mFrameHeight; // TODO: Maybe we should have various aFrameRate bitrate pair for each devices? // or for different platform - - // rc_target_bitrate needs kbit/s - config.rc_target_bitrate = (mVideoBitrate != 0 ? mVideoBitrate : DEFAULT_BITRATE_BPS)/1000; + config.rc_target_bitrate = DEFAULT_BITRATE; // in kbit/s // Setting the time base of the codec config.g_timebase.num = 1; diff --git a/dom/media/encoder/VorbisTrackEncoder.cpp b/dom/media/encoder/VorbisTrackEncoder.cpp index 500408ef352b..e40253bf985d 100644 --- a/dom/media/encoder/VorbisTrackEncoder.cpp +++ b/dom/media/encoder/VorbisTrackEncoder.cpp @@ -56,12 +56,9 @@ VorbisTrackEncoder::Init(int aChannels, int aSamplingRate) int ret = 0; vorbis_info_init(&mVorbisInfo); - double quality = mAudioBitrate ? (double)mAudioBitrate/aSamplingRate : - BASE_QUALITY; - printf("quality %f \n", quality); ret = vorbis_encode_init_vbr(&mVorbisInfo, mChannels, mSamplingRate, - quality); + BASE_QUALITY); mInitialized = (ret == 0); diff --git a/dom/media/test/manifest.js b/dom/media/test/manifest.js index 8b493619a061..f595dc5b0777 100644 --- a/dom/media/test/manifest.js +++ b/dom/media/test/manifest.js @@ -126,11 +126,6 @@ var gMediaRecorderTests = [ { name:"detodos.opus", type:"audio/ogg; codecs=opus", duration:2.9135 } ]; -// Used by video media recorder tests -var gMediaRecorderVideoTests = [ - { name:"seek.webm", type:"video/webm", width:320, height:240, duration:3.966 }, -]; - // These are files that we want to make sure we can play through. We can // also check metadata. Put files of the same type together in this list so if // something crashes we have some idea of which backend is responsible. diff --git a/dom/media/test/mochitest.ini b/dom/media/test/mochitest.ini index 539376987f07..4bd4fcb9e802 100644 --- a/dom/media/test/mochitest.ini +++ b/dom/media/test/mochitest.ini @@ -663,8 +663,6 @@ skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 914439 skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 914439 [test_mediarecorder_avoid_recursion.html] tags=msg -[test_mediarecorder_bitrate.html] -tags=msg [test_mediarecorder_creation.html] tags=msg capturestream [test_mediarecorder_creation_fail.html] diff --git a/dom/media/test/test_mediarecorder_bitrate.html b/dom/media/test/test_mediarecorder_bitrate.html deleted file mode 100644 index 8aea7b1aa7aa..000000000000 --- a/dom/media/test/test_mediarecorder_bitrate.html +++ /dev/null @@ -1,131 +0,0 @@ - - - - Test MediaRecorder Record No Timeslice - - - - - -
-
-
- - diff --git a/dom/webidl/MediaRecorder.webidl b/dom/webidl/MediaRecorder.webidl index 9202400a35f4..d3caca1cc327 100644 --- a/dom/webidl/MediaRecorder.webidl +++ b/dom/webidl/MediaRecorder.webidl @@ -51,7 +51,4 @@ interface MediaRecorder : EventTarget { dictionary MediaRecorderOptions { DOMString mimeType = ""; // Default encoding mimeType. - unsigned long audioBitsPerSecond; - unsigned long videoBitsPerSecond; - unsigned long bitsPerSecond; }; From 3bc0233be86d56256e7b8a543d6462c5ecc35ea8 Mon Sep 17 00:00:00 2001 From: Wes Kocher Date: Thu, 17 Sep 2015 13:08:32 -0700 Subject: [PATCH 113/113] Backed out changeset dca7021e514a (bug 1169633) for test_browserElement_inproc_getWebManifest.html failures CLOSED TREE --- .../BrowserElementChildPreload.js | 29 +------ dom/browser-element/BrowserElementParent.js | 5 +- dom/browser-element/mochitest/async.js | 78 ------------------- .../browserElement_getWebManifest.js | 63 --------------- .../mochitest/file_illegal_web_manifest.html | 6 -- .../mochitest/file_web_manifest.html | 6 -- .../mochitest/file_web_manifest.json | 1 - .../mochitest/mochitest-oop.ini | 1 - dom/browser-element/mochitest/mochitest.ini | 6 -- ..._browserElement_inproc_getWebManifest.html | 17 ---- ...est_browserElement_oop_getWebManifest.html | 16 ---- dom/browser-element/nsIBrowserElementAPI.idl | 6 +- dom/html/nsBrowserElement.cpp | 17 ---- dom/html/nsBrowserElement.h | 2 - dom/webidl/BrowserElement.webidl | 4 - 15 files changed, 4 insertions(+), 253 deletions(-) delete mode 100644 dom/browser-element/mochitest/async.js delete mode 100644 dom/browser-element/mochitest/browserElement_getWebManifest.js delete mode 100644 dom/browser-element/mochitest/file_illegal_web_manifest.html delete mode 100644 dom/browser-element/mochitest/file_web_manifest.html delete mode 100644 dom/browser-element/mochitest/file_web_manifest.json delete mode 100644 dom/browser-element/mochitest/test_browserElement_inproc_getWebManifest.html delete mode 100644 dom/browser-element/mochitest/test_browserElement_oop_getWebManifest.html diff --git a/dom/browser-element/BrowserElementChildPreload.js b/dom/browser-element/BrowserElementChildPreload.js index 9c2390713e62..27a9082f9ef1 100644 --- a/dom/browser-element/BrowserElementChildPreload.js +++ b/dom/browser-element/BrowserElementChildPreload.js @@ -12,15 +12,10 @@ var { classes: Cc, interfaces: Ci, results: Cr, utils: Cu } = Components; Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://gre/modules/BrowserElementPromptService.jsm"); -Cu.import("resource://gre/modules/Task.jsm"); XPCOMUtils.defineLazyServiceGetter(this, "acs", "@mozilla.org/audiochannel/service;1", "nsIAudioChannelService"); -XPCOMUtils.defineLazyModuleGetter(this, "ManifestFinder", - "resource://gre/modules/ManifestFinder.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "ManifestObtainer", - "resource://gre/modules/ManifestObtainer.jsm"); var kLongestReturnedString = 128; @@ -256,8 +251,7 @@ BrowserElementChild.prototype = { "set-audio-channel-volume": this._recvSetAudioChannelVolume, "get-audio-channel-muted": this._recvGetAudioChannelMuted, "set-audio-channel-muted": this._recvSetAudioChannelMuted, - "get-is-audio-channel-active": this._recvIsAudioChannelActive, - "get-web-manifest": this._recvGetWebManifest, + "get-is-audio-channel-active": this._recvIsAudioChannelActive } addMessageListener("browser-element-api:call", function(aMessage) { @@ -1484,27 +1478,6 @@ BrowserElementChild.prototype = { }); }, - _recvGetWebManifest: Task.async(function* (data) { - debug(`Received GetWebManifest message: (${data.json.id})`); - let manifest = null; - let hasManifest = ManifestFinder.contentHasManifestLink(content); - if (hasManifest) { - try { - manifest = yield ManifestObtainer.contentObtainManifest(content); - } catch (e) { - sendAsyncMsg('got-web-manifest', { - id: data.json.id, - errorMsg: `Error fetching web manifest: ${e}.`, - }); - return; - } - } - sendAsyncMsg('got-web-manifest', { - id: data.json.id, - successRv: manifest - }); - }), - _initFinder: function() { if (!this._finder) { try { diff --git a/dom/browser-element/BrowserElementParent.js b/dom/browser-element/BrowserElementParent.js index a61d26ad0d67..7b9e60f80620 100644 --- a/dom/browser-element/BrowserElementParent.js +++ b/dom/browser-element/BrowserElementParent.js @@ -210,8 +210,7 @@ BrowserElementParent.prototype = { "got-set-audio-channel-volume": this._gotDOMRequestResult, "got-audio-channel-muted": this._gotDOMRequestResult, "got-set-audio-channel-muted": this._gotDOMRequestResult, - "got-is-audio-channel-active": this._gotDOMRequestResult, - "got-web-manifest": this._gotDOMRequestResult, + "got-is-audio-channel-active": this._gotDOMRequestResult }; let mmSecuritySensitiveCalls = { @@ -1034,8 +1033,6 @@ BrowserElementParent.prototype = { {audioChannel: aAudioChannel}); }, - getWebManifest: defineDOMRequestMethod('get-web-manifest'), - /** * Called when the visibility of the window which owns this iframe changes. */ diff --git a/dom/browser-element/mochitest/async.js b/dom/browser-element/mochitest/async.js deleted file mode 100644 index d0007fa0964a..000000000000 --- a/dom/browser-element/mochitest/async.js +++ /dev/null @@ -1,78 +0,0 @@ -/* 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/. */ - -/* - * This is an approximate implementation of ES7's async-await pattern. - * see: https://github.com/tc39/ecmascript-asyncawait - * - * It allows for simple creation of async function and "tasks". - * - * For example: - * - * var myThinger = { - * doAsynThing: async(function*(url){ - * var result = yield fetch(url); - * return process(result); - * }); - * } - * - * And Task-like things can be created as follows: - * - * var myTask = async(function*{ - * var result = yield fetch(url); - * return result; - * }); - * //returns a promise - * - * myTask().then(doSomethingElse); - * - */ - -(function(exports) { - "use strict"; - function async(func, self) { - return function asyncFunction() { - const functionArgs = Array.from(arguments); - return new Promise(function(resolve, reject) { - var gen; - if (typeof func !== "function") { - reject(new TypeError("Expected a Function.")); - } - //not a generator, wrap it. - if (func.constructor.name !== "GeneratorFunction") { - gen = (function*() { - return func.apply(self, functionArgs); - }()); - } else { - gen = func.apply(self, functionArgs); - } - try { - step(gen.next(undefined)); - } catch (err) { - reject(err); - } - - function step({value, done}) { - if (done) { - return resolve(value); - } - if (value instanceof Promise) { - return value.then( - result => step(gen.next(result)), - error => { - try { - step(gen.throw(error)); - } catch (err) { - throw err; - } - } - ).catch(err => reject(err)); - } - step(gen.next(value)); - } - }); - }; - } - exports.async = async; -}(this || self)); diff --git a/dom/browser-element/mochitest/browserElement_getWebManifest.js b/dom/browser-element/mochitest/browserElement_getWebManifest.js deleted file mode 100644 index 31b06d0b82c3..000000000000 --- a/dom/browser-element/mochitest/browserElement_getWebManifest.js +++ /dev/null @@ -1,63 +0,0 @@ -/* Any copyright is dedicated to the public domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ -/*globals async, ok, is, SimpleTest, browserElementTestHelpers*/ - -// Bug 1169633 - getWebManifest tests -'use strict'; -SimpleTest.waitForExplicitFinish(); -browserElementTestHelpers.setEnabledPref(true); -browserElementTestHelpers.addPermission(); - -// request to load a manifest from a page that doesn't have a manifest. -// The expected result to be null. -var test1 = async(function* () { - var manifest = yield requestManifest('file_empty.html'); - is(manifest, null, 'it should be null.'); -}); - -// request to load a manifest from a page that has a manifest. -// The expected manifest to have a property name whose value is 'pass'. -var test2 = async(function* () { - var manifest = yield requestManifest('file_web_manifest.html'); - is(manifest && manifest.name, 'pass', 'it should return a manifest with name pass.'); -}); - -// Cause an exception by attempting to fetch a file URL, -// expect onerror to be called. -var test3 = async(function* () { - var gotError = false; - try { - yield requestManifest('file_illegal_web_manifest.html'); - } catch (err) { - gotError = true; - } - ok(gotError, 'onerror was called on the DOMRequest.'); -}); - -// Run the tests -Promise - .all([test1(), test2(), test3()]) - .then(SimpleTest.finish); - -function requestManifest(url) { - var iframe = document.createElement('iframe'); - iframe.setAttribute('mozbrowser', 'true'); - iframe.src = url; - document.body.appendChild(iframe); - return new Promise((resolve, reject) => { - iframe.addEventListener('mozbrowserloadend', function loadend() { - iframe.removeEventListener('mozbrowserloadend', loadend); - SimpleTest.executeSoon(() => { - var req = iframe.getWebManifest(); - req.onsuccess = () => { - document.body.removeChild(iframe); - resolve(req.result); - }; - req.onerror = () => { - document.body.removeChild(iframe); - reject(new Error(req.error)); - }; - }); - }); - }); -} diff --git a/dom/browser-element/mochitest/file_illegal_web_manifest.html b/dom/browser-element/mochitest/file_illegal_web_manifest.html deleted file mode 100644 index b4e06918950c..000000000000 --- a/dom/browser-element/mochitest/file_illegal_web_manifest.html +++ /dev/null @@ -1,6 +0,0 @@ - - - - - -

Support Page for Web Manifest Tests

diff --git a/dom/browser-element/mochitest/file_web_manifest.html b/dom/browser-element/mochitest/file_web_manifest.html deleted file mode 100644 index 783da0f47d04..000000000000 --- a/dom/browser-element/mochitest/file_web_manifest.html +++ /dev/null @@ -1,6 +0,0 @@ - - - - - -

Support Page for Web Manifest Tests

diff --git a/dom/browser-element/mochitest/file_web_manifest.json b/dom/browser-element/mochitest/file_web_manifest.json deleted file mode 100644 index 57d0c3d42ef4..000000000000 --- a/dom/browser-element/mochitest/file_web_manifest.json +++ /dev/null @@ -1 +0,0 @@ -{"name": "pass"} diff --git a/dom/browser-element/mochitest/mochitest-oop.ini b/dom/browser-element/mochitest/mochitest-oop.ini index 53942381dd3d..4e9fb0a2f2fa 100644 --- a/dom/browser-element/mochitest/mochitest-oop.ini +++ b/dom/browser-element/mochitest/mochitest-oop.ini @@ -114,4 +114,3 @@ disabled = bug 924771 [test_browserElement_oop_GetContentDimensions.html] [test_browserElement_oop_AudioChannel.html] [test_browserElement_oop_SetNFCFocus.html] -[test_browserElement_oop_getWebManifest.html] diff --git a/dom/browser-element/mochitest/mochitest.ini b/dom/browser-element/mochitest/mochitest.ini index 9bfd6c33a40d..80e978921a31 100644 --- a/dom/browser-element/mochitest/mochitest.ini +++ b/dom/browser-element/mochitest/mochitest.ini @@ -3,7 +3,6 @@ skip-if = buildapp == 'mulet' || (buildapp == 'b2g' && (toolkit != 'gonk' || deb support-files = ../../../browser/base/content/test/general/audio.ogg ../../../dom/media/test/short-video.ogv - async.js browserElementTestHelpers.js browserElement_Alert.js browserElement_AlertInFrame.js @@ -38,7 +37,6 @@ support-files = browserElement_FrameWrongURI.js browserElement_GetScreenshot.js browserElement_GetScreenshotDppx.js - browserElement_getWebManifest.js browserElement_Iconchange.js browserElement_LoadEvents.js browserElement_Manifestchange.js @@ -130,14 +128,10 @@ support-files = file_wyciwyg.html file_audio.html iframe_file_audio.html - file_web_manifest.html - file_web_manifest.json - file_illegal_web_manifest.html # Note: browserElementTestHelpers.js looks at the test's filename to determine # whether the test should be OOP. "_oop_" signals OOP, "_inproc_" signals in # process. Default is OOP. -[test_browserElement_inproc_getWebManifest.html] [test_browserElement_NoAttr.html] [test_browserElement_NoPref.html] [test_browserElement_NoPermission.html] diff --git a/dom/browser-element/mochitest/test_browserElement_inproc_getWebManifest.html b/dom/browser-element/mochitest/test_browserElement_inproc_getWebManifest.html deleted file mode 100644 index 2c52a3d396cf..000000000000 --- a/dom/browser-element/mochitest/test_browserElement_inproc_getWebManifest.html +++ /dev/null @@ -1,17 +0,0 @@ - - - - Test for Bug 1169633 - - - - - - - - - diff --git a/dom/browser-element/mochitest/test_browserElement_oop_getWebManifest.html b/dom/browser-element/mochitest/test_browserElement_oop_getWebManifest.html deleted file mode 100644 index 9a1d72cc4914..000000000000 --- a/dom/browser-element/mochitest/test_browserElement_oop_getWebManifest.html +++ /dev/null @@ -1,16 +0,0 @@ - - - - Test for Bug 1169633 - - - - - - - - - diff --git a/dom/browser-element/nsIBrowserElementAPI.idl b/dom/browser-element/nsIBrowserElementAPI.idl index 28ddce0e3912..bb7a9d5a90ab 100644 --- a/dom/browser-element/nsIBrowserElementAPI.idl +++ b/dom/browser-element/nsIBrowserElementAPI.idl @@ -9,7 +9,7 @@ interface nsIDOMDOMRequest; interface nsIFrameLoader; -[scriptable, function, uuid(00d0e19d-bd67-491f-8e85-b9905224d3bb)] +[scriptable, function, uuid(c0c2dd9b-41ef-42dd-a4c1-e456619c1941)] interface nsIBrowserElementNextPaintListener : nsISupports { void recvNextPaint(); @@ -26,7 +26,7 @@ interface nsIBrowserElementNextPaintListener : nsISupports * Interface to the BrowserElementParent implementation. All methods * but setFrameLoader throw when the remote process is dead. */ -[scriptable, uuid(1e098c3a-7d65-452d-a2b2-9ffd1b6e04bb)] +[scriptable, uuid(56bd3e12-4a8b-422a-89fc-6dc25aa30aa2)] interface nsIBrowserElementAPI : nsISupports { const long FIND_CASE_SENSITIVE = 0; @@ -100,6 +100,4 @@ interface nsIBrowserElementAPI : nsISupports void setNFCFocus(in boolean isFocus); nsIDOMDOMRequest executeScript(in DOMString script, in jsval options); - - nsIDOMDOMRequest getWebManifest(); }; diff --git a/dom/html/nsBrowserElement.cpp b/dom/html/nsBrowserElement.cpp index 1e7469dc2f7b..49993758e5fa 100644 --- a/dom/html/nsBrowserElement.cpp +++ b/dom/html/nsBrowserElement.cpp @@ -747,21 +747,4 @@ nsBrowserElement::ExecuteScript(const nsAString& aScript, return req.forget().downcast(); } -already_AddRefed -nsBrowserElement::GetWebManifest(ErrorResult& aRv) -{ - NS_ENSURE_TRUE(IsBrowserElementOrThrow(aRv), nullptr); - - nsCOMPtr req; - nsresult rv = mBrowserElementAPI->GetWebManifest(getter_AddRefs(req)); - - if (NS_WARN_IF(NS_FAILED(rv))) { - aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); - return nullptr; - } - - return req.forget().downcast(); -} - - } // namespace mozilla diff --git a/dom/html/nsBrowserElement.h b/dom/html/nsBrowserElement.h index af4053bde289..f5819ca2cd9e 100644 --- a/dom/html/nsBrowserElement.h +++ b/dom/html/nsBrowserElement.h @@ -112,8 +112,6 @@ public: const dom::BrowserElementExecuteScriptOptions& aOptions, ErrorResult& aRv); - already_AddRefed GetWebManifest(ErrorResult& aRv); - void SetNFCFocus(bool isFocus, ErrorResult& aRv); diff --git a/dom/webidl/BrowserElement.webidl b/dom/webidl/BrowserElement.webidl index 2ee6c505cf3c..72f88426170c 100644 --- a/dom/webidl/BrowserElement.webidl +++ b/dom/webidl/BrowserElement.webidl @@ -174,9 +174,5 @@ interface BrowserElementPrivileged { CheckAllPermissions="browser browser:universalxss"] DOMRequest executeScript(DOMString script, optional BrowserElementExecuteScriptOptions options); - [Throws, - Pref="dom.mozBrowserFramesEnabled", - CheckAllPermissions="browser"] - DOMRequest getWebManifest(); };