зеркало из https://github.com/mozilla/gecko-dev.git
Merge fx-team to central, a=merge
This commit is contained in:
Коммит
9fd2629734
|
@ -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) {
|
||||
|
|
|
@ -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"/>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
.module-cache
|
||||
test/coverage
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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({
|
||||
|
|
|
@ -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({
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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"
|
||||
]
|
||||
};
|
||||
};
|
|
@ -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);
|
||||
};
|
|
@ -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);
|
||||
};
|
|
@ -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");
|
|
@ -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"
|
||||
}
|
||||
}
|
|
@ -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() {
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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/);
|
||||
});
|
||||
|
|
|
@ -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});
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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");
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 } =
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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*() {
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
|
||||
|
|
|
@ -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 = [
|
||||
|
|
|
@ -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;"/>
|
||||
|
|
|
@ -14,7 +14,7 @@ label,
|
|||
#runtime-panel-projects {
|
||||
display: block;
|
||||
float: left;
|
||||
width: auto;
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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.">
|
||||
|
||||
|
|
|
@ -433,6 +433,7 @@ gbjar.sources += [
|
|||
'RemoteTabsExpandableListAdapter.java',
|
||||
'Restarter.java',
|
||||
'RestrictedProfiles.java',
|
||||
'RestrictionProvider.java',
|
||||
'ServiceNotificationClient.java',
|
||||
'SessionParser.java',
|
||||
'SharedPreferencesHelper.java',
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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/") ]
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
},
|
||||
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -21,4 +21,5 @@ Client-side, this consists of:
|
|||
main-ping
|
||||
deletion-ping
|
||||
crash-ping
|
||||
uitour-ping
|
||||
preferences
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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");
|
|
@ -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");
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -42,7 +42,6 @@ EXTRA_JS_MODULES.devtools += [
|
|||
|
||||
EXTRA_JS_MODULES.devtools += [
|
||||
'Console.jsm',
|
||||
'DevToolsUtils.jsm',
|
||||
'LayoutHelpers.jsm',
|
||||
'Loader.jsm',
|
||||
'Require.jsm',
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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().
|
||||
//
|
||||
|
|
Загрузка…
Ссылка в новой задаче