Merge m-c to inbound, a=merge

This commit is contained in:
Wes Kocher 2015-07-28 18:03:34 -07:00
commit 73188edf67
87 changed files with 823 additions and 218 deletions

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="862f0895f3f5a97200601542d99a152a46385a0b"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="21256d7665f972255d198f8af81a8df4bd0e0fc4"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9f45c1988fe72749f0659409e6e3320fabf7b79a"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="862f0895f3f5a97200601542d99a152a46385a0b"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="21256d7665f972255d198f8af81a8df4bd0e0fc4"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9f45c1988fe72749f0659409e6e3320fabf7b79a"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

View File

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="862f0895f3f5a97200601542d99a152a46385a0b"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="21256d7665f972255d198f8af81a8df4bd0e0fc4"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9f45c1988fe72749f0659409e6e3320fabf7b79a"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="8bc59310552179f9a8bc6cdd0188e2475df52fb7"/>

View File

@ -17,7 +17,7 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="862f0895f3f5a97200601542d99a152a46385a0b"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="21256d7665f972255d198f8af81a8df4bd0e0fc4"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9f45c1988fe72749f0659409e6e3320fabf7b79a"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="657894b4a1dc0a926117f4812e0940229f9f676f"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="5bb657ada461be666c35f419dbe072ed2ce632fc"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="862f0895f3f5a97200601542d99a152a46385a0b"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="21256d7665f972255d198f8af81a8df4bd0e0fc4"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9f45c1988fe72749f0659409e6e3320fabf7b79a"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="07c383a786f188904311a37f6062c2cb84c9b61d">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="862f0895f3f5a97200601542d99a152a46385a0b"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="21256d7665f972255d198f8af81a8df4bd0e0fc4"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9f45c1988fe72749f0659409e6e3320fabf7b79a"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

View File

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="862f0895f3f5a97200601542d99a152a46385a0b"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="21256d7665f972255d198f8af81a8df4bd0e0fc4"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9f45c1988fe72749f0659409e6e3320fabf7b79a"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="8bc59310552179f9a8bc6cdd0188e2475df52fb7"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="862f0895f3f5a97200601542d99a152a46385a0b"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="21256d7665f972255d198f8af81a8df4bd0e0fc4"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9f45c1988fe72749f0659409e6e3320fabf7b79a"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

View File

@ -1,9 +1,9 @@
{
"git": {
"git_revision": "862f0895f3f5a97200601542d99a152a46385a0b",
"git_revision": "21256d7665f972255d198f8af81a8df4bd0e0fc4",
"remote": "https://git.mozilla.org/releases/gaia.git",
"branch": ""
},
"revision": "b176b86e412fb3143fa31ced79faa5238d540f93",
"revision": "5ec7add1a5ed54e7c57e9fd24704624a9e84139a",
"repo_path": "integration/gaia-central"
}

View File

@ -17,7 +17,7 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="862f0895f3f5a97200601542d99a152a46385a0b"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="21256d7665f972255d198f8af81a8df4bd0e0fc4"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9f45c1988fe72749f0659409e6e3320fabf7b79a"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="657894b4a1dc0a926117f4812e0940229f9f676f"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="5bb657ada461be666c35f419dbe072ed2ce632fc"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="07c383a786f188904311a37f6062c2cb84c9b61d">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="862f0895f3f5a97200601542d99a152a46385a0b"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="21256d7665f972255d198f8af81a8df4bd0e0fc4"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9f45c1988fe72749f0659409e6e3320fabf7b79a"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

View File

@ -6696,6 +6696,10 @@ var gIdentityHandler = {
delete this._identityIconCountryLabel;
return this._identityIconCountryLabel = document.getElementById("identity-icon-country-label");
},
get _identityIcons () {
delete this._identityIcons;
return this._identityIcons = document.getElementById("identity-icons");
},
get _identityIcon () {
delete this._identityIcon;
return this._identityIcon = document.getElementById("page-proxy-favicon");
@ -6715,12 +6719,14 @@ var gIdentityHandler = {
*/
_cacheElements : function() {
delete this._identityBox;
delete this._identityIcons;
delete this._identityIconLabel;
delete this._identityIconCountryLabel;
delete this._identityIcon;
delete this._permissionsContainer;
delete this._permissionList;
this._identityBox = document.getElementById("identity-box");
this._identityIcons = document.getElementById("identity-icons");
this._identityIconLabel = document.getElementById("identity-icon-label");
this._identityIconCountryLabel = document.getElementById("identity-icon-country-label");
this._identityIcon = document.getElementById("page-proxy-favicon");
@ -7130,7 +7136,7 @@ var gIdentityHandler = {
this._identityBox.setAttribute("open", "true");
// Now open the popup, anchored off the primary chrome element
this._identityPopup.openPopup(this._identityIcon, "bottomcenter topleft");
this._identityPopup.openPopup(this._identityIcons, "bottomcenter topleft");
},
onPopupShown(event) {

View File

@ -763,11 +763,13 @@
onclick="gIdentityHandler.handleIdentityButtonEvent(event);"
onkeypress="gIdentityHandler.handleIdentityButtonEvent(event);"
ondragstart="gIdentityHandler.onDragStart(event);">
<image id="tracking-protection-icon"/>
<image id="page-proxy-favicon"
consumeanchor="identity-box"
onclick="PageProxyClickHandler(event);"
pageproxystate="invalid"/>
<hbox id="identity-icons"
consumeanchor="identity-box">
<image id="tracking-protection-icon"/>
<image id="page-proxy-favicon"
onclick="PageProxyClickHandler(event);"
pageproxystate="invalid"/>
</hbox>
<hbox id="identity-icon-labels">
<label id="identity-icon-label" class="plain" flex="1"/>
<label id="identity-icon-country-label" class="plain"/>

View File

@ -11,6 +11,9 @@ standalone/content/libs
standalone/node_modules
# Libs we don't need to check
test/shared/vendor
# Coverage files
test/coverage
test/node_modules
# These are generated react files that we don't need to check
content/js/contacts.js
content/js/conversation.js

View File

@ -1 +1,2 @@
.module-cache
test/coverage

View File

@ -56,6 +56,17 @@ You can also run it by hand in the browser/components/loop directory:
eslint --ext .js --ext .jsx --ext .jsm .
Test coverage
=============
Initial setup
cd test
npm install
To run
npm run build-coverage
It will create a `coverage` folder under test/
Front-End Unit Tests
====================
The unit tests for Loop reside in three directories:

View File

@ -7,6 +7,7 @@ if [ "$1" == "--help" ]; then
exit 0;
fi
# Causes script to abort immediately if error code is not checked.
set -e
# Main tests
@ -22,6 +23,16 @@ if [ -x "${LOOPDIR}/${ESLINT}" ]; then
echo 'eslint run finished.'
fi
# Build tests coverage.
MISSINGDEPSMSG="\nMake sure all dependencies are up to date by running
'npm install' inside the 'browser/components/loop/test/' directory.\n"
(
cd ${LOOPDIR}/test
if ! npm run-script build-coverage ; then
echo $MISSINGDEPSMSG && exit 1
fi
)
./mach xpcshell-test ${LOOPDIR}/
./mach marionette-test ${LOOPDIR}/manifest.ini

View File

@ -256,7 +256,8 @@ loop.standaloneRoomViews = (function(mozL10n) {
mixins: [
Backbone.Events,
sharedMixins.MediaSetupMixin,
sharedMixins.RoomsAudioMixin
sharedMixins.RoomsAudioMixin,
sharedMixins.DocumentTitleMixin
],
propTypes: {
@ -306,6 +307,14 @@ loop.standaloneRoomViews = (function(mozL10n) {
* @param {Object} nextState Next state object.
*/
componentWillUpdate: function(nextProps, nextState) {
if (this.state.roomState !== ROOM_STATES.READY &&
nextState.roomState === ROOM_STATES.READY) {
this.setTitle(mozL10n.get("standalone_title_with_room_name", {
roomName: nextState.roomName || this.state.roomName,
clientShortname: mozL10n.get("clientShortname2")
}));
}
if (this.state.roomState !== ROOM_STATES.MEDIA_WAIT &&
nextState.roomState === ROOM_STATES.MEDIA_WAIT) {
this.props.dispatcher.dispatch(new sharedActions.SetupStreamElements({

View File

@ -256,7 +256,8 @@ loop.standaloneRoomViews = (function(mozL10n) {
mixins: [
Backbone.Events,
sharedMixins.MediaSetupMixin,
sharedMixins.RoomsAudioMixin
sharedMixins.RoomsAudioMixin,
sharedMixins.DocumentTitleMixin
],
propTypes: {
@ -306,6 +307,14 @@ loop.standaloneRoomViews = (function(mozL10n) {
* @param {Object} nextState Next state object.
*/
componentWillUpdate: function(nextProps, nextState) {
if (this.state.roomState !== ROOM_STATES.READY &&
nextState.roomState === ROOM_STATES.READY) {
this.setTitle(mozL10n.get("standalone_title_with_room_name", {
roomName: nextState.roomName || this.state.roomName,
clientShortname: mozL10n.get("clientShortname2")
}));
}
if (this.state.roomState !== ROOM_STATES.MEDIA_WAIT &&
nextState.roomState === ROOM_STATES.MEDIA_WAIT) {
this.props.dispatcher.dispatch(new sharedActions.SetupStreamElements({

View File

@ -115,6 +115,10 @@ room_information_failure_unsupported_browser=Your browser cannot access any info
## replaced by the brand name and {{currentStatus}} will be replaced
## by the current call status (Connecting, Ringing, etc.)
standalone_title_with_status={{clientShortname}} — {{currentStatus}}
## LOCALIZATION_NOTE(standalone_title_with_room_name): {{roomName}} will be replaced
## by the name of the conversation and {{clientShortname}} will be
## replaced by the brand name.
standalone_title_with_room_name={{roomName}} — {{clientShortname}}
status_in_conversation=In conversation
status_conversation_ended=Conversation ended
status_error=Something went wrong

View File

@ -78,6 +78,7 @@ describe("loop.conversation", function() {
});
describe("#init", function() {
var OTRestore;
beforeEach(function() {
sandbox.stub(React, "render");
sandbox.stub(document.mozL10n, "initialize");
@ -93,13 +94,14 @@ describe("loop.conversation", function() {
pathname: "/"
});
OTRestore = window.OT;
window.OT = {
overrideGuidStorage: sinon.stub()
};
});
afterEach(function() {
delete window.OT;
window.OT = OTRestore;
});
it("should initialize L10n", function() {

View File

@ -0,0 +1,67 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
/* eslint-env node */
module.exports = function(config) {
"use strict";
return {
// Base path that will be used to resolve all patterns (eg. files, exclude).
basePath: "../../",
// List of files / patterns to load in the browser.
files: [],
// List of files to exclude.
exclude: [
],
// Frameworks to use.
// Available frameworks: https://npmjs.org/browse/keyword/karma-adapter .
frameworks: ["mocha"],
// Test results reporter to use.
// Possible values: "dots", "progress".
// Available reporters: https://npmjs.org/browse/keyword/karma-reporter .
reporters: ["progress", "coverage"],
coverageReporter: {
type: "html",
dir: "test/coverage/"
},
// Web server port.
port: 9876,
// Enable / disable colors in the output (reporters and logs).
colors: true,
// Level of logging.
// Possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG.
logLevel: config.LOG_INFO,
// Enable / disable watching file and executing tests whenever any file changes.
autoWatch: false,
// Start these browsers
// Available browser launchers: https://npmjs.org/browse/keyword/karma-launcher .
browsers: ["Firefox"],
// Continuous Integration mode.
// If true, Karma captures browsers, runs the tests and exits.
singleRun: true,
// Capture console output.
client: {
captureConsole: true
},
plugins: [
"karma-coverage",
"karma-mocha",
"karma-firefox-launcher"
]
};
};

View File

@ -0,0 +1,61 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
/* eslint-env node */
module.exports = function(config) {
"use strict";
var baseConfig = require("./karma.conf.base.js")(config);
// List of files / patterns to load in the browser.
baseConfig.files = baseConfig.files.concat([
"content/libs/l10n.js",
"content/shared/libs/react-0.12.2.js",
"content/shared/libs/jquery-2.1.4.js",
"content/shared/libs/lodash-3.9.3.js",
"content/shared/libs/backbone-1.2.1.js",
"test/shared/vendor/*.js",
"test/karma/stubs.js", // Stub out DOM event listener due to races.
"content/shared/js/utils.js",
"content/shared/js/models.js",
"content/shared/js/mixins.js",
"content/shared/js/websocket.js",
"content/shared/js/actions.js",
"content/shared/js/otSdkDriver.js",
"content/shared/js/validate.js",
"content/shared/js/dispatcher.js",
"content/shared/js/store.js",
"content/shared/js/conversationStore.js",
"content/shared/js/roomStates.js",
"content/shared/js/fxOSActiveRoomStore.js",
"content/shared/js/activeRoomStore.js",
"content/shared/js/views.js",
"content/shared/js/textChatStore.js",
"content/shared/js/textChatView.js",
"content/js/feedbackViews.js",
"content/js/client.js",
"content/js/conversationAppStore.js",
"content/js/roomStore.js",
"content/js/roomViews.js",
"content/js/conversationViews.js",
"content/js/conversation.js",
"test/desktop-local/*.js"
]);
// List of files to exclude.
baseConfig.exclude = baseConfig.exclude.concat([
"test/desktop-local/panel_test.js",
"test/desktop-local/contacts_test.js"
]);
// Preprocess matching files before serving them to the browser.
// Available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor .
baseConfig.preprocessors = {
"content/js/*.js": ["coverage"]
};
baseConfig.coverageReporter.dir = "test/coverage/desktop";
config.set(baseConfig);
};

View File

@ -0,0 +1,59 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
/* eslint-env node */
module.exports = function(config) {
"use strict";
var baseConfig = require("./karma.conf.base.js")(config);
// List of files / patterns to load in the browser.
baseConfig.files = baseConfig.files.concat([
"standalone/content/libs/l10n-gaia-02ca67948fe8.js",
"content/shared/libs/jquery-2.1.4.js",
"content/shared/libs/lodash-3.9.3.js",
"content/shared/libs/backbone-1.2.1.js",
"content/shared/libs/react-0.12.2.js",
"content/shared/libs/sdk.js",
"test/shared/vendor/*.js",
"content/shared/js/utils.js",
"content/shared/js/store.js",
"content/shared/js/models.js",
"content/shared/js/mixins.js",
"content/shared/js/crypto.js",
"content/shared/js/websocket.js",
"content/shared/js/validate.js",
"content/shared/js/actions.js",
"content/shared/js/dispatcher.js",
"content/shared/js/otSdkDriver.js",
"content/shared/js/roomStates.js",
"content/shared/js/fxOSActiveRoomStore.js",
"content/shared/js/activeRoomStore.js",
"content/shared/js/conversationStore.js",
"content/shared/js/views.js",
"content/shared/js/textChatStore.js",
"content/shared/js/textChatView.js",
"standalone/content/js/multiplexGum.js",
"standalone/content/js/standaloneAppStore.js",
"standalone/content/js/standaloneClient.js",
"standalone/content/js/standaloneMozLoop.js",
"standalone/content/js/fxOSMarketplace.js",
"standalone/content/js/standaloneRoomViews.js",
"standalone/content/js/standaloneMetricsStore.js",
"standalone/content/js/webapp.js",
"test/shared/*.js",
"test/standalone/*.js"
]);
// Preprocess matching files before serving them to the browser.
// Available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor .
baseConfig.preprocessors = {
"content/shared/js/*.js": ["coverage"],
"standalone/content/js/*.js": ["coverage"]
};
baseConfig.coverageReporter.dir = "test/coverage/shared_standalone";
config.set(baseConfig);
};

View File

@ -0,0 +1,8 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
// Used for desktop coverage tests because triggering methods on
// DOMContentLoaded proved to lead to race conditions.
sinon.stub(document, "addEventListener");
console.log("[stubs.js] addEventListener stubbed to prevent race conditions");

View File

@ -0,0 +1,21 @@
{
"name": "FirefoxHello",
"version": "0.0.1",
"description": "Firefox Hello test coverage",
"main": "index.js",
"directories": {
"test": "test"
},
"devDependencies": {
"istanbul": "^0.3.17",
"karma": "^0.12.37",
"karma-coverage": "^0.4.2",
"karma-firefox-launcher": "^0.1.6",
"karma-mocha": "^0.2.0"
},
"scripts": {
"build-coverage-shared": "./node_modules/.bin/karma start karma/karma.coverage.shared_standalone.js",
"build-coverage-desktop": "./node_modules/.bin/karma start karma/karma.coverage.desktop.js",
"build-coverage": "npm run build-coverage-desktop && npm run build-coverage-shared"
}
}

View File

@ -11,8 +11,8 @@ describe("loop.store.ActiveRoomStore", function () {
var FAILURE_DETAILS = loop.shared.utils.FAILURE_DETAILS;
var SCREEN_SHARE_STATES = loop.shared.utils.SCREEN_SHARE_STATES;
var ROOM_INFO_FAILURES = loop.shared.utils.ROOM_INFO_FAILURES;
var sandbox, dispatcher, store, fakeMozLoop, fakeSdkDriver;
var fakeMultiplexGum;
var sandbox, dispatcher, store, fakeMozLoop, fakeSdkDriver, fakeMultiplexGum;
var standaloneMediaRestore;
beforeEach(function() {
sandbox = sinon.sandbox.create();
@ -52,9 +52,10 @@ describe("loop.store.ActiveRoomStore", function () {
};
fakeMultiplexGum = {
reset: sandbox.spy()
reset: sandbox.spy()
};
standaloneMediaRestore = loop.standaloneMedia;
loop.standaloneMedia = {
multiplexGum: fakeMultiplexGum
};
@ -67,6 +68,7 @@ describe("loop.store.ActiveRoomStore", function () {
afterEach(function() {
sandbox.restore();
loop.standaloneMedia = standaloneMediaRestore;
});
describe("#constructor", function() {

View File

@ -431,7 +431,8 @@ describe("loop.shared.mixins", function() {
doNotDisturb: true,
getAudioBlob: sinon.spy(function(name, callback) {
callback(null, new Blob([new ArrayBuffer(10)], {type: "audio/ogg"}));
})
}),
getLoopPref: sandbox.stub()
};
fakeAudio = {

View File

@ -17,6 +17,13 @@ describe("Validator", function() {
function Y(){}
describe("#validate", function() {
function mozRTCSessionDescription() {}
var mozRTC;
beforeEach(function() {
mozRTC = new mozRTCSessionDescription();
});
it("should check for a single required dependency when no option passed",
function() {
expect(create({x: Number}, {}))
@ -67,7 +74,7 @@ describe("Validator", function() {
});
it("should check for a native constructor dependency", function() {
expect(create({foo: mozRTCSessionDescription}, {foo: "x"}))
expect(create({foo: mozRTC}, {foo: "x"}))
.to.Throw(TypeError,
/invalid dependency: foo; expected mozRTCSessionDescription/);
});

View File

@ -16,6 +16,7 @@ describe("loop.standaloneRoomViews", function() {
var sharedUtils = loop.shared.utils;
var sandbox, dispatcher, activeRoomStore, dispatch;
var fakeWindow;
beforeEach(function() {
sandbox = sinon.sandbox.create();
@ -34,12 +35,30 @@ describe("loop.standaloneRoomViews", function() {
});
sandbox.useFakeTimers();
fakeWindow = {
close: sandbox.stub(),
addEventListener: function() {},
document: { addEventListener: function(){} },
setTimeout: function(callback) { callback(); }
};
loop.shared.mixins.setRootObject(fakeWindow);
sandbox.stub(navigator.mozL10n, "get", function(key, args) {
switch(key) {
case "standalone_title_with_room_name":
return args.roomName + " — " + args.clientShortname;
default:
return key;
}
});
// Prevents audio request errors in the test console.
sandbox.useFakeXMLHttpRequest();
});
afterEach(function() {
loop.shared.mixins.setRootObject(window);
sandbox.restore();
});
@ -83,6 +102,14 @@ describe("loop.standaloneRoomViews", function() {
}
describe("#componentWillUpdate", function() {
it("should set document.title to roomName and brand name when the READY state is dispatched", function() {
activeRoomStore.setStoreState({roomName: "fakeName", roomState: ROOM_STATES.INIT});
var view = mountTestComponent();
activeRoomStore.setStoreState({roomState: ROOM_STATES.READY});
expect(fakeWindow.document.title).to.equal("fakeName — clientShortname2");
});
it("should dispatch a `SetupStreamElements` action when the MEDIA_WAIT state " +
"is entered", function() {
activeRoomStore.setStoreState({roomState: ROOM_STATES.READY});

View File

@ -47,11 +47,22 @@ describe("loop.webapp", function() {
});
describe("#init", function() {
var loopConfigRestore;
beforeEach(function() {
sandbox.stub(React, "render");
loopConfigRestore = loop.config;
loop.config = {
feedbackApiUrl: "http://fake.invalid",
serverUrl: "http://fake.invalid"
};
sandbox.stub(loop.Dispatcher.prototype, "dispatch");
});
afterEach(function() {
loop.config = loopConfigRestore;
});
it("should create the WebappRootView", function() {
loop.webapp.init();

View File

@ -9,7 +9,7 @@ const { Cc, Ci, Cu, Cr } = require("chrome");
const promise = Cu.import("resource://gre/modules/Promise.jsm", {}).Promise;
const EventEmitter = require("devtools/toolkit/event-emitter");
const { CanvasFront } = require("devtools/server/actors/canvas");
const { DevToolsUtils } = Cu.import("resource://gre/modules/devtools/DevToolsUtils.jsm", {});
const DevToolsUtils = require("devtools/toolkit/DevToolsUtils");
function CanvasDebuggerPanel(iframeWindow, toolbox) {
this.panelWin = iframeWindow;

View File

@ -102,8 +102,10 @@ Cu.import("resource:///modules/devtools/SideMenuWidget.jsm");
Cu.import("resource:///modules/devtools/VariablesView.jsm");
Cu.import("resource:///modules/devtools/VariablesViewController.jsm");
Cu.import("resource:///modules/devtools/ViewHelpers.jsm");
const { devtools } = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
const require = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools.require;
const require = devtools.require;
const DevToolsUtils = require("devtools/toolkit/DevToolsUtils");
const promise = require("devtools/toolkit/deprecated-sync-thenables");
const Editor = require("devtools/sourceeditor/editor");
const DebuggerEditor = require("devtools/sourceeditor/debugger.js");
@ -116,12 +118,6 @@ XPCOMUtils.defineLazyModuleGetter(this, "Task",
XPCOMUtils.defineLazyModuleGetter(this, "Parser",
"resource:///modules/devtools/Parser.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "devtools",
"resource://gre/modules/devtools/Loader.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "DevToolsUtils",
"resource://gre/modules/devtools/DevToolsUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "ShortcutUtils",
"resource://gre/modules/ShortcutUtils.jsm");

View File

@ -8,7 +8,7 @@
const { Cc, Ci, Cu, Cr } = require("chrome");
const { Promise: promise } = Cu.import("resource://gre/modules/Promise.jsm", {});
const EventEmitter = require("devtools/toolkit/event-emitter");
const { DevToolsUtils } = Cu.import("resource://gre/modules/devtools/DevToolsUtils.jsm", {});
const DevToolsUtils = require("devtools/toolkit/DevToolsUtils");
function DebuggerPanel(iframeWindow, toolbox) {
this.panelWin = iframeWindow;

View File

@ -10,7 +10,6 @@ const JS_URL = EXAMPLE_URL + "code_math_bogus_map.js";
// This test causes an error to be logged in the console, which appears in TBPL
// logs, so we are disabling that here.
let { DevToolsUtils } = Cu.import("resource://gre/modules/devtools/DevToolsUtils.jsm", {});
DevToolsUtils.reportingDisabled = true;
let gPanel, gDebugger, gFrames, gSources, gPrefs;

View File

@ -17,7 +17,7 @@ let { Promise: promise } = Cu.import("resource://gre/modules/devtools/deprecated
let { gDevTools } = Cu.import("resource:///modules/devtools/gDevTools.jsm", {});
let { devtools } = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
let { require } = devtools;
let { DevToolsUtils } = Cu.import("resource://gre/modules/devtools/DevToolsUtils.jsm", {});
let DevToolsUtils = require("devtools/toolkit/DevToolsUtils");
let { BrowserToolboxProcess } = Cu.import("resource:///modules/devtools/ToolboxProcess.jsm", {});
let { DebuggerServer } = Cu.import("resource://gre/modules/devtools/dbg-server.jsm", {});
let { DebuggerClient, ObjectClient } =

View File

@ -1756,6 +1756,14 @@ Toolbox.prototype = {
yield this.highlighterUtils.stopPicker();
yield this._inspector.destroy();
if (this._highlighter) {
// Note that if the toolbox is closed, this will work fine, but will fail
// in case the browser is closed and will trigger a noSuchActor message.
// We ignore the promise that |_hideBoxModel| returns, since we should still
// proceed with the rest of destruction if it fails.
// FF42+ now does the cleanup from the actor.
if (!this.highlighter.traits.autoHideOnDestroy) {
this.highlighterUtils.unhighlight();
}
yield this._highlighter.destroy();
}
if (this._selection) {

View File

@ -548,10 +548,11 @@ HTMLBreadcrumbs.prototype = {
let deferred = promise.defer();
let fallback = null;
let lastNode = null;
let moreChildren = () => {
this.walker.children(node, {
start: fallback,
start: lastNode,
maxNodes: 10,
whatToShow: Ci.nsIDOMNodeFilter.SHOW_ELEMENT
}).then(this.selectionGuard()).then(response => {
@ -563,6 +564,7 @@ HTMLBreadcrumbs.prototype = {
if (!fallback) {
fallback = node;
}
lastNode = node;
}
if (response.hasLast) {
deferred.resolve(fallback);

View File

@ -13,6 +13,7 @@ const NODES = [
{selector: "#i21", result: "i2 i21 i211 i2111"},
{selector: "#i22211", result: "i2 i22 i222 i2221 i22211"},
{selector: "#i22", result: "i2 i22 i222 i2221 i22211"},
{selector: "#i3", result: "i3 i31"},
];
add_task(function*() {

View File

@ -42,6 +42,27 @@
</div>
</div>
</article>
<article id="i3">
<link id="i31" />
<link />
<link />
<link />
<link />
<link />
<link />
<link />
<link />
<link />
<link />
<link />
<link />
<link />
<link />
<link />
<link />
<link />
<link />
</article>
<div id='pseudo-container'></div>
</body>
</html>

View File

@ -1466,11 +1466,6 @@ MarkupView.prototype = {
this._destroyer = promise.resolve();
// Note that if the toolbox is closed, this will work fine, but will fail
// in case the browser is closed and will trigger a noSuchActor message.
// We ignore the promise that |_hideBoxModel| returns, since we should still
// proceed with the rest of destruction if it fails.
this._hideBoxModel();
this._clearBriefBoxModelTimer();
this._elt.removeEventListener("click", this._onMouseClick, false);

View File

@ -8,7 +8,7 @@
const { Cc, Ci, Cu, Cr } = require("chrome");
const { Promise: promise } = Cu.import("resource://gre/modules/Promise.jsm", {});
const EventEmitter = require("devtools/toolkit/event-emitter");
const { DevToolsUtils } = Cu.import("resource://gre/modules/devtools/DevToolsUtils.jsm", {});
const DevToolsUtils = require("devtools/toolkit/DevToolsUtils");
function NetMonitorPanel(iframeWindow, toolbox) {
this.panelWin = iframeWindow;

View File

@ -10,7 +10,7 @@ let { Task } = Cu.import("resource://gre/modules/Task.jsm", {});
let { Promise } = Cu.import("resource://gre/modules/Promise.jsm", {});
let { devtools } = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
let { gDevTools } = Cu.import("resource:///modules/devtools/gDevTools.jsm", {});
let { DevToolsUtils } = Cu.import("resource://gre/modules/devtools/DevToolsUtils.jsm", {});
const DevToolsUtils = devtools.require("devtools/toolkit/DevToolsUtils");
let { DebuggerServer } = Cu.import("resource://gre/modules/devtools/dbg-server.jsm", {});
let { console } = devtools.require("resource://gre/modules/devtools/Console.jsm");
let { merge } = devtools.require("sdk/util/object");

View File

@ -50,6 +50,7 @@ const Editor = require("devtools/sourceeditor/editor");
const TargetFactory = require("devtools/framework/target").TargetFactory;
const EventEmitter = require("devtools/toolkit/event-emitter");
const {DevToolsWorker} = require("devtools/toolkit/shared/worker");
const DevToolsUtils = require("devtools/toolkit/DevToolsUtils");
const { Promise: promise } = Cu.import("resource://gre/modules/Promise.jsm", {});
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
@ -61,7 +62,6 @@ Cu.import("resource:///modules/devtools/gDevTools.jsm");
Cu.import("resource://gre/modules/osfile.jsm");
Cu.import("resource:///modules/devtools/ViewHelpers.jsm");
Cu.import("resource://gre/modules/reflect.jsm");
Cu.import("resource://gre/modules/devtools/DevToolsUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "VariablesView",
"resource:///modules/devtools/VariablesView.jsm");

View File

@ -9,9 +9,10 @@ const {FileUtils} = Cu.import("resource://gre/modules/FileUtils.jsm", {});
const {Promise: promise} = Cu.import("resource://gre/modules/Promise.jsm", {});
const {console} = Cu.import("resource://gre/modules/devtools/Console.jsm", {});
const {require} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools;
const {DevToolsUtils} = Cu.import("resource://gre/modules/devtools/DevToolsUtils.jsm", {});
const DevToolsUtils = require("devtools/toolkit/DevToolsUtils");
const {Services} = Cu.import("resource://gre/modules/Services.jsm", {});
let gScratchpadWindow; // Reference to the Scratchpad chrome window object
DevToolsUtils.testing = true;

View File

@ -9,7 +9,7 @@ const { Cc, Ci, Cu, Cr } = require("chrome");
const promise = Cu.import("resource://gre/modules/Promise.jsm", {}).Promise;
const EventEmitter = require("devtools/toolkit/event-emitter");
const { WebGLFront } = require("devtools/server/actors/webgl");
const { DevToolsUtils } = Cu.import("resource://gre/modules/devtools/DevToolsUtils.jsm", {});
const DevToolsUtils = require("devtools/toolkit/DevToolsUtils");
function ShaderEditorPanel(iframeWindow, toolbox) {
this.panelWin = iframeWindow;

View File

@ -9,7 +9,8 @@ const Ci = Components.interfaces;
const Cu = Components.utils;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
const { DevToolsUtils } = Cu.import("resource://gre/modules/devtools/DevToolsUtils.jsm", {});
const { devtools } = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
const DevToolsUtils = devtools.require("devtools/toolkit/DevToolsUtils");
XPCOMUtils.defineLazyModuleGetter(this,
"Reflect", "resource://gre/modules/reflect.jsm");

View File

@ -8,7 +8,7 @@
this.EXPORTED_SYMBOLS = ["SplitView"];
/* this must be kept in sync with CSS (ie. splitview.css) */
const LANDSCAPE_MEDIA_QUERY = "(min-width: 551px)";
const LANDSCAPE_MEDIA_QUERY = "(min-width: 701px)";
let bindings = new WeakMap();

View File

@ -43,12 +43,8 @@ box,
display: -moz-box;
}
.splitview-landscape-resizer {
cursor: ew-resize;
}
/* this is to keep in sync with SplitView.jsm's LANDSCAPE_MEDIA_QUERY */
@media (min-width: 551px) {
@media (min-width: 701px) {
.splitview-root {
-moz-box-orient: horizontal;
}
@ -79,20 +75,8 @@ ol.splitview-nav > li.splitview-filtered {
display: -moz-box;
}
.splitview-portrait-resizer {
display: none;
}
/* portrait mode */
@media (max-width: 550px) {
.splitview-landscape-splitter {
display: none;
}
.splitview-portrait-resizer {
display: -moz-box;
}
@media (max-width: 700px) {
.splitview-controller {
max-width: none;
}

View File

@ -21,13 +21,11 @@ Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource:///modules/devtools/ViewHelpers.jsm");
Cu.import("resource://gre/modules/devtools/event-emitter.js");
Cu.import("resource://gre/modules/devtools/DevToolsUtils.jsm");
const { devtools } = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
const DevToolsUtils = devtools.require("devtools/toolkit/DevToolsUtils");
Cu.import("resource://gre/modules/Task.jsm");
let {Promise: promise} = Cu.import("resource://gre/modules/Promise.jsm", {});
XPCOMUtils.defineLazyModuleGetter(this, "devtools",
"resource://gre/modules/devtools/Loader.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "PluralForm",
"resource://gre/modules/PluralForm.jsm");

View File

@ -16,7 +16,8 @@ const WIDGET_FOCUSABLE_NODES = new Set(["vbox", "hbox"]);
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Timer.jsm");
Cu.import("resource://gre/modules/devtools/DevToolsUtils.jsm");
const { devtools } = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
const DevToolsUtils = devtools.require("devtools/toolkit/DevToolsUtils");
Cu.import("resource://gre/modules/devtools/event-emitter.js");
this.EXPORTED_SYMBOLS = [

View File

@ -91,7 +91,7 @@
<xul:stack id="style-editor-chrome" class="loading theme-body">
<xul:box class="splitview-root" context="sidebar-context">
<xul:box class="splitview-root devtools-responsive-container" context="sidebar-context">
<xul:box class="splitview-controller">
<xul:box class="splitview-main">
<xul:toolbar class="devtools-toolbar">
@ -125,7 +125,7 @@
</div>
</xul:box> <!-- .splitview-nav-container -->
</xul:box> <!-- .splitview-controller -->
<xul:splitter class="devtools-side-splitter splitview-landscape-splitter devtools-invisible-splitter"/>
<xul:splitter class="devtools-side-splitter devtools-invisible-splitter"/>
<xul:box class="splitview-side-details devtools-main-content"/>
<div id="splitview-templates" hidden="true">
@ -148,9 +148,6 @@
</li>
<xul:box id="splitview-tpl-details-stylesheet" class="splitview-details">
<xul:resizer class="splitview-portrait-resizer"
dir="bottom"
element="splitview-resizer-target"/>
<xul:hbox class="stylesheet-details-container">
<xul:box class="stylesheet-editor-input textbox"
data-placeholder="&editorTextbox.placeholder;"/>

View File

@ -14,7 +14,7 @@ label,
#runtime-panel-projects {
display: block;
float: left;
width: auto;
width: 100%;
text-align: left;
}

View File

@ -65,7 +65,7 @@
}
.identity-popup-section:not(:first-child) {
border-top: 1px solid rgb(229,229,229);
border-top: 1px solid ThreeDShadow;
}
#identity-popup-securityView,
@ -126,7 +126,7 @@
.identity-popup-expander > .button-box {
padding: 0;
-moz-appearance: none;
border: solid #e5e5e5;
border: solid ThreeDShadow;
border-width: 0 0 0 1px;
}
@ -209,7 +209,7 @@
}
#identity-popup-securityView-header {
border-bottom: 1px solid #e5e5e5;
border-bottom: 1px solid ThreeDShadow;
padding-bottom: 1em;
margin-bottom: 1em;
}
@ -219,7 +219,7 @@
}
#identity-popup-content-verifier {
color: #636363;
color: Graytext;
}
#identity-popup-content-owner,
@ -277,7 +277,7 @@
#identity-popup-more-info-button {
border: none;
border-top: 1px solid hsla(210,4%,10%,.14);
border-top: 1px solid ThreeDShadow;
background: transparent;
-moz-appearance: none;
margin-top: 5px;

View File

@ -140,20 +140,3 @@
min-width: 48px;
min-height: 0;
}
/* Resizers */
.splitview-portrait-resizer {
-moz-appearance: none;
background: linear-gradient(black 1px, rgba(255,255,255,0.2) 1px),
linear-gradient(hsl(210,11%,36%), hsl(210,11%,18%));
height: 12px;
background-size: 10px 2px, 100% 12px;
background-clip: content-box, border-box;
background-repeat: repeat-y, no-repeat;
background-position: center center;
padding: 2px 0;
border-top: 1px solid hsla(210,8%,5%,.5);
border-bottom: 1px solid hsla(210,8%,5%,.5);
}

View File

@ -111,6 +111,10 @@
transition: none;
}
#urlbar[pageproxystate="invalid"] > #identity-box > #identity-icons > #tracking-protection-icon {
visibility: collapse;
}
/* MAIN IDENTITY ICON */
#page-proxy-favicon {
@ -119,26 +123,26 @@
list-style-image: url(chrome://browser/skin/identity-not-secure.svg);
}
.chromeUI > #page-proxy-favicon[pageproxystate="valid"] {
.chromeUI > #identity-icons > #page-proxy-favicon[pageproxystate="valid"] {
list-style-image: url(chrome://branding/content/identity-icons-brand.svg);
}
.verifiedDomain > #page-proxy-favicon[pageproxystate="valid"],
.verifiedIdentity > #page-proxy-favicon[pageproxystate="valid"] {
.verifiedDomain > #identity-icons > #page-proxy-favicon[pageproxystate="valid"],
.verifiedIdentity > #identity-icons > #page-proxy-favicon[pageproxystate="valid"] {
list-style-image: url(chrome://browser/skin/identity-secure.svg);
}
.mixedActiveContent > #page-proxy-favicon[pageproxystate="valid"] {
.mixedActiveContent > #identity-icons > #page-proxy-favicon[pageproxystate="valid"] {
list-style-image: url(chrome://browser/skin/identity-mixed-active-loaded.svg);
}
.weakCipher > #page-proxy-favicon[pageproxystate="valid"],
.mixedDisplayContent > #page-proxy-favicon[pageproxystate="valid"],
.mixedDisplayContentLoadedActiveBlocked > #page-proxy-favicon[pageproxystate="valid"] {
.weakCipher > #identity-icons > #page-proxy-favicon[pageproxystate="valid"],
.mixedDisplayContent > #identity-icons > #page-proxy-favicon[pageproxystate="valid"],
.mixedDisplayContentLoadedActiveBlocked > #identity-icons > #page-proxy-favicon[pageproxystate="valid"] {
list-style-image: url(chrome://browser/skin/identity-mixed-passive-loaded.svg);
}
.mixedActiveBlocked > #page-proxy-favicon[pageproxystate="valid"] {
.mixedActiveBlocked > #identity-icons > #page-proxy-favicon[pageproxystate="valid"] {
list-style-image: url(chrome://browser/skin/identity-mixed-active-blocked.svg);
}
@ -146,7 +150,7 @@
opacity: 0.3;
}
#urlbar[actiontype="searchengine"] > #identity-box > #page-proxy-favicon {
#urlbar[actiontype="searchengine"] > #identity-box > #identity-icons > #page-proxy-favicon {
-moz-image-region: inherit;
list-style-image: url(chrome://global/skin/icons/autocomplete-search.svg#search-icon);
width: 16px;

View File

@ -1221,6 +1221,7 @@ toolbarbutton[constrain-size="true"][cui-areatype="toolbar"] > .toolbarbutton-ba
#urlbar,
.searchbar-textbox {
@navbarTextboxCustomBorder@
border-radius: 1px;
}
@media (-moz-os-version: windows-vista),

View File

@ -309,6 +309,12 @@
</intent-filter>
</receiver>
<receiver android:name="org.mozilla.gecko.RestrictionProvider">
<intent-filter>
<action android:name="android.intent.action.GET_RESTRICTION_ENTRIES" />
</intent-filter>
</receiver>
<!-- Activity used for launching non-privileged WebApps via a URL -->
<activity android:name="org.mozilla.gecko.Webapp"
android:label="@string/webapp_generic_name"

View File

@ -473,6 +473,9 @@ public class BrowserApp extends GeckoApp
case LOCATION_CHANGE:
// fall through
case SELECTED:
if (mZoomedView != null) {
mZoomedView.stopZoomDisplay(false);
}
if (Tabs.getInstance().isSelectedTab(tab)) {
updateHomePagerForTab(tab);
}

View File

@ -65,30 +65,55 @@ public class RestrictedProfiles {
* These constants should be in sync with the ones from toolkit/components/parentalcontrols/nsIParentalControlServices.idl
*/
public enum Restriction {
DISALLOW_DOWNLOADS(1, "no_download_files"),
DISALLOW_INSTALL_EXTENSION(2, "no_install_extensions"),
DISALLOW_INSTALL_APPS(3, "no_install_apps"), // UserManager.DISALLOW_INSTALL_APPS
DISALLOW_BROWSE_FILES(4, "no_browse_files"),
DISALLOW_SHARE(5, "no_share"),
DISALLOW_BOOKMARK(6, "no_bookmark"),
DISALLOW_ADD_CONTACTS(7, "no_add_contacts"),
DISALLOW_SET_IMAGE(8, "no_set_image"),
DISALLOW_MODIFY_ACCOUNTS(9, "no_modify_accounts"), // UserManager.DISALLOW_MODIFY_ACCOUNTS
DISALLOW_REMOTE_DEBUGGING(10, "no_remote_debugging"),
DISALLOW_IMPORT_SETTINGS(11, "no_import_settings"),
DISALLOW_TOOLS_MENU(12, "no_tools_menu"),
DISALLOW_REPORT_SITE_ISSUE(13, "no_report_site_issue");
// These restrictions have no strings assigned because they are only used in guest mode and not shown in the
// restricted profiles settings UI
DISALLOW_DOWNLOADS(1, "no_download_files", 0, 0),
DISALLOW_BROWSE_FILES(4, "no_browse_files", 0, 0),
DISALLOW_SHARE(5, "no_share", 0, 0),
DISALLOW_BOOKMARK(6, "no_bookmark", 0, 0),
DISALLOW_ADD_CONTACTS(7, "no_add_contacts", 0, 0),
DISALLOW_SET_IMAGE(8, "no_set_image", 0, 0),
DISALLOW_MODIFY_ACCOUNTS(9, "no_modify_accounts", 0, 0), // UserManager.DISALLOW_MODIFY_ACCOUNTS
DISALLOW_REMOTE_DEBUGGING(10, "no_remote_debugging", 0, 0),
// These restrictions are used for restricted profiles and therefore need to have strings assigned for the profile
// settings UI.
DISALLOW_INSTALL_EXTENSION(2, "no_install_extensions", R.string.restriction_disallow_addons_title, R.string.restriction_disallow_addons_description),
DISALLOW_INSTALL_APPS(3, "no_install_apps", R.string.restriction_disallow_apps_title, R.string.restriction_disallow_apps_description), // UserManager.DISALLOW_INSTALL_APPS
DISALLOW_IMPORT_SETTINGS(11, "no_report_site_issue", R.string.restriction_disallow_import_settings_title, R.string.restriction_disallow_import_settings_description),
DISALLOW_TOOLS_MENU(12, "no_tools_menu", R.string.restriction_disallow_tools_menu_title, R.string.restriction_disallow_tools_menu_description),
DISALLOW_REPORT_SITE_ISSUE(13, "no_report_site_issue", R.string.restriction_disallow_report_site_issue_title, R.string.restriction_disallow_report_site_issue_description);
public final int id;
public final String name;
public final int titleResource;
public final int descriptionResource;
Restriction(final int id, final String name) {
Restriction(final int id, final String name, int titleResource, int descriptionResource) {
this.id = id;
this.name = name;
this.titleResource = titleResource;
this.descriptionResource = descriptionResource;
}
public String getTitle(Context context) {
if (titleResource == 0) {
return toString();
}
return context.getResources().getString(titleResource);
}
public String getDescription(Context context) {
if (descriptionResource == 0) {
return name;
}
return context.getResources().getString(descriptionResource);
}
}
private static List<Restriction> restrictionsOfGuestProfile = Arrays.asList(
static List<Restriction> GUEST_RESTRICTIONS = Arrays.asList(
Restriction.DISALLOW_DOWNLOADS,
Restriction.DISALLOW_INSTALL_EXTENSION,
Restriction.DISALLOW_INSTALL_APPS,
@ -103,7 +128,9 @@ public class RestrictedProfiles {
);
// Restricted profiles will automatically have these restrictions by default
private static List<Restriction> defaultRestrictionsOfRestrictedProfiles = Arrays.asList(
static List<Restriction> RESTRICTED_PROFILE_RESTRICTIONS = Arrays.asList(
Restriction.DISALLOW_INSTALL_EXTENSION,
Restriction.DISALLOW_INSTALL_APPS,
Restriction.DISALLOW_TOOLS_MENU,
Restriction.DISALLOW_REPORT_SITE_ISSUE,
Restriction.DISALLOW_IMPORT_SETTINGS
@ -125,6 +152,12 @@ public class RestrictedProfiles {
return mgr.getUserRestrictions();
}
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
private static Bundle getAppRestrictions(final Context context) {
final UserManager mgr = (UserManager) context.getSystemService(Context.USER_SERVICE);
return mgr.getApplicationRestrictions(context.getPackageName());
}
/**
* This method does the system version check for you.
*
@ -134,14 +167,18 @@ public class RestrictedProfiles {
*
* Returns true otherwise.
*/
private static boolean getRestriction(final Context context, final String name) {
private static boolean getRestriction(final Context context, final Restriction restriction) {
// Early versions don't support restrictions at all,
// so no action can be restricted.
if (Versions.preJBMR2) {
return false;
}
return getRestrictions(context).getBoolean(name, false);
if (!isUserRestricted(context)) {
return false;
}
return getAppRestrictions(context).getBoolean(restriction.name, RESTRICTED_PROFILE_RESTRICTIONS.contains(restriction));
}
private static boolean canLoadUrl(final Context context, final String url) {
@ -153,7 +190,7 @@ public class RestrictedProfiles {
try {
// If we're not in guest mode, and the system restriction isn't in place, everything is allowed.
if (!getInGuest() &&
!getRestriction(context, Restriction.DISALLOW_BROWSE_FILES.name)) {
!getRestriction(context, Restriction.DISALLOW_BROWSE_FILES)) {
return true;
}
} catch (IllegalArgumentException ex) {
@ -231,16 +268,11 @@ public class RestrictedProfiles {
return canLoadUrl(context, url);
}
return !restrictionsOfGuestProfile.contains(restriction);
}
// Hardcoded restrictions. Make restrictions configurable and read from UserManager (Bug 1180653)
if (isUserRestricted(context) && defaultRestrictionsOfRestrictedProfiles.contains(restriction)) {
return false;
return !GUEST_RESTRICTIONS.contains(restriction);
}
// NOTE: Restrictions hold the opposite intention, so we need to flip it.
return !getRestriction(context, restriction.name);
return !getRestriction(context, restriction);
}
@WrapElementForJNI

View File

@ -0,0 +1,69 @@
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
* 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/. */
package org.mozilla.gecko;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.RestrictionEntry;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import java.util.ArrayList;
/**
* Broadcast receiver providing supported restrictions to the system.
*/
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
public class RestrictionProvider extends BroadcastReceiver {
@Override
public void onReceive(final Context context, final Intent intent) {
if (AppConstants.Versions.preJBMR2) {
// This broadcast does not make any sense prior to Jelly Bean MR2.
return;
}
final PendingResult result = goAsync();
new Thread() {
@Override
public void run() {
final Bundle oldRestrictions = intent.getBundleExtra(Intent.EXTRA_RESTRICTIONS_BUNDLE);
final Bundle extras = new Bundle();
ArrayList<RestrictionEntry> entries = initRestrictions(context, oldRestrictions);
extras.putParcelableArrayList(Intent.EXTRA_RESTRICTIONS_LIST, entries);
result.setResult(Activity.RESULT_OK, null, extras);
result.finish();
}
}.start();
}
private ArrayList<RestrictionEntry> initRestrictions(Context context, Bundle oldRestrictions) {
ArrayList<RestrictionEntry> entries = new ArrayList<RestrictionEntry>();
for (RestrictedProfiles.Restriction restriction : RestrictedProfiles.RESTRICTED_PROFILE_RESTRICTIONS) {
RestrictionEntry entry = createRestrictionEntryWithDefaultValue(context, restriction,
oldRestrictions.getBoolean(restriction.name, true));
entries.add(entry);
}
return entries;
}
private RestrictionEntry createRestrictionEntryWithDefaultValue(Context context, RestrictedProfiles.Restriction restriction, boolean defaultValue) {
RestrictionEntry entry = new RestrictionEntry(restriction.name, defaultValue);
entry.setTitle(restriction.getTitle(context));
entry.setDescription(restriction.getDescription(context));
return entry;
}
}

View File

@ -501,7 +501,7 @@ public class ZoomedView extends FrameLayout implements LayerView.OnMetricsChange
moveUsingGeckoPosition(leftFromGecko, topFromGecko);
}
private void stopZoomDisplay(boolean withAnimation) {
public void stopZoomDisplay(boolean withAnimation) {
if (getVisibility() == View.VISIBLE) {
shouldSetVisibleOnUpdate = false;
hideZoomedView(withAnimation);

View File

@ -678,3 +678,18 @@ just addresses the organization to follow, e.g. "This site is run by " -->
desktop Firefox via WebIDE), so you just need to aim this device at the QR
code. -->
<!ENTITY devtools_auth_scan_header "Scanning for the QR code displayed on your other device">
<!-- Restrictions -->
<!-- Localization note: These are restrictions the device owner (e.g. parent) can enable for
a restricted profile (e.g. child). Used inside the Android settings UI. -->
<!ENTITY restriction_disallow_tools_menu_title "Disallow Tools menu">
<!ENTITY restriction_disallow_tools_menu_description "Hide Tools menu from UI.">
<!ENTITY restriction_disallow_report_site_issue_title "Disallow \'Report site issue\'">
<!ENTITY restriction_disallow_report_site_issue_description "Hide \'Report site issue\' menu item.">
<!ENTITY restriction_disallow_import_settings_title "Disallow importing settings">
<!ENTITY restriction_disallow_import_settings_description "Do not allow to import settings from other system browsers.">
<!ENTITY restriction_disallow_addons_title "Disallow add-ons">
<!ENTITY restriction_disallow_addons_description "Disallow installation of add-ons.">
<!ENTITY restriction_disallow_apps_title "Disallow apps">
<!ENTITY restriction_disallow_apps_description "Disallow installing apps from Firefox Marketplace.">

View File

@ -433,6 +433,7 @@ gbjar.sources += [
'RemoteTabsExpandableListAdapter.java',
'Restarter.java',
'RestrictedProfiles.java',
'RestrictionProvider.java',
'ServiceNotificationClient.java',
'SessionParser.java',
'SharedPreferencesHelper.java',

View File

@ -541,6 +541,18 @@
<!-- Voice search from the Awesome Bar -->
<string name="voicesearch_prompt">&voicesearch_prompt;</string>
<!-- Restrictions -->
<string name="restriction_disallow_tools_menu_title">&restriction_disallow_tools_menu_title;</string>
<string name="restriction_disallow_tools_menu_description">&restriction_disallow_tools_menu_description;</string>
<string name="restriction_disallow_report_site_issue_title">&restriction_disallow_report_site_issue_title;</string>
<string name="restriction_disallow_report_site_issue_description">&restriction_disallow_report_site_issue_description;</string>
<string name="restriction_disallow_import_settings_title">&restriction_disallow_import_settings_title;</string>
<string name="restriction_disallow_import_settings_description">&restriction_disallow_import_settings_description;</string>
<string name="restriction_disallow_addons_title">&restriction_disallow_addons_title;</string>
<string name="restriction_disallow_addons_description">&restriction_disallow_addons_description;</string>
<string name="restriction_disallow_apps_title">&restriction_disallow_apps_title;</string>
<string name="restriction_disallow_apps_description">&restriction_disallow_apps_description;</string>
<!-- Miscellaneous -->
<string name="ellipsis">&ellipsis;</string>

View File

@ -31,14 +31,20 @@ class GaiaBuildUnitTest(GaiaTest):
output_parser = TestSummaryOutputParserHelper(
config=self.config, log_obj=self.log_obj, error_list=self.error_list)
code = self.run_command([
cmd = [
'make',
'build-test-unit',
'REPORTER=mocha-tbpl-reporter',
'NODE_MODULES_SRC=npm-cache',
'VIRTUALENV_EXISTS=1',
'TRY_ENV=1'
], cwd=dirs['abs_gaia_dir'],
]
# for Mulet
if 'firefox' in self.binary_path:
cmd += ['RUNTIME=%s' % self.binary_path]
code = self.run_command(cmd, cwd=dirs['abs_gaia_dir'],
output_parser=output_parser,
output_timeout=330)

View File

@ -118,6 +118,17 @@ class GaiaIntegrationTest(GaiaTest):
overwrite='clobber'
)
cmd = [
'make',
'lint',
'NODE_MODULES_SRC=npm-cache',
'VIRTUALENV_EXISTS=1'
]
# for Mulet
if 'firefox' in self.binary_path:
cmd += ['RUNTIME=%s' % self.binary_path]
self.make_node_modules()
output_parser = GaiaLinterOutputParser(
@ -125,12 +136,7 @@ class GaiaIntegrationTest(GaiaTest):
config=self.config,
log_obj=self.log_obj)
code = self.run_command([
'make',
'lint',
'NODE_MODULES_SRC=npm-cache',
'VIRTUALENV_EXISTS=1'
], cwd=dirs['abs_gaia_dir'],
code = self.run_command(cmd, cwd=dirs['abs_gaia_dir'],
output_parser=output_parser,
output_timeout=600)

View File

@ -106,6 +106,8 @@ tests:
allowed_build_tasks:
tasks/builds/b2g_desktop_opt.yml:
task: tasks/tests/b2g_build_unit.yml
tasks/builds/mulet_linux.yml:
task: tasks/tests/mulet_build_unit.yml
gaia-js-integration:
allowed_build_tasks:
tasks/builds/b2g_desktop_opt.yml:
@ -116,6 +118,8 @@ tests:
allowed_build_tasks:
tasks/builds/b2g_desktop_opt.yml:
task: tasks/tests/b2g_linter.yml
tasks/builds/mulet_linux.yml:
task: tasks/tests/mulet_linter.yml
gaia-ui-test-accessibility:
allowed_build_tasks:
tasks/builds/b2g_desktop_opt.yml:

View File

@ -209,6 +209,8 @@ tests:
allowed_build_tasks:
tasks/builds/b2g_desktop_opt.yml:
task: tasks/tests/b2g_build_unit.yml
tasks/builds/mulet_linux.yml:
task: tasks/tests/mulet_build_unit.yml
gaia-js-integration:
allowed_build_tasks:
tasks/builds/b2g_desktop_opt.yml:
@ -219,6 +221,8 @@ tests:
allowed_build_tasks:
tasks/builds/b2g_desktop_opt.yml:
task: tasks/tests/b2g_linter.yml
tasks/builds/mulet_linux.yml:
task: tasks/tests/mulet_linter.yml
gaia-ui-test-accessibility:
allowed_build_tasks:
tasks/builds/b2g_desktop_opt.yml:

View File

@ -0,0 +1,39 @@
---
$inherits:
from: 'tasks/test.yml'
task:
metadata:
name: '[TC] - Gaia Build Unit Test'
description: Gaia Build Unit Test
payload:
command:
- entrypoint
- ./bin/pull_gaia.sh &&
- >
python ./mozharness/scripts/gaia_build_unit.py
--application firefox
--no-read-buildbot-config
--config-file ./mozharness/configs/b2g/gaia_integration_config.py
--config-file ./mozharness_configs/gaia_integration_override.py
--config-file ./mozharness_configs/remove_executables.py
--no-pull
--download-symbols ondemand
--installer-url {{build_url}}
--test-packages-url {{test_packages_url}}
--gaia-repo https://hg.mozilla.org/integration/gaia-central
--gaia-dir /home/worker
artifacts:
'public/build':
type: directory
path: '/home/worker/artifacts/'
expires: '{{#from_now}}1 year{{/from_now}}'
extra:
treeherderEnv:
- production
- staging
treeherder:
groupSymbol: "?"
symbol: 'Gbu'
productName: b2g

View File

@ -0,0 +1,38 @@
---
$inherits:
from: 'tasks/test.yml'
task:
metadata:
name: '[TC] - Gaia Linter'
description: Linter Test
payload:
command:
- entrypoint
- ./bin/pull_gaia.sh &&
- >
python ./mozharness/scripts/gaia_linter.py
--application firefox
--no-read-buildbot-config
--config-file ./mozharness/configs/b2g/gaia_integration_config.py
--config-file ./mozharness_configs/gaia_integration_override.py
--download-symbols ondemand
--no-pull
--installer-url {{build_url}}
--test-packages-url {{test_packages_url}}
--gaia-repo https://hg.mozilla.org/integration/gaia-central
--gaia-dir /home/worker
artifacts:
'public/build':
type: directory
path: '/home/worker/artifacts/'
expires: '{{#from_now}}1 year{{/from_now}}'
extra:
treeherderEnv:
- production
- staging
treeherder:
groupSymbol: "?"
symbol: 'Li'
productName: 'b2g'

View File

@ -419,6 +419,10 @@ XPCOMUtils.defineLazyGetter(this, "Prefs", () => {
store.suggestTyped = prefs.get(...PREF_SUGGEST_HISTORY_ONLYTYPED);
store.suggestSearches = prefs.get(...PREF_SUGGEST_SEARCHES);
store.maxCharsForSearchSuggestions = prefs.get(...PREF_MAX_CHARS_FOR_SUGGEST);
store.keywordEnabled = true;
try {
store.keywordEnabled = Services.prefs.getBoolPref("keyword.enabled");
} catch (ex) {}
// If history is not set, onlyTyped value should be ignored.
if (!store.suggestHistory) {
@ -473,7 +477,9 @@ XPCOMUtils.defineLazyGetter(this, "Prefs", () => {
loadPrefs(subject, topic, data);
this._ignoreNotifications = false;
},
QueryInterface: XPCOMUtils.generateQI([ Ci.nsIObserver ])
QueryInterface: XPCOMUtils.generateQI([
Ci.nsIObserver,
Ci.nsISupportsWeakReference ])
};
// Synchronize suggest.* prefs with autocomplete.enabled at initialization
@ -481,6 +487,7 @@ XPCOMUtils.defineLazyGetter(this, "Prefs", () => {
loadPrefs();
prefs.observe("", store);
Services.prefs.addObserver("keyword.enabled", store, true);
return Object.seal(store);
});
@ -1174,7 +1181,9 @@ Search.prototype = {
// If the result is something that looks like a single-worded hostname
// we need to check the domain whitelist to treat it as such.
// We also want to return a "visit" if keyword.enabled is false.
if (uri.asciiHost &&
Prefs.keywordEnabled &&
REGEXP_SINGLEWORD_HOST.test(uri.asciiHost) &&
!Services.uriFixup.isDomainWhitelisted(uri.asciiHost, -1)) {
return false;

View File

@ -61,4 +61,16 @@ add_task(function*() {
searchParam: "enable-actions",
matches: [ makeVisitMatch("[2001:db8::1]", "http://[2001:db8::1]/") ]
});
// Setting keyword.enabled to false should always try to visit.
Services.prefs.setBoolPref("keyword.enabled", false);
do_register_cleanup(() => {
Services.prefs.clearUserPref("keyword.enabled");
});
do_print("visit url, keyword.enabled = false");
yield check_autocomplete({
search: "bacon",
searchParam: "enable-actions",
matches: [ makeVisitMatch("bacon", "http://bacon/") ]
});
});

View File

@ -593,9 +593,20 @@ let Impl = {
* false otherwise.
*/
enableTelemetryRecording: function enableTelemetryRecording() {
const enabled = Preferences.get(PREF_ENABLED, false);
// The thumbnail service also runs in a content process, even with e10s off.
// We need to check if e10s is on so we don't submit child payloads for it.
// We still need xpcshell child tests to work, so we skip this if test mode is enabled.
if (Utils.isContentProcess && !this._testMode && !Services.appinfo.browserTabsRemoteAutostart) {
this._log.config("enableTelemetryRecording - not enabling Telemetry for non-e10s child process");
Telemetry.canRecordBase = false;
Telemetry.canRecordExtended = false;
return false;
}
// Enable base Telemetry recording, if needed.
// Configure base Telemetry recording.
// Unified Telemetry makes it opt-out unless the unifedOptin pref is set.
// If extended Telemetry is enabled, base recording is always on as well.
const enabled = Preferences.get(PREF_ENABLED, false);
Telemetry.canRecordBase = enabled || (IS_UNIFIED_TELEMETRY && !IS_UNIFIED_OPTIN);
#ifdef MOZILLA_OFFICIAL

View File

@ -27,13 +27,6 @@ const Utils = TelemetryUtils;
const myScope = this;
const IS_CONTENT_PROCESS = (function() {
// We cannot use Services.appinfo here because in telemetry xpcshell tests,
// appinfo is initially unavailable, and becomes available only later on.
let runtime = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime);
return runtime.processType == Ci.nsIXULRuntime.PROCESS_TYPE_CONTENT;
})();
// When modifying the payload in incompatible ways, please bump this version number
const PAYLOAD_VERSION = 4;
const PING_TYPE_MAIN = "main";
@ -58,7 +51,7 @@ const MIN_SUBSESSION_LENGTH_MS = 10 * 60 * 1000;
#expand const HISTOGRAMS_FILE_VERSION = "__HISTOGRAMS_FILE_VERSION__";
const LOGGER_NAME = "Toolkit.Telemetry";
const LOGGER_PREFIX = "TelemetrySession" + (IS_CONTENT_PROCESS ? "#content::" : "::");
const LOGGER_PREFIX = "TelemetrySession" + (Utils.isContentProcess ? "#content::" : "::");
const PREF_BRANCH = "toolkit.telemetry.";
const PREF_PREVIOUS_BUILDID = PREF_BRANCH + "previousBuildID";
@ -538,32 +531,20 @@ let TelemetryScheduler = {
}
this._lastTickTime = now;
// Check if aborted-session ping is due.
let isAbortedPingDue =
(now - this._lastSessionCheckpointTime) >= ABORTED_SESSION_UPDATE_INTERVAL_MS;
// Check if daily ping is due.
let shouldSendDaily = this._isDailyPingDue(nowDate);
// We can combine the daily-ping and the aborted-session ping in the following cases:
// - If both the daily and the aborted session pings are due (a laptop that wakes
// up after a few hours).
// - If either the daily ping is due and the other one would follow up shortly
// (whithin the coalescence threshold).
let nextSessionCheckpoint =
this._lastSessionCheckpointTime + ABORTED_SESSION_UPDATE_INTERVAL_MS;
let combineActions = (shouldSendDaily && isAbortedPingDue) || (shouldSendDaily &&
Utils.areTimesClose(now, nextSessionCheckpoint,
SCHEDULER_COALESCE_THRESHOLD_MS));
// Check if the daily ping is due.
const shouldSendDaily = this._isDailyPingDue(nowDate);
if (combineActions) {
this._log.trace("_schedulerTickLogic - Combining pings.");
// Send the daily ping and also save its payload as an aborted-session ping.
return Impl._sendDailyPing(true).then(() => this._dailyPingSucceeded(now),
() => this._dailyPingFailed(now));
} else if (shouldSendDaily) {
if (shouldSendDaily) {
this._log.trace("_schedulerTickLogic - Daily ping due.");
return Impl._sendDailyPing().then(() => this._dailyPingSucceeded(now),
() => this._dailyPingFailed(now));
} else if (isAbortedPingDue) {
}
// Check if the aborted-session ping is due. If a daily ping was saved above, it was
// already duplicated as an aborted-session ping.
const isAbortedPingDue =
(now - this._lastSessionCheckpointTime) >= ABORTED_SESSION_UPDATE_INTERVAL_MS;
if (isAbortedPingDue) {
this._log.trace("_schedulerTickLogic - Aborted session ping due.");
return this._saveAbortedPing(now);
}
@ -746,6 +727,12 @@ this.TelemetrySession = Object.freeze({
setup: function() {
return Impl.setupChromeProcess(true);
},
/**
* Used only for testing purposes.
*/
setupContent: function() {
return Impl.setupContentProcess(true);
},
/**
* Used only for testing purposes.
*/
@ -853,7 +840,7 @@ let Impl = {
} catch (ex) {}
// Only submit this if the extended set is enabled.
if (!IS_CONTENT_PROCESS && Telemetry.canRecordExtended) {
if (!Utils.isContentProcess && Telemetry.canRecordExtended) {
try {
ret.addonManager = AddonManagerPrivate.getSimpleMeasures();
ret.UITelemetry = UITelemetry.getSimpleMeasures();
@ -882,7 +869,7 @@ let Impl = {
ret.maximalNumberOfConcurrentThreads = maximalNumberOfConcurrentThreads;
}
if (IS_CONTENT_PROCESS) {
if (Utils.isContentProcess) {
return ret;
}
@ -1306,7 +1293,7 @@ let Impl = {
payloadObj.log = TelemetryLog.entries();
}
if (IS_CONTENT_PROCESS) {
if (Utils.isContentProcess) {
return payloadObj;
}
@ -1364,10 +1351,10 @@ let Impl = {
let measurements =
this.getSimpleMeasurements(reason == REASON_SAVED_SESSION, isSubsession, clearSubsession);
let info = !IS_CONTENT_PROCESS ? this.getMetadata(reason) : null;
let info = !Utils.isContentProcess ? this.getMetadata(reason) : null;
let payload = this.assemblePayloadWithMeasurements(measurements, info, reason, clearSubsession);
if (!IS_CONTENT_PROCESS && clearSubsession) {
if (!Utils.isContentProcess && clearSubsession) {
this.startNewSubsession();
// Persist session data to disk (don't wait until it completes).
let sessionData = this._getSessionDataObject();
@ -1528,10 +1515,11 @@ let Impl = {
/**
* Initializes telemetry for a content process.
*/
setupContentProcess: function setupContentProcess() {
setupContentProcess: function setupContentProcess(testing) {
this._log.trace("setupContentProcess");
if (!Telemetry.canRecordBase) {
this._log.trace("setupContentProcess - base recording is disabled, not initializing");
return;
}
@ -1545,7 +1533,7 @@ let Impl = {
this.attachObservers();
this.gatherMemory();
}.bind(this), TELEMETRY_DELAY);
}.bind(this), testing ? TELEMETRY_TEST_DELAY : TELEMETRY_DELAY);
delayedTask.arm();
},
@ -1871,11 +1859,9 @@ let Impl = {
/**
* Gather and send a daily ping.
* @param {Boolean} [saveAsAborted=false] Also saves the payload as an aborted-session
* ping.
* @return {Promise} Resolved when the ping is sent.
*/
_sendDailyPing: function(saveAsAborted = false) {
_sendDailyPing: function() {
this._log.trace("_sendDailyPing");
let payload = this.getSessionPayload(REASON_DAILY, true);
@ -1885,11 +1871,14 @@ let Impl = {
};
let promise = TelemetryController.submitExternalPing(getPingType(payload), payload, options);
// If required, also save the payload as an aborted session.
if (saveAsAborted && IS_UNIFIED_TELEMETRY) {
// Also save the payload as an aborted session. If we delay this, aborted-session can
// lag behind for the profileSubsessionCounter and other state, complicating analysis.
if (IS_UNIFIED_TELEMETRY) {
let abortedPromise = this._saveAbortedSessionPing(payload);
promise = promise.then(() => abortedPromise);
}
return promise;
},

View File

@ -12,7 +12,21 @@ const {classes: Cc, interfaces: Ci, results: Cr, utils: Cu} = Components;
const MILLISECONDS_PER_DAY = 24 * 60 * 60 * 1000;
const IS_CONTENT_PROCESS = (function() {
// We cannot use Services.appinfo here because in telemetry xpcshell tests,
// appinfo is initially unavailable, and becomes available only later on.
let runtime = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime);
return runtime.processType == Ci.nsIXULRuntime.PROCESS_TYPE_CONTENT;
})();
this.TelemetryUtils = {
/**
* True if this is a content process.
*/
get isContentProcess() {
return IS_CONTENT_PROCESS;
},
/**
* Turn a millisecond timestamp into a day timestamp.
*

View File

@ -21,4 +21,5 @@ Client-side, this consists of:
main-ping
deletion-ping
crash-ping
uitour-ping
preferences

View File

@ -3,9 +3,15 @@ Preferences
Telemetry behaviour is controlled through the preferences listed here.
*Note:* On official builds (which define ``MOZILLA_OFFICIAL``), Telemetry is only initialized when ``MOZ_TELEMETRY_REPORTING`` is defined.
Default behaviors
-----------------
On official builds (which define ``MOZILLA_OFFICIAL``), Telemetry is only initialized when ``MOZ_TELEMETRY_REPORTING`` is defined.
Sending only happens on official builds with ``MOZ_TELEMETRY_REPORTING`` defined.
Preferences
-----------
``toolkit.telemetry.unified``
This controls whether unified behavior is enabled. If true:
@ -24,6 +30,10 @@ Sending only happens on official builds with ``MOZ_TELEMETRY_REPORTING`` defined
If ``unified`` is on, this controls whether to record *extended* data.
This preference is controlled through the `Preferences` dialog.
Note that the default value here of this pref depends on the define ``RELEASE_BUILD`` and the channel.
If ``RELEASE_BUILD`` is set, ``MOZ_TELEMETRY_ON_BY_DEFAULT`` gets set, which means this pref will default to ``true``.
This is overridden by the preferences code on the "beta" channel, the pref also defaults to ``true`` there.
``datareporting.healthreport.uploadEnabled``
Send the data we record if user has consented to FHR. This preference is controlled through the `Preferences` dialog.

View File

@ -6,6 +6,8 @@ Cu.import("resource://gre/modules/PromiseUtils.jsm", this);
const Telemetry = Cc["@mozilla.org/base/telemetry;1"].getService(Ci.nsITelemetry);
const MESSAGE_TELEMETRY_PAYLOAD = "Telemetry:Payload";
const MESSAGE_TELEMETRY_GET_CHILD_PAYLOAD = "Telemetry:GetChildPayload";
const MESSAGE_CHILD_TEST_DONE = "ChildTest:Done";
const PLATFORM_VERSION = "1.9.2";
const APP_VERSION = "1";
@ -58,7 +60,12 @@ function check_histogram_values(payload) {
add_task(function*() {
if (!runningInParent) {
TelemetryController.setupContent();
TelemetrySession.setupContent();
run_child_test();
dump("... done with child test\n");
do_send_remote_message(MESSAGE_CHILD_TEST_DONE);
dump("... waiting for child payload collection\n");
yield do_await_remote_message(MESSAGE_TELEMETRY_GET_CHILD_PAYLOAD);
return;
}
@ -69,13 +76,16 @@ add_task(function*() {
yield TelemetryController.setup();
yield TelemetrySession.setup();
// Run test in child and wait until it is finished.
yield run_test_in_child("test_ChildHistograms.js");
// Run test in child, don't wait for it to finish.
let childPromise = run_test_in_child("test_ChildHistograms.js");
yield do_await_remote_message(MESSAGE_CHILD_TEST_DONE);
// Gather payload from child.
dump("... requesting child payloads\n");
let promiseMessage = do_await_remote_message(MESSAGE_TELEMETRY_PAYLOAD);
TelemetrySession.requestChildPayloads();
yield promiseMessage;
dump("... received child payload\n");
// Check child payload.
const payload = TelemetrySession.getPayload("test-ping");

View File

@ -1,18 +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/. */
"use strict";
/*
* General utilities used throughout devtools.
*
* When using chrome debugging, the debugger server is unable to debug itself.
* To avoid this, it must be loaded with a custom devtools loader with the
* invisibleToDebugger flag set to true. Everyone else, though, prefers a JSM.
*/
this.EXPORTED_SYMBOLS = [ "DevToolsUtils" ];
const { devtools } = Components.utils.import("resource://gre/modules/devtools/Loader.jsm", {});
this.DevToolsUtils = devtools.require("devtools/toolkit/DevToolsUtils.js");

View File

@ -152,7 +152,7 @@ SrcdirProvider.prototype = {
let contentObserverURI = this.fileURI(OS.Path.join(toolkitDir), "content-observer.js");
let gcliURI = this.fileURI(OS.Path.join(toolkitDir, "gcli", "source", "lib", "gcli"));
let projecteditorURI = this.fileURI(OS.Path.join(devtoolsDir, "projecteditor"));
let promiseURI = this.fileURI(OS.Path.join(modulesDir, "promise-backend.js"));
let promiseURI = this.fileURI(OS.Path.join(modulesDir, "Promise-backend.js"));
let acornURI = this.fileURI(OS.Path.join(toolkitDir, "acorn"));
let acornWalkURI = OS.Path.join(acornURI, "walk.js");
let ternURI = OS.Path.join(toolkitDir, "tern");
@ -439,7 +439,9 @@ DevToolsLoader.prototype = {
this._provider.unload("reload");
delete this._provider;
delete this._mainid;
this._chooseProvider();
this.main("main");
},
/**

View File

@ -50,7 +50,7 @@ Object.defineProperty(this, "WebConsoleClient", {
enumerable: true
});
Components.utils.import("resource://gre/modules/devtools/DevToolsUtils.jsm");
const DevToolsUtils = devtools.require("devtools/toolkit/DevToolsUtils");
this.executeSoon = DevToolsUtils.executeSoon;
this.makeInfallible = DevToolsUtils.makeInfallible;
this.values = DevToolsUtils.values;

View File

@ -42,7 +42,6 @@ EXTRA_JS_MODULES.devtools += [
EXTRA_JS_MODULES.devtools += [
'Console.jsm',
'DevToolsUtils.jsm',
'LayoutHelpers.jsm',
'Loader.jsm',
'Require.jsm',

View File

@ -158,6 +158,15 @@ let HighlighterActor = exports.HighlighterActor = protocol.ActorClass({
return this._inspector && this._inspector.conn;
},
form: function() {
return {
actor: this.actorID,
traits: {
autoHideOnDestroy: true
}
}
},
_createHighlighter: function() {
this._isPreviousWindowXUL = isXUL(this._tabActor.window);
@ -199,6 +208,7 @@ let HighlighterActor = exports.HighlighterActor = protocol.ActorClass({
destroy: function() {
protocol.Actor.prototype.destroy.call(this);
this.hideBoxModel();
this._destroyHighlighter();
events.off(this._tabActor, "navigate", this._onNavigate);
@ -416,7 +426,14 @@ let HighlighterActor = exports.HighlighterActor = protocol.ActorClass({
})
});
let HighlighterFront = protocol.FrontClass(HighlighterActor, {});
let HighlighterFront = protocol.FrontClass(HighlighterActor, {
// Update the object given a form representation off the wire.
form: function(json) {
this.actorID = json.actor;
// FF42+ HighlighterActors starts exposing custom form, with traits object
this.traits = json.traits || {};
}
});
/**
* A generic highlighter actor class that instantiate a highlighter given its

View File

@ -5,7 +5,7 @@ const Cu = Components.utils;
const Cr = Components.results;
Cu.import("resource://gre/modules/devtools/Loader.jsm");
Cu.import("resource://gre/modules/devtools/DevToolsUtils.jsm");
const DevToolsUtils = devtools.require("devtools/toolkit/DevToolsUtils");
// Register a console listener, so console messages don't just disappear
// into the ether.

View File

@ -56,7 +56,7 @@
const {components, Cc, Ci, Cu} = require("chrome");
loader.lazyImporter(this, "NetUtil", "resource://gre/modules/NetUtil.jsm");
loader.lazyImporter(this, "DevToolsUtils", "resource://gre/modules/devtools/DevToolsUtils.jsm");
const DevToolsUtils = require("devtools/toolkit/DevToolsUtils");
// The cache used in the `nsIURL` function.
const gNSURLStore = new Map();

View File

@ -18,7 +18,7 @@ loader.lazyImporter(this, "LayoutHelpers", "resource://gre/modules/devtools/Layo
loader.lazyImporter(this, "gDevTools", "resource:///modules/devtools/gDevTools.jsm");
loader.lazyImporter(this, "devtools", "resource://gre/modules/devtools/Loader.jsm");
loader.lazyImporter(this, "VariablesView", "resource:///modules/devtools/VariablesView.jsm");
loader.lazyImporter(this, "DevToolsUtils", "resource://gre/modules/devtools/DevToolsUtils.jsm");
const DevToolsUtils = require("devtools/toolkit/DevToolsUtils");
// Match the function name from the result of toString() or toSource().
//