diff --git a/AUTHORS b/AUTHORS index 5f2b03e8b8a1..2d2c6155500e 100644 --- a/AUTHORS +++ b/AUTHORS @@ -14,6 +14,7 @@ Aaron Nowack Aaron Reed Aaron Spangler Aaron Train +Abdelrhman Ahmed Achim Hasenmueller ActiveState Tool Corp. Adam Barth diff --git a/b2g/config/emulator-ics/releng-emulator-ics.tt b/b2g/config/emulator-ics/releng-emulator-ics.tt index 0d4f101c7a37..1af12208b9da 100644 --- a/b2g/config/emulator-ics/releng-emulator-ics.tt +++ b/b2g/config/emulator-ics/releng-emulator-ics.tt @@ -1,2 +1,9 @@ [ +{ +"size": 80458572, +"digest": "e5101f9dee1e462f6cbd3897ea57eede41d23981825c7b20d91d23ab461875d54d3dfc24999aa58a31e8b01f49fb3140e05ffe5af2957ef1d1afb89fd0dfe1ad", +"algorithm": "sha512", +"filename": "gcc.tar.xz", +"unpack": "True" +} ] diff --git a/b2g/config/emulator-jb/releng-emulator-jb.tt b/b2g/config/emulator-jb/releng-emulator-jb.tt index 0d4f101c7a37..1af12208b9da 100644 --- a/b2g/config/emulator-jb/releng-emulator-jb.tt +++ b/b2g/config/emulator-jb/releng-emulator-jb.tt @@ -1,2 +1,9 @@ [ +{ +"size": 80458572, +"digest": "e5101f9dee1e462f6cbd3897ea57eede41d23981825c7b20d91d23ab461875d54d3dfc24999aa58a31e8b01f49fb3140e05ffe5af2957ef1d1afb89fd0dfe1ad", +"algorithm": "sha512", +"filename": "gcc.tar.xz", +"unpack": "True" +} ] diff --git a/b2g/config/emulator-kk/releng-emulator-kk.tt b/b2g/config/emulator-kk/releng-emulator-kk.tt index 0d4f101c7a37..1af12208b9da 100644 --- a/b2g/config/emulator-kk/releng-emulator-kk.tt +++ b/b2g/config/emulator-kk/releng-emulator-kk.tt @@ -1,2 +1,9 @@ [ +{ +"size": 80458572, +"digest": "e5101f9dee1e462f6cbd3897ea57eede41d23981825c7b20d91d23ab461875d54d3dfc24999aa58a31e8b01f49fb3140e05ffe5af2957ef1d1afb89fd0dfe1ad", +"algorithm": "sha512", +"filename": "gcc.tar.xz", +"unpack": "True" +} ] diff --git a/b2g/config/emulator/releng-emulator.tt b/b2g/config/emulator/releng-emulator.tt index 0d4f101c7a37..1af12208b9da 100644 --- a/b2g/config/emulator/releng-emulator.tt +++ b/b2g/config/emulator/releng-emulator.tt @@ -1,2 +1,9 @@ [ +{ +"size": 80458572, +"digest": "e5101f9dee1e462f6cbd3897ea57eede41d23981825c7b20d91d23ab461875d54d3dfc24999aa58a31e8b01f49fb3140e05ffe5af2957ef1d1afb89fd0dfe1ad", +"algorithm": "sha512", +"filename": "gcc.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 255dce6fc8ec..d0e0c584aa85 100644 --- a/b2g/config/flame-kk/releng-flame-kk.tt +++ b/b2g/config/flame-kk/releng-flame-kk.tt @@ -5,5 +5,12 @@ "algorithm": "sha512", "filename": "backup-flame.tar.xz", "comment": "v18D" +}, +{ +"size": 80458572, +"digest": "e5101f9dee1e462f6cbd3897ea57eede41d23981825c7b20d91d23ab461875d54d3dfc24999aa58a31e8b01f49fb3140e05ffe5af2957ef1d1afb89fd0dfe1ad", +"algorithm": "sha512", +"filename": "gcc.tar.xz", +"unpack": "True" } ] diff --git a/b2g/config/flame/releng-flame.tt b/b2g/config/flame/releng-flame.tt index d4f548680596..65f9871b6796 100644 --- a/b2g/config/flame/releng-flame.tt +++ b/b2g/config/flame/releng-flame.tt @@ -3,5 +3,12 @@ "digest": "8d1a71552ffee561e93b5b3f1bb47866592ab958f908007c75561156430eb1b85a265bfc4dc2038e58dda0264daa9854877a84ef3b591c9ac2f1ab97c098e61e", "filename": "backup-flame.tar.xz", "algorithm": "sha512" +}, +{ +"size": 80458572, +"digest": "e5101f9dee1e462f6cbd3897ea57eede41d23981825c7b20d91d23ab461875d54d3dfc24999aa58a31e8b01f49fb3140e05ffe5af2957ef1d1afb89fd0dfe1ad", +"algorithm": "sha512", +"filename": "gcc.tar.xz", +"unpack": "True" } ] diff --git a/b2g/config/hamachi/releng-hamachi.tt b/b2g/config/hamachi/releng-hamachi.tt index 0735bb32f17a..ccb5e8de7496 100644 --- a/b2g/config/hamachi/releng-hamachi.tt +++ b/b2g/config/hamachi/releng-hamachi.tt @@ -10,5 +10,12 @@ "digest": "ea03de74df73b05e939c314cd15c54aac7b5488a407b7cc4f5f263f3049a1f69642c567dd35c43d0bc3f0d599d0385a26ab2dd947a6b18f9044e4918b382eea7", "algorithm": "sha512", "filename": "Adreno200-AU_LINUX_ANDROID_ICS_CHOCO_CS.04.00.03.06.001.zip" +}, +{ +"size": 80458572, +"digest": "e5101f9dee1e462f6cbd3897ea57eede41d23981825c7b20d91d23ab461875d54d3dfc24999aa58a31e8b01f49fb3140e05ffe5af2957ef1d1afb89fd0dfe1ad", +"algorithm": "sha512", +"filename": "gcc.tar.xz", +"unpack": "True" } ] diff --git a/b2g/config/hamachi/releng-limited-memory.tt b/b2g/config/hamachi/releng-limited-memory.tt index 277056f3c865..f82775ad0d29 100644 --- a/b2g/config/hamachi/releng-limited-memory.tt +++ b/b2g/config/hamachi/releng-limited-memory.tt @@ -28,5 +28,12 @@ "digest": "d6a969fad4e53b617a21026062767f4b89d301464c38e9c9d04ba7dc7dcad72f1b337c284243a81e74de713171af5dd9a13aaaa7efd10109a0847ed23bf6e539", "algorithm": "sha512", "filename": "tt_setup.sh" +}, +{ +"size": 80458572, +"digest": "e5101f9dee1e462f6cbd3897ea57eede41d23981825c7b20d91d23ab461875d54d3dfc24999aa58a31e8b01f49fb3140e05ffe5af2957ef1d1afb89fd0dfe1ad", +"algorithm": "sha512", +"filename": "gcc.tar.xz", +"unpack": "True" } ] diff --git a/b2g/config/helix/releng-helix.tt b/b2g/config/helix/releng-helix.tt index 16d015a10ddf..09b728f1f939 100644 --- a/b2g/config/helix/releng-helix.tt +++ b/b2g/config/helix/releng-helix.tt @@ -10,5 +10,12 @@ "digest": "ea03de74df73b05e939c314cd15c54aac7b5488a407b7cc4f5f263f3049a1f69642c567dd35c43d0bc3f0d599d0385a26ab2dd947a6b18f9044e4918b382eea7", "algorithm": "sha512", "filename": "Adreno200-AU_LINUX_ANDROID_ICS_CHOCO_CS.04.00.03.06.001.zip" +}, +{ +"size": 80458572, +"digest": "e5101f9dee1e462f6cbd3897ea57eede41d23981825c7b20d91d23ab461875d54d3dfc24999aa58a31e8b01f49fb3140e05ffe5af2957ef1d1afb89fd0dfe1ad", +"algorithm": "sha512", +"filename": "gcc.tar.xz", +"unpack": "True" } ] diff --git a/b2g/config/mozconfigs/common b/b2g/config/mozconfigs/common index 1dae99bacbed..b1e88fe1a710 100644 --- a/b2g/config/mozconfigs/common +++ b/b2g/config/mozconfigs/common @@ -5,3 +5,12 @@ # This file is included at the top of all b2g mozconfigs . "$topsrcdir/build/mozconfig.common" + +# Normally, we'd set this unconditionally, but this file is also used +# for local builds and there is no other mozconfig in this tree that +# is included on device builds. +if test -d $topsrcdir/../gcc/bin; then + HOST_CC="$topsrcdir/../gcc/bin/gcc" + HOST_CXX="$topsrcdir/../gcc/bin/g++" + ac_add_options --enable-stdcxx-compat +fi diff --git a/b2g/config/nexus-4/releng-mako.tt b/b2g/config/nexus-4/releng-mako.tt index 357a7d7de5b8..f83b6888fd46 100644 --- a/b2g/config/nexus-4/releng-mako.tt +++ b/b2g/config/nexus-4/releng-mako.tt @@ -16,6 +16,13 @@ "digest": "27aced8feb0e757d61df37839e62410ff30a059cfa8f04897d29ab74b787c765313acf904b1f9cf311c3e682883514df7da54197665251ef9b8bdad6bd0f62c5", "algorithm": "sha512", "filename": "lge-mako-jwr66v-985845e4.tgz" +}, +{ +"size": 80458572, +"digest": "e5101f9dee1e462f6cbd3897ea57eede41d23981825c7b20d91d23ab461875d54d3dfc24999aa58a31e8b01f49fb3140e05ffe5af2957ef1d1afb89fd0dfe1ad", +"algorithm": "sha512", +"filename": "gcc.tar.xz", +"unpack": "True" } ] diff --git a/b2g/config/wasabi/releng-wasabi.tt b/b2g/config/wasabi/releng-wasabi.tt index ee7d60b9299d..e6d428be0941 100644 --- a/b2g/config/wasabi/releng-wasabi.tt +++ b/b2g/config/wasabi/releng-wasabi.tt @@ -16,5 +16,12 @@ "digest": "709a281438607f10c9f55683303d5cc1d8720520e26a8ae45f48b7ccb9265ba8939c4a077ae3368afc891bbd7426013edfbbbb3dbdeab5b1f06e60901b141de6", "algorithm": "sha512", "filename": "boot.img" +}, +{ +"size": 80458572, +"digest": "e5101f9dee1e462f6cbd3897ea57eede41d23981825c7b20d91d23ab461875d54d3dfc24999aa58a31e8b01f49fb3140e05ffe5af2957ef1d1afb89fd0dfe1ad", +"algorithm": "sha512", +"filename": "gcc.tar.xz", +"unpack": "True" } ] diff --git a/b2g/installer/package-manifest.in b/b2g/installer/package-manifest.in index ae3fb45a5b62..be323b6171e2 100644 --- a/b2g/installer/package-manifest.in +++ b/b2g/installer/package-manifest.in @@ -732,7 +732,6 @@ @BINPATH@/res/fonts/* @BINPATH@/res/dtd/* @BINPATH@/res/html/* -@BINPATH@/res/langGroups.properties @BINPATH@/res/language.properties @BINPATH@/res/entityTables/* #ifdef XP_MACOSX diff --git a/browser/branding/aurora/pref/firefox-branding.js b/browser/branding/aurora/pref/firefox-branding.js index c945805527c5..5722368d57a9 100644 --- a/browser/branding/aurora/pref/firefox-branding.js +++ b/browser/branding/aurora/pref/firefox-branding.js @@ -26,13 +26,6 @@ pref("app.update.url.details", "https://www.mozilla.org/firefox/aurora/"); // app.update.checkInstallTime is true. pref("app.update.checkInstallTime.days", 2); -// code usage depends on contracts, please contact the Firefox module owner if you have questions -pref("browser.search.param.yahoo-fr", "moz35"); -pref("browser.search.param.yahoo-fr-ja", "mozff"); -#ifdef MOZ_METRO -pref("browser.search.param.yahoo-fr-metro", ""); -#endif - // Number of usages of the web console or scratchpad. // If this is less than 5, then pasting code into the web console or scratchpad is disabled pref("devtools.selfxss.count", 5); \ No newline at end of file diff --git a/browser/branding/nightly/pref/firefox-branding.js b/browser/branding/nightly/pref/firefox-branding.js index dc889fab9440..c51c4c70dd50 100644 --- a/browser/branding/nightly/pref/firefox-branding.js +++ b/browser/branding/nightly/pref/firefox-branding.js @@ -24,13 +24,6 @@ pref("app.update.url.details", "https://nightly.mozilla.org"); // app.update.checkInstallTime is true. pref("app.update.checkInstallTime.days", 2); -// code usage depends on contracts, please contact the Firefox module owner if you have questions -pref("browser.search.param.yahoo-fr", "moz35"); -pref("browser.search.param.yahoo-fr-ja", "mozff"); -#ifdef MOZ_METRO -pref("browser.search.param.yahoo-fr-metro", ""); -#endif - // Number of usages of the web console or scratchpad. // If this is less than 5, then pasting code into the web console or scratchpad is disabled pref("devtools.selfxss.count", 5); \ No newline at end of file diff --git a/browser/branding/official/pref/firefox-branding.js b/browser/branding/official/pref/firefox-branding.js index e7a06b9b3adc..c5758056e984 100644 --- a/browser/branding/official/pref/firefox-branding.js +++ b/browser/branding/official/pref/firefox-branding.js @@ -23,14 +23,6 @@ pref("app.update.url.details", "https://www.mozilla.org/%LOCALE%/firefox/notes") // app.update.checkInstallTime is true. pref("app.update.checkInstallTime.days", 63); -// code usage depends on contracts, please contact the Firefox module owner if you have questions -pref("browser.search.param.yahoo-fr", "moz35"); -pref("browser.search.param.yahoo-fr-ja", "mozff"); -#ifdef MOZ_METRO -pref("browser.search.param.ms-pc-metro", "MOZW"); -pref("browser.search.param.yahoo-fr-metro", "mozilla_metro_search"); -#endif - // Number of usages of the web console or scratchpad. // If this is less than 5, then pasting code into the web console or scratchpad is disabled pref("devtools.selfxss.count", 0); \ No newline at end of file diff --git a/browser/branding/unofficial/pref/firefox-branding.js b/browser/branding/unofficial/pref/firefox-branding.js index 5787b4fa15cf..27dae01f3bbb 100644 --- a/browser/branding/unofficial/pref/firefox-branding.js +++ b/browser/branding/unofficial/pref/firefox-branding.js @@ -23,13 +23,6 @@ pref("app.update.url.details", "https://nightly.mozilla.org"); // app.update.checkInstallTime is true. pref("app.update.checkInstallTime.days", 2); -// code usage depends on contracts, please contact the Firefox module owner if you have questions -pref("browser.search.param.yahoo-fr", "moz35"); -pref("browser.search.param.yahoo-fr-ja", "mozff"); -#ifdef MOZ_METRO -pref("browser.search.param.yahoo-fr-metro", ""); -#endif - // Number of usages of the web console or scratchpad. // If this is less than 5, then pasting code into the web console or scratchpad is disabled pref("devtools.selfxss.count", 0); \ No newline at end of file diff --git a/browser/components/customizableui/CustomizableUI.jsm b/browser/components/customizableui/CustomizableUI.jsm index a787dc1eb0c8..730ea11a3a13 100644 --- a/browser/components/customizableui/CustomizableUI.jsm +++ b/browser/components/customizableui/CustomizableUI.jsm @@ -3969,8 +3969,12 @@ OverflowableToolbar.prototype = { }, onOverflow: function(aEvent) { + // The rangeParent check is here because of bug 1111986 and ensuring that + // overflow events from the bookmarks toolbar items or similar things that + // manage their own overflow don't trigger an overflow on the entire toolbar if (!this._enabled || - (aEvent && aEvent.target != this._toolbar.customizationTarget)) + (aEvent && aEvent.target != this._toolbar.customizationTarget) || + (aEvent && aEvent.rangeParent)) return; let child = this._target.lastChild; diff --git a/browser/devtools/jar.mn b/browser/devtools/jar.mn index 43f64f8f5f33..133a0e63b50c 100644 --- a/browser/devtools/jar.mn +++ b/browser/devtools/jar.mn @@ -85,6 +85,8 @@ browser.jar: content/browser/devtools/webaudioeditor/views/utils.js (webaudioeditor/views/utils.js) content/browser/devtools/webaudioeditor/views/context.js (webaudioeditor/views/context.js) content/browser/devtools/webaudioeditor/views/inspector.js (webaudioeditor/views/inspector.js) + content/browser/devtools/webaudioeditor/views/properties.js (webaudioeditor/views/properties.js) + content/browser/devtools/webaudioeditor/views/automation.js (webaudioeditor/views/automation.js) content/browser/devtools/profiler.xul (profiler/profiler.xul) content/browser/devtools/profiler.js (profiler/profiler.js) content/browser/devtools/ui-recordings.js (profiler/ui-recordings.js) @@ -98,6 +100,7 @@ browser.jar: content/browser/devtools/performance/views/details-call-tree.js (performance/views/details-call-tree.js) content/browser/devtools/performance/views/details-waterfall.js (performance/views/details-waterfall.js) content/browser/devtools/performance/views/details-flamegraph.js (performance/views/details-flamegraph.js) + content/browser/devtools/performance/views/recordings.js (performance/views/recordings.js) #endif content/browser/devtools/responsivedesign/resize-commands.js (responsivedesign/resize-commands.js) content/browser/devtools/commandline.css (commandline/commandline.css) diff --git a/browser/devtools/performance/modules/recording-model.js b/browser/devtools/performance/modules/recording-model.js new file mode 100644 index 000000000000..4277cc7d4576 --- /dev/null +++ b/browser/devtools/performance/modules/recording-model.js @@ -0,0 +1,248 @@ +/* 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/. */ +"use strict"; + +const { PerformanceIO } = require("devtools/performance/io"); + +const RECORDING_IN_PROGRESS = exports.RECORDING_IN_PROGRESS = -1; +const RECORDING_UNAVAILABLE = exports.RECORDING_UNAVAILABLE = null; +/** + * Model for a wholistic profile, containing start/stop times, profiling data, frames data, + * timeline (marker, tick, memory) data, and methods to start/stop recording. + */ + +const RecordingModel = function (options={}) { + this._front = options.front; + this._performance = options.performance; + this._label = options.label || ""; +}; + +RecordingModel.prototype = { + _localStartTime: RECORDING_UNAVAILABLE, + _startTime: RECORDING_UNAVAILABLE, + _endTime: RECORDING_UNAVAILABLE, + _markers: [], + _frames: [], + _ticks: [], + _memory: [], + _profilerData: {}, + _label: "", + _imported: false, + _isRecording: false, + + /** + * Loads a recording from a file. + * + * @param nsILocalFile file + * The file to import the data form. + */ + importRecording: Task.async(function *(file) { + let recordingData = yield PerformanceIO.loadRecordingFromFile(file); + + this._imported = true; + this._label = recordingData.profilerData.profilerLabel || ""; + this._startTime = recordingData.interval.startTime; + this._endTime = recordingData.interval.endTime; + this._markers = recordingData.markers; + this._frames = recordingData.frames; + this._memory = recordingData.memory; + this._ticks = recordingData.ticks; + this._profilerData = recordingData.profilerData; + + return recordingData; + }), + + /** + * Saves the current recording to a file. + * + * @param nsILocalFile file + * The file to stream the data into. + */ + exportRecording: Task.async(function *(file) { + let recordingData = this.getAllData(); + yield PerformanceIO.saveRecordingToFile(recordingData, file); + }), + + /** + * Starts recording with the PerformanceFront, storing the start times + * on the model. + */ + startRecording: Task.async(function *() { + // Times must come from the actor in order to be self-consistent. + // However, we also want to update the view with the elapsed time + // even when the actor is not generating data. To do this we get + // the local time and use it to compute a reasonable elapsed time. + this._localStartTime = this._performance.now(); + + let { startTime } = yield this._front.startRecording({ + withTicks: true, + withMemory: true + }); + this._isRecording = true; + + this._startTime = startTime; + this._endTime = RECORDING_IN_PROGRESS; + this._markers = []; + this._frames = []; + this._memory = []; + this._ticks = []; + }), + + /** + * Stops recording with the PerformanceFront, storing the end times + * on the model. + */ + stopRecording: Task.async(function *() { + let results = yield this._front.stopRecording(); + this._isRecording = false; + + // If `endTime` is not yielded from timeline actor (< Fx36), fake it. + if (!results.endTime) { + results.endTime = this._startTime + this.getLocalElapsedTime(); + } + + this._endTime = results.endTime; + this._profilerData = results.profilerData; + this._markers = this._markers.sort((a,b) => (a.start > b.start)); + + return results; + }), + + /** + * Returns the profile's label, from `console.profile(LABEL)`. + */ + getLabel: function () { + return this._label; + }, + + /** + * Gets the amount of time elapsed locally after starting a recording. + */ + getLocalElapsedTime: function () { + return this._performance.now() - this._localStartTime; + }, + + /** + * Returns duration of this recording, in milliseconds. + */ + getDuration: function () { + let { startTime, endTime } = this.getInterval(); + return endTime - startTime; + }, + + /** + * Gets the time interval for the current recording. + * @return object + */ + getInterval: function() { + let startTime = this._startTime; + let endTime = this._endTime; + + // Compute an approximate ending time for the current recording. This is + // needed to ensure that the view updates even when new data is + // not being generated. + if (endTime == RECORDING_IN_PROGRESS) { + endTime = startTime + this.getLocalElapsedTime(); + } + + return { startTime, endTime }; + }, + + /** + * Gets the accumulated markers in the current recording. + * @return array + */ + getMarkers: function() { + return this._markers; + }, + + /** + * Gets the accumulated stack frames in the current recording. + * @return array + */ + getFrames: function() { + return this._frames; + }, + + /** + * Gets the accumulated memory measurements in this recording. + * @return array + */ + getMemory: function() { + return this._memory; + }, + + /** + * Gets the accumulated refresh driver ticks in this recording. + * @return array + */ + getTicks: function() { + return this._ticks; + }, + + /** + * Gets the profiler data in this recording. + * @return array + */ + getProfilerData: function() { + return this._profilerData; + }, + + /** + * Gets all the data in this recording. + */ + getAllData: function() { + let interval = this.getInterval(); + let markers = this.getMarkers(); + let frames = this.getFrames(); + let memory = this.getMemory(); + let ticks = this.getTicks(); + let profilerData = this.getProfilerData(); + return { interval, markers, frames, memory, ticks, profilerData }; + }, + + /** + * Returns a boolean indicating whether or not this recording model + * is recording. + */ + isRecording: function () { + return this._isRecording; + }, + + /** + * Fired whenever the PerformanceFront emits markers, memory or ticks. + */ + addTimelineData: function (eventName, ...data) { + // If this model isn't currently recording, + // ignore the timeline data. + if (!this.isRecording()) { + return; + } + + switch (eventName) { + // Accumulate markers into an array. + case "markers": + let [markers] = data; + Array.prototype.push.apply(this._markers, markers); + break; + // Accumulate stack frames into an array. + case "frames": + let [, frames] = data; + Array.prototype.push.apply(this._frames, frames); + break; + // Accumulate memory measurements into an array. + case "memory": + let [delta, measurement] = data; + this._memory.push({ delta, value: measurement.total / 1024 / 1024 }); + break; + // Save the accumulated refresh driver ticks. + case "ticks": + let [, timestamps] = data; + this._ticks = timestamps; + break; + } + } +}; + +exports.RecordingModel = RecordingModel; diff --git a/browser/devtools/performance/moz.build b/browser/devtools/performance/moz.build index e133978e6384..666a07a579dd 100644 --- a/browser/devtools/performance/moz.build +++ b/browser/devtools/performance/moz.build @@ -6,6 +6,7 @@ EXTRA_JS_MODULES.devtools.performance += [ 'modules/front.js', 'modules/io.js', + 'modules/recording-model.js', 'panel.js' ] diff --git a/browser/devtools/performance/performance-controller.js b/browser/devtools/performance/performance-controller.js index f260af377d0c..1bfe2866a3ea 100644 --- a/browser/devtools/performance/performance-controller.js +++ b/browser/devtools/performance/performance-controller.js @@ -41,6 +41,11 @@ devtools.lazyImporter(this, "CanvasGraphUtils", "resource:///modules/devtools/Graphs.jsm"); devtools.lazyImporter(this, "LineGraphWidget", "resource:///modules/devtools/Graphs.jsm"); +devtools.lazyImporter(this, "SideMenuWidget", + "resource:///modules/devtools/SideMenuWidget.jsm"); + +const { RecordingModel, RECORDING_IN_PROGRESS, RECORDING_UNAVAILABLE } = + devtools.require("devtools/performance/recording-model"); devtools.lazyImporter(this, "FlameGraphUtils", "resource:///modules/devtools/FlameGraph.jsm"); @@ -49,12 +54,17 @@ devtools.lazyImporter(this, "FlameGraph", // Events emitted by various objects in the panel. const EVENTS = { + // Emitted by the PerformanceController or RecordingView + // when a recording model is selected + RECORDING_SELECTED: "Performance:RecordingSelected", + // Emitted by the PerformanceView on record button click UI_START_RECORDING: "Performance:UI:StartRecording", UI_STOP_RECORDING: "Performance:UI:StopRecording", - // Emitted by the PerformanceView on import or export button click + // Emitted by the PerformanceView on import button click UI_IMPORT_RECORDING: "Performance:UI:ImportRecording", + // Emitted by the RecordingsView on export button click UI_EXPORT_RECORDING: "Performance:UI:ExportRecording", // When a recording is started or stopped via the PerformanceController @@ -96,11 +106,6 @@ const EVENTS = { FLAMEGRAPH_RENDERED: "Performance:UI:FlameGraphRendered" }; -// Constant defining the end time for a recording that hasn't finished -// or is not yet available. -const RECORDING_IN_PROGRESS = -1; -const RECORDING_UNAVAILABLE = null; - /** * The current target and the profiler connection, set by this tool's host. */ @@ -150,18 +155,8 @@ let PrefObserver = { * UI interaction. */ let PerformanceController = { - /** - * Permanent storage for the markers and the memory measurements streamed by - * the backend, along with the start and end timestamps. - */ - _localStartTime: RECORDING_UNAVAILABLE, - _startTime: RECORDING_UNAVAILABLE, - _endTime: RECORDING_UNAVAILABLE, - _markers: [], - _frames: [], - _memory: [], - _ticks: [], - _profilerData: {}, + _recordings: [], + _currentRecording: null, /** * Listen for events emitted by the current tab target and @@ -173,11 +168,13 @@ let PerformanceController = { this.importRecording = this.importRecording.bind(this); this.exportRecording = this.exportRecording.bind(this); this._onTimelineData = this._onTimelineData.bind(this); + this._onRecordingSelectFromView = this._onRecordingSelectFromView.bind(this); PerformanceView.on(EVENTS.UI_START_RECORDING, this.startRecording); PerformanceView.on(EVENTS.UI_STOP_RECORDING, this.stopRecording); - PerformanceView.on(EVENTS.UI_EXPORT_RECORDING, this.exportRecording); PerformanceView.on(EVENTS.UI_IMPORT_RECORDING, this.importRecording); + RecordingsView.on(EVENTS.UI_EXPORT_RECORDING, this.exportRecording); + RecordingsView.on(EVENTS.RECORDING_SELECTED, this._onRecordingSelectFromView); gFront.on("ticks", this._onTimelineData); // framerate gFront.on("markers", this._onTimelineData); // timeline markers @@ -191,8 +188,9 @@ let PerformanceController = { destroy: function() { PerformanceView.off(EVENTS.UI_START_RECORDING, this.startRecording); PerformanceView.off(EVENTS.UI_STOP_RECORDING, this.stopRecording); - PerformanceView.off(EVENTS.UI_EXPORT_RECORDING, this.exportRecording); PerformanceView.off(EVENTS.UI_IMPORT_RECORDING, this.importRecording); + RecordingsView.off(EVENTS.UI_EXPORT_RECORDING, this.exportRecording); + RecordingsView.off(EVENTS.RECORDING_SELECTED, this._onRecordingSelectFromView); gFront.off("ticks", this._onTimelineData); gFront.off("markers", this._onTimelineData); @@ -205,25 +203,11 @@ let PerformanceController = { * when the front has started to record. */ startRecording: Task.async(function *() { - // Times must come from the actor in order to be self-consistent. - // However, we also want to update the view with the elapsed time - // even when the actor is not generating data. To do this we get - // the local time and use it to compute a reasonable elapsed time. - this._localStartTime = performance.now(); + let model = this.createNewRecording(); + this.setCurrentRecording(model); + yield model.startRecording(); - let { startTime } = yield gFront.startRecording({ - withTicks: true, - withMemory: true - }); - - this._startTime = startTime; - this._endTime = RECORDING_IN_PROGRESS; - this._markers = []; - this._frames = []; - this._memory = []; - this._ticks = []; - - this.emit(EVENTS.RECORDING_STARTED); + this.emit(EVENTS.RECORDING_STARTED, model); }), /** @@ -231,63 +215,76 @@ let PerformanceController = { * when the front has stopped recording. */ stopRecording: Task.async(function *() { - let results = yield gFront.stopRecording(); + let recording = this._getLatest(); + yield recording.stopRecording(); - // If `endTime` is not yielded from timeline actor (< Fx36), fake it. - if (!results.endTime) { - results.endTime = this._startTime + this.getLocalElapsedTime(); - } - - this._endTime = results.endTime; - this._profilerData = results.profilerData; - this._markers = this._markers.sort((a,b) => (a.start > b.start)); - - this.emit(EVENTS.RECORDING_STOPPED); + this.emit(EVENTS.RECORDING_STOPPED, recording); }), /** * Saves the current recording to a file. * + * @param RecordingModel recording + * The model that holds the recording data. * @param nsILocalFile file * The file to stream the data into. */ - exportRecording: Task.async(function*(_, file) { - let recordingData = this.getAllData(); + exportRecording: Task.async(function*(_, recording, file) { + let recordingData = recording.getAllData(); yield PerformanceIO.saveRecordingToFile(recordingData, file); this.emit(EVENTS.RECORDING_EXPORTED, recordingData); }), /** - * Loads a recording from a file, replacing the current one. - * XXX: Handle multiple recordings, bug 1111004. + * Loads a recording from a file, adding it to the recordings list. * * @param nsILocalFile file * The file to import the data from. */ importRecording: Task.async(function*(_, file) { - let recordingData = yield PerformanceIO.loadRecordingFromFile(file); + let model = this.createNewRecording(); + yield model.importRecording(file); - this._startTime = recordingData.interval.startTime; - this._endTime = recordingData.interval.endTime; - this._markers = recordingData.markers; - this._frames = recordingData.frames; - this._memory = recordingData.memory; - this._ticks = recordingData.ticks; - this._profilerData = recordingData.profilerData; - - this.emit(EVENTS.RECORDING_IMPORTED, recordingData); - - // Flush the current recording. - this.emit(EVENTS.RECORDING_STARTED); - this.emit(EVENTS.RECORDING_STOPPED); + this.emit(EVENTS.RECORDING_IMPORTED, model.getAllData(), model); }), + /** + * Creates a new RecordingModel, fires events and stores it + * internally in the controller. + */ + createNewRecording: function () { + let model = new RecordingModel({ + front: gFront, + performance: performance + }); + this._recordings.push(model); + this.emit(EVENTS.RECORDING_CREATED, model); + return model; + }, + + /** + * Sets the active RecordingModel to `recording`. + */ + setCurrentRecording: function (recording) { + if (this._currentRecording !== recording) { + this._currentRecording = recording; + this.emit(EVENTS.RECORDING_SELECTED, recording); + } + }, + + /** + * Return the current active RecordingModel. + */ + getCurrentRecording: function () { + return this._currentRecording; + }, + /** * Gets the amount of time elapsed locally after starting a recording. */ - getLocalElapsedTime: function() { - return performance.now() - this._localStartTime; + getLocalElapsedTime: function () { + return this.getCurrentRecording().getLocalElapsedTime; }, /** @@ -295,17 +292,7 @@ let PerformanceController = { * @return object */ getInterval: function() { - let startTime = this._startTime; - let endTime = this._endTime; - - // Compute an approximate ending time for the current recording. This is - // needed to ensure that the view updates even when new data is - // not being generated. - if (endTime == RECORDING_IN_PROGRESS) { - endTime = startTime + this.getLocalElapsedTime(); - } - - return { startTime, endTime }; + return this.getCurrentRecording().getInterval(); }, /** @@ -313,7 +300,7 @@ let PerformanceController = { * @return array */ getMarkers: function() { - return this._markers; + return this.getCurrentRecording().getMarkers(); }, /** @@ -321,7 +308,7 @@ let PerformanceController = { * @return array */ getFrames: function() { - return this._frames; + return this.getCurrentRecording().getFrames(); }, /** @@ -329,7 +316,7 @@ let PerformanceController = { * @return array */ getMemory: function() { - return this._memory; + return this.getCurrentRecording().getMemory(); }, /** @@ -337,7 +324,7 @@ let PerformanceController = { * @return array */ getTicks: function() { - return this._ticks; + return this.getCurrentRecording().getTicks(); }, /** @@ -345,48 +332,41 @@ let PerformanceController = { * @return array */ getProfilerData: function() { - return this._profilerData; + return this.getCurrentRecording().getProfilerData(); }, /** * Gets all the data in this recording. */ getAllData: function() { - let interval = this.getInterval(); - let markers = this.getMarkers(); - let frames = this.getFrames(); - let memory = this.getMemory(); - let ticks = this.getTicks(); - let profilerData = this.getProfilerData(); - return { interval, markers, frames, memory, ticks, profilerData }; + return this.getCurrentRecording().getAllData(); + }, + + /** + /** + * Get most recently added profile that was triggered manually (via UI) + */ + _getLatest: function () { + for (let i = this._recordings.length - 1; i >= 0; i--) { + return this._recordings[i]; + } + return null; }, /** * Fired whenever the PerformanceFront emits markers, memory or ticks. */ - _onTimelineData: function (eventName, ...data) { - // Accumulate markers into an array. - if (eventName == "markers") { - let [markers] = data; - Array.prototype.push.apply(this._markers, markers); - } - // Accumulate stack frames into an array. - else if (eventName == "frames") { - let [delta, frames] = data; - Array.prototype.push.apply(this._frames, frames); - } - // Accumulate memory measurements into an array. - else if (eventName == "memory") { - let [delta, measurement] = data; - this._memory.push({ delta, value: measurement.total / 1024 / 1024 }); - } - // Save the accumulated refresh driver ticks. - else if (eventName == "ticks") { - let [delta, timestamps] = data; - this._ticks = timestamps; - } + _onTimelineData: function (...data) { + this._recordings.forEach(profile => profile.addTimelineData.apply(profile, data)); + this.emit(EVENTS.TIMELINE_DATA, ...data); + }, - this.emit(EVENTS.TIMELINE_DATA, eventName, ...data); + /** + * Fired from RecordingsView, we listen on the PerformanceController + * so we can set it here and re-emit on the controller, where all views can listen. + */ + _onRecordingSelectFromView: function (_, recording) { + this.setCurrentRecording(recording); } }; diff --git a/browser/devtools/performance/performance-view.js b/browser/devtools/performance/performance-view.js index 7a1d5cc8fcf4..900c31e32fdd 100644 --- a/browser/devtools/performance/performance-view.js +++ b/browser/devtools/performance/performance-view.js @@ -13,23 +13,21 @@ let PerformanceView = { initialize: function () { this._recordButton = $("#record-button"); this._importButton = $("#import-button"); - this._exportButton = $("#export-button"); this._onRecordButtonClick = this._onRecordButtonClick.bind(this); this._onImportButtonClick = this._onImportButtonClick.bind(this); - this._onExportButtonClick = this._onExportButtonClick.bind(this); this._lockRecordButton = this._lockRecordButton.bind(this); this._unlockRecordButton = this._unlockRecordButton.bind(this); this._recordButton.addEventListener("click", this._onRecordButtonClick); this._importButton.addEventListener("click", this._onImportButtonClick); - this._exportButton.addEventListener("click", this._onExportButtonClick); // Bind to controller events to unlock the record button PerformanceController.on(EVENTS.RECORDING_STARTED, this._unlockRecordButton); PerformanceController.on(EVENTS.RECORDING_STOPPED, this._unlockRecordButton); return promise.all([ + RecordingsView.initialize(), OverviewView.initialize(), DetailsView.initialize() ]); @@ -41,12 +39,12 @@ let PerformanceView = { destroy: function () { this._recordButton.removeEventListener("click", this._onRecordButtonClick); this._importButton.removeEventListener("click", this._onImportButtonClick); - this._exportButton.removeEventListener("click", this._onExportButtonClick); PerformanceController.off(EVENTS.RECORDING_STARTED, this._unlockRecordButton); PerformanceController.off(EVENTS.RECORDING_STOPPED, this._unlockRecordButton); return promise.all([ + RecordingsView.destroy(), OverviewView.destroy(), DetailsView.destroy() ]); @@ -94,23 +92,6 @@ let PerformanceView = { if (fp.show() == Ci.nsIFilePicker.returnOK) { this.emit(EVENTS.UI_IMPORT_RECORDING, fp.file); } - }, - - /** - * Handler for clicking the export button. - */ - _onExportButtonClick: function(e) { - let fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker); - fp.init(window, L10N.getStr("recordingsList.saveDialogTitle"), Ci.nsIFilePicker.modeSave); - fp.appendFilter(L10N.getStr("recordingsList.saveDialogJSONFilter"), "*.json"); - fp.appendFilter(L10N.getStr("recordingsList.saveDialogAllFilter"), "*.*"); - fp.defaultString = "profile.json"; - - fp.open({ done: result => { - if (result != Ci.nsIFilePicker.returnCancel) { - this.emit(EVENTS.UI_EXPORT_RECORDING, fp.file); - } - }}); } }; diff --git a/browser/devtools/performance/performance.xul b/browser/devtools/performance/performance.xul index 0b1f505bda09..39fc2febc704 100644 --- a/browser/devtools/performance/performance.xul +++ b/browser/devtools/performance/performance.xul @@ -16,93 +16,96 @@ diff --git a/media/libstagefright/binding/Box.cpp b/media/libstagefright/binding/Box.cpp index a7485528cd64..886345036d26 100644 --- a/media/libstagefright/binding/Box.cpp +++ b/media/libstagefright/binding/Box.cpp @@ -98,7 +98,7 @@ Box::Read(nsTArray* aDest) aDest->Length(), &bytes) || bytes != aDest->Length()) { // Byte ranges are being reported incorrectly - MOZ_ASSERT(false); + NS_WARNING("Read failed in mp4_demuxer::Box::Read()"); aDest->Clear(); } } diff --git a/memory/jemalloc/0005-Bug-1121314-Avoid-needing-the-arena-in-chunk_alloc_d.patch b/memory/jemalloc/0005-Bug-1121314-Avoid-needing-the-arena-in-chunk_alloc_d.patch new file mode 100644 index 000000000000..89b84dcbbe02 --- /dev/null +++ b/memory/jemalloc/0005-Bug-1121314-Avoid-needing-the-arena-in-chunk_alloc_d.patch @@ -0,0 +1,58 @@ +From 722400adde3b4cb307fdc310e6296e10e6ace7ae Mon Sep 17 00:00:00 2001 +From: Mike Hommey +Date: Wed, 14 Jan 2015 12:49:24 +0900 +Subject: [PATCH] Bug 1121314 - Avoid needing the arena in chunk_alloc_default + to avoid possible infinite loops involving a0malloc + +--- + src/chunk.c | 21 +++++++++++++-------- + 1 file changed, 13 insertions(+), 8 deletions(-) + +diff --git a/src/chunk.c b/src/chunk.c +index 7926452..32e659c 100644 +--- a/src/chunk.c ++++ b/src/chunk.c +@@ -247,27 +247,32 @@ chunk_alloc_arena(chunk_alloc_t *chunk_alloc, chunk_dalloc_t *chunk_dalloc, + return (ret); + } + + /* Default arena chunk allocation routine in the absence of user override. */ + void * + chunk_alloc_default(void *new_addr, size_t size, size_t alignment, bool *zero, + unsigned arena_ind) + { +- arena_t *arena; ++ dss_prec_t dss_prec = dss_prec_disabled; + +- arena = arena_get(tsd_fetch(), arena_ind, false, true); +- /* +- * The arena we're allocating on behalf of must have been initialized +- * already. +- */ +- assert(arena != NULL); ++ if (have_dss) { ++ arena_t *arena; ++ ++ arena = arena_get(tsd_fetch(), arena_ind, false, true); ++ /* ++ * The arena we're allocating on behalf of must have been ++ * initialized already. ++ */ ++ assert(arena != NULL); ++ dss_prec = arena->dss_prec; ++ } + + return (chunk_alloc_core(new_addr, size, alignment, false, zero, +- arena->dss_prec)); ++ dss_prec)); + } + + static void + chunk_record(extent_tree_t *chunks_szad, extent_tree_t *chunks_ad, void *chunk, + size_t size) + { + bool unzeroed; + extent_node_t *xnode, *node, *prev, *xprev, key; +-- +2.2.1.dirty + diff --git a/memory/jemalloc/src/src/chunk.c b/memory/jemalloc/src/src/chunk.c index 7926452729f2..32e659c98c9d 100644 --- a/memory/jemalloc/src/src/chunk.c +++ b/memory/jemalloc/src/src/chunk.c @@ -252,17 +252,22 @@ void * chunk_alloc_default(void *new_addr, size_t size, size_t alignment, bool *zero, unsigned arena_ind) { - arena_t *arena; + dss_prec_t dss_prec = dss_prec_disabled; - arena = arena_get(tsd_fetch(), arena_ind, false, true); - /* - * The arena we're allocating on behalf of must have been initialized - * already. - */ - assert(arena != NULL); + if (have_dss) { + arena_t *arena; + + arena = arena_get(tsd_fetch(), arena_ind, false, true); + /* + * The arena we're allocating on behalf of must have been + * initialized already. + */ + assert(arena != NULL); + dss_prec = arena->dss_prec; + } return (chunk_alloc_core(new_addr, size, alignment, false, zero, - arena->dss_prec)); + dss_prec)); } static void diff --git a/memory/jemalloc/update.sh b/memory/jemalloc/update.sh index a2b34821b3f5..0f763154562a 100755 --- a/memory/jemalloc/update.sh +++ b/memory/jemalloc/update.sh @@ -18,6 +18,7 @@ patch -p1 < ../0001-Dont-overwrite-VERSION-on-a-git-repository.patch patch -p1 < ../0002-Move-variable-declaration-to-the-top-its-block-for-M.patch patch -p1 < ../0003-Add-a-isblank-definition-for-MSVC-2013.patch patch -p1 < ../0004-Implement-stats.bookkeeping.patch +patch -p1 < ../0005-Bug-1121314-Avoid-needing-the-arena-in-chunk_alloc_d.patch cd .. hg addremove -q src diff --git a/memory/replace/dmd/test/SmokeDMD.cpp b/memory/replace/dmd/test/SmokeDMD.cpp index 253dcc406d49..85a4639e346f 100644 --- a/memory/replace/dmd/test/SmokeDMD.cpp +++ b/memory/replace/dmd/test/SmokeDMD.cpp @@ -164,7 +164,7 @@ TestUnsampled(const char* aTestName, int aNum, const char* aMode, int aSeven) // Analyze 1: reported. // Analyze 2: freed. char* e = (char*) malloc(4096); - e = (char*) realloc(e, 4097); + e = (char*) realloc(e, 7169); Report(e); // First realloc is like malloc; second realloc is shrinking. diff --git a/memory/replace/dmd/test/full-unsampled1-dark-matter-expected.txt b/memory/replace/dmd/test/full-unsampled1-dark-matter-expected.txt index f4f9182f8630..4336a0110863 100644 --- a/memory/replace/dmd/test/full-unsampled1-dark-matter-expected.txt +++ b/memory/replace/dmd/test/full-unsampled1-dark-matter-expected.txt @@ -112,7 +112,7 @@ Unreported { Once-reported { 1 block in heap block record 1 of 11 - 8,192 bytes (4,097 requested / 4,095 slop) + 8,192 bytes (7,169 requested / 1,023 slop) 67.77% of the heap (67.77% cumulative) 77.40% of once-reported (77.40% cumulative) Allocated at { diff --git a/memory/replace/dmd/test/full-unsampled1-live-expected.txt b/memory/replace/dmd/test/full-unsampled1-live-expected.txt index a6fc160437a5..8f0afb87610a 100644 --- a/memory/replace/dmd/test/full-unsampled1-live-expected.txt +++ b/memory/replace/dmd/test/full-unsampled1-live-expected.txt @@ -11,7 +11,7 @@ Invocation { Live { 1 block in heap block record 1 of 12 - 8,192 bytes (4,097 requested / 4,095 slop) + 8,192 bytes (7,169 requested / 1,023 slop) 67.77% of the heap (67.77% cumulative) Allocated at { #01: ... DMD.cpp ... diff --git a/memory/replace/dmd/test/full-unsampled2-cumulative-expected.txt b/memory/replace/dmd/test/full-unsampled2-cumulative-expected.txt index 11c0e75bb22d..6edae2f5083a 100644 --- a/memory/replace/dmd/test/full-unsampled2-cumulative-expected.txt +++ b/memory/replace/dmd/test/full-unsampled2-cumulative-expected.txt @@ -11,7 +11,7 @@ Invocation { Cumulative { 1 block in heap block record 1 of 16 - 8,192 bytes (4,097 requested / 4,095 slop) + 8,192 bytes (7,169 requested / 1,023 slop) 47.10% of the heap (47.10% cumulative) Allocated at { #01: ... DMD.cpp ... diff --git a/mobile/android/base/tests/BaseTest.java b/mobile/android/base/tests/BaseTest.java index 79ce7b9c0f54..60c6c18a11c2 100644 --- a/mobile/android/base/tests/BaseTest.java +++ b/mobile/android/base/tests/BaseTest.java @@ -181,7 +181,7 @@ abstract class BaseTest extends BaseRobocopTest { mAsserter.endTest(); // request a force quit of the browser and wait for it to take effect GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("Robocop:Quit", null)); - mSolo.sleep(7000); + mSolo.sleep(120000); // if still running, finish activities as recommended by Robotium mSolo.finishOpenedActivities(); } catch (Throwable e) { diff --git a/mobile/android/base/tests/UITest.java b/mobile/android/base/tests/UITest.java index 15f888352280..1611a60093ab 100644 --- a/mobile/android/base/tests/UITest.java +++ b/mobile/android/base/tests/UITest.java @@ -79,7 +79,7 @@ abstract class UITest extends BaseRobocopTest mAsserter.endTest(); // request a force quit of the browser and wait for it to take effect GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("Robocop:Quit", null)); - mSolo.sleep(7000); + mSolo.sleep(120000); // if still running, finish activities as recommended by Robotium mSolo.finishOpenedActivities(); } catch (Throwable e) { diff --git a/mobile/android/config/mozconfigs/common b/mobile/android/config/mozconfigs/common index 219bb027ac47..e1f46a801065 100644 --- a/mobile/android/config/mozconfigs/common +++ b/mobile/android/config/mozconfigs/common @@ -44,8 +44,8 @@ export MOZ_PACKAGE_JSSHELL=1 # Use ccache . "$topsrcdir/build/mozconfig.cache" -HOST_CC="/tools/gcc-4.7.2-0moz1/bin/gcc" -HOST_CXX="/tools/gcc-4.7.2-0moz1/bin/g++" +HOST_CC="$topsrcdir/gcc/bin/gcc" +HOST_CXX="$topsrcdir/gcc/bin/g++" # Avoid dependency on libstdc++ 4.7 ac_add_options --enable-stdcxx-compat diff --git a/mobile/android/config/tooltool-manifests/android-armv6/releng.manifest b/mobile/android/config/tooltool-manifests/android-armv6/releng.manifest index fb000b205def..752c937b7887 100644 --- a/mobile/android/config/tooltool-manifests/android-armv6/releng.manifest +++ b/mobile/android/config/tooltool-manifests/android-armv6/releng.manifest @@ -35,5 +35,12 @@ "algorithm": "sha512", "filename": "jsshell.tar.xz", "unpack": "True" +}, +{ +"size": 80458572, +"digest": "e5101f9dee1e462f6cbd3897ea57eede41d23981825c7b20d91d23ab461875d54d3dfc24999aa58a31e8b01f49fb3140e05ffe5af2957ef1d1afb89fd0dfe1ad", +"algorithm": "sha512", +"filename": "gcc.tar.xz", +"unpack": "True" } ] diff --git a/mobile/android/config/tooltool-manifests/android-x86/releng.manifest b/mobile/android/config/tooltool-manifests/android-x86/releng.manifest index 1f02d2aa81c8..8f57b5f532a8 100644 --- a/mobile/android/config/tooltool-manifests/android-x86/releng.manifest +++ b/mobile/android/config/tooltool-manifests/android-x86/releng.manifest @@ -35,5 +35,12 @@ "algorithm": "sha512", "filename": "jsshell.tar.xz", "unpack": "True" +}, +{ +"size": 80458572, +"digest": "e5101f9dee1e462f6cbd3897ea57eede41d23981825c7b20d91d23ab461875d54d3dfc24999aa58a31e8b01f49fb3140e05ffe5af2957ef1d1afb89fd0dfe1ad", +"algorithm": "sha512", +"filename": "gcc.tar.xz", +"unpack": "True" } ] diff --git a/mobile/android/config/tooltool-manifests/android/releng.manifest b/mobile/android/config/tooltool-manifests/android/releng.manifest index fb000b205def..752c937b7887 100644 --- a/mobile/android/config/tooltool-manifests/android/releng.manifest +++ b/mobile/android/config/tooltool-manifests/android/releng.manifest @@ -35,5 +35,12 @@ "algorithm": "sha512", "filename": "jsshell.tar.xz", "unpack": "True" +}, +{ +"size": 80458572, +"digest": "e5101f9dee1e462f6cbd3897ea57eede41d23981825c7b20d91d23ab461875d54d3dfc24999aa58a31e8b01f49fb3140e05ffe5af2957ef1d1afb89fd0dfe1ad", +"algorithm": "sha512", +"filename": "gcc.tar.xz", +"unpack": "True" } ] diff --git a/mobile/android/installer/package-manifest.in b/mobile/android/installer/package-manifest.in index 98872fc468c6..80769cb97f02 100644 --- a/mobile/android/installer/package-manifest.in +++ b/mobile/android/installer/package-manifest.in @@ -539,7 +539,6 @@ @BINPATH@/res/grabber.gif @BINPATH@/res/dtd/* @BINPATH@/res/html/* -@BINPATH@/res/langGroups.properties @BINPATH@/res/language.properties @BINPATH@/res/entityTables/* diff --git a/mobile/android/modules/TabMirror.jsm b/mobile/android/modules/TabMirror.jsm index 59412147f387..bc308b2741ed 100644 --- a/mobile/android/modules/TabMirror.jsm +++ b/mobile/android/modules/TabMirror.jsm @@ -24,54 +24,55 @@ let TabMirror = function(deviceId, window) { this.RTCIceCandidate = window.mozRTCIceCandidate; Services.obs.addObserver((aSubject, aTopic, aData) => this._processMessage(aData), "MediaPlayer:Response", false); - + this._sendMessage({ start: true }); + this._window = window; this._pc = new window.mozRTCPeerConnection(CONFIG, {}); - if (!this._pc) { throw "Failure creating Webrtc object"; } - this._pc.onicecandidate = this._onIceCandidate.bind(this); - - let windowId = window.BrowserApp.selectedBrowser.contentWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils).outerWindowID; - let viewport = window.BrowserApp.selectedTab.getViewport(); - let maxWidth = Math.max(viewport.cssWidth, viewport.width); - let maxHeight = Math.max(viewport.cssHeight, viewport.height); - let minRatio = Math.sqrt((maxWidth * maxHeight) / (640 * 480)); - - let screenWidth = 640; - let screenHeight = 480; - let videoWidth = 0; - let videoHeight = 0; - if (screenWidth/screenHeight > maxWidth / maxHeight) { - videoWidth = screenWidth; - videoHeight = Math.ceil(videoWidth * maxHeight / maxWidth); - } else { - videoHeight = screenHeight; - videoWidth = Math.ceil(videoHeight * maxWidth / maxHeight); - } - - let constraints = { - video: { - mediaSource: "browser", - browserWindow: windowId, - scrollWithPage: true, - advanced: [ - { width: { min: videoWidth, max: videoWidth }, - height: { min: videoHeight, max: videoHeight } - }, - { aspectRatio: maxWidth / maxHeight } - ] - } - }; - - window.navigator.mozGetUserMedia(constraints, this._onGumSuccess.bind(this), this._onGumFailure.bind(this)); }; TabMirror.prototype = { + _window: null, + _screenSize: { width: 1280, height: 720 }, + _pc: null, + _start: function() { + this._pc.onicecandidate = this._onIceCandidate.bind(this); + + let windowId = this._window.BrowserApp.selectedBrowser.contentWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils).outerWindowID; + let viewport = this._window.BrowserApp.selectedTab.getViewport(); + let maxWidth = Math.max(viewport.cssWidth, viewport.width); + let maxHeight = Math.max(viewport.cssHeight, viewport.height); + + let videoWidth = 0; + let videoHeight = 0; + if (this._screenSize.width/this._screenSize.height < maxWidth / maxHeight) { + videoWidth = this._screenSize.width; + videoHeight = Math.ceil(videoWidth * maxHeight / maxWidth); + } else { + videoHeight = this._screenSize.height; + videoWidth = Math.ceil(videoHeight * maxWidth / maxHeight); + } + + let constraints = { + video: { + mediaSource: "browser", + browserWindow: windowId, + scrollWithPage: true, + advanced: [ + { width: { min: videoWidth, max: videoWidth }, + height: { min: videoHeight, max: videoHeight } + }, + { aspectRatio: maxWidth / maxHeight } + ] + } + }; + + this._window.navigator.mozGetUserMedia(constraints, this._onGumSuccess.bind(this), this._onGumFailure.bind(this)); + }, _processMessage: function(data) { - if (!data) { return; } @@ -82,21 +83,27 @@ TabMirror.prototype = { return; } - if (msg.sdp) { - if (msg.type === "answer") { - this._processAnswer(msg); - } else { - log("Unandled sdp message type: " + msg.type); + if (msg.sdp && msg.type === "answer") { + this._processAnswer(msg); + } else if (msg.type == "size") { + if (msg.height) { + this._screenSize.height = msg.height; } - } else { + if (msg.width) { + this._screenSize.width = msg.width; + } + this._start(); + } else if (msg.candidate) { this._processIceCandidate(msg); + } else { + log("dropping unrecognized message: " + JSON.stringify(msg)); } }, // Signaling methods _processAnswer: function(msg) { this._pc.setRemoteDescription(new this.RTCSessionDescription(msg), - this._setRemoteAnswerSuccess.bind(this), failure); + this._setRemoteAnswerSuccess.bind(this), failure); }, _processIceCandidate: function(msg) { diff --git a/security/manager/ssl/tests/unit/pkcs11testmodule/pkcs11testmodule.cpp b/security/manager/ssl/tests/unit/pkcs11testmodule/pkcs11testmodule.cpp index ffb569ada7ea..60f8f5a4e57d 100644 --- a/security/manager/ssl/tests/unit/pkcs11testmodule/pkcs11testmodule.cpp +++ b/security/manager/ssl/tests/unit/pkcs11testmodule/pkcs11testmodule.cpp @@ -175,8 +175,9 @@ CK_RV Test_C_SetPIN(CK_SESSION_HANDLE, CK_UTF8CHAR_PTR, CK_ULONG, } CK_RV Test_C_OpenSession(CK_SLOT_ID, CK_FLAGS, CK_VOID_PTR, CK_NOTIFY, - CK_SESSION_HANDLE_PTR) + CK_SESSION_HANDLE_PTR phSession) { + *phSession = 1; return CKR_OK; } diff --git a/testing/config/mozharness/b2g_emulator_config.py b/testing/config/mozharness/b2g_emulator_config.py index cfca86d17ade..296c32845c49 100644 --- a/testing/config/mozharness/b2g_emulator_config.py +++ b/testing/config/mozharness/b2g_emulator_config.py @@ -79,6 +79,28 @@ config = { "run_filename": "runtestsb2g.py", "testsdir": "mochitest" }, + "mochitest-chrome": { + "options": [ + "--adbpath=%(adbpath)s", + "--b2gpath=%(b2gpath)s", + "--console-level=INFO", + "--emulator=%(emulator)s", + "--logdir=%(logcat_dir)s", + "--remote-webserver=%(remote_webserver)s", + "--xre-path=%(xre_path)s", + "--symbols-path=%(symbols_path)s", + "--busybox=%(busybox)s", + "--total-chunks=%(total_chunks)s", + "--this-chunk=%(this_chunk)s", + "--quiet", + "--chrome", + "--log-raw=%(raw_log_file)s", + "--certificate-path=%(certificate_path)s", + "--test-path=%(test_path)s" + ], + "run_filename": "runtestsb2g.py", + "testsdir": "mochitest" + }, "reftest": { "options": [ "--adbpath=%(adbpath)s", diff --git a/testing/marionette/client/marionette/geckoinstance.py b/testing/marionette/client/marionette/geckoinstance.py index 6aec94568c7f..0bc1a1477152 100644 --- a/testing/marionette/client/marionette/geckoinstance.py +++ b/testing/marionette/client/marionette/geckoinstance.py @@ -31,7 +31,7 @@ class GeckoInstance(object): "browser.tabs.remote.autostart.2": False} def __init__(self, host, port, bin, profile=None, app_args=None, symbols_path=None, - gecko_log=None, prefs=None, ): + gecko_log=None, prefs=None): self.marionette_host = host self.marionette_port = port self.bin = bin @@ -42,6 +42,9 @@ class GeckoInstance(object): else: self.profile_path = profile self.prefs = prefs + self.required_prefs = deepcopy(GeckoInstance.required_prefs) + if prefs: + self.required_prefs.update(prefs) self.app_args = app_args or [] self.runner = None self.symbols_path = symbols_path diff --git a/testing/marionette/client/marionette/marionette.py b/testing/marionette/client/marionette/marionette.py index 236e2c81f032..fe6e93b2e733 100644 --- a/testing/marionette/client/marionette/marionette.py +++ b/testing/marionette/client/marionette/marionette.py @@ -472,7 +472,7 @@ class Marionette(object): gecko_log=None, homedir=None, baseurl=None, no_window=False, logdir=None, busybox=None, symbols_path=None, timeout=None, socket_timeout=360, device_serial=None, adb_path=None, process_args=None, - adb_host=None, adb_port=None): + adb_host=None, adb_port=None, prefs=None): self.host = host self.port = self.local_port = port self.bin = bin @@ -519,7 +519,7 @@ class Marionette(object): self.instance = instance_class(host=self.host, port=self.port, bin=self.bin, profile=self.profile, app_args=app_args, symbols_path=symbols_path, - gecko_log=gecko_log) + gecko_log=gecko_log, prefs=prefs) self.instance.start() assert(self.wait_for_port()), "Timed out waiting for port!" diff --git a/testing/marionette/client/marionette/marionette_test.py b/testing/marionette/client/marionette/marionette_test.py index 996cfc423d3f..cd45db52a8b9 100644 --- a/testing/marionette/client/marionette/marionette_test.py +++ b/testing/marionette/client/marionette/marionette_test.py @@ -88,6 +88,21 @@ def skip_if_b2g(target): return wrapper +def skip_if_e10s(target): + def wrapper(self, *args, **kwargs): + with self.marionette.using_context('chrome'): + multi_process_browser = self.marionette.execute_script(""" + try { + return Services.appinfo.browserTabsRemoteAutostart; + } catch (e) { + return false; + }""") + + if multi_process_browser: + raise SkipTest('skipping due to e10s') + return target(self, *args, **kwargs) + return wrapper + def parameterized(func_suffix, *args, **kwargs): """ A decorator that can generate methods given a base method and some data. diff --git a/testing/marionette/client/marionette/runner/base.py b/testing/marionette/client/marionette/runner/base.py index 57e8da4090d8..cc6dfb001acf 100644 --- a/testing/marionette/client/marionette/runner/base.py +++ b/testing/marionette/client/marionette/runner/base.py @@ -395,6 +395,11 @@ class BaseMarionetteOptions(OptionParser): action='store_true', default=False, help='Enable the jsdebugger for marionette javascript.') + self.add_option('--e10s', + dest='e10s', + action='store_true', + default=False, + help='Enable e10s when running marionette tests.') def parse_args(self, args=None, values=None): options, tests = OptionParser.parse_args(self, args, values) @@ -447,6 +452,11 @@ class BaseMarionetteOptions(OptionParser): if options.jsdebugger: options.app_args.append('-jsdebugger') + if options.e10s: + options.prefs = { + 'browser.tabs.remote.autostart': True + } + for handler in self.verify_usage_handlers: handler(options, tests) @@ -466,7 +476,7 @@ class BaseMarionetteTestRunner(object): shuffle=False, shuffle_seed=random.randint(0, sys.maxint), sdcard=None, this_chunk=1, total_chunks=1, sources=None, server_root=None, gecko_log=None, result_callbacks=None, - adb_host=None, adb_port=None, **kwargs): + adb_host=None, adb_port=None, prefs=None, **kwargs): self.address = address self.emulator = emulator self.emulator_binary = emulator_binary @@ -508,6 +518,7 @@ class BaseMarionetteTestRunner(object): self.result_callbacks = result_callbacks if result_callbacks is not None else [] self._adb_host = adb_host self._adb_port = adb_port + self.prefs = prefs def gather_debug(test, status): rv = {} @@ -620,6 +631,7 @@ class BaseMarionetteTestRunner(object): 'timeout': self.timeout, 'adb_host': self._adb_host, 'adb_port': self._adb_port, + 'prefs': self.prefs, } if self.bin: kwargs.update({ diff --git a/testing/marionette/client/marionette/tests/unit/test_navigation.py b/testing/marionette/client/marionette/tests/unit/test_navigation.py index 2d80eae4f40b..e95ee42467c4 100644 --- a/testing/marionette/client/marionette/tests/unit/test_navigation.py +++ b/testing/marionette/client/marionette/tests/unit/test_navigation.py @@ -2,7 +2,7 @@ # 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/. -from marionette_test import MarionetteTestCase, skip_if_b2g +from marionette_test import MarionetteTestCase, skip_if_b2g, skip_if_e10s from errors import MarionetteException, TimeoutException class TestNavigate(MarionetteTestCase): @@ -77,6 +77,7 @@ class TestNavigate(MarionetteTestCase): self.assertTrue('test_iframe.html' in self.marionette.get_url()) ''' + @skip_if_e10s # Interactions with about: pages need e10s support (bug 1096488). def test_shouldnt_error_if_nonexistent_url_used(self): try: self.marionette.navigate("thisprotocoldoesnotexist://") @@ -90,6 +91,7 @@ class TestNavigate(MarionetteTestCase): print traceback.format_exc() self.fail("Should have thrown a MarionetteException instead of %s" % type(inst)) + @skip_if_e10s # Interactions with about: pages need e10s support (bug 1096488). @skip_if_b2g # about:blocked isn't a well formed uri on b2g def test_should_navigate_to_requested_about_page(self): self.marionette.navigate("about:neterror") diff --git a/testing/marionette/client/marionette/tests/unit/test_window_handles.py b/testing/marionette/client/marionette/tests/unit/test_window_handles.py index bd377f193e29..07193d8dd3d1 100644 --- a/testing/marionette/client/marionette/tests/unit/test_window_handles.py +++ b/testing/marionette/client/marionette/tests/unit/test_window_handles.py @@ -2,12 +2,13 @@ # 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/. -from marionette_test import MarionetteTestCase +from marionette_test import MarionetteTestCase, skip_if_e10s from marionette import Keys class TestWindowHandles(MarionetteTestCase): + @skip_if_e10s # Interactions with about: pages need e10s support (bug 1096488). def test_new_tab_window_handles(self): keys = [Keys.SHIFT] if self.marionette.session_capabilities['platformName'] == 'DARWIN': @@ -91,6 +92,8 @@ class TestWindowHandles(MarionetteTestCase): self.assertEqual(len(self.marionette.window_handles), 1) self.marionette.switch_to_window(start_tab) + # This sequence triggers an exception in Marionette:register with e10s on (bug 1120809). + @skip_if_e10s def test_tab_and_window_handles(self): start_tab = self.marionette.current_window_handle start_chrome_window = self.marionette.current_chrome_window_handle diff --git a/testing/marionette/mach_commands.py b/testing/marionette/mach_commands.py index 6354305d5626..7b5087d209b7 100644 --- a/testing/marionette/mach_commands.py +++ b/testing/marionette/mach_commands.py @@ -132,6 +132,8 @@ class MachCommands(MachCommandBase): help='Path to gecko log file, or "-" for stdout.') @CommandArgument('--jsdebugger', action='store_true', help='Enable the jsdebugger for marionette javascript.') + @CommandArgument('--e10s', action='store_true', + help='Enable electrolysis for marionette tests (desktop only).') @CommandArgument('tests', nargs='*', metavar='TESTS', help='Path to test(s) to run.') def run_marionette_test(self, tests, **kwargs): diff --git a/toolkit/components/aboutcompartments/content/aboutCompartments.js b/toolkit/components/aboutcompartments/content/aboutCompartments.js new file mode 100644 index 000000000000..69535c3c9bfb --- /dev/null +++ b/toolkit/components/aboutcompartments/content/aboutCompartments.js @@ -0,0 +1,75 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 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/. */ + +"use strict"; + +const { classes: Cc, interfaces: Ci, utils: Cu } = Components; + +const { AddonManager } = Cu.import("resource://gre/modules/AddonManager.jsm", {}); + +function go() { + let compartmentInfo = Cc["@mozilla.org/compartment-info;1"] + .getService(Ci.nsICompartmentInfo); + let compartments = compartmentInfo.getCompartments(); + let count = compartments.length; + let addons = {}; + for (let i = 0; i < count; i++) { + let compartment = compartments.queryElementAt(i, Ci.nsICompartment); + if (addons[compartment.addonId]) { + addons[compartment.addonId].time += compartment.time; + addons[compartment.addonId].CPOWTime += compartment.CPOWTime; + addons[compartment.addonId].compartments.push(compartment); + } else { + addons[compartment.addonId] = { + time: compartment.time, + CPOWTime: compartment.CPOWTime, + compartments: [compartment] + }; + } + } + let dataDiv = document.getElementById("data"); + for (let addon in addons) { + let el = document.createElement("tr"); + let name = document.createElement("td"); + let time = document.createElement("td"); + let cpow = document.createElement("td"); + name.className = "addon"; + time.className = "time"; + cpow.className = "cpow"; + name.textContent = addon; + AddonManager.getAddonByID(addon, function(a) { + if (a) { + name.textContent = a.name; + } + }); + time.textContent = addons[addon].time +"μs"; + cpow.textContent = addons[addon].CPOWTime +"μs"; + el.appendChild(time); + el.appendChild(cpow); + el.appendChild(name); + let div = document.createElement("tr"); + for (let comp of addons[addon].compartments) { + let c = document.createElement("tr"); + let name = document.createElement("td"); + let time = document.createElement("td"); + let cpow = document.createElement("td"); + name.className = "addon"; + time.className = "time"; + cpow.className = "cpow"; + name.textContent = comp.label; + time.textContent = comp.time +"μs"; + cpow.textContent = comp.CPOWTime +"μs"; + c.appendChild(time); + c.appendChild(cpow); + c.appendChild(name); + div.appendChild(c); + div.className = "details"; + } + el.addEventListener("click", function() { div.style.display = (div.style.display != "block" ? "block" : "none"); }); + el.appendChild(div); + dataDiv.appendChild(el); + } +} diff --git a/toolkit/components/aboutcompartments/content/aboutCompartments.xhtml b/toolkit/components/aboutcompartments/content/aboutCompartments.xhtml new file mode 100644 index 000000000000..d3de58a17806 --- /dev/null +++ b/toolkit/components/aboutcompartments/content/aboutCompartments.xhtml @@ -0,0 +1,43 @@ + + + + + + + about:compartments + + + + + + + + + + +
timetime in CPOWsname
+ + diff --git a/toolkit/components/aboutcompartments/jar.mn b/toolkit/components/aboutcompartments/jar.mn new file mode 100644 index 000000000000..ca1a3352c577 --- /dev/null +++ b/toolkit/components/aboutcompartments/jar.mn @@ -0,0 +1,7 @@ +# 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/. + +toolkit.jar: ++ content/global/aboutCompartments.xhtml (content/aboutCompartments.xhtml) ++ content/global/aboutCompartments.js (content/aboutCompartments.js) diff --git a/toolkit/components/aboutcompartments/moz.build b/toolkit/components/aboutcompartments/moz.build new file mode 100644 index 000000000000..9872f4f72dea --- /dev/null +++ b/toolkit/components/aboutcompartments/moz.build @@ -0,0 +1,23 @@ +# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# 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/. + +JAR_MANIFESTS += ['jar.mn'] + +XPIDL_MODULE = 'compartments' + +XPIDL_SOURCES += [ + 'nsICompartmentInfo.idl', +] + +UNIFIED_SOURCES += [ + 'nsCompartmentInfo.cpp' +] + +EXPORTS += [ + 'nsCompartmentInfo.h' +] + +FINAL_LIBRARY = 'xul' diff --git a/toolkit/components/aboutcompartments/nsCompartmentInfo.cpp b/toolkit/components/aboutcompartments/nsCompartmentInfo.cpp new file mode 100644 index 000000000000..6a5c1bbd97c9 --- /dev/null +++ b/toolkit/components/aboutcompartments/nsCompartmentInfo.cpp @@ -0,0 +1,94 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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 "nsCompartmentInfo.h" +#include "nsMemory.h" +#include "nsLiteralString.h" +#include "nsCRTGlue.h" +#include "nsIJSRuntimeService.h" +#include "nsServiceManagerUtils.h" +#include "nsIMutableArray.h" +#include "nsJSUtils.h" +#include "xpcpublic.h" + +class nsCompartment : public nsICompartment { +public: + nsCompartment(nsAString& aCompartmentName, nsAString& aAddonId, + uint64_t aTime, uint64_t aCPOWTime) + : mCompartmentName(aCompartmentName), mAddonId(aAddonId), mTime(aTime), mCPOWTime(aCPOWTime) {} + + NS_DECL_ISUPPORTS + + /* readonly attribute wstring compartmentName; */ + NS_IMETHOD GetCompartmentName(nsAString& aCompartmentName){ + aCompartmentName.Assign(mCompartmentName); + return NS_OK; + }; + + /* readonly attribute unsigned long time; */ + NS_IMETHOD GetTime(uint64_t* aTime) { + *aTime = mTime; + return NS_OK; + } + /* readonly attribute wstring addon id; */ + NS_IMETHOD GetAddonId(nsAString& aAddonId){ + aAddonId.Assign(mAddonId); + return NS_OK; + }; + + /* readonly attribute unsigned long CPOW time; */ + NS_IMETHOD GetCPOWTime(uint64_t* aCPOWTime) { + *aCPOWTime = mCPOWTime; + return NS_OK; + } + +private: + nsString mCompartmentName; + nsString mAddonId; + uint64_t mTime; + uint64_t mCPOWTime; + virtual ~nsCompartment() {} +}; + +NS_IMPL_ISUPPORTS(nsCompartment, nsICompartment) +NS_IMPL_ISUPPORTS(nsCompartmentInfo, nsICompartmentInfo) + +nsCompartmentInfo::nsCompartmentInfo() +{ +} + +nsCompartmentInfo::~nsCompartmentInfo() +{ +} + +NS_IMETHODIMP +nsCompartmentInfo::GetCompartments(nsIArray** aCompartments) +{ + JSRuntime* rt; + nsCOMPtr svc(do_GetService("@mozilla.org/js/xpc/RuntimeService;1")); + NS_ENSURE_TRUE(svc, NS_ERROR_FAILURE); + svc->GetRuntime(&rt); + nsCOMPtr compartments = do_CreateInstance(NS_ARRAY_CONTRACTID); + CompartmentStatsVector stats; + if (!JS_GetCompartmentStats(rt, stats)) + return NS_ERROR_OUT_OF_MEMORY; + + size_t num = stats.length(); + for (size_t pos = 0; pos < num; pos++) { + nsString addonId; + if (stats[pos].addonId) { + AssignJSFlatString(addonId, (JSFlatString*)stats[pos].addonId); + } else { + addonId.AssignLiteral(""); + } + + uint32_t cpowTime = xpc::GetCompartmentCPOWMicroseconds(stats[pos].compartment); + nsCString compartmentName(stats[pos].compartmentName); + NS_ConvertUTF8toUTF16 name(compartmentName); + compartments->AppendElement(new nsCompartment(name, addonId, stats[pos].time, cpowTime), false); + } + compartments.forget(aCompartments); + return NS_OK; +} diff --git a/toolkit/components/aboutcompartments/nsCompartmentInfo.h b/toolkit/components/aboutcompartments/nsCompartmentInfo.h new file mode 100644 index 000000000000..4efba6d92f8e --- /dev/null +++ b/toolkit/components/aboutcompartments/nsCompartmentInfo.h @@ -0,0 +1,25 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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 nsCompartmentInfo_h +#define nsCompartmentInfo_h + +#include "nsICompartmentInfo.h" + +class nsCompartmentInfo : public nsICompartmentInfo +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_NSICOMPARTMENTINFO + + nsCompartmentInfo(); + +private: + virtual ~nsCompartmentInfo(); + +protected: +}; + +#endif diff --git a/toolkit/components/aboutcompartments/nsICompartmentInfo.idl b/toolkit/components/aboutcompartments/nsICompartmentInfo.idl new file mode 100644 index 000000000000..1e07c8ad2956 --- /dev/null +++ b/toolkit/components/aboutcompartments/nsICompartmentInfo.idl @@ -0,0 +1,31 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 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 "nsISupports.idl" +#include "nsIArray.idl" + +[scriptable, uuid(13dd4c09-ff11-4943-8dc2-d96eb69c963b)] +interface nsICompartment : nsISupports { + /* name of compartment */ + readonly attribute AString compartmentName; + /* time spent executing code in this compartment in microseconds */ + readonly attribute unsigned long long time; + /* the id of the addon associated with this compartment, or null */ + readonly attribute AString addonId; + /* time spent processing CPOWs in microseconds */ + readonly attribute unsigned long long CPOWTime; +}; + +[scriptable, builtinclass, uuid(5795113a-39a1-4087-ba09-98b7d07d025a)] +interface nsICompartmentInfo : nsISupports { + nsIArray getCompartments(); +}; + +%{C++ +#define NS_COMPARTMENT_INFO_CID \ +{ 0x2d3c2f2d, 0x698d, 0x471d, \ +{ 0xba, 0x3e, 0x14, 0x44, 0xdd, 0x52, 0x1e, 0x29 } } +%} diff --git a/toolkit/components/aboutmemory/jar.mn b/toolkit/components/aboutmemory/jar.mn index 1f8ba994ebea..82af6a5333d0 100644 --- a/toolkit/components/aboutmemory/jar.mn +++ b/toolkit/components/aboutmemory/jar.mn @@ -3,7 +3,6 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. toolkit.jar: -+ content/global/aboutCompartments.xhtml (content/aboutCompartments.xhtml) + content/global/aboutMemory.js (content/aboutMemory.js) + content/global/aboutMemory.xhtml (content/aboutMemory.xhtml) + content/global/aboutMemory.css (content/aboutMemory.css) diff --git a/toolkit/components/addoncompat/RemoteAddonsChild.jsm b/toolkit/components/addoncompat/RemoteAddonsChild.jsm index 41b8a9914e18..3623244017e9 100644 --- a/toolkit/components/addoncompat/RemoteAddonsChild.jsm +++ b/toolkit/components/addoncompat/RemoteAddonsChild.jsm @@ -496,11 +496,21 @@ let RemoteAddonsChild = { _ready: false, makeReady: function() { - Prefetcher.init(); - NotificationTracker.init(); - ContentPolicyChild.init(); - AboutProtocolChild.init(); - ObserverChild.init(); + let shims = [ + Prefetcher, + NotificationTracker, + ContentPolicyChild, + AboutProtocolChild, + ObserverChild, + ]; + + for (let shim of shims) { + try { + shim.init(); + } catch(e) { + Cu.reportError(e); + } + } }, init: function(global) { @@ -520,7 +530,11 @@ let RemoteAddonsChild = { uninit: function(perTabShims) { for (let shim of perTabShims) { - shim.uninit(); + try { + shim.uninit(); + } catch(e) { + Cu.reportError(e); + } } }, }; diff --git a/toolkit/components/moz.build b/toolkit/components/moz.build index f5e3bdc3b36f..bdc5e51be384 100644 --- a/toolkit/components/moz.build +++ b/toolkit/components/moz.build @@ -10,6 +10,7 @@ if CONFIG['MOZ_ENABLE_XREMOTE']: DIRS += [ 'aboutcache', + 'aboutcompartments', 'aboutmemory', 'addoncompat', 'alerts', diff --git a/toolkit/devtools/gcli/commands/cmd.js b/toolkit/devtools/gcli/commands/cmd.js index da62694c7e11..dfa066ec7292 100644 --- a/toolkit/devtools/gcli/commands/cmd.js +++ b/toolkit/devtools/gcli/commands/cmd.js @@ -140,7 +140,7 @@ exports.items = [ let dirName = prefBranch.getComplexValue(PREF_DIR, Ci.nsISupportsString).data.trim(); - return gcli.lookupFormat("cmdStatus2", [ dirName ]); + return gcli.lookupFormat("cmdStatus3", [ dirName ]); } }, { diff --git a/toolkit/devtools/server/actors/webaudio.js b/toolkit/devtools/server/actors/webaudio.js index 6151a08c445b..c610176ba04b 100644 --- a/toolkit/devtools/server/actors/webaudio.js +++ b/toolkit/devtools/server/actors/webaudio.js @@ -45,18 +45,32 @@ const NODE_ROUTING_METHODS = [ const NODE_PROPERTIES = { "OscillatorNode": { "type": {}, - "frequency": {}, - "detune": {} + "frequency": { + "param": true + }, + "detune": { + "param": true + } }, "GainNode": { - "gain": {} + "gain": { + "param": true + } }, "DelayNode": { - "delayTime": {} + "delayTime": { + "param": true + } }, + // TODO deal with figuring out adding `detune` AudioParam + // for AudioBufferSourceNode, which is in the spec + // but not yet added in implementation + // bug 1116852 "AudioBufferSourceNode": { "buffer": { "Buffer": true }, - "playbackRate": {}, + "playbackRate": { + "param": true, + }, "loop": {}, "loopStart": {}, "loopEnd": {} @@ -79,19 +93,37 @@ const NODE_PROPERTIES = { "normalize": {}, }, "DynamicsCompressorNode": { - "threshold": {}, - "knee": {}, - "ratio": {}, + "threshold": { + "param": true + }, + "knee": { + "param": true + }, + "ratio": { + "param": true + }, "reduction": {}, - "attack": {}, - "release": {} + "attack": { + "param": true + }, + "release": { + "param": true + } }, "BiquadFilterNode": { "type": {}, - "frequency": {}, - "Q": {}, - "detune": {}, - "gain": {} + "frequency": { + "param": true + }, + "Q": { + "param": true + }, + "detune": { + "param": true + }, + "gain": { + "param": true + } }, "WaveShaperNode": { "curve": { "Float32Array": true }, @@ -401,14 +433,14 @@ let AudioNodeActor = exports.AudioNodeActor = protocol.ActorClass({ getAutomationData: method(function (paramName) { let timeline = this.automation[paramName]; - let events = timeline.events; - let values = []; - let i = 0; - if (!timeline) { return null; } + let events = timeline.events; + let values = []; + let i = 0; + if (!timeline.events.length) { return { events, values }; } @@ -421,9 +453,9 @@ let AudioNodeActor = exports.AudioNodeActor = protocol.ActorClass({ let scale = timeDelta / AUTOMATION_GRANULARITY; for (; i < AUTOMATION_GRANULARITY; i++) { - let t = firstEvent.time + (i * scale); - let value = timeline.getValueAtTime(t); - values.push({ t, value }); + let delta = firstEvent.time + (i * scale); + let value = timeline.getValueAtTime(delta); + values.push({ delta, value }); } // If the last event is setTargetAtTime, the automation @@ -432,9 +464,9 @@ let AudioNodeActor = exports.AudioNodeActor = protocol.ActorClass({ // until we're "close enough" to the target. if (lastEvent.type === "setTargetAtTime") { for (; i < AUTOMATION_GRANULARITY_MAX; i++) { - let t = firstEvent.time + (++i * scale); - let value = timeline.getValueAtTime(t); - values.push({ t, value }); + let delta = firstEvent.time + (++i * scale); + let value = timeline.getValueAtTime(delta); + values.push({ delta, value }); } } diff --git a/toolkit/devtools/server/protocol.js b/toolkit/devtools/server/protocol.js index 3b2079219fa2..7b0b3afd82e8 100644 --- a/toolkit/devtools/server/protocol.js +++ b/toolkit/devtools/server/protocol.js @@ -4,6 +4,8 @@ "use strict"; +let { Cu } = require("chrome"); +let DevToolsUtils = require("devtools/toolkit/DevToolsUtils"); let Services = require("Services"); let promise = require("devtools/toolkit/deprecated-sync-thenables"); let {Class} = require("sdk/core/heritage"); @@ -1148,7 +1150,7 @@ let Front = Class({ this.actor().then(actorID => { packet.to = actorID; this.conn._transport.send(packet); - }); + }).then(null, e => DevToolsUtils.reportException("Front.prototype.send", e)); } }, diff --git a/webapprt/test/chrome/browser_noperm.js b/webapprt/test/chrome/browser_noperm.js index 240cf1d81af7..de5310225bc5 100644 --- a/webapprt/test/chrome/browser_noperm.js +++ b/webapprt/test/chrome/browser_noperm.js @@ -18,12 +18,18 @@ function test() { let principal = document.getElementById("content").contentDocument.defaultView.document.nodePrincipal; is(DOMApplicationRegistry.getAppLocalIdByManifestURL(app.manifestURL), principal.appId, "Principal app ID correct"); + let alwaysAllowed = ["indexedDB"] + // Check if all the permissions of the app are unknown. for (let permName of AllPossiblePermissions) { // Get the value for the permission. let permValue = Services.perms.testExactPermissionFromPrincipal(principal, permName); - is(permValue, Ci.nsIPermissionManager.UNKNOWN_ACTION, "Permission " + permName + " unknown."); + if (alwaysAllowed.includes(permName)) { + is(permValue, Ci.nsIPermissionManager.ALLOW_ACTION, "Permission " + permName + " allowed."); + } else { + is(permValue, Ci.nsIPermissionManager.UNKNOWN_ACTION, "Permission " + permName + " unknown."); + } } finish(); diff --git a/xpcom/build/XPCOMInit.cpp b/xpcom/build/XPCOMInit.cpp index 60757e8fe6cc..46192551372f 100644 --- a/xpcom/build/XPCOMInit.cpp +++ b/xpcom/build/XPCOMInit.cpp @@ -50,6 +50,8 @@ #include "nsThreadManager.h" #include "nsThreadPool.h" +#include "nsCompartmentInfo.h" + #include "xptinfo.h" #include "nsIInterfaceInfoManager.h" #include "xptiprivate.h" @@ -234,6 +236,8 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsMemoryInfoDumper) NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsStatusReporterManager, Init) +NS_GENERIC_FACTORY_CONSTRUCTOR(nsCompartmentInfo) + NS_GENERIC_FACTORY_CONSTRUCTOR(nsIOUtil) NS_GENERIC_FACTORY_CONSTRUCTOR(nsSecurityConsoleMessage) diff --git a/xpcom/build/XPCOMModule.inc b/xpcom/build/XPCOMModule.inc index 6386bafc5954..3b330462fe2f 100644 --- a/xpcom/build/XPCOMModule.inc +++ b/xpcom/build/XPCOMModule.inc @@ -82,3 +82,4 @@ COMPONENT(CYCLE_COLLECTOR_LOGGER, nsCycleCollectorLoggerConstructor) COMPONENT(MESSAGE_LOOP, nsMessageLoopConstructor) COMPONENT(STATUS_REPORTER_MANAGER, nsStatusReporterManagerConstructor) + COMPONENT(COMPARTMENT_INFO, nsCompartmentInfoConstructor) \ No newline at end of file diff --git a/xpcom/build/nsXPCOMCID.h b/xpcom/build/nsXPCOMCID.h index 6b830c3f1bf6..9a82773a4e0f 100644 --- a/xpcom/build/nsXPCOMCID.h +++ b/xpcom/build/nsXPCOMCID.h @@ -90,6 +90,8 @@ */ #define NS_MESSAGE_LOOP_CONTRACTID "@mozilla.org/message-loop;1" +#define NS_COMPARTMENT_INFO_CONTRACTID "@mozilla.org/compartment-info;1" + /** * The following are the CIDs and Contract IDs of the nsISupports wrappers for * primative types.