зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-c to graphics
MozReview-Commit-ID: HlYQkwnswIh --HG-- rename : gfx/layers/ipc/CompositorVsyncScheduler.h => gfx/layers/ipc/CompositorVsyncSchedulerOwner.h rename : layout/style/test/test_flexbox_min_size_auto.html => layout/style/test/test_computed_style_min_size_auto.html rename : config/external/nss/moz.build => security/moz.build rename : config/external/nss/nss.symbols => security/nss.symbols rename : testing/marionette/components/marionettecomponent.js => testing/marionette/components/marionette.js rename : testing/web-platform/tests/XMLHttpRequest/event-upload-progress-crossorigin.sub.htm => testing/web-platform/tests/XMLHttpRequest/event-upload-progress-crossorigin.htm rename : testing/web-platform/tests/XMLHttpRequest/send-non-same-origin.sub.htm => testing/web-platform/tests/XMLHttpRequest/send-non-same-origin.htm rename : testing/web-platform/tests/html/browsers/history/the-location-interface/security_location_0.sub.htm => testing/web-platform/tests/html/browsers/history/the-location-interface/security_location_0.htm rename : testing/web-platform/tests/html/browsers/the-window-object/security-window/window-security.sub.html => testing/web-platform/tests/html/browsers/the-window-object/security-window/window-security.html rename : testing/web-platform/tests/html/browsers/windows/nested-browsing-contexts/frameElement.sub.html => testing/web-platform/tests/html/browsers/windows/nested-browsing-contexts/frameElement.html rename : testing/web-platform/tests/html/browsers/windows/targeting-cross-origin-nested-browsing-contexts.sub.html => testing/web-platform/tests/html/browsers/windows/targeting-cross-origin-nested-browsing-contexts.html rename : testing/web-platform/tests/html/dom/documents/dom-tree-accessors/Document.currentScript.sub.html => testing/web-platform/tests/html/dom/documents/dom-tree-accessors/Document.currentScript.html rename : testing/web-platform/tests/html/semantics/document-metadata/the-base-element/base_href_specified.sub.html => testing/web-platform/tests/html/semantics/document-metadata/the-base-element/base_href_specified.html rename : toolkit/components/places/tests/cpp/mock_Link.h => toolkit/components/places/tests/gtest/mock_Link.h rename : toolkit/components/places/tests/cpp/moz.build => toolkit/components/places/tests/gtest/moz.build rename : toolkit/components/places/tests/cpp/places_test_harness.h => toolkit/components/places/tests/gtest/places_test_harness.h rename : toolkit/components/places/tests/cpp/places_test_harness_tail.h => toolkit/components/places/tests/gtest/places_test_harness_tail.h rename : toolkit/components/places/tests/cpp/test_IHistory.cpp => toolkit/components/places/tests/gtest/test_IHistory.cpp rename : browser/themes/shared/filters.svg => toolkit/themes/shared/filters.svg rename : browser/themes/shared/downloads/menubutton-dropmarker.svg => toolkit/themes/shared/icons/menubutton-dropmarker.svg extra : amend_source : b446cd55619aa09f6d48941ab201fb796738d217
This commit is contained in:
Коммит
d654e9aa16
|
@ -175,7 +175,7 @@ endif
|
|||
tup:
|
||||
$(call BUILDSTATUS,TIERS make tup)
|
||||
$(call BUILDSTATUS,TIER_START make)
|
||||
$(MAKE) install-manifests buildid.h source-repo.h
|
||||
$(MAKE) buildid.h source-repo.h
|
||||
$(call BUILDSTATUS,TIER_FINISH make)
|
||||
$(call BUILDSTATUS,TIER_START tup)
|
||||
@$(TUP) $(if $(findstring s,$(filter-out --%,$(MAKEFLAGS))),,--verbose)
|
||||
|
|
|
@ -3296,17 +3296,6 @@ module.exports={
|
|||
"_retval": "longstring"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "getRawPermissionsTable",
|
||||
"request": {
|
||||
"type": "getRawPermissionsTable"
|
||||
},
|
||||
"response": {
|
||||
"value": {
|
||||
"_retval": "json"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"events": {}
|
||||
|
|
|
@ -281,6 +281,15 @@ exports.testValidateMapWithMissingKeyAndThrown = function (assert) {
|
|||
assert.deepEqual(val, { baz: "foo" });
|
||||
};
|
||||
|
||||
function forEachEnabled() {
|
||||
try {
|
||||
eval(`for each (var x in {}) {}`);
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
exports.testAddIterator = function testAddIterator (assert) {
|
||||
let obj = {};
|
||||
let keys = ["foo", "bar", "baz"];
|
||||
|
@ -303,14 +312,17 @@ exports.testAddIterator = function testAddIterator (assert) {
|
|||
for (let i = 0; i < keys.length; i++)
|
||||
assert.equal(keysItr[i], keys[i], "the key is correct");
|
||||
|
||||
let valsItr = [];
|
||||
for each (let val in obj)
|
||||
valsItr.push(val);
|
||||
assert.equal(valsItr.length, vals.length,
|
||||
"the vals iterator returns the correct number of items");
|
||||
for (let i = 0; i < vals.length; i++)
|
||||
assert.equal(valsItr[i], vals[i], "the val is correct");
|
||||
|
||||
if (forEachEnabled()) {
|
||||
eval(`
|
||||
let valsItr = [];
|
||||
for each (let val in obj)
|
||||
valsItr.push(val);
|
||||
assert.equal(valsItr.length, vals.length,
|
||||
"the vals iterator returns the correct number of items");
|
||||
for (let i = 0; i < vals.length; i++)
|
||||
assert.equal(valsItr[i], vals[i], "the val is correct");
|
||||
`);
|
||||
}
|
||||
};
|
||||
|
||||
require("sdk/test").run(exports);
|
||||
|
|
|
@ -423,9 +423,9 @@ exports["test Object Tag"] = createProxyTest("", function (helper) {
|
|||
|
||||
helper.createWorker(
|
||||
'new ' + function ContentScriptScope() {
|
||||
// <object>, <embed> and other tags return typeof 'function'
|
||||
// <object>, <embed> and other tags return typeof 'object'
|
||||
let flash = document.createElement("object");
|
||||
assert(typeof flash == "function", "<object> is typeof 'function'");
|
||||
assert(typeof flash == "object", "<object> is typeof 'function'");
|
||||
assert(flash.toString().match(/\[object HTMLObjectElement.*\]/), "<object> is HTMLObjectElement");
|
||||
assert("setAttribute" in flash, "<object> has a setAttribute method");
|
||||
done();
|
||||
|
|
|
@ -500,9 +500,6 @@ pref("app.update.socket.maxErrors", 20);
|
|||
// Enable update logging for now, to diagnose growing pains in the
|
||||
// field.
|
||||
pref("app.update.log", true);
|
||||
|
||||
// SystemUpdate API
|
||||
pref("dom.system_update.active", "@mozilla.org/updates/update-prompt;1");
|
||||
#else
|
||||
// Explicitly disable the shutdown watchdog. It's enabled by default.
|
||||
// When the updater is disabled, we want to know about shutdown hangs.
|
||||
|
@ -939,9 +936,6 @@ pref("identity.fxaccounts.skipDeviceRegistration", true);
|
|||
// Enable mapped array buffer.
|
||||
pref("dom.mapped_arraybuffer.enabled", true);
|
||||
|
||||
// SystemUpdate API
|
||||
pref("dom.system_update.enabled", true);
|
||||
|
||||
// UDPSocket API
|
||||
pref("dom.udpsocket.enabled", true);
|
||||
|
||||
|
|
|
@ -9,13 +9,6 @@ contract @mozilla.org/system-alerts-service;1 {fe33c107-82a4-41d6-8c64-5353267e0
|
|||
component {8c719f03-afe0-4aac-91ff-6c215895d467} ContentPermissionPrompt.js
|
||||
contract @mozilla.org/content-permission/prompt;1 {8c719f03-afe0-4aac-91ff-6c215895d467}
|
||||
|
||||
#ifdef MOZ_UPDATER
|
||||
# UpdatePrompt.js
|
||||
component {88b3eb21-d072-4e3b-886d-f89d8c49fe59} UpdatePrompt.js
|
||||
contract @mozilla.org/updates/update-prompt;1 {88b3eb21-d072-4e3b-886d-f89d8c49fe59}
|
||||
category system-update-provider MozillaProvider @mozilla.org/updates/update-prompt;1,{88b3eb21-d072-4e3b-886d-f89d8c49fe59}
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_B2G
|
||||
# DirectoryProvider.js
|
||||
component {9181eb7c-6f87-11e1-90b1-4f59d80dd2e5} DirectoryProvider.js
|
||||
|
|
|
@ -24,7 +24,6 @@ const ALLOW_MULTIPLE_REQUESTS = ["audio-capture", "video-capture"];
|
|||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/PermissionsTable.jsm");
|
||||
|
||||
var permissionManager = Cc["@mozilla.org/permissionmanager;1"].getService(Ci.nsIPermissionManager);
|
||||
var secMan = Cc["@mozilla.org/scriptsecuritymanager;1"].getService(Ci.nsIScriptSecurityManager);
|
||||
|
@ -67,56 +66,6 @@ function buildDefaultChoices(aTypesInfo) {
|
|||
return choices;
|
||||
}
|
||||
|
||||
/**
|
||||
* aTypesInfo is an array of {permission, access, action, deny} which keeps
|
||||
* the information of each permission. This arrary is initialized in
|
||||
* ContentPermissionPrompt.prompt and used among functions.
|
||||
*
|
||||
* aTypesInfo[].permission : permission name
|
||||
* aTypesInfo[].access : permission name + request.access
|
||||
* aTypesInfo[].action : the default action of this permission
|
||||
* aTypesInfo[].deny : true if security manager denied this app's origin
|
||||
* principal.
|
||||
* Note:
|
||||
* aTypesInfo[].permission will be sent to prompt only when
|
||||
* aTypesInfo[].action is PROMPT_ACTION and aTypesInfo[].deny is false.
|
||||
*/
|
||||
function rememberPermission(aTypesInfo, aPrincipal, aSession)
|
||||
{
|
||||
function convertPermToAllow(aPerm, aPrincipal)
|
||||
{
|
||||
let type =
|
||||
permissionManager.testExactPermissionFromPrincipal(aPrincipal, aPerm);
|
||||
if (shouldPrompt(aPerm, type)) {
|
||||
debug("add " + aPerm + " to permission manager with ALLOW_ACTION");
|
||||
if (!aSession) {
|
||||
permissionManager.addFromPrincipal(aPrincipal,
|
||||
aPerm,
|
||||
Ci.nsIPermissionManager.ALLOW_ACTION);
|
||||
} else if (PERMISSION_NO_SESSION.indexOf(aPerm) < 0) {
|
||||
permissionManager.addFromPrincipal(aPrincipal,
|
||||
aPerm,
|
||||
Ci.nsIPermissionManager.ALLOW_ACTION,
|
||||
Ci.nsIPermissionManager.EXPIRE_SESSION, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (let i in aTypesInfo) {
|
||||
// Expand the permission to see if we have multiple access properties
|
||||
// to convert
|
||||
let perm = aTypesInfo[i].permission;
|
||||
let access = PermissionsTable[perm].access;
|
||||
if (access) {
|
||||
for (let idx in access) {
|
||||
convertPermToAllow(perm + "-" + access[idx], aPrincipal);
|
||||
}
|
||||
} else {
|
||||
convertPermToAllow(perm, aPrincipal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function ContentPermissionPrompt() {}
|
||||
|
||||
ContentPermissionPrompt.prototype = {
|
||||
|
@ -296,7 +245,6 @@ ContentPermissionPrompt.prototype = {
|
|||
this.sendToBrowserWindow("permission-prompt", request, typesInfo,
|
||||
function(type, remember, choices) {
|
||||
if (type == "permission-allow") {
|
||||
rememberPermission(typesInfo, request.principal, !remember);
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
|
|
|
@ -1,783 +0,0 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
|
||||
* vim: sw=2 ts=8 et :
|
||||
*/
|
||||
/* 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/. */
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
const Cr = Components.results;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/AppConstants.jsm");
|
||||
|
||||
const VERBOSE = 1;
|
||||
var log =
|
||||
VERBOSE ?
|
||||
function log_dump(msg) { dump("UpdatePrompt: "+ msg +"\n"); } :
|
||||
function log_noop(msg) { };
|
||||
|
||||
const PREF_APPLY_PROMPT_TIMEOUT = "b2g.update.apply-prompt-timeout";
|
||||
const PREF_APPLY_IDLE_TIMEOUT = "b2g.update.apply-idle-timeout";
|
||||
const PREF_DOWNLOAD_WATCHDOG_TIMEOUT = "b2g.update.download-watchdog-timeout";
|
||||
const PREF_DOWNLOAD_WATCHDOG_MAX_RETRIES = "b2g.update.download-watchdog-max-retries";
|
||||
|
||||
const NETWORK_ERROR_OFFLINE = 111;
|
||||
const HTTP_ERROR_OFFSET = 1000;
|
||||
|
||||
const STATE_DOWNLOADING = 'downloading';
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(Services, "aus",
|
||||
"@mozilla.org/updates/update-service;1",
|
||||
"nsIApplicationUpdateService");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(Services, "um",
|
||||
"@mozilla.org/updates/update-manager;1",
|
||||
"nsIUpdateManager");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(Services, "idle",
|
||||
"@mozilla.org/widget/idleservice;1",
|
||||
"nsIIdleService");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(Services, "settings",
|
||||
"@mozilla.org/settingsService;1",
|
||||
"nsISettingsService");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(Services, 'env',
|
||||
'@mozilla.org/process/environment;1',
|
||||
'nsIEnvironment');
|
||||
|
||||
function useSettings() {
|
||||
// When we're running in the real phone, then we can use settings.
|
||||
// But when we're running as part of xpcshell, there is no settings database
|
||||
// and trying to use settings in this scenario causes lots of weird
|
||||
// assertions at shutdown time.
|
||||
if (typeof useSettings.result === "undefined") {
|
||||
useSettings.result = !Services.env.get("XPCSHELL_TEST_PROFILE_DIR");
|
||||
}
|
||||
return useSettings.result;
|
||||
}
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "SystemAppProxy",
|
||||
"resource://gre/modules/SystemAppProxy.jsm");
|
||||
|
||||
function UpdateCheckListener(updatePrompt) {
|
||||
this._updatePrompt = updatePrompt;
|
||||
}
|
||||
|
||||
UpdateCheckListener.prototype = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIUpdateCheckListener]),
|
||||
|
||||
_updatePrompt: null,
|
||||
|
||||
onCheckComplete: function UCL_onCheckComplete(request, updates, updateCount) {
|
||||
if (Services.um.activeUpdate) {
|
||||
// We're actively downloading an update, that's the update the user should
|
||||
// see, even if a newer update is available.
|
||||
this._updatePrompt.setUpdateStatus("active-update");
|
||||
this._updatePrompt.showUpdateAvailable(Services.um.activeUpdate);
|
||||
return;
|
||||
}
|
||||
|
||||
if (updateCount == 0) {
|
||||
this._updatePrompt.setUpdateStatus("no-updates");
|
||||
|
||||
if (this._updatePrompt._systemUpdateListener) {
|
||||
this._updatePrompt._systemUpdateListener.onError("no-updates");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
let update = Services.aus.selectUpdate(updates, updateCount);
|
||||
if (!update) {
|
||||
this._updatePrompt.setUpdateStatus("already-latest-version");
|
||||
|
||||
if (this._updatePrompt._systemUpdateListener) {
|
||||
this._updatePrompt._systemUpdateListener.onError("already-latest-version");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this._updatePrompt.setUpdateStatus("check-complete");
|
||||
this._updatePrompt.showUpdateAvailable(update);
|
||||
},
|
||||
|
||||
onError: function UCL_onError(request, update) {
|
||||
// nsIUpdate uses a signed integer for errorCode while any platform errors
|
||||
// require all 32 bits.
|
||||
let errorCode = update.errorCode >>> 0;
|
||||
let isNSError = (errorCode >>> 31) == 1;
|
||||
let errorMsg = "check-error-";
|
||||
|
||||
if (errorCode == NETWORK_ERROR_OFFLINE) {
|
||||
errorMsg = "retry-when-online";
|
||||
this._updatePrompt.setUpdateStatus(errorMsg);
|
||||
} else if (isNSError) {
|
||||
errorMsg = "check-error-" + errorCode;
|
||||
this._updatePrompt.setUpdateStatus(errorMsg);
|
||||
} else if (errorCode > HTTP_ERROR_OFFSET) {
|
||||
let httpErrorCode = errorCode - HTTP_ERROR_OFFSET;
|
||||
errorMsg = "check-error-http-" + httpErrorCode;
|
||||
this._updatePrompt.setUpdateStatus(errorMsg);
|
||||
}
|
||||
|
||||
if (this._updatePrompt._systemUpdateListener) {
|
||||
this._updatePrompt._systemUpdateListener.onError(errorMsg);
|
||||
}
|
||||
|
||||
Services.aus.QueryInterface(Ci.nsIUpdateCheckListener);
|
||||
Services.aus.onError(request, update);
|
||||
}
|
||||
};
|
||||
|
||||
function UpdatePrompt() {
|
||||
this.wrappedJSObject = this;
|
||||
this._updateCheckListener = new UpdateCheckListener(this);
|
||||
}
|
||||
|
||||
UpdatePrompt.prototype = {
|
||||
classID: Components.ID("{88b3eb21-d072-4e3b-886d-f89d8c49fe59}"),
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIUpdatePrompt,
|
||||
Ci.nsIUpdateCheckListener,
|
||||
Ci.nsIRequestObserver,
|
||||
Ci.nsIProgressEventSink,
|
||||
Ci.nsIObserver,
|
||||
Ci.nsISystemUpdateProvider]),
|
||||
_xpcom_factory: XPCOMUtils.generateSingletonFactory(UpdatePrompt),
|
||||
|
||||
_update: null,
|
||||
_applyPromptTimer: null,
|
||||
_waitingForIdle: false,
|
||||
_updateCheckListner: null,
|
||||
_systemUpdateListener: null,
|
||||
_availableParameters: {
|
||||
"deviceinfo.last_updated": null,
|
||||
"gecko.updateStatus": null,
|
||||
"app.update.channel": null,
|
||||
"app.update.interval": null,
|
||||
"app.update.url": null,
|
||||
},
|
||||
_pendingUpdateAvailablePackageInfo: null,
|
||||
_isPendingUpdateReady: false,
|
||||
_updateErrorQueue: [ ],
|
||||
_receivedUpdatePromptReady: false,
|
||||
|
||||
// nsISystemUpdateProvider
|
||||
checkForUpdate: function() {
|
||||
this.forceUpdateCheck();
|
||||
},
|
||||
|
||||
startDownload: function() {
|
||||
this.downloadUpdate(this._update);
|
||||
},
|
||||
|
||||
stopDownload: function() {
|
||||
this.handleDownloadCancel();
|
||||
},
|
||||
|
||||
applyUpdate: function() {
|
||||
this.handleApplyPromptResult({result: "restart"});
|
||||
},
|
||||
|
||||
setParameter: function(aName, aValue) {
|
||||
if (!this._availableParameters.hasOwnProperty(aName)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this._availableParameters[aName] = aValue;
|
||||
|
||||
switch (aName) {
|
||||
case "app.update.channel":
|
||||
case "app.update.url":
|
||||
Services.prefs.setCharPref(aName, aValue);
|
||||
break;
|
||||
case "app.update.interval":
|
||||
Services.prefs.setIntPref(aName, parseInt(aValue, 10));
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
getParameter: function(aName) {
|
||||
if (!this._availableParameters.hasOwnProperty(aName)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return this._availableParameters[aName];
|
||||
},
|
||||
|
||||
setListener: function(aListener) {
|
||||
this._systemUpdateListener = aListener;
|
||||
|
||||
// If an update is available or ready, trigger the event right away at this point.
|
||||
if (this._pendingUpdateAvailablePackageInfo) {
|
||||
this._systemUpdateListener.onUpdateAvailable(this._pendingUpdateAvailablePackageInfo.type,
|
||||
this._pendingUpdateAvailablePackageInfo.version,
|
||||
this._pendingUpdateAvailablePackageInfo.description,
|
||||
this._pendingUpdateAvailablePackageInfo.buildDate,
|
||||
this._pendingUpdateAvailablePackageInfo.size);
|
||||
// Set null when the listener is attached.
|
||||
this._pendingUpdateAvailablePackageInfo = null;
|
||||
}
|
||||
|
||||
if (this._isPendingUpdateReady) {
|
||||
this._systemUpdateListener.onUpdateReady();
|
||||
this._isPendingUpdateReady = false;
|
||||
}
|
||||
},
|
||||
|
||||
unsetListener: function(aListener) {
|
||||
this._systemUpdateListener = null;
|
||||
},
|
||||
|
||||
get applyPromptTimeout() {
|
||||
return Services.prefs.getIntPref(PREF_APPLY_PROMPT_TIMEOUT);
|
||||
},
|
||||
|
||||
get applyIdleTimeout() {
|
||||
return Services.prefs.getIntPref(PREF_APPLY_IDLE_TIMEOUT);
|
||||
},
|
||||
|
||||
handleContentStart: function UP_handleContentStart() {
|
||||
SystemAppProxy.addEventListener("mozContentEvent", this);
|
||||
},
|
||||
|
||||
// nsIUpdatePrompt
|
||||
|
||||
// FIXME/bug 737601: we should have users opt-in to downloading
|
||||
// updates when on a billed pipe. Initially, opt-in for 3g, but
|
||||
// that doesn't cover all cases.
|
||||
checkForUpdates: function UP_checkForUpdates() { },
|
||||
|
||||
showUpdateAvailable: function UP_showUpdateAvailable(aUpdate) {
|
||||
let packageInfo = {};
|
||||
packageInfo.version = aUpdate.displayVersion;
|
||||
packageInfo.description = aUpdate.statusText;
|
||||
packageInfo.buildDate = aUpdate.buildID;
|
||||
|
||||
let patch = aUpdate.selectedPatch;
|
||||
if (!patch && aUpdate.patchCount > 0) {
|
||||
// For now we just check the first patch to get size information if a
|
||||
// patch hasn't been selected yet.
|
||||
patch = aUpdate.getPatchAt(0);
|
||||
}
|
||||
|
||||
if (patch) {
|
||||
packageInfo.size = patch.size;
|
||||
packageInfo.type = patch.type;
|
||||
} else {
|
||||
log("Warning: no patches available in update");
|
||||
}
|
||||
|
||||
this._pendingUpdateAvailablePackageInfo = packageInfo;
|
||||
|
||||
if (this._systemUpdateListener) {
|
||||
this._systemUpdateListener.onUpdateAvailable(packageInfo.type,
|
||||
packageInfo.version,
|
||||
packageInfo.description,
|
||||
packageInfo.buildDate,
|
||||
packageInfo.size);
|
||||
// Set null since the event is fired.
|
||||
this._pendingUpdateAvailablePackageInfo = null;
|
||||
}
|
||||
|
||||
if (!this.sendUpdateEvent("update-available", aUpdate)) {
|
||||
|
||||
log("Unable to prompt for available update, forcing download");
|
||||
this.downloadUpdate(aUpdate);
|
||||
}
|
||||
},
|
||||
|
||||
showUpdateDownloaded: function UP_showUpdateDownloaded(aUpdate, aBackground) {
|
||||
if (this._systemUpdateListener) {
|
||||
this._systemUpdateListener.onUpdateReady();
|
||||
} else {
|
||||
this._isPendingUpdateReady = true;
|
||||
}
|
||||
|
||||
// The update has been downloaded and staged. We send the update-downloaded
|
||||
// event right away. After the user has been idle for a while, we send the
|
||||
// update-prompt-restart event, increasing the chances that we can apply the
|
||||
// update quietly without user intervention.
|
||||
this.sendUpdateEvent("update-downloaded", aUpdate);
|
||||
|
||||
if (Services.idle.idleTime >= this.applyIdleTimeout) {
|
||||
this.showApplyPrompt(aUpdate);
|
||||
return;
|
||||
}
|
||||
|
||||
let applyIdleTimeoutSeconds = this.applyIdleTimeout / 1000;
|
||||
// We haven't been idle long enough, so register an observer
|
||||
log("Update is ready to apply, registering idle timeout of " +
|
||||
applyIdleTimeoutSeconds + " seconds before prompting.");
|
||||
|
||||
this._update = aUpdate;
|
||||
this.waitForIdle();
|
||||
},
|
||||
|
||||
storeUpdateError: function UP_storeUpdateError(aUpdate) {
|
||||
log("Storing update error for later use");
|
||||
this._updateErrorQueue.push(aUpdate);
|
||||
},
|
||||
|
||||
sendStoredUpdateError: function UP_sendStoredUpdateError() {
|
||||
log("Sending stored update error");
|
||||
this._updateErrorQueue.forEach(aUpdate => {
|
||||
this.sendUpdateEvent("update-error", aUpdate);
|
||||
});
|
||||
this._updateErrorQueue = [ ];
|
||||
},
|
||||
|
||||
showUpdateError: function UP_showUpdateError(aUpdate) {
|
||||
log("Update error, state: " + aUpdate.state + ", errorCode: " +
|
||||
aUpdate.errorCode);
|
||||
if (this._systemUpdateListener) {
|
||||
this._systemUpdateListener.onError("update-error: " + aUpdate.errorCode + " " + aUpdate.statusText);
|
||||
}
|
||||
|
||||
if (!this._receivedUpdatePromptReady) {
|
||||
this.storeUpdateError(aUpdate);
|
||||
} else {
|
||||
this.sendUpdateEvent("update-error", aUpdate);
|
||||
}
|
||||
|
||||
this.setUpdateStatus(aUpdate.statusText);
|
||||
},
|
||||
|
||||
showUpdateHistory: function UP_showUpdateHistory(aParent) { },
|
||||
showUpdateInstalled: function UP_showUpdateInstalled() {
|
||||
this.setParameter("deviceinfo.last_updated", Date.now());
|
||||
|
||||
if (useSettings()) {
|
||||
let lock = Services.settings.createLock();
|
||||
lock.set("deviceinfo.last_updated", Date.now(), null, null);
|
||||
}
|
||||
},
|
||||
|
||||
// Custom functions
|
||||
|
||||
waitForIdle: function UP_waitForIdle() {
|
||||
if (this._waitingForIdle) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._waitingForIdle = true;
|
||||
Services.idle.addIdleObserver(this, this.applyIdleTimeout / 1000);
|
||||
Services.obs.addObserver(this, "quit-application", false);
|
||||
},
|
||||
|
||||
setUpdateStatus: function UP_setUpdateStatus(aStatus) {
|
||||
this.setParameter("gecko.updateStatus", aStatus);
|
||||
|
||||
if (useSettings()) {
|
||||
log("Setting gecko.updateStatus: " + aStatus);
|
||||
|
||||
let lock = Services.settings.createLock();
|
||||
lock.set("gecko.updateStatus", aStatus, null);
|
||||
}
|
||||
},
|
||||
|
||||
showApplyPrompt: function UP_showApplyPrompt(aUpdate) {
|
||||
// Notify update package is ready to apply
|
||||
if (this._systemUpdateListener) {
|
||||
this._systemUpdateListener.onUpdateReady();
|
||||
} else {
|
||||
// Set the flag to true and fire the onUpdateReady event when the listener is attached.
|
||||
this._isPendingUpdateReady = true;
|
||||
}
|
||||
|
||||
if (!this.sendUpdateEvent("update-prompt-apply", aUpdate)) {
|
||||
log("Unable to prompt, forcing restart");
|
||||
this.restartProcess();
|
||||
return;
|
||||
}
|
||||
|
||||
if (AppConstants.MOZ_B2G_RIL) {
|
||||
let window = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
let pinReq = window.navigator.mozIccManager.getCardLock("pin");
|
||||
pinReq.onsuccess = function(e) {
|
||||
if (e.target.result.enabled) {
|
||||
// The SIM is pin locked. Don't use a fallback timer. This means that
|
||||
// the user has to press Install to apply the update. If we use the
|
||||
// timer, and the timer reboots the phone, then the phone will be
|
||||
// unusable until the SIM is unlocked.
|
||||
log("SIM is pin locked. Not starting fallback timer.");
|
||||
} else {
|
||||
// This means that no pin lock is enabled, so we go ahead and start
|
||||
// the fallback timer.
|
||||
this._applyPromptTimer = this.createTimer(this.applyPromptTimeout);
|
||||
}
|
||||
}.bind(this);
|
||||
pinReq.onerror = function(e) {
|
||||
this._applyPromptTimer = this.createTimer(this.applyPromptTimeout);
|
||||
}.bind(this);
|
||||
} else {
|
||||
// Schedule a fallback timeout in case the UI is unable to respond or show
|
||||
// a prompt for some reason.
|
||||
this._applyPromptTimer = this.createTimer(this.applyPromptTimeout);
|
||||
}
|
||||
},
|
||||
|
||||
_copyProperties: ["appVersion", "buildID", "detailsURL", "displayVersion",
|
||||
"errorCode", "isOSUpdate", "platformVersion",
|
||||
"previousAppVersion", "state", "statusText"],
|
||||
|
||||
sendUpdateEvent: function UP_sendUpdateEvent(aType, aUpdate) {
|
||||
let detail = {};
|
||||
for (let property of this._copyProperties) {
|
||||
detail[property] = aUpdate[property];
|
||||
}
|
||||
|
||||
let patch = aUpdate.selectedPatch;
|
||||
if (!patch && aUpdate.patchCount > 0) {
|
||||
// For now we just check the first patch to get size information if a
|
||||
// patch hasn't been selected yet.
|
||||
patch = aUpdate.getPatchAt(0);
|
||||
}
|
||||
|
||||
if (patch) {
|
||||
detail.size = patch.size;
|
||||
detail.updateType = patch.type;
|
||||
} else {
|
||||
log("Warning: no patches available in update");
|
||||
}
|
||||
|
||||
this._update = aUpdate;
|
||||
return this.sendChromeEvent(aType, detail);
|
||||
},
|
||||
|
||||
sendChromeEvent: function UP_sendChromeEvent(aType, aDetail) {
|
||||
let detail = aDetail || {};
|
||||
detail.type = aType;
|
||||
|
||||
let sent = SystemAppProxy.dispatchEvent(detail);
|
||||
if (!sent) {
|
||||
log("Warning: Couldn't send update event " + aType +
|
||||
": no content browser. Will send again when content becomes available.");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
handleAvailableResult: function UP_handleAvailableResult(aDetail) {
|
||||
// If the user doesn't choose "download", the updater will implicitly call
|
||||
// showUpdateAvailable again after a certain period of time
|
||||
switch (aDetail.result) {
|
||||
case "download":
|
||||
this.downloadUpdate(this._update);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
handleApplyPromptResult: function UP_handleApplyPromptResult(aDetail) {
|
||||
if (this._applyPromptTimer) {
|
||||
this._applyPromptTimer.cancel();
|
||||
this._applyPromptTimer = null;
|
||||
}
|
||||
|
||||
switch (aDetail.result) {
|
||||
// Battery not okay, do not wait for idle to re-prompt
|
||||
case "low-battery":
|
||||
break;
|
||||
case "wait":
|
||||
// Wait until the user is idle before prompting to apply the update
|
||||
this.waitForIdle();
|
||||
break;
|
||||
case "restart":
|
||||
this.finishUpdate();
|
||||
this._update = null;
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
downloadUpdate: function UP_downloadUpdate(aUpdate) {
|
||||
if (!aUpdate) {
|
||||
aUpdate = Services.um.activeUpdate;
|
||||
if (!aUpdate) {
|
||||
log("No active update found to download");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
let status = Services.aus.downloadUpdate(aUpdate, true);
|
||||
if (status == STATE_DOWNLOADING) {
|
||||
Services.aus.addDownloadListener(this);
|
||||
return;
|
||||
}
|
||||
|
||||
// If the update has already been downloaded and applied, then
|
||||
// Services.aus.downloadUpdate will return immediately and not
|
||||
// call showUpdateDownloaded, so we detect this.
|
||||
if (aUpdate.state == "applied" && aUpdate.errorCode == 0) {
|
||||
this.showUpdateDownloaded(aUpdate, true);
|
||||
return;
|
||||
}
|
||||
|
||||
log("Error downloading update " + aUpdate.name + ": " + aUpdate.errorCode);
|
||||
let errorCode = aUpdate.errorCode >>> 0;
|
||||
if (errorCode == Cr.NS_ERROR_FILE_TOO_BIG) {
|
||||
aUpdate.statusText = "file-too-big";
|
||||
}
|
||||
this.showUpdateError(aUpdate);
|
||||
},
|
||||
|
||||
handleDownloadCancel: function UP_handleDownloadCancel() {
|
||||
log("Pausing download");
|
||||
Services.aus.pauseDownload();
|
||||
},
|
||||
|
||||
finishUpdate: function UP_finishUpdate() {
|
||||
if (!this._update.isOSUpdate) {
|
||||
// Standard gecko+gaia updates will just need to restart the process
|
||||
this.restartProcess();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
Services.aus.applyOsUpdate(this._update);
|
||||
}
|
||||
catch (e) {
|
||||
this._update.errorCode = Cr.NS_ERROR_FAILURE;
|
||||
this.showUpdateError(this._update);
|
||||
}
|
||||
},
|
||||
|
||||
restartProcess: function UP_restartProcess() {
|
||||
log("Update downloaded, restarting to apply it");
|
||||
|
||||
let callbackAfterSet = function() {
|
||||
if (AppConstants.platform !== "gonk") {
|
||||
let appStartup = Cc["@mozilla.org/toolkit/app-startup;1"]
|
||||
.getService(Ci.nsIAppStartup);
|
||||
appStartup.quit(appStartup.eForceQuit | appStartup.eRestart);
|
||||
} else {
|
||||
// NB: on Gonk, we rely on the system process manager to restart us.
|
||||
let pmService = Cc["@mozilla.org/power/powermanagerservice;1"]
|
||||
.getService(Ci.nsIPowerManagerService);
|
||||
pmService.restart();
|
||||
}
|
||||
}
|
||||
|
||||
if (useSettings()) {
|
||||
// Save current os version in deviceinfo.previous_os
|
||||
let lock = Services.settings.createLock({
|
||||
handle: callbackAfterSet,
|
||||
handleAbort: function(error) {
|
||||
log("Abort callback when trying to set previous_os: " + error);
|
||||
callbackAfterSet();
|
||||
}
|
||||
});
|
||||
lock.get("deviceinfo.os", {
|
||||
handle: function(name, value) {
|
||||
log("Set previous_os to: " + value);
|
||||
lock.set("deviceinfo.previous_os", value, null, null);
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
forceUpdateCheck: function UP_forceUpdateCheck() {
|
||||
log("Forcing update check");
|
||||
|
||||
let checker = Cc["@mozilla.org/updates/update-checker;1"]
|
||||
.createInstance(Ci.nsIUpdateChecker);
|
||||
checker.checkForUpdates(this._updateCheckListener, true);
|
||||
},
|
||||
|
||||
handleEvent: function UP_handleEvent(evt) {
|
||||
if (evt.type !== "mozContentEvent") {
|
||||
return;
|
||||
}
|
||||
|
||||
let detail = evt.detail;
|
||||
if (!detail) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (detail.type) {
|
||||
case "force-update-check":
|
||||
this.forceUpdateCheck();
|
||||
break;
|
||||
case "update-available-result":
|
||||
this.handleAvailableResult(detail);
|
||||
// If we started the apply prompt timer, this means that we're waiting
|
||||
// for the user to press Later or Install Now. In this situation we
|
||||
// don't want to clear this._update, becuase handleApplyPromptResult
|
||||
// needs it.
|
||||
if (this._applyPromptTimer == null && !this._waitingForIdle) {
|
||||
this._update = null;
|
||||
}
|
||||
break;
|
||||
case "update-download-cancel":
|
||||
this.handleDownloadCancel();
|
||||
break;
|
||||
case "update-prompt-apply-result":
|
||||
this.handleApplyPromptResult(detail);
|
||||
break;
|
||||
case "update-prompt-ready":
|
||||
this._receivedUpdatePromptReady = true;
|
||||
this.sendStoredUpdateError();
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
// nsIObserver
|
||||
|
||||
observe: function UP_observe(aSubject, aTopic, aData) {
|
||||
switch (aTopic) {
|
||||
case "idle":
|
||||
this._waitingForIdle = false;
|
||||
this.showApplyPrompt(this._update);
|
||||
// Fall through
|
||||
case "quit-application":
|
||||
Services.idle.removeIdleObserver(this, this.applyIdleTimeout / 1000);
|
||||
Services.obs.removeObserver(this, "quit-application");
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
// nsITimerCallback
|
||||
|
||||
notify: function UP_notify(aTimer) {
|
||||
if (aTimer == this._applyPromptTimer) {
|
||||
log("Timed out waiting for result, restarting");
|
||||
this._applyPromptTimer = null;
|
||||
this.finishUpdate();
|
||||
this._update = null;
|
||||
return;
|
||||
}
|
||||
if (aTimer == this._watchdogTimer) {
|
||||
log("Download watchdog fired");
|
||||
this._watchdogTimer = null;
|
||||
this._autoRestartDownload = true;
|
||||
Services.aus.pauseDownload();
|
||||
return;
|
||||
}
|
||||
},
|
||||
|
||||
createTimer: function UP_createTimer(aTimeoutMs) {
|
||||
let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
||||
timer.initWithCallback(this, aTimeoutMs, timer.TYPE_ONE_SHOT);
|
||||
return timer;
|
||||
},
|
||||
|
||||
// nsIRequestObserver
|
||||
|
||||
_startedSent: false,
|
||||
|
||||
_watchdogTimer: null,
|
||||
|
||||
_autoRestartDownload: false,
|
||||
_autoRestartCount: 0,
|
||||
|
||||
startWatchdogTimer: function UP_startWatchdogTimer() {
|
||||
let watchdogTimeout = 120000; // 120 seconds
|
||||
try {
|
||||
watchdogTimeout = Services.prefs.getIntPref(PREF_DOWNLOAD_WATCHDOG_TIMEOUT);
|
||||
} catch (e) {
|
||||
// This means that the preference doesn't exist. watchdogTimeout will
|
||||
// retain its default assigned above.
|
||||
}
|
||||
if (watchdogTimeout <= 0) {
|
||||
// 0 implies don't bother using the watchdog timer at all.
|
||||
this._watchdogTimer = null;
|
||||
return;
|
||||
}
|
||||
if (this._watchdogTimer) {
|
||||
this._watchdogTimer.cancel();
|
||||
} else {
|
||||
this._watchdogTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
||||
}
|
||||
this._watchdogTimer.initWithCallback(this, watchdogTimeout,
|
||||
Ci.nsITimer.TYPE_ONE_SHOT);
|
||||
},
|
||||
|
||||
stopWatchdogTimer: function UP_stopWatchdogTimer() {
|
||||
if (this._watchdogTimer) {
|
||||
this._watchdogTimer.cancel();
|
||||
this._watchdogTimer = null;
|
||||
}
|
||||
},
|
||||
|
||||
touchWatchdogTimer: function UP_touchWatchdogTimer() {
|
||||
this.startWatchdogTimer();
|
||||
},
|
||||
|
||||
onStartRequest: function UP_onStartRequest(aRequest, aContext) {
|
||||
// Wait until onProgress to send the update-download-started event, in case
|
||||
// this request turns out to fail for some reason
|
||||
this._startedSent = false;
|
||||
this.startWatchdogTimer();
|
||||
},
|
||||
|
||||
onStopRequest: function UP_onStopRequest(aRequest, aContext, aStatusCode) {
|
||||
this.stopWatchdogTimer();
|
||||
Services.aus.removeDownloadListener(this);
|
||||
let paused = !Components.isSuccessCode(aStatusCode);
|
||||
if (!paused) {
|
||||
// The download was successful, no need to restart
|
||||
this._autoRestartDownload = false;
|
||||
}
|
||||
if (this._autoRestartDownload) {
|
||||
this._autoRestartDownload = false;
|
||||
let watchdogMaxRetries = Services.prefs.getIntPref(PREF_DOWNLOAD_WATCHDOG_MAX_RETRIES);
|
||||
this._autoRestartCount++;
|
||||
if (this._autoRestartCount > watchdogMaxRetries) {
|
||||
log("Download - retry count exceeded - error");
|
||||
// We exceeded the max retries. Treat the download like an error,
|
||||
// which will give the user a chance to restart manually later.
|
||||
this._autoRestartCount = 0;
|
||||
if (Services.um.activeUpdate) {
|
||||
this.showUpdateError(Services.um.activeUpdate);
|
||||
}
|
||||
return;
|
||||
}
|
||||
log("Download - restarting download - attempt " + this._autoRestartCount);
|
||||
this.downloadUpdate(null);
|
||||
return;
|
||||
}
|
||||
this._autoRestartCount = 0;
|
||||
this.sendChromeEvent("update-download-stopped", {
|
||||
paused: paused
|
||||
});
|
||||
},
|
||||
|
||||
// nsIProgressEventSink
|
||||
|
||||
onProgress: function UP_onProgress(aRequest, aContext, aProgress,
|
||||
aProgressMax) {
|
||||
if (this._systemUpdateListener) {
|
||||
this._systemUpdateListener.onProgress(aProgress, aProgressMax);
|
||||
}
|
||||
|
||||
if (aProgress == aProgressMax) {
|
||||
// The update.mar validation done by onStopRequest may take
|
||||
// a while before the onStopRequest callback is made, so stop
|
||||
// the timer now.
|
||||
this.stopWatchdogTimer();
|
||||
} else {
|
||||
this.touchWatchdogTimer();
|
||||
}
|
||||
if (!this._startedSent) {
|
||||
this.sendChromeEvent("update-download-started", {
|
||||
total: aProgressMax
|
||||
});
|
||||
this._startedSent = true;
|
||||
}
|
||||
|
||||
this.sendChromeEvent("update-download-progress", {
|
||||
progress: aProgress,
|
||||
total: aProgressMax
|
||||
});
|
||||
},
|
||||
|
||||
onStatus: function UP_onStatus(aRequest, aUpdate, aStatus, aStatusArg) { }
|
||||
};
|
||||
|
||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([UpdatePrompt]);
|
|
@ -41,11 +41,6 @@ if CONFIG['MOZ_B2G']:
|
|||
'RecoveryService.js',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_UPDATER']:
|
||||
EXTRA_COMPONENTS += [
|
||||
'UpdatePrompt.js',
|
||||
]
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
'AboutServiceWorkers.jsm',
|
||||
'ActivityChannel.jsm',
|
||||
|
|
|
@ -774,14 +774,11 @@ bin/libfreebl_32int64_3.so
|
|||
#if defined(ENABLE_MARIONETTE) || !defined(MOZ_WIDGET_GONK)
|
||||
@RESPATH@/chrome/marionette@JAREXT@
|
||||
@RESPATH@/chrome/marionette.manifest
|
||||
@RESPATH@/components/MarionetteComponents.manifest
|
||||
@RESPATH@/components/marionettecomponent.js
|
||||
@RESPATH@/components/marionette.manifest
|
||||
@RESPATH@/components/marionette.js
|
||||
#endif
|
||||
@RESPATH@/components/AlertsService.js
|
||||
@RESPATH@/components/ContentPermissionPrompt.js
|
||||
#ifdef MOZ_UPDATER
|
||||
@RESPATH@/components/UpdatePrompt.js
|
||||
#endif
|
||||
@RESPATH@/components/DirectoryProvider.js
|
||||
@RESPATH@/components/ProcessGlobal.js
|
||||
@RESPATH@/components/OMAContentHandler.js
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -88,10 +88,20 @@ const gXPInstallObserver = {
|
|||
|
||||
const anchorID = "addons-notification-icon";
|
||||
|
||||
// Make notifications persist a minimum of 30 seconds
|
||||
// Make notifications persistent
|
||||
var options = {
|
||||
displayURI: installInfo.originatingURI,
|
||||
timeout: Date.now() + 30000,
|
||||
persistent: true,
|
||||
};
|
||||
|
||||
let acceptInstallation = () => {
|
||||
for (let install of installInfo.installs)
|
||||
install.install();
|
||||
installInfo = null;
|
||||
|
||||
Services.telemetry
|
||||
.getHistogramById("SECURITY_UI")
|
||||
.add(Ci.nsISecurityUITelemetry.WARNING_CONFIRM_ADDON_INSTALL_CLICK_THROUGH);
|
||||
};
|
||||
|
||||
let cancelInstallation = () => {
|
||||
|
@ -105,8 +115,6 @@ const gXPInstallObserver = {
|
|||
}
|
||||
}
|
||||
|
||||
this.acceptInstallation = null;
|
||||
|
||||
showNextConfirmation();
|
||||
};
|
||||
|
||||
|
@ -142,16 +150,6 @@ const gXPInstallObserver = {
|
|||
|
||||
addonList.appendChild(container);
|
||||
}
|
||||
|
||||
this.acceptInstallation = () => {
|
||||
for (let install of installInfo.installs)
|
||||
install.install();
|
||||
installInfo = null;
|
||||
|
||||
Services.telemetry
|
||||
.getHistogramById("SECURITY_UI")
|
||||
.add(Ci.nsISecurityUITelemetry.WARNING_CONFIRM_ADDON_INSTALL_CLICK_THROUGH);
|
||||
};
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
@ -187,13 +185,17 @@ const gXPInstallObserver = {
|
|||
messageString = messageString.replace("#1", brandShortName);
|
||||
messageString = messageString.replace("#2", installInfo.installs.length);
|
||||
|
||||
let cancelButton = document.getElementById("addon-install-confirmation-cancel");
|
||||
cancelButton.label = gNavigatorBundle.getString("addonInstall.cancelButton.label");
|
||||
cancelButton.accessKey = gNavigatorBundle.getString("addonInstall.cancelButton.accesskey");
|
||||
let action = {
|
||||
label: gNavigatorBundle.getString("addonInstall.acceptButton.label"),
|
||||
accessKey: gNavigatorBundle.getString("addonInstall.acceptButton.accesskey"),
|
||||
callback: acceptInstallation,
|
||||
};
|
||||
|
||||
let acceptButton = document.getElementById("addon-install-confirmation-accept");
|
||||
acceptButton.label = gNavigatorBundle.getString("addonInstall.acceptButton.label");
|
||||
acceptButton.accessKey = gNavigatorBundle.getString("addonInstall.acceptButton.accesskey");
|
||||
let secondaryAction = {
|
||||
label: gNavigatorBundle.getString("addonInstall.cancelButton.label"),
|
||||
accessKey: gNavigatorBundle.getString("addonInstall.cancelButton.accesskey"),
|
||||
callback: () => {},
|
||||
};
|
||||
|
||||
if (height) {
|
||||
notification.style.minHeight = height + "px";
|
||||
|
@ -205,8 +207,8 @@ const gXPInstallObserver = {
|
|||
}
|
||||
|
||||
let popup = PopupNotifications.show(browser, "addon-install-confirmation",
|
||||
messageString, anchorID, null, null,
|
||||
options);
|
||||
messageString, anchorID, action,
|
||||
[secondaryAction], options);
|
||||
|
||||
removeNotificationOnEnd(popup, installInfo.installs);
|
||||
|
||||
|
@ -230,9 +232,10 @@ const gXPInstallObserver = {
|
|||
var brandShortName = brandBundle.getString("brandShortName");
|
||||
|
||||
var notificationID = aTopic;
|
||||
// Make notifications persist a minimum of 30 seconds
|
||||
// Make notifications persistent
|
||||
var options = {
|
||||
displayURI: installInfo.originatingURI,
|
||||
persistent: true,
|
||||
timeout: Date.now() + 30000,
|
||||
};
|
||||
|
||||
|
@ -305,29 +308,46 @@ const gXPInstallObserver = {
|
|||
options.installs = installInfo.installs;
|
||||
options.contentWindow = browser.contentWindow;
|
||||
options.sourceURI = browser.currentURI;
|
||||
options.eventCallback = (aEvent) => {
|
||||
options.eventCallback = function(aEvent) {
|
||||
switch (aEvent) {
|
||||
case "shown":
|
||||
let notificationElement = [...this.owner.panel.childNodes]
|
||||
.find(n => n.notification == this);
|
||||
if (notificationElement) {
|
||||
if (Preferences.get("xpinstall.customConfirmationUI", false)) {
|
||||
notificationElement.setAttribute("mainactiondisabled", "true");
|
||||
} else {
|
||||
notificationElement.button.hidden = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "removed":
|
||||
options.contentWindow = null;
|
||||
options.sourceURI = null;
|
||||
break;
|
||||
}
|
||||
};
|
||||
action = {
|
||||
label: gNavigatorBundle.getString("addonInstall.acceptButton.label"),
|
||||
accessKey: gNavigatorBundle.getString("addonInstall.acceptButton.accesskey"),
|
||||
callback: () => {},
|
||||
};
|
||||
let secondaryAction = {
|
||||
label: gNavigatorBundle.getString("addonInstall.cancelButton.label"),
|
||||
accessKey: gNavigatorBundle.getString("addonInstall.cancelButton.accesskey"),
|
||||
callback: () => {
|
||||
for (let install of installInfo.installs) {
|
||||
if (install.state != AddonManager.STATE_CANCELLED) {
|
||||
install.cancel();
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
let notification = PopupNotifications.show(browser, notificationID, messageString,
|
||||
anchorID, null, null, options);
|
||||
anchorID, action,
|
||||
[secondaryAction], options);
|
||||
notification._startTime = Date.now();
|
||||
|
||||
let cancelButton = document.getElementById("addon-progress-cancel");
|
||||
cancelButton.label = gNavigatorBundle.getString("addonInstall.cancelButton.label");
|
||||
cancelButton.accessKey = gNavigatorBundle.getString("addonInstall.cancelButton.accesskey");
|
||||
|
||||
let acceptButton = document.getElementById("addon-progress-accept");
|
||||
if (Preferences.get("xpinstall.customConfirmationUI", false)) {
|
||||
acceptButton.label = gNavigatorBundle.getString("addonInstall.acceptButton.label");
|
||||
acceptButton.accessKey = gNavigatorBundle.getString("addonInstall.acceptButton.accesskey");
|
||||
} else {
|
||||
acceptButton.hidden = true;
|
||||
}
|
||||
break; }
|
||||
case "addon-install-failed": {
|
||||
// TODO This isn't terribly ideal for the multiple failure case
|
||||
|
@ -567,7 +587,7 @@ var LightWeightThemeWebInstaller = {
|
|||
};
|
||||
|
||||
let options = {
|
||||
timeout: Date.now() + 30000
|
||||
persistent: true
|
||||
};
|
||||
|
||||
PopupNotifications.show(gBrowser.selectedBrowser, "addon-theme-change",
|
||||
|
|
|
@ -278,6 +278,7 @@ var gPluginHandler = {
|
|||
|
||||
let options = {
|
||||
dismissed: !showNow,
|
||||
persistent: showNow,
|
||||
eventCallback: this._clickToPlayNotificationEventCallback,
|
||||
primaryPlugin: primaryPluginPermission,
|
||||
pluginData: pluginData,
|
||||
|
|
|
@ -5970,8 +5970,12 @@ var OfflineApps = {
|
|||
warnQuotaKB / 1024 ]);
|
||||
|
||||
let anchorID = "indexedDB-notification-icon";
|
||||
let options = {
|
||||
persistent: true,
|
||||
hideClose: true,
|
||||
};
|
||||
PopupNotifications.show(browser, "offline-app-usage", message,
|
||||
anchorID, mainAction);
|
||||
anchorID, mainAction, null, options);
|
||||
|
||||
// Now that we've warned once, prevent the warning from showing up
|
||||
// again.
|
||||
|
@ -6030,8 +6034,8 @@ var OfflineApps = {
|
|||
]);
|
||||
} else {
|
||||
let mainAction = {
|
||||
label: gNavigatorBundle.getString("offlineApps.allow"),
|
||||
accessKey: gNavigatorBundle.getString("offlineApps.allowAccessKey"),
|
||||
label: gNavigatorBundle.getString("offlineApps.allowStoring.label"),
|
||||
accessKey: gNavigatorBundle.getString("offlineApps.allowStoring.accesskey"),
|
||||
callback: function() {
|
||||
for (let [ciBrowser, ciDocId, ciUri] of notification.options.controlledItems) {
|
||||
OfflineApps.allowSite(ciBrowser, ciDocId, ciUri);
|
||||
|
@ -6039,18 +6043,20 @@ var OfflineApps = {
|
|||
}
|
||||
};
|
||||
let secondaryActions = [{
|
||||
label: gNavigatorBundle.getString("offlineApps.never"),
|
||||
accessKey: gNavigatorBundle.getString("offlineApps.neverAccessKey"),
|
||||
label: gNavigatorBundle.getString("offlineApps.dontAllow.label"),
|
||||
accessKey: gNavigatorBundle.getString("offlineApps.dontAllow.accesskey"),
|
||||
callback: function() {
|
||||
for (let [, , ciUri] of notification.options.controlledItems) {
|
||||
OfflineApps.disallowSite(ciUri);
|
||||
}
|
||||
}
|
||||
}];
|
||||
let message = gNavigatorBundle.getFormattedString("offlineApps.available",
|
||||
let message = gNavigatorBundle.getFormattedString("offlineApps.available2",
|
||||
[host]);
|
||||
let anchorID = "indexedDB-notification-icon";
|
||||
let options = {
|
||||
persistent: true,
|
||||
hideClose: true,
|
||||
controlledItems : [[Cu.getWeakReference(browser), docId, uri]]
|
||||
};
|
||||
notification = PopupNotifications.show(browser, notificationID, message,
|
||||
|
@ -6132,28 +6138,23 @@ var IndexedDBPromptHelper = {
|
|||
return;
|
||||
}
|
||||
|
||||
var host = browser.currentURI.asciiHost;
|
||||
// Get the host name if available or the file path otherwise.
|
||||
var host = browser.currentURI.asciiHost || browser.currentURI.path;
|
||||
|
||||
var message;
|
||||
var responseTopic;
|
||||
if (topic == this._permissionsPrompt) {
|
||||
message = gNavigatorBundle.getFormattedString("offlineApps.available",
|
||||
message = gNavigatorBundle.getFormattedString("offlineApps.available2",
|
||||
[ host ]);
|
||||
responseTopic = this._permissionsResponse;
|
||||
}
|
||||
|
||||
const hiddenTimeoutDuration = 30000; // 30 seconds
|
||||
const firstTimeoutDuration = 300000; // 5 minutes
|
||||
|
||||
var timeoutId;
|
||||
|
||||
var observer = requestor.getInterface(Ci.nsIObserver);
|
||||
|
||||
var mainAction = {
|
||||
label: gNavigatorBundle.getString("offlineApps.allow"),
|
||||
accessKey: gNavigatorBundle.getString("offlineApps.allowAccessKey"),
|
||||
label: gNavigatorBundle.getString("offlineApps.allowStoring.label"),
|
||||
accessKey: gNavigatorBundle.getString("offlineApps.allowStoring.accesskey"),
|
||||
callback: function() {
|
||||
clearTimeout(timeoutId);
|
||||
observer.observe(null, responseTopic,
|
||||
Ci.nsIPermissionManager.ALLOW_ACTION);
|
||||
}
|
||||
|
@ -6161,64 +6162,21 @@ var IndexedDBPromptHelper = {
|
|||
|
||||
var secondaryActions = [
|
||||
{
|
||||
label: gNavigatorBundle.getString("offlineApps.never"),
|
||||
accessKey: gNavigatorBundle.getString("offlineApps.neverAccessKey"),
|
||||
label: gNavigatorBundle.getString("offlineApps.dontAllow.label"),
|
||||
accessKey: gNavigatorBundle.getString("offlineApps.dontAllow.accesskey"),
|
||||
callback: function() {
|
||||
clearTimeout(timeoutId);
|
||||
observer.observe(null, responseTopic,
|
||||
Ci.nsIPermissionManager.DENY_ACTION);
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
// This will be set to the result of PopupNotifications.show().
|
||||
var notification;
|
||||
|
||||
function timeoutNotification() {
|
||||
// Remove the notification.
|
||||
if (notification) {
|
||||
notification.remove();
|
||||
}
|
||||
|
||||
// Clear all of our timeout stuff. We may be called directly, not just
|
||||
// when the timeout actually elapses.
|
||||
clearTimeout(timeoutId);
|
||||
|
||||
// And tell the page that the popup timed out.
|
||||
observer.observe(null, responseTopic,
|
||||
Ci.nsIPermissionManager.UNKNOWN_ACTION);
|
||||
}
|
||||
|
||||
var options = {
|
||||
eventCallback: function(state) {
|
||||
// Don't do anything if the timeout has not been set yet.
|
||||
if (!timeoutId) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If the popup is being dismissed start the short timeout.
|
||||
if (state == "dismissed") {
|
||||
clearTimeout(timeoutId);
|
||||
timeoutId = setTimeout(timeoutNotification, hiddenTimeoutDuration);
|
||||
return;
|
||||
}
|
||||
|
||||
// If the popup is being re-shown then clear the timeout allowing
|
||||
// unlimited waiting.
|
||||
if (state == "shown") {
|
||||
clearTimeout(timeoutId);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
notification = PopupNotifications.show(browser, topic, message,
|
||||
this._notificationIcon, mainAction,
|
||||
secondaryActions, options);
|
||||
|
||||
// Set the timeoutId after the popup has been created, and use the long
|
||||
// timeout value. If the user doesn't notice the popup after this amount of
|
||||
// time then it is most likely not visible and we want to alert the page.
|
||||
timeoutId = setTimeout(timeoutNotification, firstTimeoutDuration);
|
||||
PopupNotifications.show(browser, topic, message,
|
||||
this._notificationIcon, mainAction,
|
||||
secondaryActions, {
|
||||
persistent: true,
|
||||
hideClose: true,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
<label id="webRTC-selectWindow-label"
|
||||
control="webRTC-selectWindow-menulist"/>
|
||||
<menulist id="webRTC-selectWindow-menulist"
|
||||
oncommand="webrtcUI.updateMainActionLabel(this);">
|
||||
oncommand="webrtcUI.updateWarningLabel(this);">
|
||||
<menupopup id="webRTC-selectWindow-menupopup"/>
|
||||
</menulist>
|
||||
<description id="webRTC-all-windows-shared" hidden="true">&getUserMedia.allWindowsShared.message;</description>
|
||||
|
@ -66,16 +66,8 @@
|
|||
<progressmeter id="addon-progress-notification-progressmeter"/>
|
||||
<label id="addon-progress-notification-progresstext" crop="end"/>
|
||||
</popupnotificationcontent>
|
||||
<button id="addon-progress-cancel"
|
||||
oncommand="this.parentNode.cancel();"/>
|
||||
<button id="addon-progress-accept" disabled="true"/>
|
||||
</popupnotification>
|
||||
|
||||
<popupnotification id="addon-install-confirmation-notification" hidden="true">
|
||||
<popupnotificationcontent id="addon-install-confirmation-content" orient="vertical"/>
|
||||
<button id="addon-install-confirmation-cancel"
|
||||
oncommand="PopupNotifications.getNotification('addon-install-confirmation').remove();"/>
|
||||
<button id="addon-install-confirmation-accept"
|
||||
oncommand="gXPInstallObserver.acceptInstallation();
|
||||
PopupNotifications.getNotification('addon-install-confirmation').remove();"/>
|
||||
</popupnotification>
|
||||
|
|
|
@ -2860,7 +2860,14 @@
|
|||
this.mIsBusy = true;
|
||||
}
|
||||
|
||||
this._swapBrowserDocShells(aOurTab, otherBrowser);
|
||||
this._swapBrowserDocShells(aOurTab, otherBrowser, Ci.nsIBrowser.SWAP_DEFAULT);
|
||||
}
|
||||
|
||||
// Unregister the previously opened URI
|
||||
if (otherBrowser.registeredOpenURI) {
|
||||
this._unifiedComplete.unregisterOpenPage(otherBrowser.registeredOpenURI,
|
||||
otherBrowser.getAttribute("usercontextid") || 0);
|
||||
delete otherBrowser.registeredOpenURI;
|
||||
}
|
||||
|
||||
// Handle findbar data (if any)
|
||||
|
@ -2893,9 +2900,21 @@
|
|||
</body>
|
||||
</method>
|
||||
|
||||
<method name="swapBrowsers">
|
||||
<parameter name="aOurTab"/>
|
||||
<parameter name="aOtherBrowser"/>
|
||||
<parameter name="aFlags"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
this._swapBrowserDocShells(aOurTab, aOtherBrowser, aFlags);
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="_swapBrowserDocShells">
|
||||
<parameter name="aOurTab"/>
|
||||
<parameter name="aOtherBrowser"/>
|
||||
<parameter name="aFlags"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
// Unhook our progress listener
|
||||
|
@ -2937,15 +2956,17 @@
|
|||
remoteBrowser._outerWindowIDBrowserMap.set(aOtherBrowser.outerWindowID, aOtherBrowser);
|
||||
}
|
||||
|
||||
// Swap permanentKey properties.
|
||||
let ourPermanentKey = ourBrowser.permanentKey;
|
||||
ourBrowser.permanentKey = aOtherBrowser.permanentKey;
|
||||
aOtherBrowser.permanentKey = ourPermanentKey;
|
||||
aOurTab.permanentKey = ourBrowser.permanentKey;
|
||||
if (remoteBrowser) {
|
||||
let otherTab = remoteBrowser.getTabForBrowser(aOtherBrowser);
|
||||
if (otherTab) {
|
||||
otherTab.permanentKey = aOtherBrowser.permanentKey;
|
||||
if (!(aFlags & Ci.nsIBrowser.SWAP_KEEP_PERMANENT_KEY)) {
|
||||
// Swap permanentKey properties.
|
||||
let ourPermanentKey = ourBrowser.permanentKey;
|
||||
ourBrowser.permanentKey = aOtherBrowser.permanentKey;
|
||||
aOtherBrowser.permanentKey = ourPermanentKey;
|
||||
aOurTab.permanentKey = ourBrowser.permanentKey;
|
||||
if (remoteBrowser) {
|
||||
let otherTab = remoteBrowser.getTabForBrowser(aOtherBrowser);
|
||||
if (otherTab) {
|
||||
otherTab.permanentKey = aOtherBrowser.permanentKey;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2965,18 +2986,16 @@
|
|||
<parameter name="aOtherBrowser"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
// If the current URI is registered as open remove it from the list.
|
||||
if (aOurBrowser.registeredOpenURI) {
|
||||
this._unifiedComplete.unregisterOpenPage(aOurBrowser.registeredOpenURI,
|
||||
aOurBrowser.getAttribute("usercontextid") || 0);
|
||||
delete aOurBrowser.registeredOpenURI;
|
||||
}
|
||||
|
||||
// If the other/new URI is registered as open then copy it over.
|
||||
// Swap the registeredOpenURI properties of the two browsers
|
||||
let tmp = aOurBrowser.registeredOpenURI;
|
||||
delete aOurBrowser.registeredOpenURI;
|
||||
if (aOtherBrowser.registeredOpenURI) {
|
||||
aOurBrowser.registeredOpenURI = aOtherBrowser.registeredOpenURI;
|
||||
delete aOtherBrowser.registeredOpenURI;
|
||||
}
|
||||
if (tmp) {
|
||||
aOtherBrowser.registeredOpenURI = tmp;
|
||||
}
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
|
|
@ -329,9 +329,10 @@ var gTests = [
|
|||
yield setSignedInUser();
|
||||
let tab = yield promiseNewTabLoadEvent("about:accounts");
|
||||
// sign the user out - the tab should have action=signin
|
||||
let loadPromise = promiseOneMessage(tab, "test:document:load");
|
||||
yield signOut();
|
||||
// wait for the new load.
|
||||
yield promiseOneMessage(tab, "test:document:load");
|
||||
yield loadPromise;
|
||||
is(tab.linkedBrowser.contentDocument.location.href, "about:accounts?action=signin");
|
||||
}
|
||||
},
|
||||
|
@ -435,12 +436,11 @@ function promiseNewTabLoadEvent(aUrl)
|
|||
let browser = tab.linkedBrowser;
|
||||
let mm = browser.messageManager;
|
||||
|
||||
// give it an e10s-friendly content script to help with our tests.
|
||||
mm.loadFrameScript(CHROME_BASE + "content_aboutAccounts.js", true);
|
||||
// give it an e10s-friendly content script to help with our tests,
|
||||
// and wait for it to tell us about the load.
|
||||
return promiseOneMessage(tab, "test:document:load").then(
|
||||
() => tab
|
||||
);
|
||||
let promise = promiseOneMessage(tab, "test:document:load");
|
||||
mm.loadFrameScript(CHROME_BASE + "content_aboutAccounts.js", true);
|
||||
return promise.then(() => tab);
|
||||
}
|
||||
|
||||
// Returns a promise which is resolved with the iframe's URL after a new
|
||||
|
@ -451,13 +451,13 @@ function promiseNewTabWithIframeLoadEvent(aUrl) {
|
|||
let browser = tab.linkedBrowser;
|
||||
let mm = browser.messageManager;
|
||||
|
||||
// give it an e10s-friendly content script to help with our tests.
|
||||
mm.loadFrameScript(CHROME_BASE + "content_aboutAccounts.js", true);
|
||||
// give it an e10s-friendly content script to help with our tests,
|
||||
// and wait for it to tell us about the iframe load.
|
||||
mm.addMessageListener("test:iframe:load", function onFrameLoad(message) {
|
||||
mm.removeMessageListener("test:iframe:load", onFrameLoad);
|
||||
deferred.resolve([tab, message.data.url]);
|
||||
});
|
||||
mm.loadFrameScript(CHROME_BASE + "content_aboutAccounts.js", true);
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
|
|
|
@ -78,6 +78,8 @@ function waitForProgressNotification(aPanelOpen = false, aExpectedCount = 1) {
|
|||
let nodes = Array.from(PopupNotifications.panel.childNodes);
|
||||
let notification = nodes.find(n => n.id == notificationId + "-notification");
|
||||
ok(notification, `Should have seen the right notification`);
|
||||
ok(notification.button.hasAttribute("disabled"),
|
||||
"The install button should be disabled");
|
||||
}
|
||||
|
||||
return PopupNotifications.panel;
|
||||
|
@ -116,13 +118,13 @@ function waitForNotification(aId, aExpectedCount = 1) {
|
|||
yield observerPromise;
|
||||
yield panelEventPromise;
|
||||
|
||||
info("Saw a notification");
|
||||
info("Saw a " + aId + " notification");
|
||||
ok(PopupNotifications.isPanelOpen, "Panel should be open");
|
||||
is(PopupNotifications.panel.childNodes.length, aExpectedCount, "Should be the right number of notifications");
|
||||
if (PopupNotifications.panel.childNodes.length) {
|
||||
let nodes = Array.from(PopupNotifications.panel.childNodes);
|
||||
let notification = nodes.find(n => n.id == aId + "-notification");
|
||||
ok(notification, `Should have seen the right notification`);
|
||||
ok(notification, "Should have seen the " + aId + " notification");
|
||||
}
|
||||
|
||||
return PopupNotifications.panel;
|
||||
|
@ -142,8 +144,8 @@ function waitForNotificationClose() {
|
|||
function waitForInstallDialog() {
|
||||
return Task.spawn(function* () {
|
||||
if (Preferences.get("xpinstall.customConfirmationUI", false)) {
|
||||
yield waitForNotification("addon-install-confirmation");
|
||||
return;
|
||||
let panel = yield waitForNotification("addon-install-confirmation");
|
||||
return panel.childNodes[0];
|
||||
}
|
||||
|
||||
info("Waiting for install dialog");
|
||||
|
@ -176,7 +178,7 @@ function waitForInstallDialog() {
|
|||
let button = domwindow.document.documentElement.getButton("accept");
|
||||
button.disabled = false;
|
||||
|
||||
return;
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -187,18 +189,18 @@ function removeTab() {
|
|||
]);
|
||||
}
|
||||
|
||||
function acceptInstallDialog() {
|
||||
function acceptInstallDialog(installDialog) {
|
||||
if (Preferences.get("xpinstall.customConfirmationUI", false)) {
|
||||
document.getElementById("addon-install-confirmation-accept").click();
|
||||
installDialog.button.click();
|
||||
} else {
|
||||
let win = Services.wm.getMostRecentWindow("Addons:Install");
|
||||
win.document.documentElement.acceptDialog();
|
||||
}
|
||||
}
|
||||
|
||||
function cancelInstallDialog() {
|
||||
function cancelInstallDialog(installDialog) {
|
||||
if (Preferences.get("xpinstall.customConfirmationUI", false)) {
|
||||
document.getElementById("addon-install-confirmation-cancel").click();
|
||||
installDialog.secondaryButton.click();
|
||||
} else {
|
||||
let win = Services.wm.getMostRecentWindow("Addons:Install");
|
||||
win.document.documentElement.cancelDialog();
|
||||
|
@ -293,10 +295,10 @@ function test_blockedInstall() {
|
|||
ok(PopupNotifications.isPanelOpen, "Notification should still be open");
|
||||
notification = panel.childNodes[0];
|
||||
is(notification.id, "addon-progress-notification", "Should have seen the progress notification");
|
||||
yield dialogPromise;
|
||||
let installDialog = yield dialogPromise;
|
||||
|
||||
notificationPromise = waitForNotification("addon-install-restart");
|
||||
acceptInstallDialog();
|
||||
acceptInstallDialog(installDialog);
|
||||
panel = yield notificationPromise;
|
||||
|
||||
notification = panel.childNodes[0];
|
||||
|
@ -328,14 +330,14 @@ function test_whitelistedInstall() {
|
|||
BrowserTestUtils.openNewForegroundTab(gBrowser, TESTROOT + "installtrigger.html?"
|
||||
+ triggers).then(newTab => tab = newTab);
|
||||
yield progressPromise;
|
||||
yield dialogPromise;
|
||||
let installDialog = yield dialogPromise;
|
||||
yield BrowserTestUtils.waitForCondition(() => !!tab, "tab should be present");
|
||||
|
||||
is(gBrowser.selectedTab, tab,
|
||||
"tab selected in response to the addon-install-confirmation notification");
|
||||
|
||||
let notificationPromise = waitForNotification("addon-install-restart");
|
||||
acceptInstallDialog();
|
||||
acceptInstallDialog(installDialog);
|
||||
let panel = yield notificationPromise;
|
||||
|
||||
let notification = panel.childNodes[0];
|
||||
|
@ -440,10 +442,10 @@ function test_restartless() {
|
|||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers);
|
||||
yield progressPromise;
|
||||
yield dialogPromise;
|
||||
let installDialog = yield dialogPromise;
|
||||
|
||||
let notificationPromise = waitForNotification("addon-install-complete");
|
||||
acceptInstallDialog();
|
||||
acceptInstallDialog(installDialog);
|
||||
let panel = yield notificationPromise;
|
||||
|
||||
let notification = panel.childNodes[0];
|
||||
|
@ -482,10 +484,10 @@ function test_multiple() {
|
|||
}));
|
||||
BrowserTestUtils.openNewForegroundTab(gBrowser, TESTROOT + "installtrigger.html?" + triggers);
|
||||
let panel = yield progressPromise;
|
||||
yield dialogPromise;
|
||||
let installDialog = yield dialogPromise;
|
||||
|
||||
let notificationPromise = waitForNotification("addon-install-restart");
|
||||
acceptInstallDialog();
|
||||
acceptInstallDialog(installDialog);
|
||||
yield notificationPromise;
|
||||
|
||||
let notification = panel.childNodes[0];
|
||||
|
@ -512,7 +514,9 @@ function test_multiple() {
|
|||
function test_sequential() {
|
||||
return Task.spawn(function* () {
|
||||
// This test is only relevant if using the new doorhanger UI
|
||||
if (!Preferences.get("xpinstall.customConfirmationUI", false)) {
|
||||
// TODO: this subtest is disabled until multiple notification prompts are
|
||||
// reworked in bug 1188152
|
||||
if (true || !Preferences.get("xpinstall.customConfirmationUI", false)) {
|
||||
return;
|
||||
}
|
||||
let pm = Services.perms;
|
||||
|
@ -525,7 +529,7 @@ function test_sequential() {
|
|||
}));
|
||||
BrowserTestUtils.openNewForegroundTab(gBrowser, TESTROOT + "installtrigger.html?" + triggers);
|
||||
yield progressPromise;
|
||||
yield dialogPromise;
|
||||
let installDialog = yield dialogPromise;
|
||||
|
||||
// Should see the right add-on
|
||||
let container = document.getElementById("addon-install-confirmation-content");
|
||||
|
@ -564,7 +568,7 @@ function test_sequential() {
|
|||
is(container.childNodes.length, 1, "Should be one item listed");
|
||||
is(container.childNodes[0].firstChild.getAttribute("value"), "XPI Test", "Should have the right add-on");
|
||||
|
||||
cancelInstallDialog();
|
||||
cancelInstallDialog(installDialog);
|
||||
|
||||
ok(PopupNotifications.isPanelOpen, "Panel should still be open");
|
||||
is(PopupNotifications.panel.childNodes.length, 1, "Should be the right number of notifications");
|
||||
|
@ -577,7 +581,7 @@ function test_sequential() {
|
|||
|
||||
Services.perms.remove(makeURI("http://example.com"), "install");
|
||||
let closePromise = waitForNotificationClose();
|
||||
cancelInstallDialog();
|
||||
cancelInstallDialog(installDialog);
|
||||
yield closePromise;
|
||||
yield BrowserTestUtils.removeTab(gBrowser.selectedTab);
|
||||
});
|
||||
|
@ -603,7 +607,7 @@ function test_someUnverified() {
|
|||
}));
|
||||
BrowserTestUtils.openNewForegroundTab(gBrowser, TESTROOT + "installtrigger.html?" + triggers);
|
||||
yield progressPromise;
|
||||
yield dialogPromise;
|
||||
let installDialog = yield dialogPromise;
|
||||
|
||||
let notification = document.getElementById("addon-install-confirmation-notification");
|
||||
let message = notification.getAttribute("label");
|
||||
|
@ -620,7 +624,7 @@ function test_someUnverified() {
|
|||
is(container.childNodes[1].childNodes.length, 1, "Shouldn't have the unverified marker");
|
||||
|
||||
let notificationPromise = waitForNotification("addon-install-restart");
|
||||
acceptInstallDialog();
|
||||
acceptInstallDialog(installDialog);
|
||||
yield notificationPromise;
|
||||
|
||||
let [addon, theme] = yield new Promise(resolve => {
|
||||
|
@ -660,7 +664,7 @@ function test_allUnverified() {
|
|||
}));
|
||||
BrowserTestUtils.openNewForegroundTab(gBrowser, TESTROOT + "installtrigger.html?" + triggers);
|
||||
yield progressPromise;
|
||||
yield dialogPromise;
|
||||
let installDialog = yield dialogPromise;
|
||||
|
||||
let notification = document.getElementById("addon-install-confirmation-notification");
|
||||
let message = notification.getAttribute("label");
|
||||
|
@ -672,7 +676,7 @@ function test_allUnverified() {
|
|||
is(container.childNodes[0].childNodes.length, 1, "Shouldn't have the unverified marker");
|
||||
|
||||
let notificationPromise = waitForNotification("addon-install-complete");
|
||||
acceptInstallDialog();
|
||||
acceptInstallDialog(installDialog);
|
||||
yield notificationPromise;
|
||||
|
||||
let addon = yield new Promise(resolve => {
|
||||
|
@ -695,10 +699,10 @@ function test_url() {
|
|||
yield BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
|
||||
gBrowser.loadURI(TESTROOT + "amosigned.xpi");
|
||||
yield progressPromise;
|
||||
yield dialogPromise;
|
||||
let installDialog = yield dialogPromise;
|
||||
|
||||
let notificationPromise = waitForNotification("addon-install-restart");
|
||||
acceptInstallDialog();
|
||||
acceptInstallDialog(installDialog);
|
||||
let panel = yield notificationPromise;
|
||||
|
||||
let notification = panel.childNodes[0];
|
||||
|
@ -863,10 +867,10 @@ function test_reload() {
|
|||
}));
|
||||
BrowserTestUtils.openNewForegroundTab(gBrowser, TESTROOT + "installtrigger.html?" + triggers);
|
||||
yield progressPromise;
|
||||
yield dialogPromise;
|
||||
let installDialog = yield dialogPromise;
|
||||
|
||||
let notificationPromise = waitForNotification("addon-install-restart");
|
||||
acceptInstallDialog();
|
||||
acceptInstallDialog(installDialog);
|
||||
let panel = yield notificationPromise;
|
||||
|
||||
let notification = panel.childNodes[0];
|
||||
|
@ -906,10 +910,10 @@ function test_theme() {
|
|||
}));
|
||||
BrowserTestUtils.openNewForegroundTab(gBrowser, TESTROOT + "installtrigger.html?" + triggers);
|
||||
yield progressPromise;
|
||||
yield dialogPromise;
|
||||
let installDialog = yield dialogPromise;
|
||||
|
||||
let notificationPromise = waitForNotification("addon-install-restart");
|
||||
acceptInstallDialog();
|
||||
acceptInstallDialog(installDialog);
|
||||
let panel = yield notificationPromise;
|
||||
|
||||
let notification = panel.childNodes[0];
|
||||
|
@ -986,11 +990,11 @@ function test_renotifyInstalled() {
|
|||
}));
|
||||
BrowserTestUtils.openNewForegroundTab(gBrowser, TESTROOT + "installtrigger.html?" + triggers);
|
||||
yield progressPromise;
|
||||
yield dialogPromise;
|
||||
let installDialog = yield dialogPromise;
|
||||
|
||||
// Wait for the complete notification
|
||||
let notificationPromise = waitForNotification("addon-install-restart");
|
||||
acceptInstallDialog();
|
||||
acceptInstallDialog(installDialog);
|
||||
let panel = yield notificationPromise;
|
||||
|
||||
let closePromise = waitForNotificationClose();
|
||||
|
@ -1005,13 +1009,13 @@ function test_renotifyInstalled() {
|
|||
dialogPromise = waitForInstallDialog();
|
||||
gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers);
|
||||
yield progressPromise;
|
||||
yield dialogPromise;
|
||||
installDialog = yield dialogPromise;
|
||||
|
||||
info("Timeouts after this probably mean bug 589954 regressed");
|
||||
|
||||
// Wait for the complete notification
|
||||
notificationPromise = waitForNotification("addon-install-restart");
|
||||
acceptInstallDialog();
|
||||
acceptInstallDialog(installDialog);
|
||||
yield notificationPromise;
|
||||
|
||||
let installs = yield getInstalls();
|
||||
|
@ -1046,7 +1050,6 @@ function test_cancel() {
|
|||
is(PopupNotifications.panel.childNodes.length, 1, "Should be only one notification");
|
||||
notification = panel.childNodes[0];
|
||||
is(notification.id, "addon-progress-notification", "Should have seen the progress notification");
|
||||
let button = document.getElementById("addon-progress-cancel");
|
||||
|
||||
// Cancel the download
|
||||
let install = notification.notification.options.installs[0];
|
||||
|
@ -1058,7 +1061,7 @@ function test_cancel() {
|
|||
}
|
||||
});
|
||||
});
|
||||
EventUtils.synthesizeMouseAtCenter(button, {});
|
||||
EventUtils.synthesizeMouseAtCenter(notification.secondaryButton, {});
|
||||
yield cancelledPromise;
|
||||
|
||||
yield new Promise(resolve => executeSoon(resolve));
|
||||
|
|
|
@ -12,6 +12,8 @@ skip-if = (os == "linux" && (debug || asan))
|
|||
skip-if = (os == "linux" && (debug || asan))
|
||||
[browser_popupNotification_4.js]
|
||||
skip-if = (os == "linux" && (debug || asan))
|
||||
[browser_popupNotification_5.js]
|
||||
skip-if = (os == "linux" && (debug || asan))
|
||||
[browser_popupNotification_checkbox.js]
|
||||
skip-if = (os == "linux" && (debug || asan))
|
||||
[browser_reshow_in_background.js]
|
||||
|
|
|
@ -47,6 +47,50 @@ var tests = [
|
|||
ok(this.notifyObj.removedCallbackTriggered, "removed callback triggered");
|
||||
}
|
||||
},
|
||||
{ id: "Test#2b",
|
||||
run: function() {
|
||||
this.notifyObj = new BasicNotification(this.id);
|
||||
this.notifyObj.secondaryActions.push({
|
||||
label: "Extra Secondary Action",
|
||||
accessKey: "E",
|
||||
callback: () => this.extraSecondaryActionClicked = true,
|
||||
});
|
||||
showNotification(this.notifyObj);
|
||||
},
|
||||
onShown: function(popup) {
|
||||
checkPopup(popup, this.notifyObj);
|
||||
triggerSecondaryCommand(popup, 1);
|
||||
},
|
||||
onHidden: function(popup) {
|
||||
ok(this.extraSecondaryActionClicked, "extra secondary action was clicked");
|
||||
ok(!this.notifyObj.dismissalCallbackTriggered, "dismissal callback wasn't triggered");
|
||||
ok(this.notifyObj.removedCallbackTriggered, "removed callback triggered");
|
||||
}
|
||||
},
|
||||
{ id: "Test#2c",
|
||||
run: function() {
|
||||
this.notifyObj = new BasicNotification(this.id);
|
||||
this.notifyObj.secondaryActions.push({
|
||||
label: "Extra Secondary Action",
|
||||
accessKey: "E",
|
||||
callback: () => ok(false, "unexpected callback invocation"),
|
||||
}, {
|
||||
label: "Other Extra Secondary Action",
|
||||
accessKey: "O",
|
||||
callback: () => this.extraSecondaryActionClicked = true,
|
||||
});
|
||||
showNotification(this.notifyObj);
|
||||
},
|
||||
onShown: function(popup) {
|
||||
checkPopup(popup, this.notifyObj);
|
||||
triggerSecondaryCommand(popup, 2);
|
||||
},
|
||||
onHidden: function(popup) {
|
||||
ok(this.extraSecondaryActionClicked, "extra secondary action was clicked");
|
||||
ok(!this.notifyObj.dismissalCallbackTriggered, "dismissal callback wasn't triggered");
|
||||
ok(this.notifyObj.removedCallbackTriggered, "removed callback triggered");
|
||||
}
|
||||
},
|
||||
{ id: "Test#3",
|
||||
run: function() {
|
||||
this.notifyObj = new BasicNotification(this.id);
|
||||
|
|
|
@ -187,22 +187,6 @@ var tests = [
|
|||
goNext();
|
||||
}
|
||||
},
|
||||
// Test notification "Not Now" menu item
|
||||
{ id: "Test#8",
|
||||
run: function() {
|
||||
this.notifyObj = new BasicNotification(this.id);
|
||||
this.notification = showNotification(this.notifyObj);
|
||||
},
|
||||
onShown: function(popup) {
|
||||
checkPopup(popup, this.notifyObj);
|
||||
triggerSecondaryCommand(popup, 1);
|
||||
},
|
||||
onHidden: function(popup) {
|
||||
ok(this.notifyObj.dismissalCallbackTriggered, "dismissal callback triggered");
|
||||
this.notification.remove();
|
||||
ok(this.notifyObj.removedCallbackTriggered, "removed callback triggered");
|
||||
}
|
||||
},
|
||||
// Test notification close button
|
||||
{ id: "Test#9",
|
||||
run: function() {
|
||||
|
|
|
@ -160,23 +160,6 @@ var tests = [
|
|||
goNext();
|
||||
}
|
||||
},
|
||||
// the hideNotNow option
|
||||
{ id: "Test#7",
|
||||
run: function() {
|
||||
this.notifyObj = new BasicNotification(this.id);
|
||||
this.notifyObj.options.hideNotNow = true;
|
||||
this.notifyObj.mainAction.dismiss = true;
|
||||
this.notification = showNotification(this.notifyObj);
|
||||
},
|
||||
onShown: function(popup) {
|
||||
// checkPopup verifies that the Not Now item is hidden, and that no separator is added.
|
||||
checkPopup(popup, this.notifyObj);
|
||||
triggerMainCommand(popup);
|
||||
},
|
||||
onHidden: function(popup) {
|
||||
this.notification.remove();
|
||||
}
|
||||
},
|
||||
// the main action callback can keep the notification.
|
||||
{ id: "Test#8",
|
||||
run: function() {
|
||||
|
@ -227,68 +210,5 @@ var tests = [
|
|||
notification.remove();
|
||||
goNext();
|
||||
}
|
||||
},
|
||||
// panel updates should fire the showing and shown callbacks again.
|
||||
{ id: "Test#11",
|
||||
run: function() {
|
||||
this.notifyObj = new BasicNotification(this.id);
|
||||
this.notification = showNotification(this.notifyObj);
|
||||
},
|
||||
onShown: function(popup) {
|
||||
checkPopup(popup, this.notifyObj);
|
||||
|
||||
this.notifyObj.showingCallbackTriggered = false;
|
||||
this.notifyObj.shownCallbackTriggered = false;
|
||||
|
||||
// Force an update of the panel. This is typically called
|
||||
// automatically when receiving 'activate' or 'TabSelect' events,
|
||||
// but from a setTimeout, which is inconvenient for the test.
|
||||
PopupNotifications._update();
|
||||
|
||||
checkPopup(popup, this.notifyObj);
|
||||
|
||||
this.notification.remove();
|
||||
},
|
||||
onHidden: function() { }
|
||||
},
|
||||
// A first dismissed notification shouldn't stop _update from showing a second notification
|
||||
{ id: "Test#12",
|
||||
run: function() {
|
||||
this.notifyObj1 = new BasicNotification(this.id);
|
||||
this.notifyObj1.id += "_1";
|
||||
this.notifyObj1.anchorID = "default-notification-icon";
|
||||
this.notifyObj1.options.dismissed = true;
|
||||
this.notification1 = showNotification(this.notifyObj1);
|
||||
|
||||
this.notifyObj2 = new BasicNotification(this.id);
|
||||
this.notifyObj2.id += "_2";
|
||||
this.notifyObj2.anchorID = "geo-notification-icon";
|
||||
this.notifyObj2.options.dismissed = true;
|
||||
this.notification2 = showNotification(this.notifyObj2);
|
||||
|
||||
this.notification2.dismissed = false;
|
||||
PopupNotifications._update();
|
||||
},
|
||||
onShown: function(popup) {
|
||||
checkPopup(popup, this.notifyObj2);
|
||||
this.notification1.remove();
|
||||
this.notification2.remove();
|
||||
},
|
||||
onHidden: function(popup) { }
|
||||
},
|
||||
// The anchor icon should be shown for notifications in background windows.
|
||||
{ id: "Test#13",
|
||||
run: function() {
|
||||
let notifyObj = new BasicNotification(this.id);
|
||||
notifyObj.options.dismissed = true;
|
||||
let win = gBrowser.replaceTabWithWindow(gBrowser.addTab("about:blank"));
|
||||
whenDelayedStartupFinished(win, function() {
|
||||
showNotification(notifyObj);
|
||||
let anchor = document.getElementById("default-notification-icon");
|
||||
is(anchor.getAttribute("showing"), "true", "the anchor is shown");
|
||||
win.close();
|
||||
goNext();
|
||||
});
|
||||
}
|
||||
}
|
||||
];
|
||||
|
|
|
@ -0,0 +1,265 @@
|
|||
/* 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/. */
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
ok(PopupNotifications, "PopupNotifications object exists");
|
||||
ok(PopupNotifications.panel, "PopupNotifications panel exists");
|
||||
|
||||
setup();
|
||||
goNext();
|
||||
}
|
||||
|
||||
var gNotification;
|
||||
|
||||
var tests = [
|
||||
// panel updates should fire the showing and shown callbacks again.
|
||||
{ id: "Test#1",
|
||||
run: function() {
|
||||
this.notifyObj = new BasicNotification(this.id);
|
||||
this.notification = showNotification(this.notifyObj);
|
||||
},
|
||||
onShown: function(popup) {
|
||||
checkPopup(popup, this.notifyObj);
|
||||
|
||||
this.notifyObj.showingCallbackTriggered = false;
|
||||
this.notifyObj.shownCallbackTriggered = false;
|
||||
|
||||
// Force an update of the panel. This is typically called
|
||||
// automatically when receiving 'activate' or 'TabSelect' events,
|
||||
// but from a setTimeout, which is inconvenient for the test.
|
||||
PopupNotifications._update();
|
||||
|
||||
checkPopup(popup, this.notifyObj);
|
||||
|
||||
this.notification.remove();
|
||||
},
|
||||
onHidden: function() { }
|
||||
},
|
||||
// A first dismissed notification shouldn't stop _update from showing a second notification
|
||||
{ id: "Test#2",
|
||||
run: function() {
|
||||
this.notifyObj1 = new BasicNotification(this.id);
|
||||
this.notifyObj1.id += "_1";
|
||||
this.notifyObj1.anchorID = "default-notification-icon";
|
||||
this.notifyObj1.options.dismissed = true;
|
||||
this.notification1 = showNotification(this.notifyObj1);
|
||||
|
||||
this.notifyObj2 = new BasicNotification(this.id);
|
||||
this.notifyObj2.id += "_2";
|
||||
this.notifyObj2.anchorID = "geo-notification-icon";
|
||||
this.notifyObj2.options.dismissed = true;
|
||||
this.notification2 = showNotification(this.notifyObj2);
|
||||
|
||||
this.notification2.dismissed = false;
|
||||
PopupNotifications._update();
|
||||
},
|
||||
onShown: function(popup) {
|
||||
checkPopup(popup, this.notifyObj2);
|
||||
this.notification1.remove();
|
||||
this.notification2.remove();
|
||||
},
|
||||
onHidden: function(popup) { }
|
||||
},
|
||||
// The anchor icon should be shown for notifications in background windows.
|
||||
{ id: "Test#3",
|
||||
run: function() {
|
||||
let notifyObj = new BasicNotification(this.id);
|
||||
notifyObj.options.dismissed = true;
|
||||
let win = gBrowser.replaceTabWithWindow(gBrowser.addTab("about:blank"));
|
||||
whenDelayedStartupFinished(win, function() {
|
||||
showNotification(notifyObj);
|
||||
let anchor = document.getElementById("default-notification-icon");
|
||||
is(anchor.getAttribute("showing"), "true", "the anchor is shown");
|
||||
win.close();
|
||||
goNext();
|
||||
});
|
||||
}
|
||||
},
|
||||
// Test that persistent doesn't allow the notification to persist after
|
||||
// navigation.
|
||||
{ id: "Test#4",
|
||||
run: function* () {
|
||||
this.oldSelectedTab = gBrowser.selectedTab;
|
||||
gBrowser.selectedTab = gBrowser.addTab("about:blank");
|
||||
yield promiseTabLoadEvent(gBrowser.selectedTab, "http://example.com/");
|
||||
this.notifyObj = new BasicNotification(this.id);
|
||||
this.notifyObj.addOptions({
|
||||
persistent: true
|
||||
});
|
||||
this.notification = showNotification(this.notifyObj);
|
||||
},
|
||||
onShown: function* (popup) {
|
||||
this.complete = false;
|
||||
|
||||
yield promiseTabLoadEvent(gBrowser.selectedTab, "http://example.org/");
|
||||
yield promiseTabLoadEvent(gBrowser.selectedTab, "http://example.com/");
|
||||
|
||||
// This code should not be executed.
|
||||
ok(false, "Should have removed the notification after navigation");
|
||||
// Properly dismiss and cleanup in case the unthinkable happens.
|
||||
this.complete = true;
|
||||
triggerSecondaryCommand(popup, 0);
|
||||
},
|
||||
onHidden: function(popup) {
|
||||
ok(!this.complete, "Should have hidden the notification after navigation");
|
||||
this.notification.remove();
|
||||
gBrowser.removeTab(gBrowser.selectedTab);
|
||||
gBrowser.selectedTab = this.oldSelectedTab;
|
||||
}
|
||||
},
|
||||
// Test that persistent allows the notification to persist until explicitly
|
||||
// dismissed.
|
||||
{ id: "Test#5",
|
||||
run: function* () {
|
||||
this.oldSelectedTab = gBrowser.selectedTab;
|
||||
gBrowser.selectedTab = gBrowser.addTab("about:blank");
|
||||
yield promiseTabLoadEvent(gBrowser.selectedTab, "http://example.com/");
|
||||
this.notifyObj = new BasicNotification(this.id);
|
||||
this.notifyObj.addOptions({
|
||||
persistent: true
|
||||
});
|
||||
this.notification = showNotification(this.notifyObj);
|
||||
},
|
||||
onShown: function* (popup) {
|
||||
this.complete = false;
|
||||
|
||||
// Notification should persist after attempt to dismiss by clicking on the
|
||||
// content area.
|
||||
let browser = gBrowser.selectedBrowser;
|
||||
yield BrowserTestUtils.synthesizeMouseAtCenter("body", {}, browser)
|
||||
|
||||
// Notification should be hidden after dismissal via Don't Allow.
|
||||
this.complete = true;
|
||||
triggerSecondaryCommand(popup, 0);
|
||||
},
|
||||
onHidden: function(popup) {
|
||||
ok(this.complete, "Should have hidden the notification after clicking Not Now");
|
||||
this.notification.remove();
|
||||
gBrowser.removeTab(gBrowser.selectedTab);
|
||||
gBrowser.selectedTab = this.oldSelectedTab;
|
||||
}
|
||||
},
|
||||
// Test that persistent panels are still open after switching to another tab
|
||||
// and back.
|
||||
{ id: "Test#6a",
|
||||
run: function* () {
|
||||
this.notifyObj = new BasicNotification(this.id);
|
||||
this.notifyObj.options.persistent = true;
|
||||
gNotification = showNotification(this.notifyObj);
|
||||
},
|
||||
onShown: function* (popup) {
|
||||
this.oldSelectedTab = gBrowser.selectedTab;
|
||||
gBrowser.selectedTab = gBrowser.addTab("about:blank");
|
||||
info("Waiting for the new tab to load.");
|
||||
yield promiseTabLoadEvent(gBrowser.selectedTab, "http://example.com/");
|
||||
},
|
||||
onHidden: function(popup) {
|
||||
ok(true, "Should have hidden the notification after tab switch");
|
||||
gBrowser.removeTab(gBrowser.selectedTab);
|
||||
gBrowser.selectedTab = this.oldSelectedTab;
|
||||
}
|
||||
},
|
||||
// Second part of the previous test that compensates for the limitation in
|
||||
// runNextTest that expects a single onShown/onHidden invocation per test.
|
||||
{ id: "Test#6b",
|
||||
run: function* () {
|
||||
let id = PopupNotifications.panel.firstChild.getAttribute("popupid");
|
||||
ok(id.endsWith("Test#6a"), "Should have found the notification from Test6a");
|
||||
ok(PopupNotifications.isPanelOpen, "Should have shown the popup again after getting back to the tab");
|
||||
gNotification.remove();
|
||||
gNotification = null;
|
||||
goNext();
|
||||
}
|
||||
},
|
||||
// Test that persistent panels are still open after switching to another
|
||||
// window and back.
|
||||
{ id: "Test#7",
|
||||
run: function* () {
|
||||
this.oldSelectedTab = gBrowser.selectedTab;
|
||||
gBrowser.selectedTab = gBrowser.addTab("about:blank");
|
||||
let notifyObj = new BasicNotification(this.id);
|
||||
notifyObj.options.persistent = true;
|
||||
this.notification = showNotification(notifyObj);
|
||||
let win = gBrowser.replaceTabWithWindow(gBrowser.addTab("about:blank"));
|
||||
whenDelayedStartupFinished(win, () => {
|
||||
ok(notifyObj.shownCallbackTriggered, "Should have triggered the shown callback");
|
||||
let anchor = win.document.getElementById("default-notification-icon");
|
||||
win.PopupNotifications._reshowNotifications(anchor);
|
||||
ok(win.PopupNotifications.panel.childNodes.length == 0,
|
||||
"no notification displayed in new window");
|
||||
ok(PopupNotifications.isPanelOpen, "Should be still showing the popup in the first window");
|
||||
win.close();
|
||||
let id = PopupNotifications.panel.firstChild.getAttribute("popupid");
|
||||
ok(id.endsWith("Test#7"), "Should have found the notification from Test7");
|
||||
ok(PopupNotifications.isPanelOpen, "Should have shown the popup again after getting back to the window");
|
||||
this.notification.remove();
|
||||
gBrowser.removeTab(gBrowser.selectedTab);
|
||||
gBrowser.selectedTab = this.oldSelectedTab;
|
||||
goNext();
|
||||
});
|
||||
}
|
||||
},
|
||||
// Test that only the first persistent notification is shown on update
|
||||
{ id: "Test#8",
|
||||
run: function() {
|
||||
this.notifyObj1 = new BasicNotification(this.id);
|
||||
this.notifyObj1.id += "_1";
|
||||
this.notifyObj1.anchorID = "default-notification-icon";
|
||||
this.notifyObj1.options.persistent = true;
|
||||
this.notification1 = showNotification(this.notifyObj1);
|
||||
|
||||
this.notifyObj2 = new BasicNotification(this.id);
|
||||
this.notifyObj2.id += "_2";
|
||||
this.notifyObj2.anchorID = "geo-notification-icon";
|
||||
this.notifyObj2.options.persistent = true;
|
||||
this.notification2 = showNotification(this.notifyObj2);
|
||||
|
||||
PopupNotifications._update();
|
||||
},
|
||||
onShown: function(popup) {
|
||||
checkPopup(popup, this.notifyObj1);
|
||||
this.notification1.remove();
|
||||
this.notification2.remove();
|
||||
},
|
||||
onHidden: function(popup) { }
|
||||
},
|
||||
// Test that persistent notifications are shown stacked by anchor on update
|
||||
{ id: "Test#9",
|
||||
run: function() {
|
||||
this.notifyObj1 = new BasicNotification(this.id);
|
||||
this.notifyObj1.id += "_1";
|
||||
this.notifyObj1.anchorID = "default-notification-icon";
|
||||
this.notifyObj1.options.persistent = true;
|
||||
this.notification1 = showNotification(this.notifyObj1);
|
||||
|
||||
this.notifyObj2 = new BasicNotification(this.id);
|
||||
this.notifyObj2.id += "_2";
|
||||
this.notifyObj2.anchorID = "geo-notification-icon";
|
||||
this.notifyObj2.options.persistent = true;
|
||||
this.notification2 = showNotification(this.notifyObj2);
|
||||
|
||||
this.notifyObj3 = new BasicNotification(this.id);
|
||||
this.notifyObj3.id += "_3";
|
||||
this.notifyObj3.anchorID = "default-notification-icon";
|
||||
this.notifyObj3.options.persistent = true;
|
||||
this.notification3 = showNotification(this.notifyObj3);
|
||||
|
||||
PopupNotifications._update();
|
||||
},
|
||||
onShown: function(popup) {
|
||||
let notifications = popup.childNodes;
|
||||
is(notifications.length, 2, "two notifications displayed");
|
||||
let [notification1, notification2] = notifications;
|
||||
is(notification1.id, this.notifyObj1.id + "-notification", "id 1 matches");
|
||||
is(notification2.id, this.notifyObj3.id + "-notification", "id 2 matches");
|
||||
|
||||
this.notification1.remove();
|
||||
this.notification2.remove();
|
||||
this.notification3.remove();
|
||||
},
|
||||
onHidden: function(popup) { }
|
||||
},
|
||||
];
|
|
@ -213,25 +213,24 @@ function checkPopup(popup, notifyObj) {
|
|||
is(notification.getAttribute("buttonaccesskey"),
|
||||
notifyObj.mainAction.accessKey, "main action accesskey matches");
|
||||
}
|
||||
let actualSecondaryActions =
|
||||
if (notifyObj.secondaryActions && notifyObj.secondaryActions.length > 0) {
|
||||
let secondaryAction = notifyObj.secondaryActions[0];
|
||||
is(notification.getAttribute("secondarybuttonlabel"), secondaryAction.label,
|
||||
"secondary action label matches");
|
||||
is(notification.getAttribute("secondarybuttonaccesskey"),
|
||||
secondaryAction.accessKey, "secondary action accesskey matches");
|
||||
}
|
||||
// Additional secondary actions appear as menu items.
|
||||
let actualExtraSecondaryActions =
|
||||
Array.filter(notification.childNodes, child => child.nodeName == "menuitem");
|
||||
let secondaryActions = notifyObj.secondaryActions || [];
|
||||
let actualSecondaryActionsCount = actualSecondaryActions.length;
|
||||
if (notifyObj.options.hideNotNow) {
|
||||
is(notification.getAttribute("hidenotnow"), "true", "'Not Now' item hidden");
|
||||
if (secondaryActions.length)
|
||||
is(notification.lastChild.tagName, "menuitem", "no menuseparator");
|
||||
}
|
||||
else if (secondaryActions.length) {
|
||||
is(notification.lastChild.tagName, "menuseparator", "menuseparator exists");
|
||||
}
|
||||
is(actualSecondaryActionsCount, secondaryActions.length,
|
||||
actualSecondaryActions.length + " secondary actions");
|
||||
secondaryActions.forEach(function(a, i) {
|
||||
is(actualSecondaryActions[i].getAttribute("label"), a.label,
|
||||
"label for secondary action " + i + " matches");
|
||||
is(actualSecondaryActions[i].getAttribute("accesskey"), a.accessKey,
|
||||
"accessKey for secondary action " + i + " matches");
|
||||
let extraSecondaryActions = notifyObj.secondaryActions ? notifyObj.secondaryActions.slice(1) : [];
|
||||
is(actualExtraSecondaryActions.length, extraSecondaryActions.length,
|
||||
"number of extra secondary actions matches");
|
||||
extraSecondaryActions.forEach(function(a, i) {
|
||||
is(actualExtraSecondaryActions[i].getAttribute("label"), a.label,
|
||||
"label for extra secondary action " + i + " matches");
|
||||
is(actualExtraSecondaryActions[i].getAttribute("accesskey"), a.accessKey,
|
||||
"accessKey for extra secondary action " + i + " matches");
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -263,8 +262,7 @@ function triggerMainCommand(popup) {
|
|||
ok(notifications.length > 0, "at least one notification displayed");
|
||||
let notification = notifications[0];
|
||||
info("Triggering main command for notification " + notification.id);
|
||||
// 20, 10 so that the inner button is hit
|
||||
EventUtils.synthesizeMouse(notification.button, 20, 10, {});
|
||||
EventUtils.synthesizeMouseAtCenter(notification.button, {});
|
||||
}
|
||||
|
||||
function triggerSecondaryCommand(popup, index) {
|
||||
|
@ -272,17 +270,21 @@ function triggerSecondaryCommand(popup, index) {
|
|||
ok(notifications.length > 0, "at least one notification displayed");
|
||||
let notification = notifications[0];
|
||||
info("Triggering secondary command for notification " + notification.id);
|
||||
// Cancel the arrow panel slide-in transition (bug 767133) such that
|
||||
// it won't interfere with us interacting with the dropdown.
|
||||
document.getAnonymousNodes(popup)[0].style.transition = "none";
|
||||
|
||||
notification.button.focus();
|
||||
if (index == 0) {
|
||||
EventUtils.synthesizeMouseAtCenter(notification.secondaryButton, {});
|
||||
return;
|
||||
}
|
||||
|
||||
// Extra secondary actions appear in a menu.
|
||||
notification.secondaryButton.nextSibling.nextSibling.focus();
|
||||
|
||||
popup.addEventListener("popupshown", function handle() {
|
||||
popup.removeEventListener("popupshown", handle, false);
|
||||
info("Command popup open for notification " + notification.id);
|
||||
// Press down until the desired command is selected
|
||||
for (let i = 0; i <= index; i++) {
|
||||
// Press down until the desired command is selected. Decrease index by one
|
||||
// since the secondary action was handled above.
|
||||
for (let i = 0; i <= index - 1; i++) {
|
||||
EventUtils.synthesizeKey("VK_DOWN", {});
|
||||
}
|
||||
// Activate
|
||||
|
|
|
@ -111,32 +111,44 @@ function clickAddonRemoveButton(tab, aCallback) {
|
|||
}
|
||||
|
||||
function activateOneProvider(manifest, finishActivation, aCallback) {
|
||||
info("activating provider " + manifest.name);
|
||||
let panel = document.getElementById("servicesInstall-notification");
|
||||
BrowserTestUtils.waitForEvent(PopupNotifications.panel, "popupshown").then(() => {
|
||||
ok(!panel.hidden, "servicesInstall-notification panel opened");
|
||||
if (finishActivation)
|
||||
panel.button.click();
|
||||
else
|
||||
panel.closebutton.click();
|
||||
});
|
||||
BrowserTestUtils.waitForEvent(PopupNotifications.panel, "popuphidden").then(() => {
|
||||
ok(panel.hidden, "servicesInstall-notification panel hidden");
|
||||
if (!finishActivation) {
|
||||
ok(panel.hidden, "activation panel is not showing");
|
||||
executeSoon(aCallback);
|
||||
} else {
|
||||
waitForProviderLoad(manifest.origin).then(() => {
|
||||
checkSocialUI();
|
||||
executeSoon(aCallback);
|
||||
});
|
||||
}
|
||||
});
|
||||
Task.spawn(function* () {
|
||||
info("activating provider " + manifest.name);
|
||||
|
||||
// the test will continue as the popup events fire...
|
||||
activateProvider(manifest.origin, function() {
|
||||
info("waiting on activation panel to open/close...");
|
||||
});
|
||||
// Wait for the helper callback and the popup shown event in any order.
|
||||
let popupShown = BrowserTestUtils.waitForEvent(PopupNotifications.panel,
|
||||
"popupshown");
|
||||
yield new Promise(resolve => activateProvider(manifest.origin, resolve));
|
||||
yield popupShown;
|
||||
|
||||
info("servicesInstall-notification panel opened");
|
||||
|
||||
// Start waiting for the activation event before the click on the button.
|
||||
let providerLoaded = finishActivation ?
|
||||
waitForProviderLoad(manifest.origin) : null;
|
||||
let popupHidden = BrowserTestUtils.waitForEvent(PopupNotifications.panel,
|
||||
"popuphidden");
|
||||
|
||||
// We need to wait for PopupNotifications.jsm to place the element.
|
||||
let notification;
|
||||
yield BrowserTestUtils.waitForCondition(
|
||||
() => (notification = PopupNotifications.panel.childNodes[0]));
|
||||
is(notification.id, "servicesInstall-notification");
|
||||
|
||||
if (finishActivation) {
|
||||
notification.button.click();
|
||||
} else {
|
||||
notification.closebutton.click();
|
||||
}
|
||||
|
||||
yield providerLoaded;
|
||||
yield popupHidden;
|
||||
|
||||
info("servicesInstall-notification panel hidden");
|
||||
|
||||
if (finishActivation) {
|
||||
checkSocialUI();
|
||||
}
|
||||
}).then(() => executeSoon(aCallback)).catch(ex => ok(false, ex));
|
||||
}
|
||||
|
||||
var gTestDomains = ["https://example.com", "https://test1.example.com", "https://test2.example.com"];
|
||||
|
|
|
@ -474,7 +474,7 @@ var gTests = [
|
|||
},
|
||||
|
||||
{
|
||||
desc: "'Always Allow' ignored and not shown on http pages",
|
||||
desc: "'Always Allow' disabled on http pages",
|
||||
run: function* checkNoAlwaysOnHttp() {
|
||||
// Load an http page instead of the https version.
|
||||
let browser = gBrowser.selectedBrowser;
|
||||
|
@ -494,16 +494,16 @@ var gTests = [
|
|||
yield promise;
|
||||
yield expectObserverCalled("getUserMedia:request");
|
||||
|
||||
// Ensure that the 'Always Allow' action isn't shown.
|
||||
let alwaysLabel = gNavigatorBundle.getString("getUserMedia.always.label");
|
||||
ok(!!alwaysLabel, "found the 'Always Allow' localized label");
|
||||
let labels = [];
|
||||
// Ensure that checking the 'Remember this decision' checkbox disables
|
||||
// 'Allow'.
|
||||
let notification = PopupNotifications.panel.firstChild;
|
||||
for (let node of notification.childNodes) {
|
||||
if (node.localName == "menuitem")
|
||||
labels.push(node.getAttribute("label"));
|
||||
}
|
||||
is(labels.indexOf(alwaysLabel), -1, "The 'Always Allow' item isn't shown");
|
||||
let checkbox = notification.checkbox;
|
||||
ok(!!checkbox, "checkbox is present");
|
||||
ok(!checkbox.checked, "checkbox is not checked");
|
||||
checkbox.click();
|
||||
ok(checkbox.checked, "checkbox now checked");
|
||||
ok(notification.button.disabled, "Allow button is disabled");
|
||||
ok(!notification.hasAttribute("warninghidden"), "warning message is shown");
|
||||
|
||||
// Cleanup.
|
||||
yield closeStream(true);
|
||||
|
|
|
@ -305,22 +305,17 @@ const kActionNever = 3;
|
|||
|
||||
function activateSecondaryAction(aAction) {
|
||||
let notification = PopupNotifications.panel.firstChild;
|
||||
notification.button.focus();
|
||||
let popup = notification.menupopup;
|
||||
popup.addEventListener("popupshown", function() {
|
||||
popup.removeEventListener("popupshown", arguments.callee, false);
|
||||
|
||||
// Press 'down' as many time as needed to select the requested action.
|
||||
while (aAction--)
|
||||
EventUtils.synthesizeKey("VK_DOWN", {});
|
||||
|
||||
// Activate
|
||||
EventUtils.synthesizeKey("VK_RETURN", {});
|
||||
}, false);
|
||||
|
||||
// One down event to open the popup
|
||||
EventUtils.synthesizeKey("VK_DOWN",
|
||||
{ altKey: !navigator.platform.includes("Mac") });
|
||||
switch (aAction) {
|
||||
case kActionNever:
|
||||
notification.checkbox.setAttribute("checked", true); // fallthrough
|
||||
case kActionDeny:
|
||||
notification.secondaryButton.click();
|
||||
break;
|
||||
case kActionAlways:
|
||||
notification.checkbox.setAttribute("checked", true);
|
||||
notification.button.click();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function getMediaCaptureState() {
|
||||
|
|
|
@ -83,7 +83,7 @@
|
|||
.subviewbutton[usercontextid] > .toolbarbutton-icon,
|
||||
#userContext-indicator {
|
||||
background-image: var(--identity-icon);
|
||||
filter: url(chrome://browser/skin/filters.svg#fill);
|
||||
filter: url(chrome://global/skin/filters.svg#fill);
|
||||
fill: var(--identity-icon-color);
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
|
|
|
@ -87,8 +87,9 @@ add_task(function* testBrowserActionDisabled() {
|
|||
},
|
||||
},
|
||||
|
||||
background() {
|
||||
browser.browserAction.disable();
|
||||
background: async function() {
|
||||
await browser.browserAction.disable();
|
||||
browser.test.sendMessage("browserAction-disabled");
|
||||
},
|
||||
|
||||
files: {
|
||||
|
@ -101,6 +102,8 @@ add_task(function* testBrowserActionDisabled() {
|
|||
|
||||
yield extension.startup();
|
||||
|
||||
yield extension.awaitMessage("browserAction-disabled");
|
||||
|
||||
const {GlobalManager, Management: {global: {browserActionFor}}} = Cu.import("resource://gre/modules/Extension.jsm", {});
|
||||
|
||||
let ext = GlobalManager.extensionMap.get(extension.id);
|
||||
|
@ -108,6 +111,9 @@ add_task(function* testBrowserActionDisabled() {
|
|||
|
||||
let widget = getBrowserActionWidget(extension).forWindow(window);
|
||||
|
||||
is(widget.node.getAttribute("disabled"), "true", "Button is disabled");
|
||||
is(browserAction.pendingPopup, null, "Have no pending popup prior to click");
|
||||
|
||||
// Test canceled click.
|
||||
EventUtils.synthesizeMouseAtCenter(widget.node, {type: "mousedown", button: 0}, window);
|
||||
|
||||
|
|
|
@ -104,8 +104,6 @@ add_task(function* testWindowCreate() {
|
|||
promiseTabUpdated("http://example.org/"),
|
||||
]);
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, 0));
|
||||
|
||||
window = await browser.windows.create({url: ["http://example.com/", "http://example.org/"]});
|
||||
await readyPromise;
|
||||
|
||||
|
|
|
@ -84,6 +84,8 @@ add_task(function* testWindowsEvents() {
|
|||
let win2Id = yield extension.awaitMessage("window-created");
|
||||
info(`Window 2 ID: ${win2Id}`);
|
||||
|
||||
win2.focus();
|
||||
|
||||
winId = yield extension.awaitMessage(`window-focus-changed`);
|
||||
is(winId, win2Id, "Got focus change event for the correct window ID.");
|
||||
|
||||
|
|
|
@ -23,12 +23,10 @@ var {CustomizableUI} = Cu.import("resource:///modules/CustomizableUI.jsm");
|
|||
// copied to the sub-directory "test-oop-extensions", which we detect here, and
|
||||
// use to select our configuration.
|
||||
if (gTestPath.includes("test-oop-extensions")) {
|
||||
add_task(() => {
|
||||
return SpecialPowers.pushPrefEnv({set: [
|
||||
["dom.ipc.processCount", 1],
|
||||
["extensions.webextensions.remote", true],
|
||||
]});
|
||||
});
|
||||
SpecialPowers.pushPrefEnv({set: [
|
||||
["dom.ipc.processCount", 1],
|
||||
["extensions.webextensions.remote", true],
|
||||
]});
|
||||
}
|
||||
|
||||
// Bug 1239884: Our tests occasionally hit a long GC pause at unpredictable
|
||||
|
|
|
@ -2854,8 +2854,8 @@ var E10SAccessibilityCheck = {
|
|||
let options = {
|
||||
popupIconURL: "chrome://browser/skin/e10s-64@2x.png",
|
||||
learnMoreURL: Services.urlFormatter.formatURLPref("app.support.e10sAccessibilityUrl"),
|
||||
persistent: true,
|
||||
persistWhileVisible: true,
|
||||
hideNotNow: true,
|
||||
};
|
||||
|
||||
notification =
|
||||
|
|
|
@ -141,7 +141,17 @@ var gEditItemOverlay = {
|
|||
yield PlacesUtils.keywords.fetch({ url: this._paneInfo.uri.spec },
|
||||
e => entries.push(e));
|
||||
if (entries.length > 0) {
|
||||
this._keyword = newKeyword = entries[0].keyword;
|
||||
// We show an existing keyword if either POST data was not provided, or
|
||||
// if the POST data is the same.
|
||||
let existingKeyword = entries[0].keyword;
|
||||
let postData = this._paneInfo.postData;
|
||||
if (postData) {
|
||||
let sameEntry = entries.find(e => e.postData === postData);
|
||||
existingKeyword = sameEntry ? sameEntry.keyword : "";
|
||||
}
|
||||
if (existingKeyword) {
|
||||
this._keyword = newKeyword = existingKeyword;
|
||||
}
|
||||
}
|
||||
}
|
||||
this._initTextField(this._keywordField, newKeyword);
|
||||
|
|
|
@ -8,7 +8,7 @@ add_task(function* () {
|
|||
url: TEST_URL,
|
||||
}, function* (browser) {
|
||||
// We must wait for the context menu code to build metadata.
|
||||
yield openContextMenuForContentSelector(browser, 'form > input[name="search"]');
|
||||
yield openContextMenuForContentSelector(browser, '#form1 > input[name="search"]');
|
||||
|
||||
yield withBookmarksDialog(true, AddKeywordForSearchField, function* (dialogWin) {
|
||||
let acceptBtn = dialogWin.document.documentElement.getButton("accept");
|
||||
|
@ -47,6 +47,61 @@ add_task(function* () {
|
|||
});
|
||||
});
|
||||
|
||||
add_task(function* reopen_same_field() {
|
||||
yield PlacesUtils.keywords.insert({
|
||||
url: TEST_URL,
|
||||
keyword: "kw",
|
||||
postData: "accenti%3D%E0%E8%EC%F2%F9&search%3D%25s"
|
||||
});
|
||||
registerCleanupFunction(function* () {
|
||||
yield PlacesUtils.keywords.remove("kw");
|
||||
});
|
||||
// Reopening on the same input field should show the existing keyword.
|
||||
yield BrowserTestUtils.withNewTab({
|
||||
gBrowser,
|
||||
url: TEST_URL,
|
||||
}, function* (browser) {
|
||||
// We must wait for the context menu code to build metadata.
|
||||
yield openContextMenuForContentSelector(browser, '#form1 > input[name="search"]');
|
||||
|
||||
yield withBookmarksDialog(true, AddKeywordForSearchField, function* (dialogWin) {
|
||||
let acceptBtn = dialogWin.document.documentElement.getButton("accept");
|
||||
ok(acceptBtn.disabled, "Accept button is disabled");
|
||||
|
||||
let elt = dialogWin.document.getElementById("editBMPanel_keywordField");
|
||||
is(elt.value, "kw");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
add_task(function* open_other_field() {
|
||||
yield PlacesUtils.keywords.insert({
|
||||
url: TEST_URL,
|
||||
keyword: "kw2",
|
||||
postData: "search%3D%25s"
|
||||
});
|
||||
registerCleanupFunction(function* () {
|
||||
yield PlacesUtils.keywords.remove("kw2");
|
||||
});
|
||||
// Reopening on another field of the same page that has different postData
|
||||
// should not show the existing keyword.
|
||||
yield BrowserTestUtils.withNewTab({
|
||||
gBrowser,
|
||||
url: TEST_URL,
|
||||
}, function* (browser) {
|
||||
// We must wait for the context menu code to build metadata.
|
||||
yield openContextMenuForContentSelector(browser, '#form2 > input[name="search"]');
|
||||
|
||||
yield withBookmarksDialog(true, AddKeywordForSearchField, function* (dialogWin) {
|
||||
let acceptBtn = dialogWin.document.documentElement.getButton("accept");
|
||||
ok(acceptBtn.disabled, "Accept button is disabled");
|
||||
|
||||
let elt = dialogWin.document.getElementById("editBMPanel_keywordField");
|
||||
is(elt.value, "");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function getPostDataString(stream) {
|
||||
let sis = Cc["@mozilla.org/scriptableinputstream;1"]
|
||||
.createInstance(Ci.nsIScriptableInputStream);
|
||||
|
|
|
@ -5,9 +5,13 @@
|
|||
<meta http-equiv="Content-Type" content="text/html;charset=windows-1252">
|
||||
</head>
|
||||
<body>
|
||||
<form method="POST" action="keyword_form.html">
|
||||
<form id="form1" method="POST" action="keyword_form.html">
|
||||
<input type="hidden" name="accenti" value="àèìòù">
|
||||
<input type="text" name="search">
|
||||
</form>
|
||||
<form id="form2" method="POST" action="keyword_form.html">
|
||||
<input type="hidden" name="accenti" value="ùòìèà">
|
||||
<input type="text" name="search">
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -24,9 +24,9 @@ add_task(function* test() {
|
|||
|
||||
if (aPrivateMode) {
|
||||
// Make sure the notification is correctly displayed without a remember control
|
||||
is(notification.secondaryActions.length, 0, "Secondary actions shouldn't exist (always/never remember)");
|
||||
ok(!notification.options.checkbox.show, "Secondary actions should exist (always/never remember)");
|
||||
} else {
|
||||
ok(notification.secondaryActions.length > 1, "Secondary actions should exist (always/never remember)");
|
||||
ok(notification.options.checkbox.show, "Secondary actions should exist (always/never remember)");
|
||||
}
|
||||
notification.remove();
|
||||
|
||||
|
|
|
@ -30,8 +30,8 @@ this.SessionHistory = Object.freeze({
|
|||
return SessionHistoryInternal.isEmpty(docShell);
|
||||
},
|
||||
|
||||
collect: function (docShell) {
|
||||
return SessionHistoryInternal.collect(docShell);
|
||||
collect: function (docShell, aFromIdx = -1) {
|
||||
return SessionHistoryInternal.collect(docShell, aFromIdx);
|
||||
},
|
||||
|
||||
restore: function (docShell, tabData) {
|
||||
|
@ -69,11 +69,15 @@ var SessionHistoryInternal = {
|
|||
*
|
||||
* @param docShell
|
||||
* The docShell that owns the session history.
|
||||
* @param aFromIdx
|
||||
* The starting local index to collect the history from.
|
||||
* @return An object reprereseting a partial global history update.
|
||||
*/
|
||||
collect: function (docShell) {
|
||||
collect: function (docShell, aFromIdx = -1) {
|
||||
let loadContext = docShell.QueryInterface(Ci.nsILoadContext);
|
||||
let webNavigation = docShell.QueryInterface(Ci.nsIWebNavigation);
|
||||
let history = webNavigation.sessionHistory.QueryInterface(Ci.nsISHistoryInternal);
|
||||
let ihistory = history.QueryInterface(Ci.nsISHistory);
|
||||
|
||||
let data = {entries: [], userContextId: loadContext.originAttributes.userContextId };
|
||||
|
||||
|
@ -107,6 +111,23 @@ var SessionHistoryInternal = {
|
|||
}
|
||||
}
|
||||
|
||||
// Check if we should discard some of the entries which didn't change
|
||||
if (aFromIdx > -1) {
|
||||
data.entries.splice(0, aFromIdx + 1);
|
||||
}
|
||||
|
||||
// Transform the entries from local to global index space.
|
||||
data.index += ihistory.globalIndexOffset;
|
||||
data.fromIdx = aFromIdx + ihistory.globalIndexOffset;
|
||||
|
||||
// If we are not the most recent partialSHistory in our groupedSHistory, we
|
||||
// need to make certain that we don't replace the entries from the following
|
||||
// SHistories - so we replace only the number of entries which our SHistory
|
||||
// takes up.
|
||||
if (ihistory.globalIndexOffset + ihistory.count < ihistory.globalCount) {
|
||||
data.toIdx = data.fromIdx + ihistory.count;
|
||||
}
|
||||
|
||||
return data;
|
||||
},
|
||||
|
||||
|
|
|
@ -971,6 +971,18 @@ var SessionStoreInternal = {
|
|||
this.resetEpoch(target);
|
||||
}
|
||||
break;
|
||||
case "BrowserWillChangeProcess":
|
||||
let promise = TabStateFlusher.flush(target);
|
||||
target.frameLoader.addProcessChangeBlockingPromise(promise);
|
||||
break;
|
||||
case "BrowserChangedProcess":
|
||||
let newEpoch = 1 + Math.max(this.getCurrentEpoch(target),
|
||||
this.getCurrentEpoch(aEvent.otherBrowser));
|
||||
this.setCurrentEpoch(target, newEpoch);
|
||||
target.messageManager.sendAsyncMessage("SessionStore:becomeActiveProcess", {
|
||||
epoch: newEpoch
|
||||
});
|
||||
break;
|
||||
default:
|
||||
throw new Error(`unhandled event ${aEvent.type}?`);
|
||||
}
|
||||
|
@ -1037,6 +1049,8 @@ var SessionStoreInternal = {
|
|||
|
||||
// Keep track of a browser's latest frameLoader.
|
||||
aWindow.gBrowser.addEventListener("XULFrameLoaderCreated", this);
|
||||
aWindow.gBrowser.addEventListener("BrowserChangedProcess", this);
|
||||
aWindow.gBrowser.addEventListener("BrowserWillChangeProcess", this);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -1291,6 +1305,8 @@ var SessionStoreInternal = {
|
|||
}, this);
|
||||
|
||||
aWindow.gBrowser.removeEventListener("XULFrameLoaderCreated", this);
|
||||
aWindow.gBrowser.removeEventListener("BrowserChangedProcess", this);
|
||||
aWindow.gBrowser.removeEventListener("BrowserWillChangeProcess", this);
|
||||
|
||||
let winData = this._windows[aWindow.__SSi];
|
||||
|
||||
|
@ -4412,6 +4428,14 @@ var SessionStoreInternal = {
|
|||
return next;
|
||||
},
|
||||
|
||||
/**
|
||||
* Manually set the epoch to a given value.
|
||||
*/
|
||||
setCurrentEpoch(aBrowser, aEpoch) {
|
||||
this._browserEpochs.set(aBrowser.permanentKey, aEpoch);
|
||||
return aEpoch;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the current epoch for the given <browser>. If we haven't assigned
|
||||
* a new epoch this will default to zero for new tabs.
|
||||
|
|
|
@ -113,15 +113,19 @@ var TabStateCacheInternal = {
|
|||
}
|
||||
|
||||
let history = data.history;
|
||||
let toIdx = history.entries.length;
|
||||
if ("toIdx" in change) {
|
||||
toIdx = Math.min(toIdx, change.toIdx + 1);
|
||||
}
|
||||
|
||||
for (let key of Object.keys(change)) {
|
||||
if (key == "entries") {
|
||||
if (change.fromIdx != kLastIndex) {
|
||||
history.entries.splice(change.fromIdx + 1);
|
||||
while (change.entries.length) {
|
||||
history.entries.push(change.entries.shift());
|
||||
}
|
||||
let start = change.fromIdx + 1;
|
||||
history.entries.splice.apply(
|
||||
history.entries, [start, toIdx - start].concat(change.entries));
|
||||
}
|
||||
} else if (key != "fromIndex") {
|
||||
} else if (key != "fromIdx" && key != "toIdx") {
|
||||
history[key] = change[key];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -114,6 +114,7 @@ var MessageListener = {
|
|||
"SessionStore:restoreTabContent",
|
||||
"SessionStore:resetRestore",
|
||||
"SessionStore:flush",
|
||||
"SessionStore:becomeActiveProcess",
|
||||
],
|
||||
|
||||
init: function () {
|
||||
|
@ -148,6 +149,18 @@ var MessageListener = {
|
|||
case "SessionStore:flush":
|
||||
this.flush(data);
|
||||
break;
|
||||
case "SessionStore:becomeActiveProcess":
|
||||
let shistory = docShell.QueryInterface(Ci.nsIWebNavigation).sessionHistory;
|
||||
// Check if we are at the end of the current session history, if we are,
|
||||
// it is safe for us to collect and transmit our session history, so
|
||||
// transmit all of it. Otherwise, we only want to transmit our index changes,
|
||||
// so collect from kLastIndex.
|
||||
if (shistory.globalCount - shistory.globalIndexOffset == shistory.count) {
|
||||
SessionHistoryListener.collect();
|
||||
} else {
|
||||
SessionHistoryListener.collectFrom(kLastIndex);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
debug("received unknown message '" + name + "'");
|
||||
break;
|
||||
|
@ -255,9 +268,12 @@ var SessionHistoryListener = {
|
|||
},
|
||||
|
||||
collect: function () {
|
||||
this._fromIdx = kNoIndex;
|
||||
// We want to send down a historychange even for full collects in case our
|
||||
// session history is a partial session history, in which case we don't have
|
||||
// enough information for a full update. collectFrom(-1) tells the collect
|
||||
// function to collect all data avaliable in this process.
|
||||
if (docShell) {
|
||||
MessageQueue.push("history", () => SessionHistory.collect(docShell));
|
||||
this.collectFrom(-1);
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -286,15 +302,7 @@ var SessionHistoryListener = {
|
|||
return null;
|
||||
}
|
||||
|
||||
let history = SessionHistory.collect(docShell);
|
||||
if (kLastIndex == idx) {
|
||||
history.entries = [];
|
||||
} else {
|
||||
history.entries.splice(0, this._fromIdx + 1);
|
||||
}
|
||||
|
||||
history.fromIdx = this._fromIdx;
|
||||
|
||||
let history = SessionHistory.collect(docShell, this._fromIdx);
|
||||
this._fromIdx = kNoIndex;
|
||||
return history;
|
||||
});
|
||||
|
|
|
@ -238,3 +238,5 @@ run-if = e10s && crashreporter
|
|||
[browser_undoCloseById.js]
|
||||
skip-if = debug
|
||||
[browser_docshell_uuid_consistency.js]
|
||||
[browser_grouped_session_store.js]
|
||||
skip-if = !e10s # GroupedSHistory is e10s-only
|
||||
|
|
|
@ -0,0 +1,135 @@
|
|||
add_task(function* () {
|
||||
const URIs = [
|
||||
"data:text/html,1",
|
||||
"data:text/html,2",
|
||||
"data:text/html,3",
|
||||
"data:text/html,4",
|
||||
"data:text/html,5",
|
||||
];
|
||||
|
||||
const {TabStateCache} = Cu.import("resource:///modules/sessionstore/TabStateCache.jsm", {});
|
||||
const {TabStateFlusher} = Cu.import("resource:///modules/sessionstore/TabStateFlusher.jsm", {});
|
||||
|
||||
yield SpecialPowers.pushPrefEnv({
|
||||
set: [["browser.groupedhistory.enabled", true]]
|
||||
});
|
||||
|
||||
// Check that the data stored in the TabStateCache is correct for the current state.
|
||||
function* validate(browser, length, index) {
|
||||
yield TabStateFlusher.flush(browser);
|
||||
let {history} = TabStateCache.get(browser);
|
||||
is(history.entries.length, length, "Lengths match");
|
||||
for (let i = 0; i < length; ++i) {
|
||||
is(history.entries[i].url, URIs[i], "URI at index " + i + " matches");
|
||||
}
|
||||
is(history.index, index, "Index matches");
|
||||
yield ContentTask.spawn(browser, [index, length], function* ([index, length]) {
|
||||
let webNav = content.window.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation);
|
||||
is(webNav.canGoForward, index < length, "canGoForward is correct");
|
||||
is(webNav.canGoBack, index > 1, "canGoBack is correct");
|
||||
});
|
||||
}
|
||||
|
||||
// Wait for a process change and then fulfil the promise.
|
||||
function awaitProcessChange(browser) {
|
||||
return new Promise(resolve => {
|
||||
browser.addEventListener("BrowserChangedProcess", function bcp(e) {
|
||||
browser.removeEventListener("BrowserChangedProcess", bcp);
|
||||
ok(true, "The browser changed process!");
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Order of events:
|
||||
// Load [0], load [1], prerender [2], load [2], load [3]
|
||||
// Back [2], Back [1], Forward [2], Back [0], Forward [3]
|
||||
// Prerender [4], Back [0], Forward [2], Load [3'], Back [0].
|
||||
yield BrowserTestUtils.withNewTab({ gBrowser, url: URIs[0] }, function* (browser1) {
|
||||
yield* validate(browser1, 1, 1);
|
||||
|
||||
browser1.loadURI(URIs[1], null, null);
|
||||
yield BrowserTestUtils.browserLoaded(browser1);
|
||||
yield* validate(browser1, 2, 2);
|
||||
|
||||
// Create a new hidden prerendered tab to swap to.
|
||||
let tab2 = gBrowser.loadOneTab(URIs[2], {
|
||||
referrerPolicy: Ci.nsIHttpChannel.REFERRER_POLICY_DEFAULT,
|
||||
allowThirdPartyFixup: true,
|
||||
relatedToCurrent: true,
|
||||
isPrerendered: true,
|
||||
});
|
||||
yield BrowserTestUtils.browserLoaded(tab2.linkedBrowser);
|
||||
browser1.frameLoader.appendPartialSessionHistoryAndSwap(
|
||||
tab2.linkedBrowser.frameLoader);
|
||||
yield awaitProcessChange(browser1);
|
||||
yield* validate(browser1, 3, 3);
|
||||
|
||||
browser1.loadURI(URIs[3], null, null);
|
||||
yield BrowserTestUtils.browserLoaded(browser1);
|
||||
yield* validate(browser1, 4, 4);
|
||||
|
||||
// In process navigate back.
|
||||
let p = BrowserTestUtils.waitForContentEvent(browser1, "pageshow");
|
||||
browser1.goBack();
|
||||
yield p;
|
||||
yield* validate(browser1, 4, 3);
|
||||
|
||||
// Cross process navigate back.
|
||||
browser1.goBack();
|
||||
yield awaitProcessChange(browser1);
|
||||
yield* validate(browser1, 4, 2);
|
||||
|
||||
// Cross process navigate forward.
|
||||
browser1.goForward();
|
||||
yield awaitProcessChange(browser1);
|
||||
yield* validate(browser1, 4, 3);
|
||||
|
||||
// Navigate across process to a page which was not recently loaded.
|
||||
browser1.gotoIndex(0);
|
||||
yield awaitProcessChange(browser1);
|
||||
yield* validate(browser1, 4, 1);
|
||||
|
||||
// Navigate across process to a page which was not recently loaded in the other direction.
|
||||
browser1.gotoIndex(3);
|
||||
yield awaitProcessChange(browser1);
|
||||
yield* validate(browser1, 4, 4);
|
||||
|
||||
// Create a new hidden prerendered tab to swap to
|
||||
let tab3 = gBrowser.loadOneTab(URIs[4], {
|
||||
referrerPolicy: Ci.nsIHttpChannel.REFERRER_POLICY_DEFAULT,
|
||||
allowThirdPartyFixup: true,
|
||||
relatedToCurrent: true,
|
||||
isPrerendered: true,
|
||||
});
|
||||
yield BrowserTestUtils.browserLoaded(tab3.linkedBrowser);
|
||||
browser1.frameLoader.appendPartialSessionHistoryAndSwap(
|
||||
tab3.linkedBrowser.frameLoader);
|
||||
yield awaitProcessChange(browser1);
|
||||
yield* validate(browser1, 5, 5);
|
||||
|
||||
browser1.gotoIndex(0);
|
||||
yield awaitProcessChange(browser1);
|
||||
yield* validate(browser1, 5, 1);
|
||||
|
||||
browser1.gotoIndex(2);
|
||||
yield awaitProcessChange(browser1);
|
||||
yield* validate(browser1, 5, 3);
|
||||
|
||||
// Load a new page and make sure it throws out all of the following entries.
|
||||
URIs[3] = "data:text/html,NEW";
|
||||
browser1.loadURI(URIs[3]);
|
||||
yield BrowserTestUtils.browserLoaded(browser1);
|
||||
yield* validate(browser1, 4, 4);
|
||||
|
||||
browser1.gotoIndex(0);
|
||||
yield awaitProcessChange(browser1);
|
||||
yield* validate(browser1, 4, 1);
|
||||
|
||||
// XXX: This will be removed automatically by the owning tab closing in the
|
||||
// future, but this is not supported yet.
|
||||
gBrowser.removeTab(tab2);
|
||||
gBrowser.removeTab(tab3);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,3 @@
|
|||
. "$topsrcdir/browser/config/mozconfigs/linux64/nightly"
|
||||
|
||||
ac_add_options --enable-stylo
|
|
@ -0,0 +1,3 @@
|
|||
. "$topsrcdir/browser/config/mozconfigs/linux64/debug"
|
||||
|
||||
ac_add_options --enable-stylo
|
|
@ -158,7 +158,7 @@ const FlyWebPermissionPromptIntegration = (base) => ({
|
|||
notificationIcon.setAttribute("aria-label",
|
||||
"View the publish-server request");
|
||||
notificationIcon.style.filter =
|
||||
"url('chrome://browser/skin/filters.svg#fill')";
|
||||
"url('chrome://global/skin/filters.svg#fill')";
|
||||
notificationIcon.style.fill = "currentcolor";
|
||||
notificationIcon.style.opacity = "0.4";
|
||||
notificationPopupBox.appendChild(notificationIcon);
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
This is the pdf.js project output, https://github.com/mozilla/pdf.js
|
||||
|
||||
Current extension version is: 1.6.315
|
||||
Current extension version is: 1.6.329
|
||||
|
|
|
@ -93,6 +93,7 @@ function initializeDefaultPreferences() {
|
|||
"useOnlyCssZoom": false,
|
||||
"externalLinkTarget": 0,
|
||||
"enhanceTextSelection": false,
|
||||
"renderer": "canvas",
|
||||
"renderInteractiveForms": false,
|
||||
"disablePageLabels": false
|
||||
}
|
||||
|
|
|
@ -51,6 +51,7 @@ var DEFAULT_PREFERENCES =
|
|||
"useOnlyCssZoom": false,
|
||||
"externalLinkTarget": 0,
|
||||
"enhanceTextSelection": false,
|
||||
"renderer": "canvas",
|
||||
"renderInteractiveForms": false,
|
||||
"disablePageLabels": false
|
||||
}
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -375,6 +375,9 @@ if (typeof PDFJSDev !== 'undefined' && PDFJSDev.test('FIREFOX || MOZCENTRAL')) {
|
|||
}
|
||||
|
||||
var networkManager = this._manager;
|
||||
if (!networkManager.isHttp) {
|
||||
return false;
|
||||
}
|
||||
var fullRequestXhrId = this._fullRequestId;
|
||||
var fullRequestXhr = networkManager.getRequestXhr(fullRequestXhrId);
|
||||
if (fullRequestXhr.getResponseHeader('Accept-Ranges') !== 'bytes') {
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
(function(window) {
|
||||
var gLanguage = '';
|
||||
var gExternalLocalizerServices = null;
|
||||
var gReadyState = 'loading';
|
||||
|
||||
// fetch an l10n objects
|
||||
function getL10nData(key) {
|
||||
|
@ -99,6 +100,8 @@
|
|||
|
||||
translateFragment();
|
||||
|
||||
gReadyState = 'complete';
|
||||
|
||||
// fire a 'localized' DOM event
|
||||
var evtObject = document.createEvent('Event');
|
||||
evtObject.initEvent('localized', false, false);
|
||||
|
@ -135,6 +138,8 @@
|
|||
return (rtlList.indexOf(shortCode) >= 0) ? 'rtl' : 'ltr';
|
||||
},
|
||||
|
||||
getReadyState: function() { return gReadyState; },
|
||||
|
||||
setExternalLocalizerServices: function (externalLocalizerServices) {
|
||||
gExternalLocalizerServices = externalLocalizerServices;
|
||||
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -76,7 +76,6 @@ PresentationPermissionPrompt.prototype = {
|
|||
},
|
||||
get popupOptions() {
|
||||
return {
|
||||
hideNotNow: true,
|
||||
removeOnDismissal: true,
|
||||
popupIconURL: kNotificationPopupIcon, // Icon shown on prompt content
|
||||
eventCallback: (aTopic, aNewBrowser) => {
|
||||
|
@ -127,7 +126,7 @@ PresentationPermissionPrompt.prototype = {
|
|||
notificationIcon.setAttribute("role", "button");
|
||||
notificationIcon.setAttribute("tooltiptext",
|
||||
GetString("presentation.urlbar.tooltiptext"));
|
||||
notificationIcon.style.filter = "url('chrome://browser/skin/filters.svg#fill')";
|
||||
notificationIcon.style.filter = "url('chrome://global/skin/filters.svg#fill')";
|
||||
notificationIcon.style.fill = "currentcolor";
|
||||
notificationIcon.style.opacity = "0.4";
|
||||
notificationPopupBox.appendChild(notificationIcon);
|
||||
|
@ -162,7 +161,7 @@ PresentationPermissionPrompt.prototype = {
|
|||
this._isResponded = true;
|
||||
this.request.cancel(Cr.NS_ERROR_NOT_AVAILABLE);
|
||||
},
|
||||
dismiss: true, // For hideNotNow.
|
||||
dismiss: true,
|
||||
}];
|
||||
},
|
||||
// PRIVATE APIs
|
||||
|
|
|
@ -527,8 +527,8 @@
|
|||
|
||||
@RESPATH@/chrome/marionette@JAREXT@
|
||||
@RESPATH@/chrome/marionette.manifest
|
||||
@RESPATH@/components/MarionetteComponents.manifest
|
||||
@RESPATH@/components/marionettecomponent.js
|
||||
@RESPATH@/components/marionette.manifest
|
||||
@RESPATH@/components/marionette.js
|
||||
|
||||
#ifdef MOZ_WEBSPEECH
|
||||
@RESPATH@/components/dom_webspeechsynth.xpt
|
||||
|
|
|
@ -315,13 +315,11 @@ newWindowButton.tooltip=Open a new window (%S)
|
|||
newTabButton.tooltip=Open a new tab (%S)
|
||||
|
||||
# Offline web applications
|
||||
offlineApps.available=This website (%S) is asking to store data on your computer for offline use.
|
||||
offlineApps.allow=Allow
|
||||
offlineApps.allowAccessKey=A
|
||||
offlineApps.never=Never for This Site
|
||||
offlineApps.neverAccessKey=e
|
||||
offlineApps.notNow=Not Now
|
||||
offlineApps.notNowAccessKey=N
|
||||
offlineApps.available2=Will you allow %S to store data on your computer?
|
||||
offlineApps.allowStoring.label=Allow Storing Data
|
||||
offlineApps.allowStoring.accesskey=A
|
||||
offlineApps.dontAllow.label=Don’t Allow
|
||||
offlineApps.dontAllow.accesskey=n
|
||||
|
||||
offlineApps.usage=This website (%S) is now storing more than %SMB of data on your computer for offline use.
|
||||
offlineApps.manageUsage=Show settings
|
||||
|
@ -368,24 +366,21 @@ puAlertText=Click here for details
|
|||
|
||||
# Geolocation UI
|
||||
|
||||
# LOCALIZATION NOTE (geolocation.shareLocation geolocation.alwaysShareLocation geolocation.neverShareLocation):
|
||||
# If you're having trouble with the word Share, please use Allow and Block in your language.
|
||||
geolocation.shareLocation=Share Location
|
||||
geolocation.shareLocation.accesskey=a
|
||||
geolocation.alwaysShareLocation=Always Share Location
|
||||
geolocation.alwaysShareLocation.accesskey=A
|
||||
geolocation.neverShareLocation=Never Share Location
|
||||
geolocation.neverShareLocation.accesskey=N
|
||||
geolocation.shareWithSite2=Would you like to share your location with this site?
|
||||
geolocation.shareWithFile2=Would you like to share your location with this file?
|
||||
geolocation.allowLocation=Allow Location Access
|
||||
geolocation.allowLocation.accesskey=A
|
||||
geolocation.dontAllowLocation=Don’t Allow
|
||||
geolocation.dontAllowLocation.accesskey=n
|
||||
geolocation.shareWithSite3=Will you allow %S to access your location?
|
||||
geolocation.shareWithFile3=Will you allow this local file to access your location?
|
||||
geolocation.remember=Remember this decision
|
||||
|
||||
webNotifications.receiveForSession=Receive for this session
|
||||
webNotifications.receiveForSession.accesskey=s
|
||||
webNotifications.alwaysReceive=Always Receive Notifications
|
||||
webNotifications.alwaysReceive.accesskey=A
|
||||
webNotifications.neverShow=Always Block Notifications
|
||||
webNotifications.neverShow.accesskey=N
|
||||
webNotifications.receiveFromSite=Would you like to receive notifications from this site?
|
||||
webNotifications.remember=Remember this decision
|
||||
webNotifications.rememberForSession=Remember decision for this session
|
||||
webNotifications.allow=Allow Notifications
|
||||
webNotifications.allow.accesskey=A
|
||||
webNotifications.dontAllow=Don’t Allow
|
||||
webNotifications.dontAllow.accesskey=n
|
||||
webNotifications.receiveFromSite2=Will you allow %S to send notifications?
|
||||
# LOCALIZATION NOTE (webNotifications.upgradeTitle): When using native notifications on OS X, the title may be truncated around 32 characters.
|
||||
webNotifications.upgradeTitle=Upgraded notifications
|
||||
# LOCALIZATION NOTE (webNotifications.upgradeBody): When using native notifications on OS X, the body may be truncated around 100 characters in some views.
|
||||
|
@ -473,19 +468,19 @@ social.error.closeSidebar.accesskey=C
|
|||
# LOCALIZATION NOTE: %1$S is the label for the toolbar button, %2$S is the associated badge numbering that the social provider may provide.
|
||||
social.aria.toolbarButtonBadgeText=%1$S (%2$S)
|
||||
|
||||
# LOCALIZATION NOTE (getUserMedia.shareCamera.message, getUserMedia.shareMicrophone.message,
|
||||
# getUserMedia.shareScreen.message, getUserMedia.shareCameraAndMicrophone.message,
|
||||
# getUserMedia.shareScreenAndMicrophone.message, getUserMedia.shareCameraAndAudioCapture.message,
|
||||
# getUserMedia.shareAudioCapture.message, getUserMedia.shareScreenAndAudioCapture.message):
|
||||
# LOCALIZATION NOTE (getUserMedia.shareCamera2.message, getUserMedia.shareMicrophone2.message,
|
||||
# getUserMedia.shareScreen2.message, getUserMedia.shareCameraAndMicrophone2.message,
|
||||
# getUserMedia.shareScreenAndMicrophone2.message, getUserMedia.shareCameraAndAudioCapture2.message,
|
||||
# getUserMedia.shareAudioCapture2.message, getUserMedia.shareScreenAndAudioCapture2.message):
|
||||
# %S is the website origin (e.g. www.mozilla.org)
|
||||
getUserMedia.shareCamera.message = Would you like to share your camera with %S?
|
||||
getUserMedia.shareMicrophone.message = Would you like to share your microphone with %S?
|
||||
getUserMedia.shareScreen.message = Would you like to share your screen with %S?
|
||||
getUserMedia.shareCameraAndMicrophone.message = Would you like to share your camera and microphone with %S?
|
||||
getUserMedia.shareCameraAndAudioCapture.message = Would you like to share your camera and this tab’s audio with %S?
|
||||
getUserMedia.shareScreenAndMicrophone.message = Would you like to share your microphone and screen with %S?
|
||||
getUserMedia.shareScreenAndAudioCapture.message = Would you like to share this tab’s audio and your screen with %S?
|
||||
getUserMedia.shareAudioCapture.message = Would you like to share this tab’s audio with %S?
|
||||
getUserMedia.shareCamera2.message = Will you allow %S to use your camera?
|
||||
getUserMedia.shareMicrophone2.message = Will you allow %S to use your microphone?
|
||||
getUserMedia.shareScreen2.message = Will you allow %S to see your screen or application window?
|
||||
getUserMedia.shareCameraAndMicrophone2.message = Will you allow %S to use your camera and microphone?
|
||||
getUserMedia.shareCameraAndAudioCapture2.message = Will you allow %S to use your camera and listen to this tab’s audio?
|
||||
getUserMedia.shareScreenAndMicrophone2.message = Will you allow %S to use your microphone and see your screen or application window?
|
||||
getUserMedia.shareScreenAndAudioCapture2.message = Will you allow %S to listen to this tab’s audio and see your screen or application window?
|
||||
getUserMedia.shareAudioCapture2.message = Will you allow %S to listen to this tab’s audio?
|
||||
# LOCALIZATION NOTE (getUserMedia.shareScreenWarning.message): NB: inserted via innerHTML, so please don't use <, > or & in this string.
|
||||
# %S will be the 'learn more' link
|
||||
getUserMedia.shareScreenWarning.message = Only share screens with sites you trust. Sharing can allow deceptive sites to browse as you and steal your private data. %S
|
||||
|
@ -515,22 +510,18 @@ getUserMedia.shareMonitor.label = Screen %S
|
|||
# Replacement for #1 is the name of the application.
|
||||
# Replacement for #2 is the number of windows currently displayed by the application.
|
||||
getUserMedia.shareApplicationWindowCount.label=#1 (#2 window);#1 (#2 windows)
|
||||
# LOCALIZATION NOTE (getUserMedia.shareSelectedDevices.label):
|
||||
# Semicolon-separated list of plural forms. See:
|
||||
# http://developer.mozilla.org/en/docs/Localization_and_Plurals
|
||||
# The number of devices can be either one or two.
|
||||
getUserMedia.shareSelectedDevices.label = Share Selected Device;Share Selected Devices
|
||||
getUserMedia.shareSelectedDevices.accesskey = S
|
||||
getUserMedia.shareScreen.label = Share Screen
|
||||
getUserMedia.shareApplication.label = Share Selected Application
|
||||
getUserMedia.shareWindow.label = Share Selected Window
|
||||
getUserMedia.shareSelectedItems.label = Share Selected Items
|
||||
getUserMedia.always.label = Always Share
|
||||
getUserMedia.always.accesskey = A
|
||||
getUserMedia.denyRequest.label = Don’t Share
|
||||
getUserMedia.denyRequest.accesskey = D
|
||||
getUserMedia.never.label = Never Share
|
||||
getUserMedia.never.accesskey = N
|
||||
getUserMedia.allow.label = Allow
|
||||
getUserMedia.allow.accesskey = A
|
||||
getUserMedia.dontAllow.label = Don’t Allow
|
||||
getUserMedia.dontAllow.accesskey = D
|
||||
getUserMedia.remember=Remember this decision
|
||||
# LOCALIZATION NOTE (ggetUserMedia.reasonForNoPermanentAllow.screen,
|
||||
# getUserMedia.reasonForNoPermanentAllow.audio,
|
||||
# getUserMedia.reasonForNoPermanentAllow.insecure):
|
||||
# %S is brandShortName
|
||||
getUserMedia.reasonForNoPermanentAllow.screen=%S can not allow permanent access to your screen or application without asking which one to share.
|
||||
getUserMedia.reasonForNoPermanentAllow.audio=%S can not allow permanent access to your tab’s audio without asking which tab to share.
|
||||
getUserMedia.reasonForNoPermanentAllow.insecure=Your connection to this site is not secure. To protect you, %S will only allow access for this session.
|
||||
|
||||
getUserMedia.sharingMenu.label = Tabs sharing devices
|
||||
getUserMedia.sharingMenu.accesskey = d
|
||||
|
|
|
@ -226,7 +226,10 @@ this.PermissionPromptPrototype = {
|
|||
*
|
||||
* If action is not set, expireType will be ignored.
|
||||
* callback (function, optional)
|
||||
* A callback function that will fire if the user makes this choice.
|
||||
* A callback function that will fire if the user makes this choice, with
|
||||
* a single parameter, state. State is an Object that contains the property
|
||||
* checkboxChecked, which identifies whether the checkbox to remember this
|
||||
* decision was checked.
|
||||
*/
|
||||
get promptActions() {
|
||||
return [];
|
||||
|
@ -297,14 +300,14 @@ this.PermissionPromptPrototype = {
|
|||
let action = {
|
||||
label: promptAction.label,
|
||||
accessKey: promptAction.accessKey,
|
||||
callback: () => {
|
||||
callback: state => {
|
||||
if (promptAction.callback) {
|
||||
promptAction.callback();
|
||||
}
|
||||
|
||||
if (this.permissionKey) {
|
||||
// Remember permissions.
|
||||
if (promptAction.action) {
|
||||
if (state && state.checkboxChecked && promptAction.action) {
|
||||
Services.perms.addFromPrincipal(this.principal,
|
||||
this.permissionKey,
|
||||
promptAction.action,
|
||||
|
@ -337,6 +340,9 @@ this.PermissionPromptPrototype = {
|
|||
if (!options.hasOwnProperty('displayURI') || options.displayURI) {
|
||||
options.displayURI = this.principal.URI;
|
||||
}
|
||||
// Permission prompts are always persistent and don't have a close button.
|
||||
options.persistent = true;
|
||||
options.hideClose = true;
|
||||
|
||||
this.onBeforeShow();
|
||||
chromeWin.PopupNotifications.show(this.browser,
|
||||
|
@ -413,9 +419,25 @@ GeolocationPermissionPrompt.prototype = {
|
|||
|
||||
get popupOptions() {
|
||||
let pref = "browser.geolocation.warning.infoURL";
|
||||
return {
|
||||
let options = {
|
||||
learnMoreURL: Services.urlFormatter.formatURLPref(pref),
|
||||
displayURI: false
|
||||
};
|
||||
|
||||
if (this.principal.URI.schemeIs("file")) {
|
||||
options.checkbox = { show: false };
|
||||
} else {
|
||||
// Don't offer "always remember" action in PB mode
|
||||
options.checkbox = {
|
||||
show: !PrivateBrowsingUtils.isWindowPrivate(this.browser.ownerGlobal)
|
||||
};
|
||||
}
|
||||
|
||||
if (options.checkbox.show) {
|
||||
options.checkbox.label = gBrowserBundle.GetStringFromName("geolocation.remember");
|
||||
}
|
||||
|
||||
return options;
|
||||
},
|
||||
|
||||
get notificationID() {
|
||||
|
@ -429,9 +451,14 @@ GeolocationPermissionPrompt.prototype = {
|
|||
get message() {
|
||||
let message;
|
||||
if (this.principal.URI.schemeIs("file")) {
|
||||
message = gBrowserBundle.GetStringFromName("geolocation.shareWithFile2");
|
||||
message = gBrowserBundle.GetStringFromName("geolocation.shareWithFile3");
|
||||
} else {
|
||||
message = gBrowserBundle.GetStringFromName("geolocation.shareWithSite2");
|
||||
let hostPort = "<>";
|
||||
try {
|
||||
hostPort = this.principal.URI.hostPort;
|
||||
} catch (ex) { }
|
||||
message = gBrowserBundle.formatStringFromName("geolocation.shareWithSite3",
|
||||
[hostPort], 1);
|
||||
}
|
||||
return message;
|
||||
},
|
||||
|
@ -448,44 +475,33 @@ GeolocationPermissionPrompt.prototype = {
|
|||
|
||||
let secHistogram = Services.telemetry.getHistogramById("SECURITY_UI");
|
||||
|
||||
let actions = [{
|
||||
label: gBrowserBundle.GetStringFromName("geolocation.shareLocation"),
|
||||
return [{
|
||||
label: gBrowserBundle.GetStringFromName("geolocation.allowLocation"),
|
||||
accessKey:
|
||||
gBrowserBundle.GetStringFromName("geolocation.shareLocation.accesskey"),
|
||||
gBrowserBundle.GetStringFromName("geolocation.allowLocation.accesskey"),
|
||||
action: null,
|
||||
expireType: null,
|
||||
callback: function() {
|
||||
secHistogram.add(SHARE_LOCATION);
|
||||
callback: function(state) {
|
||||
if (state && state.checkboxChecked) {
|
||||
secHistogram.add(ALWAYS_SHARE);
|
||||
} else {
|
||||
secHistogram.add(SHARE_LOCATION);
|
||||
}
|
||||
},
|
||||
}, {
|
||||
label: gBrowserBundle.GetStringFromName("geolocation.dontAllowLocation"),
|
||||
accessKey:
|
||||
gBrowserBundle.GetStringFromName("geolocation.dontAllowLocation.accesskey"),
|
||||
action: Ci.nsIPermissionManager.DENY_ACTION,
|
||||
expireType: PrivateBrowsingUtils.isWindowPrivate(this.browser.ownerGlobal) ?
|
||||
Ci.nsIPermissionManager.EXPIRE_SESSION :
|
||||
null,
|
||||
callback: function(state) {
|
||||
if (state && state.checkboxChecked) {
|
||||
secHistogram.add(NEVER_SHARE);
|
||||
}
|
||||
},
|
||||
}];
|
||||
|
||||
if (!this.principal.URI.schemeIs("file")) {
|
||||
// Always share location action.
|
||||
actions.push({
|
||||
label: gBrowserBundle.GetStringFromName("geolocation.alwaysShareLocation"),
|
||||
accessKey:
|
||||
gBrowserBundle.GetStringFromName("geolocation.alwaysShareLocation.accesskey"),
|
||||
action: Ci.nsIPermissionManager.ALLOW_ACTION,
|
||||
expireType: null,
|
||||
callback: function() {
|
||||
secHistogram.add(ALWAYS_SHARE);
|
||||
},
|
||||
});
|
||||
|
||||
// Never share location action.
|
||||
actions.push({
|
||||
label: gBrowserBundle.GetStringFromName("geolocation.neverShareLocation"),
|
||||
accessKey:
|
||||
gBrowserBundle.GetStringFromName("geolocation.neverShareLocation.accesskey"),
|
||||
action: Ci.nsIPermissionManager.DENY_ACTION,
|
||||
expireType: null,
|
||||
callback: function() {
|
||||
secHistogram.add(NEVER_SHARE);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
return actions;
|
||||
},
|
||||
|
||||
onBeforeShow() {
|
||||
|
@ -520,25 +536,23 @@ DesktopNotificationPermissionPrompt.prototype = {
|
|||
let learnMoreURL =
|
||||
Services.urlFormatter.formatURLPref("app.support.baseURL") + "push";
|
||||
|
||||
// The eventCallback is bound to the Notification that's being
|
||||
// shown. We'll stash a reference to this in the closure so that
|
||||
// the request can be cancelled.
|
||||
let prompt = this;
|
||||
|
||||
let eventCallback = function(type) {
|
||||
if (type == "dismissed") {
|
||||
// Bug 1259148: Hide the doorhanger icon. Unlike other permission
|
||||
// doorhangers, the user can't restore the doorhanger using the icon
|
||||
// in the location bar. Instead, the site will be notified that the
|
||||
// doorhanger was dismissed.
|
||||
this.remove();
|
||||
prompt.request.cancel();
|
||||
}
|
||||
let checkbox = {
|
||||
show: true,
|
||||
checked: true,
|
||||
label: gBrowserBundle.GetStringFromName("webNotifications.remember")
|
||||
};
|
||||
|
||||
// In PB mode, the "always remember" checkbox should only remember for the
|
||||
// session.
|
||||
if (PrivateBrowsingUtils.isWindowPrivate(this.browser.ownerGlobal)) {
|
||||
checkbox.label =
|
||||
gBrowserBundle.GetStringFromName("webNotifications.rememberForSession");
|
||||
}
|
||||
|
||||
return {
|
||||
learnMoreURL,
|
||||
eventCallback,
|
||||
checkbox,
|
||||
displayURI: false
|
||||
};
|
||||
},
|
||||
|
||||
|
@ -551,43 +565,35 @@ DesktopNotificationPermissionPrompt.prototype = {
|
|||
},
|
||||
|
||||
get message() {
|
||||
return gBrowserBundle.GetStringFromName("webNotifications.receiveFromSite");
|
||||
let hostPort = "<>";
|
||||
try {
|
||||
hostPort = this.principal.URI.hostPort;
|
||||
} catch (ex) { }
|
||||
return gBrowserBundle.formatStringFromName("webNotifications.receiveFromSite2",
|
||||
[hostPort], 1);
|
||||
},
|
||||
|
||||
get promptActions() {
|
||||
let promptActions;
|
||||
// Only show "allow for session" in PB mode, we don't
|
||||
// support "allow for session" in non-PB mode.
|
||||
if (PrivateBrowsingUtils.isBrowserPrivate(this.browser)) {
|
||||
promptActions = [
|
||||
{
|
||||
label: gBrowserBundle.GetStringFromName("webNotifications.receiveForSession"),
|
||||
accessKey:
|
||||
gBrowserBundle.GetStringFromName("webNotifications.receiveForSession.accesskey"),
|
||||
action: Ci.nsIPermissionManager.ALLOW_ACTION,
|
||||
expireType: Ci.nsIPermissionManager.EXPIRE_SESSION,
|
||||
}
|
||||
];
|
||||
} else {
|
||||
promptActions = [
|
||||
{
|
||||
label: gBrowserBundle.GetStringFromName("webNotifications.alwaysReceive"),
|
||||
accessKey:
|
||||
gBrowserBundle.GetStringFromName("webNotifications.alwaysReceive.accesskey"),
|
||||
action: Ci.nsIPermissionManager.ALLOW_ACTION,
|
||||
expireType: null,
|
||||
},
|
||||
{
|
||||
label: gBrowserBundle.GetStringFromName("webNotifications.neverShow"),
|
||||
accessKey:
|
||||
gBrowserBundle.GetStringFromName("webNotifications.neverShow.accesskey"),
|
||||
action: Ci.nsIPermissionManager.DENY_ACTION,
|
||||
expireType: null,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
return promptActions;
|
||||
return [
|
||||
{
|
||||
label: gBrowserBundle.GetStringFromName("webNotifications.allow"),
|
||||
accessKey:
|
||||
gBrowserBundle.GetStringFromName("webNotifications.allow.accesskey"),
|
||||
action: Ci.nsIPermissionManager.ALLOW_ACTION,
|
||||
expireType: PrivateBrowsingUtils.isBrowserPrivate(this.browser) ?
|
||||
Ci.nsIPermissionManager.EXPIRE_SESSION :
|
||||
null,
|
||||
},
|
||||
{
|
||||
label: gBrowserBundle.GetStringFromName("webNotifications.dontAllow"),
|
||||
accessKey:
|
||||
gBrowserBundle.GetStringFromName("webNotifications.dontAllow.accesskey"),
|
||||
action: Ci.nsIPermissionManager.DENY_ACTION,
|
||||
expireType: PrivateBrowsingUtils.isBrowserPrivate(this.browser) ?
|
||||
Ci.nsIPermissionManager.EXPIRE_SESSION :
|
||||
null,
|
||||
},
|
||||
];
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -567,6 +567,7 @@ this.SocialService = {
|
|||
|
||||
let options = {
|
||||
learnMoreURL: Services.urlFormatter.formatURLPref("app.support.baseURL") + "social-api",
|
||||
persistent: true,
|
||||
};
|
||||
let anchor = "servicesInstall-notification-icon";
|
||||
let notificationid = "servicesInstall";
|
||||
|
|
|
@ -63,21 +63,18 @@ function clickMainAction() {
|
|||
}
|
||||
|
||||
/**
|
||||
* For an opened PopupNotification, clicks on a secondary action,
|
||||
* For an opened PopupNotification, clicks on the secondary action,
|
||||
* and waits for the panel to fully close.
|
||||
*
|
||||
* @param {int} index
|
||||
* The 0-indexed index of the secondary menuitem to choose.
|
||||
* @return {Promise}
|
||||
* Resolves once the panel has fired the "popuphidden"
|
||||
* event.
|
||||
*/
|
||||
function clickSecondaryAction(index) {
|
||||
function clickSecondaryAction() {
|
||||
let removePromise =
|
||||
BrowserTestUtils.waitForEvent(PopupNotifications.panel, "popuphidden");
|
||||
let popupNotification = getPopupNotificationNode();
|
||||
let menuitems = popupNotification.children;
|
||||
menuitems[index].click();
|
||||
popupNotification.secondaryButton.click();
|
||||
return removePromise;
|
||||
}
|
||||
|
||||
|
@ -255,6 +252,13 @@ add_task(function* test_with_permission_key() {
|
|||
permissionKey: kTestPermissionKey,
|
||||
message: kTestMessage,
|
||||
promptActions: [mainAction, secondaryAction],
|
||||
popupOptions: {
|
||||
checkbox: {
|
||||
label: "Remember this decision",
|
||||
show: true,
|
||||
checked: true
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let shownPromise =
|
||||
|
@ -274,7 +278,7 @@ add_task(function* test_with_permission_key() {
|
|||
// First test denying the permission request.
|
||||
Assert.equal(notification.secondaryActions.length, 1,
|
||||
"There should only be 1 secondary action");
|
||||
yield clickSecondaryAction(0);
|
||||
yield clickSecondaryAction();
|
||||
curPerm = Services.perms.testPermissionFromPrincipal(principal,
|
||||
kTestPermissionKey);
|
||||
Assert.equal(curPerm, Ci.nsIPermissionManager.DENY_ACTION,
|
||||
|
@ -429,7 +433,7 @@ add_task(function* test_no_request() {
|
|||
// First test denying the permission request.
|
||||
Assert.equal(notification.secondaryActions.length, 1,
|
||||
"There should only be 1 secondary action");
|
||||
yield clickSecondaryAction(0);
|
||||
yield clickSecondaryAction();
|
||||
Assert.ok(denied, "The secondaryAction callback should have fired");
|
||||
Assert.ok(!allowed, "The mainAction callback should not have fired");
|
||||
|
||||
|
|
|
@ -18,6 +18,10 @@ XPCOMUtils.defineLazyModuleGetter(this, "AppConstants",
|
|||
XPCOMUtils.defineLazyModuleGetter(this, "PluralForm",
|
||||
"resource://gre/modules/PluralForm.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "gBrandBundle", function() {
|
||||
return Services.strings.createBundle("chrome://branding/locale/brand.properties");
|
||||
});
|
||||
|
||||
this.webrtcUI = {
|
||||
init: function() {
|
||||
Services.obs.addObserver(maybeAddMenuIndicator, "browser-delayed-startup-finished", false);
|
||||
|
@ -155,20 +159,10 @@ this.webrtcUI = {
|
|||
identityBox.click();
|
||||
},
|
||||
|
||||
updateMainActionLabel: function(aMenuList) {
|
||||
updateWarningLabel: function(aMenuList) {
|
||||
let type = aMenuList.selectedItem.getAttribute("devicetype");
|
||||
let document = aMenuList.ownerDocument;
|
||||
document.getElementById("webRTC-all-windows-shared").hidden = type != "Screen";
|
||||
|
||||
// If we are also requesting audio in addition to screen sharing,
|
||||
// always use a generic label.
|
||||
if (!document.getElementById("webRTC-selectMicrophone").hidden)
|
||||
type = "";
|
||||
|
||||
let bundle = document.defaultView.gNavigatorBundle;
|
||||
let stringId = "getUserMedia.share" + (type || "SelectedItems") + ".label";
|
||||
let popupnotification = aMenuList.parentNode.parentNode;
|
||||
popupnotification.setAttribute("buttonlabel", bundle.getString(stringId));
|
||||
},
|
||||
|
||||
receiveMessage: function(aMessage) {
|
||||
|
@ -294,21 +288,13 @@ function prompt(aBrowser, aRequest) {
|
|||
let host = getHost(uri);
|
||||
let chromeDoc = aBrowser.ownerDocument;
|
||||
let stringBundle = chromeDoc.defaultView.gNavigatorBundle;
|
||||
let stringId = "getUserMedia.share" + requestTypes.join("And") + ".message";
|
||||
let stringId = "getUserMedia.share" + requestTypes.join("And") + "2.message";
|
||||
let message = stringBundle.getFormattedString(stringId, [host]);
|
||||
|
||||
let mainLabel;
|
||||
if (sharingScreen || sharingAudio) {
|
||||
mainLabel = stringBundle.getString("getUserMedia.shareSelectedItems.label");
|
||||
} else {
|
||||
let string = stringBundle.getString("getUserMedia.shareSelectedDevices.label");
|
||||
mainLabel = PluralForm.get(requestTypes.length, string);
|
||||
}
|
||||
|
||||
let notification; // Used by action callbacks.
|
||||
let mainAction = {
|
||||
label: mainLabel,
|
||||
accessKey: stringBundle.getString("getUserMedia.shareSelectedDevices.accesskey"),
|
||||
label: stringBundle.getString("getUserMedia.allow.label"),
|
||||
accessKey: stringBundle.getString("getUserMedia.allow.accesskey"),
|
||||
// The real callback will be set during the "showing" event. The
|
||||
// empty function here is so that PopupNotifications.show doesn't
|
||||
// reject the action.
|
||||
|
@ -317,45 +303,46 @@ function prompt(aBrowser, aRequest) {
|
|||
|
||||
let secondaryActions = [
|
||||
{
|
||||
label: stringBundle.getString("getUserMedia.denyRequest.label"),
|
||||
accessKey: stringBundle.getString("getUserMedia.denyRequest.accesskey"),
|
||||
callback: function() {
|
||||
label: stringBundle.getString("getUserMedia.dontAllow.label"),
|
||||
accessKey: stringBundle.getString("getUserMedia.dontAllow.accesskey"),
|
||||
callback: function(aState) {
|
||||
denyRequest(notification.browser, aRequest);
|
||||
if (aState && aState.checkboxChecked) {
|
||||
let perms = Services.perms;
|
||||
if (audioDevices.length)
|
||||
perms.add(uri, "microphone", perms.DENY_ACTION);
|
||||
if (videoDevices.length)
|
||||
perms.add(uri, "camera", perms.DENY_ACTION);
|
||||
}
|
||||
}
|
||||
}
|
||||
];
|
||||
// Bug 1037438: implement 'never' for screen sharing.
|
||||
if (!sharingScreen && !sharingAudio) {
|
||||
secondaryActions.push({
|
||||
label: stringBundle.getString("getUserMedia.never.label"),
|
||||
accessKey: stringBundle.getString("getUserMedia.never.accesskey"),
|
||||
callback: function() {
|
||||
denyRequest(notification.browser, aRequest);
|
||||
// Let someone save "Never" for http sites so that they can be stopped from
|
||||
// bothering you with doorhangers.
|
||||
let perms = Services.perms;
|
||||
if (audioDevices.length)
|
||||
perms.add(uri, "microphone", perms.DENY_ACTION);
|
||||
if (videoDevices.length)
|
||||
perms.add(uri, "camera", perms.DENY_ACTION);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (aRequest.secure && !sharingScreen && !sharingAudio) {
|
||||
// Don't show the 'Always' action if the connection isn't secure, or for
|
||||
// screen/audio sharing (because we can't guess which window the user wants
|
||||
// to share without prompting).
|
||||
secondaryActions.unshift({
|
||||
label: stringBundle.getString("getUserMedia.always.label"),
|
||||
accessKey: stringBundle.getString("getUserMedia.always.accesskey"),
|
||||
callback: function(aState) {
|
||||
mainAction.callback(aState, true);
|
||||
}
|
||||
});
|
||||
let productName = gBrandBundle.GetStringFromName("brandShortName");
|
||||
|
||||
// Disable the permanent 'Allow' action if the connection isn't secure, or for
|
||||
// screen/audio sharing (because we can't guess which window the user wants to
|
||||
// share without prompting).
|
||||
let reasonForNoPermanentAllow = "";
|
||||
if (sharingScreen) {
|
||||
reasonForNoPermanentAllow = "getUserMedia.reasonForNoPermanentAllow.screen";
|
||||
} else if (sharingAudio) {
|
||||
reasonForNoPermanentAllow = "getUserMedia.reasonForNoPermanentAllow.audio";
|
||||
} else if (!aRequest.secure) {
|
||||
reasonForNoPermanentAllow = "getUserMedia.reasonForNoPermanentAllow.insecure";
|
||||
}
|
||||
|
||||
let options = {
|
||||
persistent: true,
|
||||
hideClose: true,
|
||||
checkbox: {
|
||||
label: stringBundle.getString("getUserMedia.remember"),
|
||||
checkedState: reasonForNoPermanentAllow ? {
|
||||
disableMainAction: true,
|
||||
warningLabel: stringBundle.getFormattedString(reasonForNoPermanentAllow,
|
||||
[productName])
|
||||
} : undefined,
|
||||
},
|
||||
eventCallback: function(aTopic, aNewBrowser) {
|
||||
if (aTopic == "swapping")
|
||||
return true;
|
||||
|
@ -603,7 +590,8 @@ function prompt(aBrowser, aRequest) {
|
|||
if (!sharingAudio)
|
||||
listDevices(micMenupopup, audioDevices);
|
||||
|
||||
this.mainAction.callback = function(aState, aRemember) {
|
||||
this.mainAction.callback = function(aState) {
|
||||
let remember = aState && aState.checkboxChecked;
|
||||
let allowedDevices = [];
|
||||
let perms = Services.perms;
|
||||
if (videoDevices.length) {
|
||||
|
@ -617,7 +605,7 @@ function prompt(aBrowser, aRequest) {
|
|||
perms.add(uri, "MediaManagerVideo", perms.ALLOW_ACTION,
|
||||
perms.EXPIRE_SESSION);
|
||||
}
|
||||
if (aRemember) {
|
||||
if (remember) {
|
||||
perms.add(uri, "camera",
|
||||
allowCamera ? perms.ALLOW_ACTION : perms.DENY_ACTION);
|
||||
}
|
||||
|
@ -628,7 +616,7 @@ function prompt(aBrowser, aRequest) {
|
|||
let allowMic = audioDeviceIndex != "-1";
|
||||
if (allowMic)
|
||||
allowedDevices.push(audioDeviceIndex);
|
||||
if (aRemember) {
|
||||
if (remember) {
|
||||
perms.add(uri, "microphone",
|
||||
allowMic ? perms.ALLOW_ACTION : perms.DENY_ACTION);
|
||||
}
|
||||
|
@ -643,7 +631,7 @@ function prompt(aBrowser, aRequest) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (aRemember) {
|
||||
if (remember) {
|
||||
// Remember on which URIs we set persistent permissions so that we
|
||||
// can remove them if the user clicks 'Stop Sharing'.
|
||||
aBrowser._devicePermissionURIs = aBrowser._devicePermissionURIs || [];
|
||||
|
|
|
@ -344,6 +344,6 @@ menuitem[cmd="cmd_clearhistory"][disabled] {
|
|||
|
||||
.search-setting-button-compact > .button-box > .button-icon {
|
||||
list-style-image: url("chrome://browser/skin/gear.svg");
|
||||
filter: url(chrome://browser/skin/filters.svg#fill);
|
||||
filter: url(chrome://global/skin/filters.svg#fill);
|
||||
fill: currentColor;
|
||||
}
|
||||
|
|
|
@ -326,6 +326,6 @@
|
|||
|
||||
.search-setting-button-compact > .button-box > .button-icon {
|
||||
list-style-image: url("chrome://browser/skin/gear.svg");
|
||||
filter: url(chrome://browser/skin/filters.svg#fill);
|
||||
filter: url(chrome://global/skin/filters.svg#fill);
|
||||
fill: currentColor;
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
width: 16px;
|
||||
height: 16px;
|
||||
margin: 7px;
|
||||
filter: url(chrome://browser/skin/filters.svg#fill);
|
||||
filter: url(chrome://global/skin/filters.svg#fill);
|
||||
fill: currentColor;
|
||||
}
|
||||
|
||||
|
|
|
@ -423,7 +423,7 @@ description#identity-popup-content-verifier,
|
|||
width: 16px;
|
||||
height: 16px;
|
||||
list-style-image: url(chrome://browser/skin/panel-icons.svg#cancel);
|
||||
filter: url(chrome://browser/skin/filters.svg#fill);
|
||||
filter: url(chrome://global/skin/filters.svg#fill);
|
||||
fill: graytext;
|
||||
}
|
||||
|
||||
|
|
|
@ -296,7 +296,7 @@ window:not([chromehidden~="toolbar"]) #urlbar-wrapper {
|
|||
|
||||
.tab-icon-sound[soundplaying],
|
||||
.tab-icon-sound[muted] {
|
||||
filter: url(chrome://browser/skin/filters.svg#fill) !important; /* removes drop-shadow filter */
|
||||
filter: url(chrome://global/skin/filters.svg#fill) !important; /* removes drop-shadow filter */
|
||||
}
|
||||
|
||||
/* Don't need space for the tab curves (66px - 30px) */
|
||||
|
|
|
@ -103,7 +103,7 @@
|
|||
width: 16px;
|
||||
height: 16px;
|
||||
margin: 0;
|
||||
filter: url("chrome://browser/skin/filters.svg#fill");
|
||||
filter: url("chrome://global/skin/filters.svg#fill");
|
||||
fill: currentColor;
|
||||
}
|
||||
|
||||
|
|
|
@ -138,8 +138,8 @@ toolbarseparator.downloadsDropmarkerSplitter {
|
|||
.downloadsDropmarker > .button-box > .button-menu-dropmarker > .dropmarker-icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
list-style-image: url("chrome://browser/skin/downloads/menubutton-dropmarker.svg");
|
||||
filter: url("chrome://browser/skin/filters.svg#fill");
|
||||
list-style-image: url("chrome://global/skin/icons/menubutton-dropmarker.svg");
|
||||
filter: url("chrome://global/skin/filters.svg#fill");
|
||||
fill: currentColor;
|
||||
}
|
||||
|
||||
|
@ -267,7 +267,7 @@ richlistitem[type="download"] > .downloadMainArea {
|
|||
width: 16px;
|
||||
height: 16px;
|
||||
margin: 1px;
|
||||
filter: url("chrome://browser/skin/filters.svg#fill");
|
||||
filter: url("chrome://global/skin/filters.svg#fill");
|
||||
fill: currentColor;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
<?xml version="1.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/. -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg">
|
||||
<filter id="fill">
|
||||
<feComposite in="FillPaint" in2="SourceGraphic" operator="in"/>
|
||||
</filter>
|
||||
</svg>
|
До Ширина: | Высота: | Размер: 383 B |
|
@ -52,10 +52,8 @@
|
|||
skin/classic/browser/customizableui/whimsy@2x.png (../shared/customizableui/whimsy@2x.png)
|
||||
skin/classic/browser/downloads/contentAreaDownloadsView.css (../shared/downloads/contentAreaDownloadsView.css)
|
||||
skin/classic/browser/downloads/download-blocked.svg (../shared/downloads/download-blocked.svg)
|
||||
skin/classic/browser/downloads/menubutton-dropmarker.svg (../shared/downloads/menubutton-dropmarker.svg)
|
||||
skin/classic/browser/downloads/download-summary.svg (../shared/downloads/download-summary.svg)
|
||||
skin/classic/browser/drm-icon.svg (../shared/drm-icon.svg)
|
||||
skin/classic/browser/filters.svg (../shared/filters.svg)
|
||||
skin/classic/browser/fullscreen/insecure.svg (../shared/fullscreen/insecure.svg)
|
||||
skin/classic/browser/fullscreen/secure.svg (../shared/fullscreen/secure.svg)
|
||||
skin/classic/browser/heartbeat-icon.svg (../shared/heartbeat-icon.svg)
|
||||
|
|
|
@ -9,7 +9,7 @@ toolbarpaletteitem[place="palette"] > :-moz-any(@primaryToolbarButtons@) {
|
|||
:-moz-any(@primaryToolbarButtons@)[cui-areatype="menu-panel"][panel-multiview-anchor=true] > .toolbarbutton-icon,
|
||||
:-moz-any(@primaryToolbarButtons@)[cui-areatype="menu-panel"][panel-multiview-anchor=true] > .toolbarbutton-badge-stack > .toolbarbutton-icon,
|
||||
:-moz-any(@primaryToolbarButtons@)[cui-areatype="menu-panel"][panel-multiview-anchor=true] > .toolbarbutton-menubutton-button > .toolbarbutton-icon {
|
||||
filter: url(chrome://browser/skin/filters.svg#fill);
|
||||
filter: url(chrome://global/skin/filters.svg#fill);
|
||||
fill: currentColor;
|
||||
}
|
||||
|
||||
|
|
|
@ -39,15 +39,21 @@
|
|||
}
|
||||
}
|
||||
|
||||
.popup-notification-icon {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
margin-inline-end: 10px;
|
||||
#notification-popup > .panel-arrowcontainer > .panel-arrowcontent {
|
||||
/* In order to display the action buttons near the edge of the arrow panel we
|
||||
* have to reset its default padding and specify the padding in the individual
|
||||
* "popupnotification" elements instead. To keep the rounded borders of the
|
||||
* panel, we also have to ensure the contents are clipped to the border box
|
||||
* by hiding the overflow, and we have to override the "display" property so
|
||||
* that the height of the contents is computed correctly in that case. */
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.notification-anchor-icon:not(.plugin-blocked):-moz-lwtheme,
|
||||
#blocked-permissions-container > .blocked-permission-icon:-moz-lwtheme {
|
||||
filter: url(chrome://browser/skin/filters.svg#fill);
|
||||
filter: url(chrome://global/skin/filters.svg#fill);
|
||||
fill: currentColor;
|
||||
}
|
||||
|
||||
|
|
|
@ -207,7 +207,7 @@
|
|||
.tab-icon-sound[muted],
|
||||
.tab-icon-sound[blocked] {
|
||||
list-style-image: url(chrome://browser/skin/tabbrowser/tab-audio.svg#tab-audio);
|
||||
filter: url(chrome://browser/skin/filters.svg#fill);
|
||||
filter: url(chrome://global/skin/filters.svg#fill);
|
||||
fill: currentColor;
|
||||
}
|
||||
|
||||
|
@ -222,13 +222,13 @@
|
|||
.tab-icon-sound:-moz-lwtheme-darktext[soundplaying],
|
||||
.tab-icon-sound:-moz-lwtheme-darktext[muted],
|
||||
.tab-icon-sound:-moz-lwtheme-darktext[blocked] {
|
||||
filter: url(chrome://browser/skin/filters.svg#fill) drop-shadow(1px 1px 1px white);
|
||||
filter: url(chrome://global/skin/filters.svg#fill) drop-shadow(1px 1px 1px white);
|
||||
}
|
||||
|
||||
.tab-icon-sound:-moz-lwtheme-brighttext[soundplaying],
|
||||
.tab-icon-sound:-moz-lwtheme-brighttext[muted],
|
||||
.tab-icon-sound:-moz-lwtheme-brighttext[blocked] {
|
||||
filter: url(chrome://browser/skin/filters.svg#fill) drop-shadow(1px 1px 1px black);
|
||||
filter: url(chrome://global/skin/filters.svg#fill) drop-shadow(1px 1px 1px black);
|
||||
}
|
||||
|
||||
.tab-icon-sound[soundplaying]:not(:hover),
|
||||
|
@ -553,7 +553,7 @@
|
|||
.alltabs-endimage[muted],
|
||||
.alltabs-endimage[blocked] {
|
||||
list-style-image: url(chrome://browser/skin/tabbrowser/tab-audio.svg#tab-audio);
|
||||
filter: url(chrome://browser/skin/filters.svg#fill);
|
||||
filter: url(chrome://global/skin/filters.svg#fill);
|
||||
fill: currentColor;
|
||||
}
|
||||
|
||||
|
|
|
@ -2668,19 +2668,16 @@ notification.pluginVulnerable > .notification-inner > .messageCloseButton {
|
|||
|
||||
#ContentSelectDropdown > menupopup > menucaption,
|
||||
#ContentSelectDropdown > menupopup > menuitem {
|
||||
padding: 4px 6px;
|
||||
padding: 0 6px;
|
||||
border-width: 0;
|
||||
}
|
||||
|
||||
#ContentSelectDropdown > menupopup > menucaption > .menu-iconic-text,
|
||||
#ContentSelectDropdown > menupopup > menuitem > .menu-iconic-text {
|
||||
font: message-box;
|
||||
font-size: 11px;
|
||||
/**
|
||||
* Remove the extra vertical padding set by menu.css since
|
||||
* the menuitem itself will include enough padding.
|
||||
*/
|
||||
padding-top: 0px;
|
||||
padding-bottom: 0px;
|
||||
/* Padding should follow the 4/12 ratio, where 12px is the default font-size
|
||||
with 4px being the preferred padding size. */
|
||||
padding-top: .3333em;
|
||||
padding-bottom: .3333em;
|
||||
}
|
||||
|
||||
#ContentSelectDropdown > menupopup > menucaption > .menu-iconic-text {
|
||||
|
@ -2700,8 +2697,10 @@ notification.pluginVulnerable > .notification-inner > .messageCloseButton {
|
|||
color: GrayText;
|
||||
}
|
||||
|
||||
#ContentSelectDropdown > .isOpenedViaTouch > menucaption,
|
||||
#ContentSelectDropdown > .isOpenedViaTouch > menuitem {
|
||||
padding-top: 11px;
|
||||
padding-bottom: 11px;
|
||||
#ContentSelectDropdown > .isOpenedViaTouch > menucaption > .menu-iconic-text,
|
||||
#ContentSelectDropdown > .isOpenedViaTouch > menuitem > .menu-iconic-text {
|
||||
/* Touch padding should follow the 11/12 ratio, where 12px is the default
|
||||
font-size with 11px being the preferred padding size. */
|
||||
padding-top: .9167em;
|
||||
padding-bottom: .9167em;
|
||||
}
|
||||
|
|
|
@ -336,6 +336,6 @@
|
|||
|
||||
.search-setting-button-compact > .button-box > .button-icon {
|
||||
list-style-image: url("chrome://browser/skin/gear.svg");
|
||||
filter: url(chrome://browser/skin/filters.svg#fill);
|
||||
filter: url(chrome://global/skin/filters.svg#fill);
|
||||
fill: currentColor;
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ this.PermissionPrompts = {
|
|||
Services.prefs.setCharPref("media.getusermedia.screensharing.allowed_domains",
|
||||
"test1.example.com");
|
||||
Services.prefs.setBoolPref("extensions.install.requireBuiltInCerts", false);
|
||||
Services.prefs.setBoolPref("signon.rememberSignons", true);
|
||||
},
|
||||
|
||||
configurations: {
|
||||
|
|
|
@ -156,6 +156,8 @@ if test -n "$MOZ_SYSTEM_NSPR" -o -n "$NSPR_CFLAGS" -o -n "$NSPR_LIBS"; then
|
|||
,
|
||||
AC_MSG_ERROR([system NSPR does not support PR_UINT64 or including prtypes.h does not provide it]))
|
||||
CFLAGS=$_SAVE_CFLAGS
|
||||
NSPR_INCLUDE_DIR=`echo ${NSPR_CFLAGS} | sed -e 's/.*-I\([^ ]*\).*/\1/'`
|
||||
NSPR_LIB_DIR=`echo ${NSPR_LIBS} | sed -e 's/.*-L\([^ ]*\).*/\1/'`
|
||||
elif test -z "$JS_POSIX_NSPR"; then
|
||||
NSPR_INCLUDE_DIR="${DIST}/include/nspr"
|
||||
NSPR_CFLAGS="-I${NSPR_INCLUDE_DIR}"
|
||||
|
|
|
@ -4,7 +4,9 @@
|
|||
# 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/.
|
||||
|
||||
gyp_vars = {
|
||||
include('gyp_base.mozbuild')
|
||||
|
||||
gyp_vars.update({
|
||||
'lsan': 0,
|
||||
'asan': 0,
|
||||
'build_with_mozilla': 1,
|
||||
|
@ -69,16 +71,9 @@ gyp_vars = {
|
|||
# linker to throw away uneeded bits.
|
||||
'include_isac': 1,
|
||||
'include_pcm16b': 1,
|
||||
}
|
||||
})
|
||||
|
||||
os = CONFIG['OS_TARGET']
|
||||
|
||||
if os == 'WINNT':
|
||||
gyp_vars.update(
|
||||
MSVS_VERSION=CONFIG['_MSVS_VERSION'],
|
||||
MSVS_OS_BITS=64 if CONFIG['HAVE_64BIT_BUILD'] else 32,
|
||||
)
|
||||
elif os == 'Android':
|
||||
if os == 'Android':
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
|
||||
gyp_vars['build_with_gonk'] = 1
|
||||
gyp_vars['moz_widget_toolkit_gonk'] = 1
|
||||
|
@ -92,28 +87,6 @@ elif os == 'Android':
|
|||
android_toolchain=CONFIG.get('ANDROID_TOOLCHAIN', ''),
|
||||
)
|
||||
|
||||
flavors = {
|
||||
'WINNT': 'win',
|
||||
'Android': 'linux' if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk' else 'android',
|
||||
'Linux': 'linux',
|
||||
'Darwin': 'mac' if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa' else 'ios',
|
||||
'SunOS': 'solaris',
|
||||
'GNU/kFreeBSD': 'freebsd',
|
||||
'DragonFly': 'dragonfly',
|
||||
'FreeBSD': 'freebsd',
|
||||
'NetBSD': 'netbsd',
|
||||
'OpenBSD': 'openbsd',
|
||||
}
|
||||
gyp_vars['OS'] = flavors.get(os)
|
||||
|
||||
arches = {
|
||||
'x86_64': 'x64',
|
||||
'x86': 'ia32',
|
||||
'aarch64': 'arm64',
|
||||
}
|
||||
|
||||
gyp_vars['target_arch'] = arches.get(CONFIG['CPU_ARCH'], CONFIG['CPU_ARCH'])
|
||||
|
||||
if CONFIG['ARM_ARCH']:
|
||||
if int(CONFIG['ARM_ARCH']) < 7:
|
||||
gyp_vars['armv7'] = 0
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
gyp_vars = {}
|
||||
|
||||
os = CONFIG['OS_TARGET']
|
||||
|
||||
if os == 'WINNT':
|
||||
gyp_vars.update(
|
||||
MSVS_VERSION=CONFIG['_MSVS_VERSION'],
|
||||
MSVS_OS_BITS=64 if CONFIG['HAVE_64BIT_BUILD'] else 32,
|
||||
)
|
||||
|
||||
flavors = {
|
||||
'WINNT': 'win',
|
||||
'Android': 'linux' if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk' else 'android',
|
||||
'Linux': 'linux',
|
||||
'Darwin': 'mac' if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa' else 'ios',
|
||||
'SunOS': 'solaris',
|
||||
'GNU/kFreeBSD': 'freebsd',
|
||||
'DragonFly': 'dragonfly',
|
||||
'FreeBSD': 'freebsd',
|
||||
'NetBSD': 'netbsd',
|
||||
'OpenBSD': 'openbsd',
|
||||
}
|
||||
gyp_vars['OS'] = flavors.get(os)
|
||||
|
||||
arches = {
|
||||
'x86_64': 'x64',
|
||||
'x86': 'ia32',
|
||||
'aarch64': 'arm64',
|
||||
}
|
||||
|
||||
gyp_vars['host_arch'] = arches.get(CONFIG['HOST_CPU_ARCH'], CONFIG['HOST_CPU_ARCH'])
|
||||
gyp_vars['target_arch'] = arches.get(CONFIG['CPU_ARCH'], CONFIG['CPU_ARCH'])
|
|
@ -520,6 +520,7 @@ def host_variables(host):
|
|||
HOST_OS_ARCH=os_arch,
|
||||
)
|
||||
|
||||
set_config('HOST_CPU_ARCH', delayed_getattr(host, 'cpu'))
|
||||
set_config('HOST_OS_ARCH', delayed_getattr(host_variables, 'HOST_OS_ARCH'))
|
||||
add_old_configure_assignment('HOST_OS_ARCH',
|
||||
delayed_getattr(host_variables, 'HOST_OS_ARCH'))
|
||||
|
|
|
@ -1,485 +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/.
|
||||
|
||||
ifndef MOZ_SYSTEM_NSS
|
||||
|
||||
CC_WRAPPER =
|
||||
CXX_WRAPPER =
|
||||
|
||||
default::
|
||||
|
||||
include $(topsrcdir)/config/makefiles/functions.mk
|
||||
|
||||
NSS_LIBS = \
|
||||
nss3 \
|
||||
nssutil3 \
|
||||
smime3 \
|
||||
ssl3 \
|
||||
$(NULL)
|
||||
|
||||
ifdef MOZ_FOLD_LIBS
|
||||
NSS_DLLS = $(LIBRARY_NAME)
|
||||
else
|
||||
NSS_DLLS = $(NSS_LIBS)
|
||||
endif
|
||||
|
||||
NSS_EXTRA_DLLS = \
|
||||
nssckbi \
|
||||
softokn3 \
|
||||
$(NULL)
|
||||
|
||||
ifndef NSS_DISABLE_DBM
|
||||
NSS_EXTRA_DLLS += nssdbm3
|
||||
endif
|
||||
|
||||
SDK_LIBS = crmf
|
||||
|
||||
ifneq (,$(filter WINNT,$(OS_ARCH)))
|
||||
SDK_LIBS += $(NSS_DLLS)
|
||||
endif
|
||||
|
||||
# Default
|
||||
HAVE_FREEBL_LIBS = 1
|
||||
|
||||
# 32-bit HP-UX PA-RISC
|
||||
ifeq ($(OS_ARCH), HP-UX)
|
||||
ifneq ($(OS_TEST), ia64)
|
||||
ifndef HAVE_64BIT_BUILD
|
||||
HAVE_FREEBL_LIBS =
|
||||
HAVE_FREEBL_LIBS_32INT32 = 1
|
||||
HAVE_FREEBL_LIBS_32FPU = 1
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
# SunOS SPARC
|
||||
ifeq ($(OS_ARCH), SunOS)
|
||||
ifneq (86,$(findstring 86,$(OS_TEST)))
|
||||
ifdef HAVE_64BIT_BUILD
|
||||
HAVE_FREEBL_LIBS =
|
||||
HAVE_FREEBL_LIBS_64 = 1
|
||||
else
|
||||
HAVE_FREEBL_LIBS =
|
||||
HAVE_FREEBL_LIBS_32FPU = 1
|
||||
HAVE_FREEBL_LIBS_32INT64 = 1
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(OS_TARGET),Linux)
|
||||
HAVE_FREEBL_LIBS =
|
||||
HAVE_FREEBL_LIBS_PRIV = 1
|
||||
FREEBL_LOWHASH_FLAG = FREEBL_LOWHASH=1
|
||||
endif
|
||||
|
||||
ifdef HAVE_FREEBL_LIBS
|
||||
NSS_EXTRA_DLLS += freebl3
|
||||
endif
|
||||
ifdef HAVE_FREEBL_LIBS_PRIV
|
||||
NSS_EXTRA_DLLS += freeblpriv3
|
||||
endif
|
||||
ifdef HAVE_FREEBL_LIBS_32INT32
|
||||
NSS_EXTRA_DLLS += freebl_32int_3
|
||||
endif
|
||||
ifdef HAVE_FREEBL_LIBS_32FPU
|
||||
NSS_EXTRA_DLLS += freebl_32fpu_3
|
||||
endif
|
||||
ifdef HAVE_FREEBL_LIBS_32INT64
|
||||
NSS_EXTRA_DLLS += freebl_32int64_3
|
||||
endif
|
||||
ifdef HAVE_FREEBL_LIBS_64
|
||||
NSS_EXTRA_DLLS += freebl_64int_3
|
||||
NSS_EXTRA_DLLS += freebl_64fpu_3
|
||||
endif
|
||||
|
||||
# For all variables such as DLLFLAGS, that may contain $(DIST)
|
||||
DIST := $(ABS_DIST)
|
||||
# TODO: move this all to configure, but in Python
|
||||
ifndef MOZ_BUILD_NSPR
|
||||
NSPR_INCLUDE_DIR = $(firstword $(filter -I%,$(NSPR_CFLAGS)))
|
||||
ifneq (,$(strip $(NSPR_INCLUDE_DIR)))
|
||||
NSPR_INCLUDE_DIR := $(subst -I,,$(subst -I$(DIST),-I$(ABS_DIST),$(NSPR_INCLUDE_DIR)))
|
||||
else
|
||||
$(error Your NSPR CFLAGS are broken!)
|
||||
endif
|
||||
NSPR_LIB_DIR = $(firstword $(filter -L%,$(NSPR_LIBS)))
|
||||
ifneq (,$(strip $(NSPR_LIB_DIR)))
|
||||
NSPR_LIB_DIR := $(subst -L,,$(subst -L$(DIST),-L$(ABS_DIST),$(NSPR_LIB_DIR)))
|
||||
else
|
||||
$(error Your NSPR LDFLAGS are broken!)
|
||||
endif
|
||||
endif
|
||||
|
||||
# To get debug symbols from NSS
|
||||
export MOZ_DEBUG_SYMBOLS
|
||||
|
||||
DEFAULT_GMAKE_FLAGS =
|
||||
DEFAULT_GMAKE_FLAGS += CC='$(CC)'
|
||||
DEFAULT_GMAKE_FLAGS += MT='$(MT)'
|
||||
DEFAULT_GMAKE_FLAGS += LD='$(LD)'
|
||||
DEFAULT_GMAKE_FLAGS += SOURCE_MD_DIR=$(ABS_DIST)
|
||||
DEFAULT_GMAKE_FLAGS += SOURCE_MDHEADERS_DIR=$(NSPR_INCLUDE_DIR)
|
||||
DEFAULT_GMAKE_FLAGS += DIST=$(ABS_DIST)
|
||||
DEFAULT_GMAKE_FLAGS += NSPR_INCLUDE_DIR=$(NSPR_INCLUDE_DIR)
|
||||
DEFAULT_GMAKE_FLAGS += NSPR_LIB_DIR=$(NSPR_LIB_DIR)
|
||||
DEFAULT_GMAKE_FLAGS += MOZILLA_CLIENT=1
|
||||
DEFAULT_GMAKE_FLAGS += NO_MDUPDATE=1
|
||||
DEFAULT_GMAKE_FLAGS += NSS_ENABLE_ECC=1
|
||||
DEFAULT_GMAKE_FLAGS += NSS_ENABLE_TLS_1_3=1
|
||||
ifeq ($(OS_ARCH)_$(GNU_CC),WINNT_1)
|
||||
DEFAULT_GMAKE_FLAGS += OS_DLLFLAGS='-static-libgcc' NSPR31_LIB_PREFIX=lib
|
||||
endif
|
||||
ifndef MOZ_SYSTEM_SQLITE
|
||||
ifdef MOZ_FOLD_LIBS
|
||||
DEFAULT_GMAKE_FLAGS += SQLITE_LIB_NAME=nss3
|
||||
else
|
||||
DEFAULT_GMAKE_FLAGS += SQLITE_LIB_NAME=mozsqlite3
|
||||
DEFAULT_GMAKE_FLAGS += SQLITE_LIB_DIR=$(ABS_DIST)/../config/external/sqlite
|
||||
endif # MOZ_FOLD_LIBS
|
||||
DEFAULT_GMAKE_FLAGS += SQLITE_INCLUDE_DIR=$(ABS_DIST)/include
|
||||
endif
|
||||
ifdef NSS_DISABLE_DBM
|
||||
DEFAULT_GMAKE_FLAGS += NSS_DISABLE_DBM=1
|
||||
endif
|
||||
# Hack to force NSS build system to use "normal" object directories
|
||||
DEFAULT_GMAKE_FLAGS += topsrcdir='$(topsrcdir)'
|
||||
# topsrcdir can't be expanded here because msys path mangling likes to break
|
||||
# paths in that case.
|
||||
DEFAULT_GMAKE_FLAGS += BUILD='$(MOZ_BUILD_ROOT)/security/$$(subst $$(topsrcdir)/security/,,$$(CURDIR))'
|
||||
DEFAULT_GMAKE_FLAGS += BUILD_TREE='$$(BUILD)' OBJDIR='$$(BUILD)' DEPENDENCIES='$$(BUILD)/.deps' SINGLE_SHLIB_DIR='$$(BUILD)'
|
||||
DEFAULT_GMAKE_FLAGS += SOURCE_XP_DIR=$(ABS_DIST)
|
||||
ifndef MOZ_DEBUG
|
||||
DEFAULT_GMAKE_FLAGS += BUILD_OPT=1 OPT_CODE_SIZE=1
|
||||
endif
|
||||
ifdef GNU_CC
|
||||
DEFAULT_GMAKE_FLAGS += NS_USE_GCC=1
|
||||
else
|
||||
DEFAULT_GMAKE_FLAGS += NS_USE_GCC=
|
||||
endif
|
||||
ifdef USE_N32
|
||||
# It is not really necessary to specify USE_PTHREADS=1. USE_PTHREADS
|
||||
# merely adds _PTH to coreconf's OBJDIR name.
|
||||
DEFAULT_GMAKE_FLAGS += USE_N32=1 USE_PTHREADS=1
|
||||
endif
|
||||
ifdef HAVE_64BIT_BUILD
|
||||
DEFAULT_GMAKE_FLAGS += USE_64=1
|
||||
endif
|
||||
ifeq ($(OS_ARCH),WINNT)
|
||||
DEFAULT_GMAKE_FLAGS += OS_TARGET=WIN95
|
||||
ifdef MOZ_DEBUG
|
||||
ifndef MOZ_NO_DEBUG_RTL
|
||||
DEFAULT_GMAKE_FLAGS += USE_DEBUG_RTL=1
|
||||
endif
|
||||
endif
|
||||
endif # WINNT
|
||||
ifeq ($(OS_ARCH),Darwin)
|
||||
# Make nsinstall use absolute symlinks by default when building NSS
|
||||
# for Mozilla on Mac OS X. (Bugzilla bug 193164)
|
||||
ifndef NSDISTMODE
|
||||
DEFAULT_GMAKE_FLAGS += NSDISTMODE=absolute_symlink
|
||||
endif
|
||||
ifdef MACOS_SDK_DIR
|
||||
DEFAULT_GMAKE_FLAGS += MACOS_SDK_DIR=$(MACOS_SDK_DIR)
|
||||
endif
|
||||
endif
|
||||
|
||||
# Turn off TLS compression support because it requires system zlib.
|
||||
# See bug 580679 comment 18.
|
||||
DEFAULT_GMAKE_FLAGS += NSS_SSL_ENABLE_ZLIB=
|
||||
|
||||
# Disable building of the test programs in security/nss/lib/zlib
|
||||
DEFAULT_GMAKE_FLAGS += PROGRAMS=
|
||||
|
||||
# Disable creating .chk files. They will be generated from packager.mk
|
||||
# When bug 681624 lands, we can replace CHECKLOC= with SKIP_SHLIBSIGN=1
|
||||
DEFAULT_GMAKE_FLAGS += CHECKLOC=
|
||||
|
||||
ifdef CROSS_COMPILE
|
||||
|
||||
DEFAULT_GMAKE_FLAGS += \
|
||||
NATIVE_CC='$(HOST_CC)' \
|
||||
CC='$(CC)' \
|
||||
CCC='$(CXX)' \
|
||||
AS='$(AS)' \
|
||||
AR='$(AR) $(AR_FLAGS:$@=$$@)' \
|
||||
RANLIB='$(RANLIB)' \
|
||||
RC='$(RC) $(RCFLAGS)' \
|
||||
OS_ARCH='$(OS_ARCH)' \
|
||||
OS_TEST='$(OS_TEST)' \
|
||||
CPU_ARCH='$(TARGET_CPU)' \
|
||||
$(NULL)
|
||||
|
||||
# Android has pthreads integrated into -lc, so OS_PTHREAD is set to nothing
|
||||
ifeq ($(OS_TARGET), Android)
|
||||
DEFAULT_GMAKE_FLAGS += \
|
||||
OS_RELEASE='2.6' \
|
||||
OS_PTHREAD= \
|
||||
$(NULL)
|
||||
|
||||
DEFAULT_GMAKE_FLAGS += ARCHFLAG='$(filter-out -W%,$(CFLAGS)) -DCHECK_FORK_GETPID $(addprefix -DANDROID_VERSION=,$(ANDROID_VERSION)) -include $(topsrcdir)/security/manager/android_stub.h'
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef WRAP_LDFLAGS
|
||||
NSS_EXTRA_LDFLAGS += $(WRAP_LDFLAGS)
|
||||
endif
|
||||
|
||||
# The SHARED_LIBS part is needed unconditionally on Android. It's not
|
||||
# clear why this is the case, but see bug 1133073 (starting around
|
||||
# comment #8) for context.
|
||||
ifneq (,$(or $(MOZ_GLUE_WRAP_LDFLAGS), $(filter Android, $(OS_TARGET))))
|
||||
NSS_EXTRA_LDFLAGS += $(SHARED_LIBS:$(DEPTH)%=$(MOZ_BUILD_ROOT)%) $(MOZ_GLUE_WRAP_LDFLAGS)
|
||||
endif
|
||||
|
||||
ifneq (,$(NSS_EXTRA_LDFLAGS))
|
||||
DEFAULT_GMAKE_FLAGS += \
|
||||
LDFLAGS='$(LDFLAGS) $(NSS_EXTRA_LDFLAGS)' \
|
||||
DSO_LDOPTS='$(DSO_LDOPTS) $(LDFLAGS) $(NSS_EXTRA_LDFLAGS)' \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
DEFAULT_GMAKE_FLAGS += FREEBL_NO_DEPEND=0 $(FREEBL_LOWHASH_FLAG)
|
||||
DEFAULT_GMAKE_FLAGS += NSS_ALLOW_SSLKEYLOGFILE=1
|
||||
|
||||
ifdef MOZ_NO_WLZDEFS
|
||||
DEFAULT_GMAKE_FLAGS += ZDEFS_FLAG=
|
||||
endif
|
||||
ifdef MOZ_CFLAGS_NSS
|
||||
NSS_XCFLAGS += $(filter-out -W%,$(CFLAGS))
|
||||
DEFAULT_GMAKE_FLAGS += DARWIN_DYLIB_VERSIONS='-compatibility_version 1 -current_version 1 $(LDFLAGS)'
|
||||
endif
|
||||
ifeq (1_1,$(CLANG_CL)_$(MOZ_ASAN))
|
||||
XLDFLAGS := $(OS_LDFLAGS)
|
||||
DEFAULT_GMAKE_FLAGS += XLDFLAGS='$(XLDFLAGS)'
|
||||
endif
|
||||
|
||||
DEFAULT_GMAKE_FLAGS += NSS_NO_PKCS11_BYPASS=1
|
||||
|
||||
# Put NSS headers directly under $(DIST)/include
|
||||
DEFAULT_GMAKE_FLAGS += PUBLIC_EXPORT_DIR='$(ABS_DIST)/include/$$(MODULE)'
|
||||
DEFAULT_GMAKE_FLAGS += SOURCE_XPHEADERS_DIR='$$(SOURCE_XP_DIR)/include/$$(MODULE)'
|
||||
DEFAULT_GMAKE_FLAGS += MODULE_INCLUDES='$$(addprefix -I$$(SOURCE_XP_DIR)/include/,$$(REQUIRES))'
|
||||
|
||||
# Work around NSS's MAKE_OBJDIR being racy. See bug #836220
|
||||
DEFAULT_GMAKE_FLAGS += MAKE_OBJDIR='$$(INSTALL) -D $$(OBJDIR)'
|
||||
|
||||
# Work around NSS adding IMPORT_LIBRARY to TARGETS with no rule for
|
||||
# it, creating race conditions. See bug #836220
|
||||
DEFAULT_GMAKE_FLAGS += TARGETS='$$(LIBRARY) $$(SHARED_LIBRARY) $$(PROGRAM)'
|
||||
|
||||
ifdef MOZ_FOLD_LIBS_FLAGS
|
||||
NSS_XCFLAGS += $(MOZ_FOLD_LIBS_FLAGS)
|
||||
endif
|
||||
|
||||
# Pass on the MSVC target arch from the main build system.
|
||||
# Note this is case- and switch-character sensitive, while
|
||||
# the MSVC option is not.
|
||||
ifeq (WINNT,$(OS_TARGET))
|
||||
NSS_XCFLAGS += $(filter -arch:%,$(CFLAGS))
|
||||
endif
|
||||
|
||||
# Export accumulated XCFLAGS to modify nss defaults.
|
||||
DEFAULT_GMAKE_FLAGS += XCFLAGS='$(NSS_XCFLAGS)'
|
||||
|
||||
NSS_SRCDIR = $(topsrcdir)
|
||||
|
||||
NSS_DIRS =
|
||||
ifndef MOZ_FOLD_LIBS
|
||||
NSS_DIRS += nss/lib
|
||||
else
|
||||
ifndef NSS_DISABLE_DBM
|
||||
NSS_DIRS += nss/lib/dbm
|
||||
endif
|
||||
endif
|
||||
NSS_DIRS += \
|
||||
nss/cmd/lib \
|
||||
nss/cmd/shlibsign \
|
||||
$(NULL)
|
||||
|
||||
ifdef ENABLE_TESTS
|
||||
NSS_DIRS += \
|
||||
nss/cmd/certutil \
|
||||
nss/cmd/pk12util \
|
||||
nss/cmd/modutil \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
ifneq (,$(filter %--build-id,$(LDFLAGS)))
|
||||
DEFAULT_GMAKE_ENV = LDFLAGS=-Wl,--build-id
|
||||
endif
|
||||
|
||||
ifdef MOZ_FOLD_LIBS
|
||||
# TODO: The following can be replaced by something simpler when bug 844880
|
||||
# is fixed.
|
||||
# All static libraries required for nss, smime, ssl and nssutil.
|
||||
# The strip is needed to remove potential linefeed characters, since they hang
|
||||
# around in some cases on Windows.
|
||||
NSS_STATIC_LIBS := $(strip $(shell $(MAKE) --no-print-directory -f $(srcdir)/nss.mk DEPTH='$(DEPTH)' topsrcdir='$(topsrcdir)' srcdir='$(srcdir)' echo-variable-libs))
|
||||
# Corresponding build directories
|
||||
NSS_STATIC_DIRS := $(foreach lib,$(NSS_STATIC_LIBS),$(patsubst %/,%,$(dir $(lib))))
|
||||
NSS_DIRS += $(NSS_STATIC_DIRS)
|
||||
|
||||
# TODO: The following can be replaced by something simpler when bug 844884
|
||||
# is fixed.
|
||||
# Remaining nss/lib directories
|
||||
NSS_DIRS += nss/lib/freebl nss/lib/softoken nss/lib/jar nss/lib/crmf nss/lib/ckfw
|
||||
|
||||
DEFAULT_GMAKE_FLAGS += NSS_DISABLE_LIBPKIX=1
|
||||
|
||||
ifeq (WINNT,$(OS_TARGET))
|
||||
NSS_DIRS += nss/lib/zlib
|
||||
endif
|
||||
endif # MOZ_FOLD_LIBS
|
||||
|
||||
# Filter-out $(LIBRARY_NAME) because it's already handled in config/rules.mk.
|
||||
NSS_DIST_DLL_FILES := $(addprefix $(DIST)/lib/$(DLL_PREFIX),$(addsuffix $(DLL_SUFFIX),$(filter-out $(LIBRARY_NAME),$(NSS_DLLS)) $(NSS_EXTRA_DLLS)))
|
||||
NSS_DIST_DLL_DEST := $(DIST)/bin
|
||||
NSS_DIST_DLL_TARGET := target
|
||||
INSTALL_TARGETS += NSS_DIST_DLL
|
||||
|
||||
ifeq ($(OS_ARCH)_$(1), SunOS_softokn3)
|
||||
# has to use copy mode on Solaris, see #665509
|
||||
$(DIST)/bin/$(DLL_PREFIX)softokn3$(DLL_SUFFIX): INSTALL := $(INSTALL) -t
|
||||
endif
|
||||
|
||||
NSS_SDK_LIB_FILES := \
|
||||
$(addprefix $(DIST)/lib/$(LIB_PREFIX),$(addsuffix .$(LIB_SUFFIX),$(SDK_LIBS))) \
|
||||
$(addprefix $(DIST)/bin/$(DLL_PREFIX),$(addsuffix $(DLL_SUFFIX),$(NSS_DLLS))) \
|
||||
$(NULL)
|
||||
NSS_SDK_LIB_DEST := $(DIST)/sdk/lib
|
||||
NSS_SDK_LIB_TARGET := target
|
||||
INSTALL_TARGETS += NSS_SDK_LIB
|
||||
|
||||
ifdef MOZ_FOLD_LIBS
|
||||
# Add all static libraries for nss, smime, ssl and nssutil
|
||||
STATIC_LIBS += $(addprefix $(DEPTH)/security/,$(NSS_STATIC_LIBS))
|
||||
|
||||
IMPORT_LIB_FILES = $(IMPORT_LIBRARY)
|
||||
IMPORT_LIB_DEST ?= $(DIST)/lib
|
||||
IMPORT_LIB_TARGET = target
|
||||
INSTALL_TARGETS += IMPORT_LIB
|
||||
|
||||
endif # MOZ_FOLD_LIBS
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
ifeq (1,$(ALLOW_COMPILER_WARNINGS))
|
||||
DEFAULT_GMAKE_FLAGS += NSS_ENABLE_WERROR=0
|
||||
endif
|
||||
|
||||
# Can't pass this in DEFAULT_GMAKE_FLAGS because that overrides
|
||||
# definitions in NSS, so just export it into the sub-make's environment.
|
||||
ifeq (WINNT_1,$(OS_TARGET)_$(MOZ_MEMORY))
|
||||
DLLFLAGS := -LIBPATH:$(ABS_DIST)/../mozglue/build -DEFAULTLIB:mozglue
|
||||
export DLLFLAGS
|
||||
endif
|
||||
|
||||
ifdef MOZ_FOLD_LIBS
|
||||
# Force the linker to include everything from the static libraries.
|
||||
EXPAND_LIBS_EXEC += --extract
|
||||
|
||||
$(SHARED_LIBRARY): $(addprefix $(DEPTH)/security/,$(NSS_STATIC_LIBS))
|
||||
|
||||
ifdef IMPORT_LIB_SUFFIX
|
||||
IMPORT_PREFIX = $(LIB_PREFIX)
|
||||
IMPORT_SUFFIX = .$(IMPORT_LIB_SUFFIX)
|
||||
else
|
||||
IMPORT_PREFIX = $(DLL_PREFIX)
|
||||
IMPORT_SUFFIX = $(DLL_SUFFIX)
|
||||
endif
|
||||
|
||||
NSPR_IMPORT_LIBS = $(addprefix $(DIST)/lib/$(IMPORT_PREFIX),$(addsuffix $(IMPORT_SUFFIX),nspr4 plc4 plds4))
|
||||
SQLITE_IMPORT_LIB = $(DIST)/lib/$(IMPORT_PREFIX)mozsqlite3$(IMPORT_SUFFIX)
|
||||
|
||||
# TODO: The following can be replaced by something simpler when bug 844884
|
||||
# is fixed.
|
||||
# Associate target files with the rules that build them.
|
||||
$(DIST)/lib/$(LIB_PREFIX)crmf.$(LIB_SUFFIX): libs-nss/lib/crmf
|
||||
$(DIST)/lib/$(DLL_PREFIX)freebl3$(DLL_SUFFIX): libs-nss/lib/freebl
|
||||
$(DIST)/lib/$(DLL_PREFIX)nssckbi$(DLL_SUFFIX): libs-nss/lib/ckfw
|
||||
$(DIST)/lib/$(DLL_PREFIX)softokn3$(DLL_SUFFIX): libs-nss/lib/softoken
|
||||
$(DIST)/lib/$(DLL_PREFIX)nssdbm3$(DLL_SUFFIX): libs-nss/lib/softoken
|
||||
$(foreach lib,$(NSS_STATIC_LIBS),$(eval $(DEPTH)/security/$(lib): libs-$(patsubst %/,%,$(dir $(lib)))))
|
||||
|
||||
# Create fake import libraries for the folded libraries, so that linking
|
||||
# against them works both for the NSS build system (see dependencies below)
|
||||
# and for the rest of the mozilla build system.
|
||||
$(NSPR_IMPORT_LIBS) \
|
||||
$(SQLITE_IMPORT_LIB) \
|
||||
$(DIST)/lib/$(IMPORT_PREFIX)nssutil3$(IMPORT_SUFFIX) \
|
||||
$(DIST)/lib/$(IMPORT_PREFIX)ssl3$(IMPORT_SUFFIX) \
|
||||
$(DIST)/lib/$(IMPORT_PREFIX)smime3$(IMPORT_SUFFIX): $(DIST)/lib/$(IMPORT_PREFIX)nss3$(IMPORT_SUFFIX)
|
||||
ifeq (WINNT,$(OS_TARGET))
|
||||
cp $< $@
|
||||
else
|
||||
ln -sf $< $@
|
||||
endif
|
||||
|
||||
# Interdependencies between nss sub-directories, and dependencies on NSPR/SQLite
|
||||
libs-nss/lib/ckfw: libs-nss/lib/nss/../base $(NSPR_IMPORT_LIBS)
|
||||
libs-nss/lib/softoken: $(NSPR_IMPORT_LIBS) $(SQLITE_IMPORT_LIB)
|
||||
libs-nss/lib/softoken: libs-nss/lib/freebl
|
||||
ifndef NSS_DISABLE_DBM
|
||||
libs-nss/lib/softoken: libs-nss/lib/dbm
|
||||
endif
|
||||
libs-nss/lib/softoken: $(DIST)/lib/$(IMPORT_PREFIX)nssutil3$(IMPORT_SUFFIX)
|
||||
libs-nss/lib/freebl: $(DIST)/lib/$(IMPORT_PREFIX)nssutil3$(IMPORT_SUFFIX) $(NSPR_IMPORT_LIBS)
|
||||
|
||||
# For each directory where we build static libraries, force the NSS build system
|
||||
# to only build static libraries.
|
||||
$(addprefix libs-,$(NSS_STATIC_DIRS)): DEFAULT_GMAKE_FLAGS += SHARED_LIBRARY= IMPORT_LIBRARY=
|
||||
else
|
||||
$(STATIC_LIBS) $(NSS_DIST_DLL_FILES) $(NSS_SDK_LIB_FILES): libs-nss/lib
|
||||
endif # MOZ_FOLD_LIBS
|
||||
|
||||
ifeq ($(NSINSTALL_PY),$(NSINSTALL))
|
||||
DEFAULT_GMAKE_FLAGS += PYTHON='$(PYTHON)'
|
||||
DEFAULT_GMAKE_FLAGS += NSINSTALL_PY='$(abspath $(topsrcdir)/config/nsinstall.py)'
|
||||
DEFAULT_GMAKE_FLAGS += NSINSTALL='$$(PYTHON) $$(NSINSTALL_PY)'
|
||||
else
|
||||
DEFAULT_GMAKE_FLAGS += NSINSTALL='$(abspath $(NSINSTALL))'
|
||||
endif
|
||||
ifeq ($(OS_ARCH),WINNT)
|
||||
DEFAULT_GMAKE_FLAGS += INSTALL='$$(NSINSTALL) -t'
|
||||
endif
|
||||
DEFAULT_GMAKE_FLAGS += $(EXTRA_GMAKE_FLAGS)
|
||||
|
||||
$(addprefix libs-,$(NSS_DIRS)): libs-%:
|
||||
# Work around NSS's export rule being racy when recursing for private_export
|
||||
# See bug #836220.
|
||||
$(addprefix export-,$(NSS_DIRS)): EXTRA_GMAKE_FLAGS = PRIVATE_EXPORTS=
|
||||
$(addprefix export-,$(NSS_DIRS)): export-%: private_export-%
|
||||
$(addprefix private_export-,$(NSS_DIRS)): EXTRA_GMAKE_FLAGS =
|
||||
$(addprefix private_export-,$(NSS_DIRS)): private_export-%:
|
||||
|
||||
$(foreach p,libs export private_export,$(addprefix $(p)-,$(NSS_DIRS))):
|
||||
$(DEFAULT_GMAKE_ENV) $(MAKE) -C $(NSS_SRCDIR)/security/$* $(@:-$*=) $(DEFAULT_GMAKE_FLAGS)
|
||||
|
||||
export:: $(addprefix export-,$(NSS_DIRS))
|
||||
|
||||
$(addprefix clean-,$(NSS_DIRS)): clean-%:
|
||||
$(MAKE) -C $(NSS_SRCDIR)/security/$* $(DEFAULT_GMAKE_FLAGS) clean
|
||||
|
||||
clean clobber clobber_all realclean distclean depend:: $(addprefix clean-,$(NSS_DIRS))
|
||||
|
||||
NSS_CMD_TARGETS := $(addprefix libs-,$(filter-out nss/cmd/lib,$(filter nss/cmd/%,$(NSS_DIRS))))
|
||||
target:: $(NSS_CMD_TARGETS)
|
||||
|
||||
ifdef MOZ_FOLD_LIBS
|
||||
$(NSS_CMD_TARGETS): $(addprefix $(DIST)/lib/$(IMPORT_PREFIX),$(addsuffix $(IMPORT_SUFFIX),$(NSS_LIBS)))
|
||||
libs-nss/cmd/modutil: libs-nss/lib/jar
|
||||
ifeq (WINNT,$(OS_TARGET))
|
||||
libs-nss/cmd/modutil: libs-nss/lib/zlib
|
||||
endif
|
||||
$(NSS_CMD_TARGETS): libs-nss/cmd/lib
|
||||
else
|
||||
$(NSS_CMD_TARGETS): libs-nss/lib libs-nss/cmd/lib
|
||||
endif # MOZ_FOLD_LIBS
|
||||
|
||||
# Work around NSS build system race condition creating certdata.c in
|
||||
# security/nss/lib/ckfw/builtins. See bug #836220.
|
||||
libs-nss/lib$(if $(MOZ_FOLD_LIBS),/ckfw): $(call mkdir_deps,$(DEPTH)/security/nss/lib/ckfw/builtins)
|
||||
|
||||
endif
|
|
@ -1,20 +0,0 @@
|
|||
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
Library('crmf')
|
||||
|
||||
if CONFIG['MOZ_SYSTEM_NSS']:
|
||||
OS_LIBS += [l for l in CONFIG['NSS_LIBS'] if l.startswith('-L')]
|
||||
OS_LIBS += ['-lcrmf']
|
||||
else:
|
||||
USE_LIBS += [
|
||||
# The dependency on nss is not real, but is required to force the
|
||||
# parent directory being built before this one. This has no
|
||||
# practical effect on linkage, since the only thing linking crmf
|
||||
# will need nss anyways.
|
||||
'nss',
|
||||
'static:/security/nss/lib/crmf/crmf',
|
||||
]
|
|
@ -1,42 +0,0 @@
|
|||
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
DIRS += ['crmf']
|
||||
|
||||
if CONFIG['MOZ_SYSTEM_NSS']:
|
||||
Library('nss')
|
||||
OS_LIBS += CONFIG['NSS_LIBS']
|
||||
elif CONFIG['MOZ_FOLD_LIBS']:
|
||||
GeckoSharedLibrary('nss', linkage=None)
|
||||
# TODO: The library name can be changed when bug 845217 is fixed.
|
||||
SHARED_LIBRARY_NAME = 'nss3'
|
||||
|
||||
SDK_LIBRARY = True
|
||||
|
||||
USE_LIBS += [
|
||||
'nspr4',
|
||||
'plc4',
|
||||
'plds4',
|
||||
]
|
||||
|
||||
OS_LIBS += CONFIG['REALTIME_LIBS']
|
||||
|
||||
SYMBOLS_FILE = 'nss.symbols'
|
||||
else:
|
||||
Library('nss')
|
||||
USE_LIBS += [
|
||||
'/security/nss/lib/nss/nss3',
|
||||
'/security/nss/lib/smime/smime3',
|
||||
'/security/nss/lib/ssl/ssl3',
|
||||
'/security/nss/lib/util/nssutil3',
|
||||
'sqlite',
|
||||
]
|
||||
|
||||
# XXX: We should fix these warnings.
|
||||
ALLOW_COMPILER_WARNINGS = True
|
||||
|
||||
if CONFIG['NSS_EXTRA_SYMBOLS_FILE']:
|
||||
DEFINES['NSS_EXTRA_SYMBOLS_FILE'] = CONFIG['NSS_EXTRA_SYMBOLS_FILE']
|
|
@ -1,27 +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/.
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
|
||||
dirs :=
|
||||
|
||||
define add_dirs
|
||||
SHARED_LIBRARY_DIRS :=
|
||||
include $(topsrcdir)/security/$(1)/config.mk
|
||||
dirs += $$(addprefix $(1)/,$$(SHARED_LIBRARY_DIRS)) $(1)
|
||||
endef
|
||||
$(foreach dir,util nss ssl smime,$(eval $(call add_dirs,nss/lib/$(dir))))
|
||||
|
||||
libs :=
|
||||
define add_lib
|
||||
LIBRARY_NAME :=
|
||||
include $(topsrcdir)/security/$(1)/manifest.mn
|
||||
libs += $$(addprefix $(1)/,$(LIB_PREFIX)$$(LIBRARY_NAME).$(LIB_SUFFIX))
|
||||
endef
|
||||
$(foreach dir,$(dirs),$(eval $(call add_lib,$(dir))))
|
||||
|
||||
echo-variable-%:
|
||||
@echo $($*)
|
|
@ -165,16 +165,13 @@ ifeq ($(MOZ_WIDGET_TOOLKIT),gtk3)
|
|||
toolkit/library/target: widget/gtk/mozgtk/gtk3/target
|
||||
endif
|
||||
ifdef MOZ_LDAP_XPCOM
|
||||
ldap/target: config/external/nss/target mozglue/build/target
|
||||
ldap/target: security/target mozglue/build/target
|
||||
toolkit/library/target: ldap/target
|
||||
endif
|
||||
ifeq ($(MOZ_REPLACE_MALLOC_LINKAGE),dummy library)
|
||||
mozglue/build/target memory/replace/logalloc/replay/target: memory/replace/dummy/target
|
||||
endif
|
||||
endif
|
||||
ifeq (,$(MOZ_SYSTEM_NSPR)$(MOZ_SYSTEM_NSS)$(MOZ_FOLD_LIBS))
|
||||
config/external/nss/target: config/external/nspr/pr/target config/external/nspr/ds/target config/external/nspr/libc/target
|
||||
endif
|
||||
# Most things are built during compile (target/host), but some things happen during export
|
||||
# Those need to depend on config/export for system wrappers.
|
||||
$(addprefix build/unix/stdc++compat/,target host) build/clang-plugin/target: config/export
|
||||
|
|
|
@ -32,8 +32,6 @@
|
|||
<!ENTITY runtimeMenu_accesskey "R">
|
||||
<!ENTITY runtimeMenu_disconnect_label "Disconnect">
|
||||
<!ENTITY runtimeMenu_disconnect_accesskey "D">
|
||||
<!ENTITY runtimeMenu_showPermissionTable_label "Permissions Table">
|
||||
<!ENTITY runtimeMenu_showPermissionTable_accesskey "P">
|
||||
<!ENTITY runtimeMenu_takeScreenshot_label "Screenshot">
|
||||
<!ENTITY runtimeMenu_takeScreenshot_accesskey "S">
|
||||
<!ENTITY runtimeMenu_showDetails_label "Runtime Info">
|
||||
|
@ -141,10 +139,6 @@
|
|||
<!ENTITY prefs_options_autosavefiles "Autosave files">
|
||||
<!ENTITY prefs_options_autosavefiles_tooltip "Automatically save edited files before running project">
|
||||
|
||||
<!-- Permissions Table -->
|
||||
<!ENTITY permissionstable_title "Permissions Table">
|
||||
<!ENTITY permissionstable_name_header "Name">
|
||||
|
||||
<!-- Runtime Details -->
|
||||
<!ENTITY runtimedetails_title "Runtime Info">
|
||||
<!ENTITY runtimedetails_adbIsRoot "ADB is root: ">
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
/* 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/. */
|
||||
|
||||
/* globals NetMonitorView */
|
||||
|
||||
"use strict";
|
||||
|
||||
const { DOM } = require("devtools/client/shared/vendor/react");
|
||||
const { L10N } = require("../l10n");
|
||||
|
||||
const { button } = DOM;
|
||||
|
||||
/*
|
||||
* Clear button component
|
||||
* A type of tool button is responsible for cleaning network requests.
|
||||
*/
|
||||
function ClearButton() {
|
||||
return button({
|
||||
id: "requests-menu-clear-button",
|
||||
className: "devtools-button devtools-clear-icon",
|
||||
title: L10N.getStr("netmonitor.toolbar.clear"),
|
||||
onClick: () => {
|
||||
NetMonitorView.RequestsMenu.clear();
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = ClearButton;
|
|
@ -3,8 +3,10 @@
|
|||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
DevToolsModules(
|
||||
'clear-button.js',
|
||||
'filter-buttons.js',
|
||||
'search-box.js',
|
||||
'summary-button.js',
|
||||
'toggle-button.js',
|
||||
'toolbar.js',
|
||||
)
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const {
|
||||
createFactory,
|
||||
DOM,
|
||||
} = require("devtools/client/shared/vendor/react");
|
||||
const ClearButton = createFactory(require("./clear-button"));
|
||||
const FilterButtons = createFactory(require("./filter-buttons"));
|
||||
const SearchBox = createFactory(require("./search-box"));
|
||||
const SummaryButton = createFactory(require("./summary-button"));
|
||||
const ToggleButton = createFactory(require("./toggle-button"));
|
||||
|
||||
const { span } = DOM;
|
||||
|
||||
/*
|
||||
* Network monitor toolbar component
|
||||
* Toolbar contains a set of useful tools to control network requests
|
||||
*/
|
||||
function Toolbar() {
|
||||
return span({ className: "devtools-toolbar devtools-toolbar-container" },
|
||||
span({ className: "devtools-toolbar-group" },
|
||||
ClearButton(),
|
||||
FilterButtons()
|
||||
),
|
||||
span({ className: "devtools-toolbar-group" },
|
||||
SummaryButton(),
|
||||
SearchBox(),
|
||||
ToggleButton()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = Toolbar;
|
|
@ -21,20 +21,8 @@
|
|||
data-localization-bundle="devtools/client/locales/netmonitor.properties">
|
||||
|
||||
<vbox id="network-inspector-view" flex="1">
|
||||
<hbox id="netmonitor-toolbar" class="devtools-toolbar">
|
||||
<html:div xmlns="http://www.w3.org/1999/xhtml"
|
||||
id="react-clear-button-hook"/>
|
||||
<html:div xmlns="http://www.w3.org/1999/xhtml"
|
||||
id="react-filter-buttons-hook"/>
|
||||
<spacer id="requests-menu-spacer"
|
||||
flex="1"/>
|
||||
<html:div xmlns="http://www.w3.org/1999/xhtml"
|
||||
id="react-summary-button-hook"/>
|
||||
<html:div xmlns="http://www.w3.org/1999/xhtml"
|
||||
id="react-search-box-hook"/>
|
||||
<html:div xmlns="http://www.w3.org/1999/xhtml"
|
||||
id="react-details-pane-toggle-hook"/>
|
||||
</hbox>
|
||||
<html:div xmlns="http://www.w3.org/1999/xhtml"
|
||||
id="react-toolbar-hook"/>
|
||||
<hbox id="network-table-and-sidebar"
|
||||
class="devtools-responsive-container"
|
||||
flex="1">
|
||||
|
|
|
@ -10,9 +10,6 @@
|
|||
|
||||
add_task(function* () {
|
||||
requestLongerTimeout(2);
|
||||
let { getSummary } = require("devtools/client/netmonitor/selectors/index");
|
||||
let { L10N } = require("devtools/client/netmonitor/l10n");
|
||||
let { PluralForm } = require("devtools/shared/plural-form");
|
||||
|
||||
let { tab, monitor } = yield initNetMonitor(FILTERING_URL);
|
||||
info("Starting test... ");
|
||||
|
@ -20,6 +17,11 @@ add_task(function* () {
|
|||
let { $, NetMonitorView, gStore } = monitor.panelWin;
|
||||
let { RequestsMenu } = NetMonitorView;
|
||||
|
||||
let winRequire = monitor.panelWin.require;
|
||||
let { getSummary } = winRequire("devtools/client/netmonitor/selectors/index");
|
||||
let { L10N } = winRequire("devtools/client/netmonitor/l10n");
|
||||
let { PluralForm } = winRequire("devtools/shared/plural-form");
|
||||
|
||||
RequestsMenu.lazyUpdate = false;
|
||||
testStatus();
|
||||
|
||||
|
|
|
@ -2,21 +2,14 @@
|
|||
* 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/. */
|
||||
|
||||
/* globals dumpn, $, NetMonitorView */
|
||||
/* globals dumpn, $ */
|
||||
|
||||
"use strict";
|
||||
|
||||
const { createFactory, DOM } = require("devtools/client/shared/vendor/react");
|
||||
const { createFactory } = require("devtools/client/shared/vendor/react");
|
||||
const ReactDOM = require("devtools/client/shared/vendor/react-dom");
|
||||
const Provider = createFactory(require("devtools/client/shared/vendor/react-redux").Provider);
|
||||
const FilterButtons = createFactory(require("./components/filter-buttons"));
|
||||
const ToggleButton = createFactory(require("./components/toggle-button"));
|
||||
const SearchBox = createFactory(require("./components/search-box"));
|
||||
const SummaryButton = createFactory(require("./components/summary-button"));
|
||||
const { L10N } = require("./l10n");
|
||||
|
||||
// Shortcuts
|
||||
const { button } = DOM;
|
||||
const Toolbar = createFactory(require("./components/toolbar"));
|
||||
|
||||
/**
|
||||
* Functions handling the toolbar view: expand/collapse button etc.
|
||||
|
@ -27,63 +20,26 @@ function ToolbarView() {
|
|||
|
||||
ToolbarView.prototype = {
|
||||
/**
|
||||
* Initialization function, called when the debugger is started.
|
||||
* Initialization function, called when the network monitor is started.
|
||||
*/
|
||||
initialize: function (store) {
|
||||
dumpn("Initializing the ToolbarView");
|
||||
|
||||
this._clearContainerNode = $("#react-clear-button-hook");
|
||||
this._filterContainerNode = $("#react-filter-buttons-hook");
|
||||
this._summaryContainerNode = $("#react-summary-button-hook");
|
||||
this._searchContainerNode = $("#react-search-box-hook");
|
||||
this._toggleContainerNode = $("#react-details-pane-toggle-hook");
|
||||
this._toolbarNode = $("#react-toolbar-hook");
|
||||
|
||||
// clear button
|
||||
ReactDOM.render(button({
|
||||
id: "requests-menu-clear-button",
|
||||
className: "devtools-button devtools-clear-icon",
|
||||
title: L10N.getStr("netmonitor.toolbar.clear"),
|
||||
onClick: () => {
|
||||
NetMonitorView.RequestsMenu.clear();
|
||||
}
|
||||
}), this._clearContainerNode);
|
||||
|
||||
// filter button
|
||||
ReactDOM.render(Provider(
|
||||
{ store },
|
||||
FilterButtons()
|
||||
), this._filterContainerNode);
|
||||
|
||||
// summary button
|
||||
ReactDOM.render(Provider(
|
||||
{ store },
|
||||
SummaryButton()
|
||||
), this._summaryContainerNode);
|
||||
|
||||
// search box
|
||||
ReactDOM.render(Provider(
|
||||
{ store },
|
||||
SearchBox()
|
||||
), this._searchContainerNode);
|
||||
|
||||
// details pane toggle button
|
||||
ReactDOM.render(Provider(
|
||||
{ store },
|
||||
ToggleButton()
|
||||
), this._toggleContainerNode);
|
||||
Toolbar()
|
||||
), this._toolbarNode);
|
||||
},
|
||||
|
||||
/**
|
||||
* Destruction function, called when the debugger is closed.
|
||||
* Destruction function, called when the network monitor is closed.
|
||||
*/
|
||||
destroy: function () {
|
||||
dumpn("Destroying the ToolbarView");
|
||||
|
||||
ReactDOM.unmountComponentAtNode(this._clearContainerNode);
|
||||
ReactDOM.unmountComponentAtNode(this._filterContainerNode);
|
||||
ReactDOM.unmountComponentAtNode(this._summaryContainerNode);
|
||||
ReactDOM.unmountComponentAtNode(this._searchContainerNode);
|
||||
ReactDOM.unmountComponentAtNode(this._toggleContainerNode);
|
||||
ReactDOM.unmountComponentAtNode(this._toolbarNode);
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
@ -124,7 +124,7 @@ define(function (require, exports, module) {
|
|||
items = [DOM.span({className: "length"}, isEmpty ? "" : object.length)];
|
||||
brackets = needSpace(false);
|
||||
} else {
|
||||
let max = (mode == "short") ? 3 : 300;
|
||||
let max = (mode == "short") ? 3 : 10;
|
||||
items = this.arrayIterator(object, max);
|
||||
brackets = needSpace(items.length > 0);
|
||||
}
|
||||
|
|
|
@ -123,7 +123,7 @@ define(function (require, exports, module) {
|
|||
items = [span({className: "length"}, isEmpty ? "" : objectLength)];
|
||||
brackets = needSpace(false);
|
||||
} else {
|
||||
let max = (mode == "short") ? 3 : 300;
|
||||
let max = (mode == "short") ? 3 : 10;
|
||||
items = this.arrayIterator(object, max);
|
||||
brackets = needSpace(items.length > 0);
|
||||
}
|
||||
|
|
|
@ -146,7 +146,7 @@ define(function (require, exports, module) {
|
|||
render: function () {
|
||||
let object = this.props.object;
|
||||
let props = this.safeEntriesIterator(object,
|
||||
(this.props.mode == "long") ? 100 : 3);
|
||||
(this.props.mode == "long") ? 10 : 3);
|
||||
|
||||
let objectLink = this.props.objectLink || span;
|
||||
if (this.props.mode == "tiny") {
|
||||
|
|
|
@ -197,7 +197,7 @@ define(function (require, exports, module) {
|
|||
render: function () {
|
||||
let object = this.props.object;
|
||||
let props = this.safePropIterator(object,
|
||||
(this.props.mode == "long") ? 100 : 3);
|
||||
(this.props.mode == "long") ? 10 : 3);
|
||||
|
||||
let objectLink = this.props.objectLink || span;
|
||||
if (this.props.mode == "tiny") {
|
||||
|
|
|
@ -32,12 +32,13 @@ define(function (require, exports, module) {
|
|||
},
|
||||
|
||||
getTitle: function (grip) {
|
||||
const title = "#text";
|
||||
if (this.props.objectLink) {
|
||||
return this.props.objectLink({
|
||||
object: grip
|
||||
}, "#text ");
|
||||
}, title);
|
||||
}
|
||||
return "";
|
||||
return title;
|
||||
},
|
||||
|
||||
render: function () {
|
||||
|
@ -57,33 +58,17 @@ define(function (require, exports, module) {
|
|||
});
|
||||
}
|
||||
|
||||
if (mode == "short" || mode == "tiny") {
|
||||
return (
|
||||
DOM.span(baseConfig,
|
||||
this.getTitle(grip),
|
||||
DOM.span({className: "nodeValue"},
|
||||
"\"" + this.getTextContent(grip) + "\""
|
||||
)
|
||||
)
|
||||
);
|
||||
if (mode == "tiny") {
|
||||
return DOM.span(baseConfig, this.getTitle(grip));
|
||||
}
|
||||
|
||||
let objectLink = this.props.objectLink || DOM.span;
|
||||
return (
|
||||
DOM.span(baseConfig,
|
||||
this.getTitle(grip),
|
||||
objectLink({
|
||||
object: grip
|
||||
}, "<"),
|
||||
DOM.span({className: "nodeTag"}, "TextNode"),
|
||||
" textContent=\"",
|
||||
DOM.span({className: "nodeValue"},
|
||||
this.getTextContent(grip)
|
||||
),
|
||||
"\"",
|
||||
objectLink({
|
||||
object: grip
|
||||
}, ">;")
|
||||
" ",
|
||||
`"${this.getTextContent(grip)}"`
|
||||
)
|
||||
)
|
||||
);
|
||||
},
|
||||
|
|
|
@ -26,7 +26,7 @@ window.onload = Task.async(function* () {
|
|||
let componentUnderTest = ArrayRep;
|
||||
const maxLength = {
|
||||
short: 3,
|
||||
long: 300
|
||||
long: 10
|
||||
};
|
||||
|
||||
try {
|
||||
|
@ -222,14 +222,10 @@ window.onload = Task.async(function* () {
|
|||
|
||||
function testArray() {
|
||||
let stub = [
|
||||
"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m",
|
||||
"n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"
|
||||
];
|
||||
"a", "b", "c", "d", "e", "f", "g", "h", "i", "j"];
|
||||
|
||||
const defaultOutput = `[ "a", "b", "c", "d", "e", "f", "g", "h", "i", "j",` +
|
||||
` "k", "l", "m", "n", "o", "p", "q", "r", "s", "t",` +
|
||||
` "u", "v", "w", "x", "y", "z" ]`;
|
||||
const shortOutput = `[ "a", "b", "c", 23 more… ]`;
|
||||
const defaultOutput = `[ "a", "b", "c", "d", "e", "f", "g", "h", "i", "j" ]`;
|
||||
const shortOutput = `[ "a", "b", "c", 7 more… ]`;
|
||||
|
||||
const modeTests = [
|
||||
{
|
||||
|
@ -238,7 +234,7 @@ window.onload = Task.async(function* () {
|
|||
},
|
||||
{
|
||||
mode: "tiny",
|
||||
expectedOutput: `[26]`,
|
||||
expectedOutput: `[10]`,
|
||||
},
|
||||
{
|
||||
mode: "short",
|
||||
|
|
|
@ -23,7 +23,7 @@ window.onload = Task.async(function* () {
|
|||
let componentUnderTest = GripArray;
|
||||
const maxLength = {
|
||||
short: 3,
|
||||
long: 300
|
||||
long: 10
|
||||
};
|
||||
|
||||
try {
|
||||
|
|
|
@ -174,8 +174,8 @@ window.onload = Task.async(function* () {
|
|||
`Map { key-0: "value-0", key-1: "value-1", key-2: "value-2", 98 more… }`;
|
||||
|
||||
// Generate string with 101 entries, which is the max limit for 'long' mode.
|
||||
let longString = Array.from({length: 100}).map((_, i) => `key-${i}: "value-${i}"`);
|
||||
const longOutput = `Map { ${longString.join(", ")}, 1 more… }`;
|
||||
let longString = Array.from({length: 10}).map((_, i) => `key-${i}: "value-${i}"`);
|
||||
const longOutput = `Map { ${longString.join(", ")}, 91 more… }`;
|
||||
|
||||
const modeTests = [
|
||||
{
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче