mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-17 14:25:49 +00:00
Merge mozilla-central to mozilla-inboud
--HG-- rename : security/certverifier/TrustOverride-AppleGoogleData.inc => security/certverifier/TrustOverride-AppleGoogleDigiCertData.inc rename : security/manager/tools/crtshToDNStruct/crtshToDNStruct.py => security/manager/tools/crtshToIdentifyingStruct/crtshToIdentifyingStruct.py rename : security/manager/tools/crtshToDNStruct/requirements.txt => security/manager/tools/crtshToIdentifyingStruct/requirements.txt extra : rebase_source : 6bcbd2a80706f4f4b36bbb1e53c260ea495babf8
This commit is contained in:
commit
ce3c40d6ba
@ -24,7 +24,6 @@ gfx/tests/chrome/**
|
||||
gfx/tests/mochitest/**
|
||||
gfx/tests/unit/**
|
||||
image/**
|
||||
intl/**
|
||||
layout/**
|
||||
memory/replace/dmd/test/**
|
||||
modules/**
|
||||
@ -303,6 +302,12 @@ dom/media/webvtt/**
|
||||
gfx/ots/**
|
||||
gfx/skia/**
|
||||
|
||||
# intl/ exclusions
|
||||
intl/icu/**
|
||||
intl/locale/**
|
||||
intl/strres/**
|
||||
intl/uconv/**
|
||||
|
||||
# Exclude everything but self-hosted JS
|
||||
js/ductwork/**
|
||||
js/examples/**
|
||||
|
@ -8009,7 +8009,9 @@ var gIdentityHandler = {
|
||||
nameLabel.setAttribute("class", "identity-popup-permission-label");
|
||||
nameLabel.textContent = SitePermissions.getPermissionLabel(aPermission.id);
|
||||
|
||||
if (aPermission.id == "popup") {
|
||||
let isPolicyPermission = aPermission.scope == SitePermissions.SCOPE_POLICY;
|
||||
|
||||
if (aPermission.id == "popup" && !isPolicyPermission) {
|
||||
let menulist = document.createElement("menulist");
|
||||
let menupopup = document.createElement("menupopup");
|
||||
let block = document.createElement("vbox");
|
||||
@ -8064,6 +8066,17 @@ var gIdentityHandler = {
|
||||
}
|
||||
stateLabel.textContent = SitePermissions.getCurrentStateLabel(state, scope);
|
||||
|
||||
container.appendChild(img);
|
||||
container.appendChild(nameLabel);
|
||||
container.appendChild(stateLabel);
|
||||
|
||||
/* We return the permission item here without a remove button if the permission is a
|
||||
SCOPE_POLICY permission. Policy permissions cannot be removed/changed for the duration
|
||||
of the browser session. */
|
||||
if (isPolicyPermission) {
|
||||
return container;
|
||||
}
|
||||
|
||||
let button = document.createElement("button");
|
||||
button.setAttribute("class", "identity-popup-permission-remove-button");
|
||||
let tooltiptext = gNavigatorBundle.getString("permissions.remove.tooltip");
|
||||
@ -8128,9 +8141,6 @@ var gIdentityHandler = {
|
||||
histogram.add(aPermission.id, permissionType);
|
||||
});
|
||||
|
||||
container.appendChild(img);
|
||||
container.appendChild(nameLabel);
|
||||
container.appendChild(stateLabel);
|
||||
container.appendChild(button);
|
||||
|
||||
return container;
|
||||
|
@ -69,7 +69,7 @@ function initRow(aPartId) {
|
||||
|
||||
var checkbox = document.getElementById(aPartId + "Def");
|
||||
var command = document.getElementById("cmd_" + aPartId + "Toggle");
|
||||
var {state} = SitePermissions.get(gPermURI, aPartId);
|
||||
var {state, scope} = SitePermissions.get(gPermURI, aPartId);
|
||||
let defaultState = SitePermissions.getDefault(aPartId);
|
||||
|
||||
if (state != defaultState) {
|
||||
@ -79,6 +79,12 @@ function initRow(aPartId) {
|
||||
checkbox.checked = true;
|
||||
command.setAttribute("disabled", "true");
|
||||
}
|
||||
|
||||
if (scope == SitePermissions.SCOPE_POLICY) {
|
||||
checkbox.setAttribute("disabled", "true");
|
||||
command.setAttribute("disabled", "true");
|
||||
}
|
||||
|
||||
setRadioState(aPartId, state);
|
||||
}
|
||||
|
||||
|
@ -224,3 +224,45 @@ add_task(async function testPermissionShortcuts() {
|
||||
SitePermissions.remove(gBrowser.currentURI, "shortcuts");
|
||||
});
|
||||
});
|
||||
|
||||
// Test the control center UI when policy permissions are set.
|
||||
add_task(async function testPolicyPermission() {
|
||||
await BrowserTestUtils.withNewTab(PERMISSIONS_PAGE, async function() {
|
||||
await SpecialPowers.pushPrefEnv({set: [
|
||||
["dom.disable_open_during_load", true],
|
||||
]});
|
||||
|
||||
let permissionsList = document.getElementById("identity-popup-permission-list");
|
||||
SitePermissions.set(gBrowser.currentURI, "popup", SitePermissions.ALLOW, SitePermissions.SCOPE_POLICY);
|
||||
|
||||
await openIdentityPopup();
|
||||
|
||||
// Check if the icon, nameLabel and stateLabel are visible.
|
||||
let img, labelText, labels;
|
||||
|
||||
img = permissionsList.querySelector("image.identity-popup-permission-icon");
|
||||
ok(img, "There is an image for the popup permission");
|
||||
ok(img.classList.contains("popup-icon"), "proper class is in image class");
|
||||
|
||||
labelText = SitePermissions.getPermissionLabel("popup");
|
||||
labels = permissionsList.querySelectorAll(".identity-popup-permission-label");
|
||||
is(labels.length, 1, "One permission visible in main view");
|
||||
is(labels[0].textContent, labelText, "Correct name label value");
|
||||
|
||||
labelText = SitePermissions.getCurrentStateLabel(SitePermissions.ALLOW, SitePermissions.SCOPE_POLICY);
|
||||
labels = permissionsList.querySelectorAll(".identity-popup-permission-state-label");
|
||||
is(labels[0].textContent, labelText, "Correct state label value");
|
||||
|
||||
// Check if the menulist and the remove button are hidden.
|
||||
// The menulist is specific to the "popup" permission.
|
||||
let menulist = document.getElementById("identity-popup-popup-menulist");
|
||||
ok(menulist == null, "The popup permission menulist is not visible");
|
||||
|
||||
let removeButton = permissionsList.querySelector(".identity-popup-permission-remove-button");
|
||||
ok(removeButton == null, "The permission remove button is not visible");
|
||||
|
||||
Services.perms.removeAll();
|
||||
await closeIdentityPopup();
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -27,7 +27,6 @@ support-files =
|
||||
file_inspectedwindow_reload_target.sjs
|
||||
file_indexedDB.html
|
||||
file_serviceWorker.html
|
||||
locale/chrome.manifest
|
||||
webNav_createdTarget.html
|
||||
webNav_createdTargetSource.html
|
||||
webNav_createdTargetSource_subframe.html
|
||||
|
@ -7,14 +7,17 @@
|
||||
/* import-globals-from head.js */
|
||||
|
||||
{
|
||||
const chromeRegistry = Cc["@mozilla.org/chrome/chrome-registry;1"].getService(Ci.nsIChromeRegistry);
|
||||
// At the moment extension language negotiation is tied to Firefox language
|
||||
// negotiation result. That means that to test an extension in `es-ES`, we need
|
||||
// to mock `es-ES` being available in Firefox and then request it.
|
||||
//
|
||||
// In the future, we should provide some way for tests to decouple their
|
||||
// language selection from that of Firefox.
|
||||
const avLocales = Services.locale.getAvailableLocales();
|
||||
|
||||
let localeDir = new URL("locale/", gTestPath).href;
|
||||
let {file} = chromeRegistry.convertChromeURL(Services.io.newURI(localeDir)).QueryInterface(Ci.nsIFileURL);
|
||||
|
||||
Components.manager.addBootstrappedManifestLocation(file);
|
||||
Services.locale.setAvailableLocales(["en-US", "es-ES"]);
|
||||
registerCleanupFunction(() => {
|
||||
Components.manager.removeBootstrappedManifestLocation(file);
|
||||
Services.locale.setAvailableLocales(avLocales);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1 +0,0 @@
|
||||
locale global es-ES resource://gre/chrome/en-US/locale/en-US/global/
|
@ -716,15 +716,9 @@ BrowserGlue.prototype = {
|
||||
|
||||
|
||||
// Initialize the default l10n resource sources for L10nRegistry.
|
||||
const multilocalePath = "resource://gre/res/multilocale.json";
|
||||
L10nRegistry.bootstrap = fetch(multilocalePath).then(d => d.json()).then(({ locales }) => {
|
||||
const toolkitSource = new FileSource("toolkit", locales, "resource://gre/localization/{locale}/");
|
||||
L10nRegistry.registerSource(toolkitSource);
|
||||
const appSource = new FileSource("app", locales, "resource://app/localization/{locale}/");
|
||||
L10nRegistry.registerSource(appSource);
|
||||
}).catch(e => {
|
||||
Services.console.logStringMessage(`Could not load multilocale.json. Error: ${e}`);
|
||||
});
|
||||
let locales = Services.locale.getPackagedLocales();
|
||||
const appSource = new FileSource("app", locales, "resource://app/localization/{locale}/");
|
||||
L10nRegistry.registerSource(appSource);
|
||||
|
||||
Services.obs.notifyObservers(null, "browser-ui-startup-complete");
|
||||
},
|
||||
|
@ -1382,11 +1382,12 @@ var PlacesControllerDragHelper = {
|
||||
unwrappedNode.id <= 0 || PlacesUtils.isRootItem(unwrappedNode.id)) {
|
||||
return false;
|
||||
}
|
||||
let parentId = unwrappedNode.parent;
|
||||
if (parentId <= 0 ||
|
||||
parentId == PlacesUtils.placesRootId ||
|
||||
parentId == PlacesUtils.tagsFolderId ||
|
||||
unwrappedNode.grandParentId == PlacesUtils.tagsFolderId) {
|
||||
|
||||
let parentGuid = unwrappedNode.parentGuid;
|
||||
// If there's no parent Guid, this was likely a virtual query that returns
|
||||
// bookmarks, such as a tags query.
|
||||
if (!parentGuid ||
|
||||
parentGuid == PlacesUtils.bookmarks.rootGuid) {
|
||||
return false;
|
||||
}
|
||||
// leftPaneFolderId and allBookmarksFolderId are lazy getters running
|
||||
@ -1394,7 +1395,7 @@ var PlacesControllerDragHelper = {
|
||||
// them first, especially because isCommandEnabled may be called way
|
||||
// before the left pane folder is even necessary.
|
||||
if (typeof Object.getOwnPropertyDescriptor(PlacesUIUtils, "leftPaneFolderId").get != "function" &&
|
||||
(parentId == PlacesUIUtils.leftPaneFolderId)) {
|
||||
(unwrappedNode.parent == PlacesUIUtils.leftPaneFolderId)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -50,6 +50,8 @@ skip-if = (os == 'win' && ccov) # Bug 1423667
|
||||
[browser_check_correct_controllers.js]
|
||||
skip-if = (os == 'win' && ccov) # Bug 1423667
|
||||
[browser_click_bookmarks_on_toolbar.js]
|
||||
[browser_controller_onDrop_sidebar.js]
|
||||
skip-if = (os == 'win' && ccov) # Bug 1423667
|
||||
[browser_controller_onDrop_tagFolder.js]
|
||||
skip-if = (os == 'win' && ccov) # Bug 1423667
|
||||
[browser_controller_onDrop.js]
|
||||
|
@ -0,0 +1,157 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
const TEST_URL = "about:buildconfig";
|
||||
|
||||
add_task(async function setup() {
|
||||
// Clean before and after so we don't have anything in the folders.
|
||||
await PlacesUtils.bookmarks.eraseEverything();
|
||||
|
||||
registerCleanupFunction(async function() {
|
||||
await PlacesUtils.bookmarks.eraseEverything();
|
||||
});
|
||||
});
|
||||
|
||||
// Simulating actual drag and drop is hard for a xul tree as we can't get the
|
||||
// required source elements, so we have to do a lot more work by hand.
|
||||
async function simulateDrop(selectTargets, sourceBm, dropEffect, targetGuid,
|
||||
isVirtualRoot = false) {
|
||||
await withSidebarTree("bookmarks", async function(tree) {
|
||||
for (let target of selectTargets) {
|
||||
tree.selectItems([target]);
|
||||
if (tree.selectedNode instanceof Ci.nsINavHistoryContainerResultNode) {
|
||||
tree.selectedNode.containerOpen = true;
|
||||
}
|
||||
}
|
||||
|
||||
let dataTransfer = {
|
||||
_data: [],
|
||||
dropEffect,
|
||||
mozCursor: "auto",
|
||||
mozItemCount: 1,
|
||||
types: [ PlacesUtils.TYPE_X_MOZ_PLACE ],
|
||||
mozTypesAt(i) {
|
||||
return [this._data[0].type];
|
||||
},
|
||||
mozGetDataAt(i) {
|
||||
return this._data[0].data;
|
||||
},
|
||||
mozSetDataAt(type, data, index) {
|
||||
this._data.push({
|
||||
type,
|
||||
data,
|
||||
index
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
let event = {
|
||||
dataTransfer,
|
||||
preventDefault() {},
|
||||
stopPropagation() {},
|
||||
};
|
||||
|
||||
tree._controller.setDataTransfer(event);
|
||||
|
||||
Assert.equal(dataTransfer.mozTypesAt(0), PlacesUtils.TYPE_X_MOZ_PLACE,
|
||||
"Should have x-moz-place as the first data type.");
|
||||
|
||||
let dataObject = JSON.parse(dataTransfer.mozGetDataAt(0));
|
||||
|
||||
let guid = isVirtualRoot ? dataObject.concreteGuid : dataObject.itemGuid;
|
||||
|
||||
Assert.equal(guid, sourceBm.guid,
|
||||
"Should have the correct guid.");
|
||||
Assert.equal(dataObject.title, PlacesUtils.bookmarks.getLocalizedTitle(sourceBm),
|
||||
"Should have the correct title.");
|
||||
|
||||
Assert.equal(dataTransfer.dropEffect, dropEffect);
|
||||
|
||||
let ip = new InsertionPoint({
|
||||
parentId: await PlacesUtils.promiseItemId(targetGuid),
|
||||
parentGuid: targetGuid,
|
||||
index: 0,
|
||||
orientation: Ci.nsITreeView.DROP_ON
|
||||
});
|
||||
|
||||
await PlacesControllerDragHelper.onDrop(ip, dataTransfer);
|
||||
});
|
||||
}
|
||||
|
||||
add_task(async function test_move_normal_bm_in_sidebar() {
|
||||
let bm = await PlacesUtils.bookmarks.insert({
|
||||
parentGuid: PlacesUtils.bookmarks.toolbarGuid,
|
||||
title: "Fake",
|
||||
url: TEST_URL
|
||||
});
|
||||
|
||||
await simulateDrop([bm.guid], bm, "move", PlacesUtils.bookmarks.unfiledGuid);
|
||||
|
||||
let newBm = await PlacesUtils.bookmarks.fetch(bm.guid);
|
||||
|
||||
Assert.equal(newBm.parentGuid, PlacesUtils.bookmarks.unfiledGuid,
|
||||
"Should have moved to the new parent.");
|
||||
|
||||
let oldLocationBm = await PlacesUtils.bookmarks.fetch({
|
||||
parentGuid: PlacesUtils.bookmarks.toolbarGuid,
|
||||
index: 0
|
||||
});
|
||||
|
||||
Assert.ok(!oldLocationBm,
|
||||
"Should not have a bookmark at the old location.");
|
||||
});
|
||||
|
||||
add_task(async function test_try_move_root_in_sidebar() {
|
||||
let menuFolder = await PlacesUtils.bookmarks.fetch(PlacesUtils.bookmarks.menuGuid);
|
||||
await simulateDrop([menuFolder.guid], menuFolder, "move",
|
||||
PlacesUtils.bookmarks.toolbarGuid, true);
|
||||
|
||||
menuFolder = await PlacesUtils.bookmarks.fetch(PlacesUtils.bookmarks.menuGuid);
|
||||
|
||||
Assert.equal(menuFolder.parentGuid, PlacesUtils.bookmarks.rootGuid,
|
||||
"Should have remained in the root");
|
||||
|
||||
let newFolder = await PlacesUtils.bookmarks.fetch({
|
||||
parentGuid: PlacesUtils.bookmarks.toolbarGuid,
|
||||
index: 0,
|
||||
});
|
||||
|
||||
Assert.notEqual(newFolder.guid, menuFolder.guid,
|
||||
"Should have created a different folder");
|
||||
Assert.equal(newFolder.title, PlacesUtils.bookmarks.getLocalizedTitle(menuFolder),
|
||||
"Should have copied the folder title.");
|
||||
Assert.equal(newFolder.type, PlacesUtils.bookmarks.TYPE_BOOKMARK,
|
||||
"Should have a bookmark type (for a folder shortcut).");
|
||||
Assert.equal(newFolder.url, "place:folder=BOOKMARKS_MENU",
|
||||
"Should have the correct url for the folder shortcut.");
|
||||
});
|
||||
|
||||
add_task(async function test_try_move_bm_within_two_root_folder_queries() {
|
||||
await PlacesUtils.bookmarks.eraseEverything();
|
||||
|
||||
let bookmark = await PlacesUtils.bookmarks.insert({
|
||||
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||
title: "Fake",
|
||||
url: TEST_URL
|
||||
});
|
||||
|
||||
let queryType = Ci.nsINavHistoryQueryOptions.QUERY_TYPE_BOOKMARKS;
|
||||
|
||||
let queries = await PlacesUtils.bookmarks.insertTree({
|
||||
guid: PlacesUtils.bookmarks.toolbarGuid,
|
||||
children: [{
|
||||
title: "Query",
|
||||
url: `place:queryType=${queryType}&terms=Fake`
|
||||
}]
|
||||
});
|
||||
|
||||
await simulateDrop([queries[0].guid, bookmark.guid],
|
||||
bookmark, "move", PlacesUtils.bookmarks.toolbarGuid);
|
||||
|
||||
let newBm = await PlacesUtils.bookmarks.fetch(bookmark.guid);
|
||||
|
||||
Assert.equal(newBm.parentGuid, PlacesUtils.bookmarks.toolbarGuid,
|
||||
"should have moved the bookmark to a new folder.");
|
||||
});
|
@ -80,6 +80,7 @@ this.SiteDataManager = {
|
||||
cookies: [],
|
||||
persisted: false,
|
||||
quotaUsage: 0,
|
||||
lastAccessed: 0,
|
||||
principals: [],
|
||||
appCacheList: [],
|
||||
};
|
||||
@ -153,6 +154,9 @@ this.SiteDataManager = {
|
||||
if (item.persisted) {
|
||||
site.persisted = true;
|
||||
}
|
||||
if (site.lastAccessed < item.lastAccessed) {
|
||||
site.lastAccessed = item.lastAccessed;
|
||||
}
|
||||
site.principals.push(principal);
|
||||
site.quotaUsage += item.usage;
|
||||
}
|
||||
@ -174,6 +178,9 @@ this.SiteDataManager = {
|
||||
let cookie = cookiesEnum.getNext().QueryInterface(Ci.nsICookie2);
|
||||
let site = this._getOrInsertSite(cookie.rawHost);
|
||||
site.cookies.push(cookie);
|
||||
if (site.lastAccessed < cookie.lastAccessed) {
|
||||
site.lastAccessed = cookie.lastAccessed;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@ -228,7 +235,8 @@ this.SiteDataManager = {
|
||||
cookies: site.cookies,
|
||||
host,
|
||||
usage,
|
||||
persisted: site.persisted
|
||||
persisted: site.persisted,
|
||||
lastAccessed: new Date(site.lastAccessed / 1000),
|
||||
});
|
||||
}
|
||||
return list;
|
||||
|
@ -576,8 +576,8 @@
|
||||
<checkbox id="automaticallySubmitCrashesBox"
|
||||
class="tail-with-learn-more"
|
||||
preference="browser.crashReports.unsubmittedCheck.autoSubmit2"
|
||||
label="&alwaysSubmitCrashReports1.label;"
|
||||
accesskey="&alwaysSubmitCrashReports1.accesskey;"/>
|
||||
label="&sendBackloggedCrashReports.label;"
|
||||
accesskey="&sendBackloggedCrashReports.accesskey;"/>
|
||||
<label id="crashReporterLearnMore"
|
||||
class="learnMore text-link">&crashReporterLearnMore.label;</label>
|
||||
</hbox>
|
||||
|
@ -64,6 +64,8 @@ add_task(async function() {
|
||||
let request = Services.qms.clearStoragesForPrincipal(principal, null, true);
|
||||
request.callback = resolve;
|
||||
});
|
||||
|
||||
await SiteDataManager.removeAll();
|
||||
await BrowserTestUtils.removeTab(gBrowser.selectedTab);
|
||||
}).skip(); // Bug 1414751
|
||||
|
||||
@ -144,13 +146,12 @@ add_task(async function() {
|
||||
await acceptRemovePromise;
|
||||
await updatePromise;
|
||||
await promiseServiceWorkersCleared();
|
||||
await SiteDataManager.removeAll();
|
||||
await BrowserTestUtils.removeTab(gBrowser.selectedTab);
|
||||
});
|
||||
|
||||
// Test showing and removing sites with cookies.
|
||||
add_task(async function() {
|
||||
SiteDataManager.removeAll();
|
||||
|
||||
// Add some test cookies.
|
||||
let uri = Services.io.newURI("https://example.com");
|
||||
let uri2 = Services.io.newURI("https://example.org");
|
||||
@ -165,12 +166,28 @@ add_task(async function() {
|
||||
Services.cookies.add(uri.host, uri.pathQueryRef, "test3", "3",
|
||||
false, false, false, Date.now() + 1000 * 60 * 60, { privateBrowsingId: 1 });
|
||||
|
||||
// Get the exact creation date from the cookies (to avoid intermittents
|
||||
// from minimal time differences, since we round up to minutes).
|
||||
let cookiesEnum1 = Services.cookies.getCookiesFromHost(uri.host);
|
||||
// We made two valid cookies for example.com.
|
||||
cookiesEnum1.getNext();
|
||||
let cookiesEnum2 = Services.cookies.getCookiesFromHost(uri2.host);
|
||||
let cookie1 = cookiesEnum1.getNext().QueryInterface(Ci.nsICookie2);
|
||||
let cookie2 = cookiesEnum2.getNext().QueryInterface(Ci.nsICookie2);
|
||||
|
||||
let formatter = new Services.intl.DateTimeFormat(undefined, {
|
||||
dateStyle: "short", timeStyle: "short",
|
||||
});
|
||||
|
||||
let creationDate1 = formatter.format(new Date(cookie1.lastAccessed / 1000));
|
||||
let creationDate2 = formatter.format(new Date(cookie2.lastAccessed / 1000));
|
||||
|
||||
await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true });
|
||||
|
||||
// Open the site data manager and remove one site.
|
||||
await openSiteDataSettingsDialog();
|
||||
let removeDialogOpenPromise = promiseWindowDialogOpen("accept", REMOVE_DIALOG_URL);
|
||||
ContentTask.spawn(gBrowser.selectedBrowser, null, function() {
|
||||
await ContentTask.spawn(gBrowser.selectedBrowser, {creationDate1, creationDate2}, function(args) {
|
||||
let frameDoc = content.gSubDialog._topDialog._frame.contentDocument;
|
||||
|
||||
let siteItems = frameDoc.getElementsByTagName("richlistitem");
|
||||
@ -183,11 +200,13 @@ add_task(async function() {
|
||||
is(columns[0].value, "example.com", "Should show the correct host.");
|
||||
is(columns[2].value, "2", "Should show the correct number of cookies.");
|
||||
is(columns[3].value, "", "Should show no site data.");
|
||||
is(columns[4].value, args.creationDate1, "Should show the correct date.");
|
||||
|
||||
columns = site2.querySelectorAll(".item-box > label");
|
||||
is(columns[0].value, "example.org", "Should show the correct host.");
|
||||
is(columns[2].value, "1", "Should show the correct number of cookies.");
|
||||
is(columns[3].value, "", "Should show no site data.");
|
||||
is(columns[4].value, args.creationDate2, "Should show the correct date.");
|
||||
|
||||
let removeBtn = frameDoc.getElementById("removeSelected");
|
||||
let saveBtn = frameDoc.getElementById("save");
|
||||
@ -203,7 +222,7 @@ add_task(async function() {
|
||||
// Open the site data manager and remove another site.
|
||||
await openSiteDataSettingsDialog();
|
||||
let acceptRemovePromise = promiseAlertDialogOpen("accept");
|
||||
ContentTask.spawn(gBrowser.selectedBrowser, null, function() {
|
||||
await ContentTask.spawn(gBrowser.selectedBrowser, {creationDate1}, function(args) {
|
||||
let frameDoc = content.gSubDialog._topDialog._frame.contentDocument;
|
||||
|
||||
let siteItems = frameDoc.getElementsByTagName("richlistitem");
|
||||
@ -215,6 +234,7 @@ add_task(async function() {
|
||||
is(columns[0].value, "example.com", "Should show the correct host.");
|
||||
is(columns[2].value, "2", "Should show the correct number of cookies.");
|
||||
is(columns[3].value, "", "Should show no site data.");
|
||||
is(columns[4].value, args.creationDate1, "Should show the correct date.");
|
||||
|
||||
let removeBtn = frameDoc.getElementById("removeSelected");
|
||||
let saveBtn = frameDoc.getElementById("save");
|
||||
|
@ -112,7 +112,7 @@ add_task(async function() {
|
||||
await openSiteDataSettingsDialog();
|
||||
assertAllSitesNotListed(win);
|
||||
|
||||
mockSiteDataManager.unregister();
|
||||
await mockSiteDataManager.unregister();
|
||||
await BrowserTestUtils.removeTab(gBrowser.selectedTab);
|
||||
|
||||
function removeAllSitesOneByOne() {
|
||||
@ -224,7 +224,7 @@ add_task(async function() {
|
||||
await openSiteDataSettingsDialog();
|
||||
assertSitesListed(doc, fakeHosts.slice(2));
|
||||
|
||||
mockSiteDataManager.unregister();
|
||||
await mockSiteDataManager.unregister();
|
||||
await BrowserTestUtils.removeTab(gBrowser.selectedTab);
|
||||
|
||||
function removeSelectedSite(hosts) {
|
||||
@ -300,7 +300,7 @@ add_task(async function() {
|
||||
await openSiteDataSettingsDialog();
|
||||
assertSitesListed(doc, fakeHosts.filter(host => !host.includes("xyz")));
|
||||
|
||||
mockSiteDataManager.unregister();
|
||||
await mockSiteDataManager.unregister();
|
||||
await BrowserTestUtils.removeTab(gBrowser.selectedTab);
|
||||
});
|
||||
|
||||
@ -358,6 +358,6 @@ add_task(async function() {
|
||||
await openSiteDataSettingsDialog();
|
||||
assertAllSitesNotListed(win);
|
||||
|
||||
mockSiteDataManager.unregister();
|
||||
await mockSiteDataManager.unregister();
|
||||
await BrowserTestUtils.removeTab(gBrowser.selectedTab);
|
||||
});
|
||||
|
@ -42,7 +42,7 @@ add_task(async function() {
|
||||
await openSiteDataSettingsDialog();
|
||||
assertSitesListed(doc, fakeHosts.filter(host => host != "shopping.xyz.com"));
|
||||
|
||||
mockSiteDataManager.unregister();
|
||||
await mockSiteDataManager.unregister();
|
||||
await BrowserTestUtils.removeTab(gBrowser.selectedTab);
|
||||
});
|
||||
|
||||
@ -104,7 +104,7 @@ add_task(async function() {
|
||||
DownloadUtils.convertByteUnits(quotaUsage * mockSiteDataManager.fakeSites.length));
|
||||
is(columns[3].value, expected, "Should sum up usages across scheme, port and origin attributes");
|
||||
|
||||
mockSiteDataManager.unregister();
|
||||
await mockSiteDataManager.unregister();
|
||||
await BrowserTestUtils.removeTab(gBrowser.selectedTab);
|
||||
});
|
||||
|
||||
@ -116,19 +116,19 @@ add_task(async function() {
|
||||
usage: 1024,
|
||||
origin: "https://account.xyz.com",
|
||||
cookies: 6,
|
||||
persisted: true
|
||||
persisted: true,
|
||||
},
|
||||
{
|
||||
usage: 1024 * 2,
|
||||
origin: "https://books.foo.com",
|
||||
cookies: 0,
|
||||
persisted: false
|
||||
persisted: false,
|
||||
},
|
||||
{
|
||||
usage: 1024 * 3,
|
||||
origin: "http://cinema.bar.com",
|
||||
cookies: 3,
|
||||
persisted: true
|
||||
persisted: true,
|
||||
},
|
||||
]);
|
||||
|
||||
@ -174,7 +174,7 @@ add_task(async function() {
|
||||
statusCol.click();
|
||||
assertSortByStatus("descending");
|
||||
|
||||
mockSiteDataManager.unregister();
|
||||
await mockSiteDataManager.unregister();
|
||||
await BrowserTestUtils.removeTab(gBrowser.selectedTab);
|
||||
|
||||
function assertSortByBaseDomain(order) {
|
||||
@ -250,3 +250,69 @@ add_task(async function() {
|
||||
return mockSiteDataManager.fakeSites.find(site => site.principal.URI.host == host);
|
||||
}
|
||||
});
|
||||
|
||||
// Test sorting based on access date (separate from cookies for simplicity,
|
||||
// since cookies access date affects this as well, but we don't mock our cookies)
|
||||
add_task(async function() {
|
||||
mockSiteDataManager.register(SiteDataManager, [
|
||||
{
|
||||
usage: 1024,
|
||||
origin: "https://account.xyz.com",
|
||||
persisted: true,
|
||||
lastAccessed: (Date.now() - 120 * 1000) * 1000,
|
||||
},
|
||||
{
|
||||
usage: 1024 * 2,
|
||||
origin: "https://books.foo.com",
|
||||
persisted: false,
|
||||
lastAccessed: (Date.now() - 240 * 1000) * 1000,
|
||||
},
|
||||
{
|
||||
usage: 1024 * 3,
|
||||
origin: "http://cinema.bar.com",
|
||||
persisted: true,
|
||||
lastAccessed: Date.now() * 1000,
|
||||
},
|
||||
]);
|
||||
|
||||
let updatePromise = promiseSiteDataManagerSitesUpdated();
|
||||
await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true });
|
||||
await updatePromise;
|
||||
await openSiteDataSettingsDialog();
|
||||
|
||||
// eslint-disable-next-line mozilla/no-cpows-in-tests
|
||||
let dialog = content.gSubDialog._topDialog;
|
||||
let dialogFrame = dialog._frame;
|
||||
let frameDoc = dialogFrame.contentDocument;
|
||||
let lastAccessedCol = frameDoc.getElementById("lastAccessedCol");
|
||||
let sitesList = frameDoc.getElementById("sitesList");
|
||||
|
||||
// Test sorting on the date column
|
||||
lastAccessedCol.click();
|
||||
assertSortByDate("ascending");
|
||||
lastAccessedCol.click();
|
||||
assertSortByDate("descending");
|
||||
|
||||
await mockSiteDataManager.unregister();
|
||||
await BrowserTestUtils.removeTab(gBrowser.selectedTab);
|
||||
|
||||
function assertSortByDate(order) {
|
||||
let siteItems = sitesList.getElementsByTagName("richlistitem");
|
||||
for (let i = 0; i < siteItems.length - 1; ++i) {
|
||||
let aHost = siteItems[i].getAttribute("host");
|
||||
let bHost = siteItems[i + 1].getAttribute("host");
|
||||
let a = findSiteByHost(aHost);
|
||||
let b = findSiteByHost(bHost);
|
||||
let result = a.lastAccessed - b.lastAccessed;
|
||||
if (order == "ascending") {
|
||||
Assert.lessOrEqual(result, 0, "Should sort sites in the ascending order by date");
|
||||
} else {
|
||||
Assert.greaterOrEqual(result, 0, "Should sort sites in the descending order date");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function findSiteByHost(host) {
|
||||
return mockSiteDataManager.fakeSites.find(site => site.principal.URI.host == host);
|
||||
}
|
||||
});
|
||||
|
@ -229,7 +229,8 @@ const mockSiteDataManager = {
|
||||
let result = this.fakeSites.map(site => ({
|
||||
origin: site.principal.origin,
|
||||
usage: site.usage,
|
||||
persisted: site.persisted
|
||||
persisted: site.persisted,
|
||||
lastAccessed: site.lastAccessed,
|
||||
}));
|
||||
onUsageResult({ result, resultCode: Components.results.NS_OK });
|
||||
},
|
||||
@ -270,9 +271,9 @@ const mockSiteDataManager = {
|
||||
}
|
||||
},
|
||||
|
||||
unregister() {
|
||||
async unregister() {
|
||||
await this._SiteDataManager.removeAll();
|
||||
this.fakeSites = null;
|
||||
this._SiteDataManager.removeAll();
|
||||
this._SiteDataManager._qms = this._originalQMS;
|
||||
this._SiteDataManager._removeQuotaUsage = this._originalRemoveQuotaUsage;
|
||||
}
|
||||
|
@ -67,6 +67,10 @@ let gSiteDataSettings = {
|
||||
addColumnItem(null, "1");
|
||||
}
|
||||
|
||||
// Add "Last Used" column.
|
||||
addColumnItem(site.lastAccessed > 0 ?
|
||||
this._formatter.format(site.lastAccessed) : null, "2");
|
||||
|
||||
item.appendChild(container);
|
||||
return item;
|
||||
},
|
||||
@ -77,6 +81,10 @@ let gSiteDataSettings = {
|
||||
.addEventListener(eventType, callback.bind(gSiteDataSettings));
|
||||
}
|
||||
|
||||
this._formatter = new Services.intl.DateTimeFormat(undefined, {
|
||||
dateStyle: "short", timeStyle: "short",
|
||||
});
|
||||
|
||||
this._list = document.getElementById("sitesList");
|
||||
this._searchBox = document.getElementById("searchBox");
|
||||
this._prefStrBundle = document.getElementById("bundlePreferences");
|
||||
@ -95,6 +103,7 @@ let gSiteDataSettings = {
|
||||
setEventListener("sitesList", "select", this.onSelect);
|
||||
setEventListener("hostCol", "click", this.onClickTreeCol);
|
||||
setEventListener("usageCol", "click", this.onClickTreeCol);
|
||||
setEventListener("lastAccessedCol", "click", this.onClickTreeCol);
|
||||
setEventListener("cookiesCol", "click", this.onClickTreeCol);
|
||||
setEventListener("statusCol", "click", this.onClickTreeCol);
|
||||
setEventListener("cancel", "command", this.close);
|
||||
@ -161,6 +170,10 @@ let gSiteDataSettings = {
|
||||
case "usageCol":
|
||||
sortFunc = (a, b) => a.usage - b.usage;
|
||||
break;
|
||||
|
||||
case "lastAccessedCol":
|
||||
sortFunc = (a, b) => a.lastAccessed - b.lastAccessed;
|
||||
break;
|
||||
}
|
||||
if (sortDirection === "descending") {
|
||||
sites.sort((a, b) => sortFunc(b, a));
|
||||
|
@ -42,6 +42,7 @@
|
||||
<treecol flex="1" width="50" label="&cookiesCol.label;" id="cookiesCol"/>
|
||||
<!-- Sorted by usage so the user can quickly see which sites use the most data. -->
|
||||
<treecol flex="1" width="50" label="&usageCol.label;" id="usageCol" data-isCurrentSortCol="true"/>
|
||||
<treecol flex="2" width="50" label="&lastAccessedCol.label;" id="lastAccessedCol" />
|
||||
</listheader>
|
||||
</richlistbox>
|
||||
</vbox>
|
||||
|
32
browser/extensions/onboarding/bootstrap.js
vendored
32
browser/extensions/onboarding/bootstrap.js
vendored
@ -10,7 +10,7 @@ XPCOMUtils.defineLazyModuleGetters(this, {
|
||||
OnboardingTourType: "resource://onboarding/modules/OnboardingTourType.jsm",
|
||||
OnboardingTelemetry: "resource://onboarding/modules/OnboardingTelemetry.jsm",
|
||||
Services: "resource://gre/modules/Services.jsm",
|
||||
fxAccounts: "resource://gre/modules/FxAccounts.jsm",
|
||||
UIState: "resource://services-sync/UIState.jsm",
|
||||
});
|
||||
|
||||
const {PREF_STRING, PREF_BOOL, PREF_INT} = Ci.nsIPrefBranch;
|
||||
@ -89,33 +89,28 @@ let syncTourChecker = {
|
||||
},
|
||||
|
||||
observe(subject, topic) {
|
||||
switch (topic) {
|
||||
case "fxaccounts:onlogin":
|
||||
this.setComplete();
|
||||
break;
|
||||
case "fxaccounts:onlogout":
|
||||
this._loggedIn = false;
|
||||
break;
|
||||
const state = UIState.get();
|
||||
if (state.status == UIState.STATUS_NOT_CONFIGURED) {
|
||||
this._loggedIn = false;
|
||||
} else {
|
||||
this.setComplete();
|
||||
}
|
||||
},
|
||||
|
||||
init() {
|
||||
// Check if we've already logged in at startup.
|
||||
fxAccounts.getSignedInUser().then(user => {
|
||||
if (user) {
|
||||
this.setComplete();
|
||||
}
|
||||
// Observe for login action if we haven't logged in yet.
|
||||
this.register();
|
||||
});
|
||||
const state = UIState.get();
|
||||
if (state.status != UIState.STATUS_NOT_CONFIGURED) {
|
||||
this.setComplete();
|
||||
}
|
||||
this.register();
|
||||
},
|
||||
|
||||
register() {
|
||||
if (this._registered) {
|
||||
return;
|
||||
}
|
||||
Services.obs.addObserver(this, "fxaccounts:onlogin");
|
||||
Services.obs.addObserver(this, "fxaccounts:onlogout");
|
||||
Services.obs.addObserver(this, "sync-ui-state:update");
|
||||
this._registered = true;
|
||||
},
|
||||
|
||||
@ -128,8 +123,7 @@ let syncTourChecker = {
|
||||
if (!this._registered) {
|
||||
return;
|
||||
}
|
||||
Services.obs.removeObserver(this, "fxaccounts:onlogin");
|
||||
Services.obs.removeObserver(this, "fxaccounts:onlogout");
|
||||
Services.obs.removeObserver(this, "sync-ui-state:update");
|
||||
this._registered = false;
|
||||
},
|
||||
|
||||
|
@ -145,6 +145,8 @@ res/table-remove-column.gif
|
||||
res/table-remove-row-active.gif
|
||||
res/table-remove-row-hover.gif
|
||||
res/table-remove-row.gif
|
||||
res/multilocale.txt
|
||||
update.locale
|
||||
# Aurora branding
|
||||
browser/chrome/browser/content/branding/icon64.png
|
||||
browser/chrome/devtools/content/framework/dev-edition-promo/dev-edition-logo.png
|
||||
|
@ -86,7 +86,7 @@ endif
|
||||
@$(MAKE) -C ../../devtools/shim/locales AB_CD=$* XPI_NAME=locale-$* XPI_ROOT_APPID='$(XPI_ROOT_APPID)'
|
||||
@$(MAKE) -B searchplugins AB_CD=$* XPI_NAME=locale-$*
|
||||
@$(MAKE) libs AB_CD=$* XPI_NAME=locale-$* PREF_DIR=$(PREF_DIR)
|
||||
@$(MAKE) multilocale.json-$* AB_CD=$* XPI_NAME=locale-$*
|
||||
@$(MAKE) multilocale.txt-$* AB_CD=$* XPI_NAME=locale-$*
|
||||
@$(MAKE) -C $(DEPTH)/$(MOZ_BRANDING_DIRECTORY)/locales AB_CD=$* XPI_NAME=locale-$*
|
||||
|
||||
chrome-%: AB_CD=$*
|
||||
|
@ -41,8 +41,8 @@ available. -->
|
||||
<!ENTITY collectBrowserErrors.accesskey "b">
|
||||
<!ENTITY collectBrowserErrorsLearnMore.label "Learn more">
|
||||
|
||||
<!ENTITY alwaysSubmitCrashReports1.label "Allow &brandShortName; to send crash reports to Mozilla">
|
||||
<!ENTITY alwaysSubmitCrashReports1.accesskey "c">
|
||||
<!ENTITY sendBackloggedCrashReports.label "Allow &brandShortName; to send backlogged crash reports on your behalf">
|
||||
<!ENTITY sendBackloggedCrashReports.accesskey "c">
|
||||
<!ENTITY crashReporterLearnMore.label "Learn more">
|
||||
|
||||
<!ENTITY networkTab.label "Network">
|
||||
|
@ -7,6 +7,7 @@
|
||||
<!ENTITY statusCol.label "Status">
|
||||
<!ENTITY cookiesCol.label "Cookies">
|
||||
<!ENTITY usageCol.label "Storage">
|
||||
<!ENTITY lastAccessedCol.label "Last Used">
|
||||
<!ENTITY searchTextboxPlaceHolder "Search websites">
|
||||
<!ENTITY searchTextboxPlaceHolder.accesskey "S">
|
||||
<!ENTITY removeSelected.label "Remove Selected">
|
||||
|
@ -149,6 +149,7 @@ this.SitePermissions = {
|
||||
SCOPE_TEMPORARY: "{SitePermissions.SCOPE_TEMPORARY}",
|
||||
SCOPE_SESSION: "{SitePermissions.SCOPE_SESSION}",
|
||||
SCOPE_PERSISTENT: "{SitePermissions.SCOPE_PERSISTENT}",
|
||||
SCOPE_POLICY: "{SitePermissions.SCOPE_POLICY}",
|
||||
|
||||
_defaultPrefBranch: Services.prefs.getBranch("permissions.default."),
|
||||
|
||||
@ -188,7 +189,10 @@ this.SitePermissions = {
|
||||
let scope = this.SCOPE_PERSISTENT;
|
||||
if (permission.expireType == Services.perms.EXPIRE_SESSION) {
|
||||
scope = this.SCOPE_SESSION;
|
||||
} else if (permission.expireType == Services.perms.EXPIRE_POLICY) {
|
||||
scope = this.SCOPE_POLICY;
|
||||
}
|
||||
|
||||
result.push({
|
||||
id: permission.type,
|
||||
scope,
|
||||
@ -358,6 +362,8 @@ this.SitePermissions = {
|
||||
result.state = permission.capability;
|
||||
if (permission.expireType == Services.perms.EXPIRE_SESSION) {
|
||||
result.scope = this.SCOPE_SESSION;
|
||||
} else if (permission.expireType == Services.perms.EXPIRE_POLICY) {
|
||||
result.scope = this.SCOPE_POLICY;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -430,6 +436,8 @@ this.SitePermissions = {
|
||||
let perms_scope = Services.perms.EXPIRE_NEVER;
|
||||
if (scope == this.SCOPE_SESSION) {
|
||||
perms_scope = Services.perms.EXPIRE_SESSION;
|
||||
} else if (scope == this.SCOPE_POLICY) {
|
||||
perms_scope = Services.perms.EXPIRE_POLICY;
|
||||
}
|
||||
|
||||
Services.perms.add(uri, permissionID, state, perms_scope);
|
||||
@ -541,13 +549,13 @@ this.SitePermissions = {
|
||||
case this.PROMPT:
|
||||
return gStringBundle.GetStringFromName("state.current.prompt");
|
||||
case this.ALLOW:
|
||||
if (scope && scope != this.SCOPE_PERSISTENT)
|
||||
if (scope && scope != this.SCOPE_PERSISTENT && scope != this.SCOPE_POLICY)
|
||||
return gStringBundle.GetStringFromName("state.current.allowedTemporarily");
|
||||
return gStringBundle.GetStringFromName("state.current.allowed");
|
||||
case this.ALLOW_COOKIES_FOR_SESSION:
|
||||
return gStringBundle.GetStringFromName("state.current.allowedForSession");
|
||||
case this.BLOCK:
|
||||
if (scope && scope != this.SCOPE_PERSISTENT)
|
||||
if (scope && scope != this.SCOPE_PERSISTENT && scope != this.SCOPE_POLICY)
|
||||
return gStringBundle.GetStringFromName("state.current.blockedTemporarily");
|
||||
return gStringBundle.GetStringFromName("state.current.blocked");
|
||||
default:
|
||||
|
@ -343,15 +343,6 @@ PreviewController.prototype = {
|
||||
}
|
||||
};
|
||||
|
||||
XPCOMUtils.defineLazyGetter(PreviewController.prototype, "canvasPreviewFlags",
|
||||
function() {
|
||||
let canvasInterface = Ci.nsIDOMCanvasRenderingContext2D;
|
||||
return canvasInterface.DRAWWINDOW_DRAW_VIEW
|
||||
| canvasInterface.DRAWWINDOW_DRAW_CARET
|
||||
| canvasInterface.DRAWWINDOW_ASYNC_DECODE_IMAGES
|
||||
| canvasInterface.DRAWWINDOW_DO_NOT_FLUSH;
|
||||
});
|
||||
|
||||
// TabWindow
|
||||
|
||||
/*
|
||||
|
@ -173,9 +173,8 @@ nsChromeProtocolHandler::NewChannel2(nsIURI* aURI,
|
||||
bool exists = false;
|
||||
file->Exists(&exists);
|
||||
if (!exists) {
|
||||
nsAutoCString path;
|
||||
file->GetNativePath(path);
|
||||
printf("Chrome file doesn't exist: %s\n", path.get());
|
||||
printf("Chrome file doesn't exist: %s\n",
|
||||
file->HumanReadablePath().get());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -735,12 +735,6 @@ nsChromeRegistryChrome::ManifestLocale(ManifestProcessingContext& cx, int lineno
|
||||
if (NS_FAILED(rv)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mainPackage.Equals(package)) {
|
||||
// We should refresh the LocaleService, since the available
|
||||
// locales changed.
|
||||
LocaleService::GetInstance()->AvailableLocalesChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -44,6 +44,7 @@ registerCleanupFunction(function() {
|
||||
add_task(async function() {
|
||||
// Windows XP and 8.1 test slaves are terribly slow at this test.
|
||||
requestLongerTimeout(5);
|
||||
await pushPref("devtools.chrome.enabled", true);
|
||||
await pushPref("devtools.debugger.remote-enabled", true);
|
||||
|
||||
gProcess = await initChromeDebugger();
|
||||
|
@ -12,6 +12,7 @@ var gProcess;
|
||||
function test() {
|
||||
// Windows XP and 8.1 test slaves are terribly slow at this test.
|
||||
requestLongerTimeout(5);
|
||||
Services.prefs.setBoolPref("devtools.chrome.enabled", true);
|
||||
Services.prefs.setBoolPref("devtools.debugger.remote-enabled", true);
|
||||
|
||||
initChromeDebugger(aOnClose).then(aProcess => {
|
||||
@ -57,6 +58,7 @@ function aOnClose() {
|
||||
}
|
||||
|
||||
registerCleanupFunction(function () {
|
||||
Services.prefs.clearUserPref("devtools.chrome.enabled");
|
||||
Services.prefs.clearUserPref("devtools.debugger.remote-enabled");
|
||||
gProcess = null;
|
||||
});
|
||||
|
@ -91,9 +91,28 @@ EventEmitter.decorate(BrowserToolboxProcess);
|
||||
* @return object
|
||||
*/
|
||||
BrowserToolboxProcess.init = function (onClose, onRun, options) {
|
||||
if (!Services.prefs.getBoolPref("devtools.chrome.enabled") ||
|
||||
!Services.prefs.getBoolPref("devtools.debugger.remote-enabled")) {
|
||||
console.error("Could not start Browser Toolbox, you need to enable it.");
|
||||
return null;
|
||||
}
|
||||
return new BrowserToolboxProcess(onClose, onRun, options);
|
||||
};
|
||||
|
||||
/**
|
||||
* Figure out if there are any open Browser Toolboxes that'll need to be restored.
|
||||
* @return bool
|
||||
*/
|
||||
BrowserToolboxProcess.getBrowserToolboxSessionState = function () {
|
||||
for (let process of processes.values()) {
|
||||
// Don't worry about addon toolboxes, we only want to restore the Browser Toolbox.
|
||||
if (!process._options || !process._options.addonID) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Passes a set of options to the BrowserAddonActors for the given ID.
|
||||
*
|
||||
|
@ -17,6 +17,7 @@ loader.lazyRequireGetter(this, "ToolboxHostManager", "devtools/client/framework/
|
||||
loader.lazyRequireGetter(this, "gDevToolsBrowser", "devtools/client/framework/devtools-browser", true);
|
||||
loader.lazyRequireGetter(this, "HUDService", "devtools/client/webconsole/hudservice", true);
|
||||
loader.lazyImporter(this, "ScratchpadManager", "resource://devtools/client/scratchpad/scratchpad-manager.jsm");
|
||||
loader.lazyImporter(this, "BrowserToolboxProcess", "resource://devtools/client/framework/ToolboxProcess.jsm");
|
||||
|
||||
loader.lazyRequireGetter(this, "WebExtensionInspectedWindowFront",
|
||||
"devtools/shared/fronts/webextension-inspected-window", true);
|
||||
@ -397,6 +398,7 @@ DevTools.prototype = {
|
||||
*/
|
||||
saveDevToolsSession: function (state) {
|
||||
state.browserConsole = HUDService.getBrowserConsoleSessionState();
|
||||
state.browserToolbox = BrowserToolboxProcess.getBrowserToolboxSessionState();
|
||||
|
||||
// Check if the module is loaded to avoid loading ScratchpadManager for no reason.
|
||||
state.scratchpads = [];
|
||||
@ -408,11 +410,15 @@ DevTools.prototype = {
|
||||
/**
|
||||
* Restore the devtools session state as provided by SessionStore.
|
||||
*/
|
||||
restoreDevToolsSession: function ({scratchpads, browserConsole}) {
|
||||
restoreDevToolsSession: function ({scratchpads, browserConsole, browserToolbox}) {
|
||||
if (scratchpads) {
|
||||
ScratchpadManager.restoreSession(scratchpads);
|
||||
}
|
||||
|
||||
if (browserToolbox) {
|
||||
BrowserToolboxProcess.init();
|
||||
}
|
||||
|
||||
if (browserConsole && !HUDService.getBrowserConsole()) {
|
||||
HUDService.toggleBrowserConsole();
|
||||
}
|
||||
|
@ -5,8 +5,8 @@
|
||||
// On debug test slave, it takes about 50s to run the test.
|
||||
requestLongerTimeout(4);
|
||||
|
||||
add_task(function* runTest() {
|
||||
yield new Promise(done => {
|
||||
add_task(async function() {
|
||||
await new Promise(done => {
|
||||
let options = {"set": [
|
||||
["devtools.debugger.prompt-connection", false],
|
||||
["devtools.debugger.remote-enabled", true],
|
||||
@ -48,18 +48,22 @@ add_task(function* runTest() {
|
||||
});
|
||||
|
||||
let { BrowserToolboxProcess } = ChromeUtils.import("resource://devtools/client/framework/ToolboxProcess.jsm", {});
|
||||
is(BrowserToolboxProcess.getBrowserToolboxSessionState(), false, "No session state initially");
|
||||
|
||||
let closePromise;
|
||||
yield new Promise(onRun => {
|
||||
await new Promise(onRun => {
|
||||
closePromise = new Promise(onClose => {
|
||||
info("Opening the browser toolbox\n");
|
||||
BrowserToolboxProcess.init(onClose, onRun);
|
||||
});
|
||||
});
|
||||
ok(true, "Browser toolbox started\n");
|
||||
is(BrowserToolboxProcess.getBrowserToolboxSessionState(), true, "Has session state");
|
||||
|
||||
yield onCustomMessage;
|
||||
await onCustomMessage;
|
||||
ok(true, "Received the custom message");
|
||||
|
||||
yield closePromise;
|
||||
await closePromise;
|
||||
ok(true, "Browser toolbox process just closed");
|
||||
is(BrowserToolboxProcess.getBrowserToolboxSessionState(), false, "No session state after closing");
|
||||
});
|
||||
|
@ -16,7 +16,8 @@ var { Toolbox } = require("devtools/client/framework/toolbox");
|
||||
var Services = require("Services");
|
||||
var { DebuggerClient } = require("devtools/shared/client/debugger-client");
|
||||
var { PrefsHelper } = require("devtools/client/shared/prefs");
|
||||
var { Task } = require("devtools/shared/task");
|
||||
|
||||
const STATUS_REVEAL_TIME = 5000;
|
||||
|
||||
/**
|
||||
* Shortcuts for accessing various debugger preferences.
|
||||
@ -28,9 +29,20 @@ var Prefs = new PrefsHelper("devtools.debugger", {
|
||||
|
||||
var gToolbox, gClient;
|
||||
|
||||
var connect = Task.async(function* () {
|
||||
window.removeEventListener("load", connect);
|
||||
function appendStatusMessage(msg) {
|
||||
let statusMessage = document.getElementById("status-message");
|
||||
statusMessage.value += msg + "\n";
|
||||
if (msg.stack) {
|
||||
statusMessage.value += msg.stack + "\n";
|
||||
}
|
||||
}
|
||||
|
||||
function revealStatusMessage() {
|
||||
let statusMessageContainer = document.getElementById("status-message-container");
|
||||
statusMessageContainer.hidden = false;
|
||||
}
|
||||
|
||||
var connect = async function () {
|
||||
// Initiate the connection
|
||||
let env = Components.classes["@mozilla.org/process/environment;1"]
|
||||
.getService(Components.interfaces.nsIEnvironment);
|
||||
@ -44,24 +56,29 @@ var connect = Task.async(function* () {
|
||||
throw new Error("Must pass a port in an env variable with MOZ_BROWSER_TOOLBOX_PORT");
|
||||
}
|
||||
|
||||
let transport = yield DebuggerClient.socketConnect({
|
||||
host: Prefs.chromeDebuggingHost,
|
||||
let host = Prefs.chromeDebuggingHost;
|
||||
let webSocket = Prefs.chromeDebuggingWebSocket;
|
||||
appendStatusMessage(`Connecting to ${host}:${port}, ws: ${webSocket}`);
|
||||
let transport = await DebuggerClient.socketConnect({
|
||||
host,
|
||||
port,
|
||||
webSocket: Prefs.chromeDebuggingWebSocket,
|
||||
webSocket,
|
||||
});
|
||||
gClient = new DebuggerClient(transport);
|
||||
yield gClient.connect();
|
||||
appendStatusMessage("Start protocol client for connection");
|
||||
await gClient.connect();
|
||||
|
||||
appendStatusMessage("Get root form for toolbox");
|
||||
if (addonID) {
|
||||
let { addons } = yield gClient.listAddons();
|
||||
let { addons } = await gClient.listAddons();
|
||||
let addonActor = addons.filter(addon => addon.id === addonID).pop();
|
||||
let isTabActor = addonActor.isWebExtension;
|
||||
openToolbox({form: addonActor, chrome: true, isTabActor});
|
||||
await openToolbox({form: addonActor, chrome: true, isTabActor});
|
||||
} else {
|
||||
let response = yield gClient.getProcess();
|
||||
openToolbox({form: response.form, chrome: true});
|
||||
let response = await gClient.getProcess();
|
||||
await openToolbox({form: response.form, chrome: true});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// Certain options should be toggled since we can assume chrome debugging here
|
||||
function setPrefDefaults() {
|
||||
@ -78,47 +95,55 @@ function setPrefDefaults() {
|
||||
Services.prefs.setBoolPref("devtools.preference.new-panel-enabled", false);
|
||||
Services.prefs.setBoolPref("layout.css.emulate-moz-box-with-flex", false);
|
||||
}
|
||||
window.addEventListener("load", function () {
|
||||
window.addEventListener("load", async function () {
|
||||
let cmdClose = document.getElementById("toolbox-cmd-close");
|
||||
cmdClose.addEventListener("command", onCloseCommand);
|
||||
setPrefDefaults();
|
||||
connect().catch(e => {
|
||||
let errorMessageContainer = document.getElementById("error-message-container");
|
||||
let errorMessage = document.getElementById("error-message");
|
||||
errorMessage.value = e.message || e;
|
||||
errorMessageContainer.hidden = false;
|
||||
// Reveal status message if connecting is slow or if an error occurs
|
||||
let delayedStatusReveal = setTimeout(() => {
|
||||
revealStatusMessage();
|
||||
}, STATUS_REVEAL_TIME);
|
||||
try {
|
||||
await connect();
|
||||
clearTimeout(delayedStatusReveal);
|
||||
} catch (e) {
|
||||
appendStatusMessage(e);
|
||||
revealStatusMessage();
|
||||
console.error(e);
|
||||
});
|
||||
});
|
||||
}
|
||||
}, { once: true });
|
||||
|
||||
function onCloseCommand(event) {
|
||||
window.close();
|
||||
}
|
||||
|
||||
function openToolbox({ form, chrome, isTabActor }) {
|
||||
async function openToolbox({ form, chrome, isTabActor }) {
|
||||
let options = {
|
||||
form: form,
|
||||
client: gClient,
|
||||
chrome: chrome,
|
||||
isTabActor: isTabActor
|
||||
};
|
||||
TargetFactory.forRemoteTab(options).then(target => {
|
||||
let frame = document.getElementById("toolbox-iframe");
|
||||
appendStatusMessage(`Create toolbox target: ${JSON.stringify(arguments, null, 2)}`);
|
||||
let target = await TargetFactory.forRemoteTab(options);
|
||||
let frame = document.getElementById("toolbox-iframe");
|
||||
|
||||
// Remember the last panel that was used inside of this profile.
|
||||
// But if we are testing, then it should always open the debugger panel.
|
||||
let selectedTool =
|
||||
Services.prefs.getCharPref("devtools.browsertoolbox.panel",
|
||||
Services.prefs.getCharPref("devtools.toolbox.selectedTool",
|
||||
"jsdebugger"));
|
||||
// Remember the last panel that was used inside of this profile.
|
||||
// But if we are testing, then it should always open the debugger panel.
|
||||
let selectedTool =
|
||||
Services.prefs.getCharPref("devtools.browsertoolbox.panel",
|
||||
Services.prefs.getCharPref("devtools.toolbox.selectedTool",
|
||||
"jsdebugger"));
|
||||
|
||||
options = { customIframe: frame };
|
||||
gDevTools.showToolbox(target,
|
||||
selectedTool,
|
||||
Toolbox.HostType.CUSTOM,
|
||||
options)
|
||||
.then(onNewToolbox);
|
||||
});
|
||||
options = { customIframe: frame };
|
||||
appendStatusMessage(`Show toolbox with ${selectedTool} selected`);
|
||||
let toolbox = await gDevTools.showToolbox(
|
||||
target,
|
||||
selectedTool,
|
||||
Toolbox.HostType.CUSTOM,
|
||||
options
|
||||
);
|
||||
onNewToolbox(toolbox);
|
||||
}
|
||||
|
||||
function onNewToolbox(toolbox) {
|
||||
@ -147,7 +172,7 @@ function evaluateTestScript(script, toolbox) {
|
||||
Cu.evalInSandbox(script, sandbox);
|
||||
}
|
||||
|
||||
function bindToolboxHandlers() {
|
||||
async function bindToolboxHandlers() {
|
||||
gToolbox.once("destroyed", quitApp);
|
||||
window.addEventListener("unload", onUnload);
|
||||
|
||||
@ -157,9 +182,8 @@ function bindToolboxHandlers() {
|
||||
updateBadgeText(false);
|
||||
|
||||
// Once the debugger panel opens listen for thread pause / resume.
|
||||
gToolbox.getPanelWhenReady("jsdebugger").then(panel => {
|
||||
setupThreadListeners(panel);
|
||||
});
|
||||
let panel = await gToolbox.getPanelWhenReady("jsdebugger");
|
||||
setupThreadListeners(panel);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -37,9 +37,9 @@
|
||||
for example when viewing network request details. -->
|
||||
<popupset id="mainPopupSet"></popupset>
|
||||
|
||||
<vbox id="error-message-container" hidden="true" flex="1">
|
||||
<box>&browserToolboxErrorMessage;</box>
|
||||
<textbox multiline="true" id="error-message" flex="1"></textbox>
|
||||
<vbox id="status-message-container" hidden="true" flex="1">
|
||||
<box>&browserToolboxStatusMessage;</box>
|
||||
<textbox multiline="true" id="status-message" flex="1"></textbox>
|
||||
</vbox>
|
||||
|
||||
<tooltip id="aHTMLTooltip" page="true"/>
|
||||
|
@ -307,27 +307,34 @@ class BoxModelMain extends PureComponent {
|
||||
switch (keyCode) {
|
||||
case KeyCodes.DOM_VK_RETURN:
|
||||
if (!isEditable) {
|
||||
this.setState({ focusable: true });
|
||||
let editableBox = this.layouts[level].get(keyCode);
|
||||
if (editableBox) {
|
||||
editableBox.boxModelEditable.focus();
|
||||
}
|
||||
this.setState({ focusable: true }, () => {
|
||||
let editableBox = this.layouts[level].get(keyCode);
|
||||
if (editableBox) {
|
||||
editableBox.boxModelEditable.focus();
|
||||
}
|
||||
});
|
||||
}
|
||||
break;
|
||||
case KeyCodes.DOM_VK_DOWN:
|
||||
case KeyCodes.DOM_VK_UP:
|
||||
if (!editingMode) {
|
||||
event.preventDefault();
|
||||
this.setState({ focusable: false });
|
||||
event.stopPropagation();
|
||||
this.setState({ focusable: false }, () => {
|
||||
let nextLayout = this.layouts[level].get(keyCode);
|
||||
|
||||
let nextLayout = this.layouts[level].get(keyCode);
|
||||
this.setAriaActive(nextLayout);
|
||||
if (!nextLayout) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (target && target._editable) {
|
||||
target.blur();
|
||||
}
|
||||
this.setAriaActive(nextLayout);
|
||||
|
||||
this.props.boxModelContainer.focus();
|
||||
if (target && target._editable) {
|
||||
target.blur();
|
||||
}
|
||||
|
||||
this.props.boxModelContainer.focus();
|
||||
});
|
||||
}
|
||||
break;
|
||||
case KeyCodes.DOM_VK_TAB:
|
||||
@ -340,8 +347,9 @@ class BoxModelMain extends PureComponent {
|
||||
if (target._editable) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
this.setState({ focusable: false });
|
||||
this.props.boxModelContainer.focus();
|
||||
this.setState({ focusable: false }, () => {
|
||||
this.props.boxModelContainer.focus();
|
||||
});
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -45,16 +45,18 @@ class Font extends PureComponent {
|
||||
});
|
||||
}
|
||||
|
||||
onFontToggle() {
|
||||
onFontToggle(event) {
|
||||
this.setState({
|
||||
isFontExpanded: !this.state.isFontExpanded
|
||||
});
|
||||
event.stopPropagation();
|
||||
}
|
||||
|
||||
onFontFaceRuleToggle() {
|
||||
onFontFaceRuleToggle(event) {
|
||||
this.setState({
|
||||
isFontFaceRuleExpanded: !this.state.isFontFaceRuleExpanded
|
||||
});
|
||||
event.stopPropagation();
|
||||
}
|
||||
|
||||
renderFontCSS(cssFamilyName) {
|
||||
|
@ -44,8 +44,9 @@ class FontPreview extends PureComponent {
|
||||
this.setState({ isFocused: false });
|
||||
}
|
||||
|
||||
onClick() {
|
||||
onClick(event) {
|
||||
this.setState({ isFocused: true });
|
||||
event.stopPropagation();
|
||||
}
|
||||
|
||||
onChange(event) {
|
||||
|
@ -34,11 +34,13 @@ class Accordion extends PureComponent {
|
||||
this.renderContainer = this.renderContainer.bind(this);
|
||||
}
|
||||
|
||||
handleHeaderClick(i) {
|
||||
handleHeaderClick(i, event) {
|
||||
const opened = [...this.state.opened];
|
||||
const created = [...this.state.created];
|
||||
const item = this.props.items[i];
|
||||
|
||||
event.stopPropagation();
|
||||
|
||||
opened[i] = !opened[i];
|
||||
created[i] = true;
|
||||
|
||||
@ -67,7 +69,7 @@ class Accordion extends PureComponent {
|
||||
|
||||
div(
|
||||
{ className: "_header",
|
||||
onClick: () => this.handleHeaderClick(i) },
|
||||
onClick: event => this.handleHeaderClick(i, event) },
|
||||
span({ className: arrowClassName }),
|
||||
item.header
|
||||
),
|
||||
|
@ -10,9 +10,10 @@
|
||||
<!ENTITY toggleToolboxF12.keycode "VK_F12">
|
||||
<!ENTITY toggleToolboxF12.keytext "F12">
|
||||
|
||||
<!-- LOCALIZATION NOTE (browserToolboxErrorMessage): This is the label
|
||||
- shown next to error details when the Browser Toolbox is unable to open. -->
|
||||
<!ENTITY browserToolboxErrorMessage "Error opening Browser Toolbox:">
|
||||
<!-- LOCALIZATION NOTE (browserToolboxStatusMessage): This is the label
|
||||
- shown next to status details when the Browser Toolbox fails to connect or
|
||||
- appears to be taking a while to do so. -->
|
||||
<!ENTITY browserToolboxStatusMessage "Browser Toolbox connection status:">
|
||||
|
||||
<!-- LOCALIZATION NOTE (options.context.advancedSettings): This is the label for
|
||||
- the heading of the advanced settings group in the options panel. -->
|
||||
|
193
devtools/client/shared/vendor/REACT_UPGRADING.md
vendored
193
devtools/client/shared/vendor/REACT_UPGRADING.md
vendored
@ -28,11 +28,14 @@ We need to disable minification and tree shaking as they overcomplicate the upgr
|
||||
- Find a method called `function getRollupOutputOptions()`
|
||||
- After `sourcemap: false` add `treeshake: false` and `freeze: false`
|
||||
- Change this:
|
||||
|
||||
```js
|
||||
// Apply dead code elimination and/or minification.
|
||||
isProduction &&
|
||||
```
|
||||
|
||||
To this:
|
||||
|
||||
```js
|
||||
{
|
||||
transformBundle(source) {
|
||||
@ -78,6 +81,7 @@ if (process.env.NODE_ENV === 'production') {
|
||||
```
|
||||
|
||||
To this:
|
||||
|
||||
```js
|
||||
module.exports = require('./cjs/react-test-renderer-shallow.development.js');
|
||||
```
|
||||
@ -112,192 +116,3 @@ cp build/packages/react-test-renderer/react-test-renderer-shallow.js <gecko-dev>
|
||||
```
|
||||
|
||||
From this point we will no longer need your react repository so feel free to delete it.
|
||||
|
||||
## Patching
|
||||
|
||||
### Patching react-dom
|
||||
|
||||
Open `devtools/client/shared/vendor/react-dom.js` and `devtools/client/shared/vendor/react-dom-dev.js`.
|
||||
|
||||
The following change should be made to **BOTH** files.
|
||||
|
||||
To have React's event system working correctly in certain XUL situations, ReactDOM must be monkey patched with a fix.
|
||||
|
||||
Turn this:
|
||||
|
||||
```js
|
||||
var ReactDOM$2 = Object.freeze({
|
||||
default: ReactDOM
|
||||
});
|
||||
```
|
||||
|
||||
Into this:
|
||||
|
||||
```js
|
||||
//--------------------------------------------------------------------------------------
|
||||
// START MONKEY PATCH
|
||||
/**
|
||||
* This section contains a monkey patch for React DOM, so that it functions correctly in
|
||||
* certain XUL situations. React centralizes events to specific DOM nodes by only
|
||||
* binding a single listener to the document of the page. It then captures these events,
|
||||
* and then uses a SyntheticEvent system to dispatch these throughout the page.
|
||||
*
|
||||
* In privileged XUL with a XUL iframe, and React in both documents, this system breaks.
|
||||
* By design, these XUL frames can still talk to each other, while in a normal HTML
|
||||
* situation, they would not be able to. The events from the XUL iframe propagate to the
|
||||
* parent document as well. This leads to the React event system incorrectly dispatching
|
||||
* TWO SyntheticEvents for for every ONE action.
|
||||
*
|
||||
* The fix here is trick React into thinking that the owning document for every node in
|
||||
* a XUL iframe to be the toolbox.xul. This is done by creating a Proxy object that
|
||||
* captures any usage of HTMLElement.ownerDocument, and then passing in the toolbox.xul
|
||||
* document rather than (for example) the netmonitor.xul document. React will then hook
|
||||
* up the event system correctly on the top level controlling document.
|
||||
*
|
||||
* @return {object} The proxied and monkey patched ReactDOM
|
||||
*/
|
||||
function monkeyPatchReactDOM(ReactDOM) {
|
||||
// This is the actual monkey patched function.
|
||||
const reactDomRender = monkeyPatchRender(ReactDOM);
|
||||
|
||||
// Proxied method calls might need to be bound, but do this lazily with caching.
|
||||
const lazyFunctionBinding = functionLazyBinder();
|
||||
|
||||
// Create a proxy, but the render property is not writable on the ReactDOM object, so
|
||||
// a direct proxy will fail with an error. Instead, create a proxy on a a blank object.
|
||||
// Pass on getting and setting behaviors.
|
||||
return new Proxy({}, {
|
||||
get: (target, name) => {
|
||||
if (name === "render") {
|
||||
return reactDomRender;
|
||||
}
|
||||
return lazyFunctionBinding(ReactDOM, name);
|
||||
},
|
||||
set: (target, name, value) => {
|
||||
ReactDOM[name] = value;
|
||||
return true;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a function that replaces the ReactDOM.render method. It does this by
|
||||
* creating a proxy for the dom node being mounted. This proxy rewrites the
|
||||
* "ownerDocument" property to point to the toolbox.xul document. This function
|
||||
* is only used for XUL iframes inside of a XUL document.
|
||||
*
|
||||
* @param {object} ReactDOM
|
||||
* @return {function} The patched ReactDOM.render function.
|
||||
*/
|
||||
function monkeyPatchRender(ReactDOM) {
|
||||
const elementProxyCache = new WeakMap();
|
||||
|
||||
return (...args) => {
|
||||
const container = args[1];
|
||||
const toolboxDoc = getToolboxDocIfXulOnly(container);
|
||||
|
||||
if (toolboxDoc) {
|
||||
// Re-use any existing cached HTMLElement proxies.
|
||||
let proxy = elementProxyCache.get(container);
|
||||
|
||||
if (!proxy) {
|
||||
// Proxied method calls need to be bound, but do this lazily.
|
||||
const lazyFunctionBinding = functionLazyBinder();
|
||||
|
||||
// Create a proxy to the container HTMLElement. If React tries to access the
|
||||
// ownerDocument, pass in the toolbox's document, as the event dispatching system
|
||||
// is rooted from the toolbox document.
|
||||
proxy = new Proxy(container, {
|
||||
get: function (target, name) {
|
||||
if (name === "ownerDocument") {
|
||||
return toolboxDoc;
|
||||
}
|
||||
return lazyFunctionBinding(target, name);
|
||||
}
|
||||
});
|
||||
|
||||
elementProxyCache.set(container, proxy);
|
||||
}
|
||||
|
||||
// Update the args passed to ReactDOM.render.
|
||||
args[1] = proxy;
|
||||
}
|
||||
|
||||
return ReactDOM.render.apply(this, args);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to access the containing toolbox XUL document, but only if all of the iframes
|
||||
* in the heirarchy are XUL documents. Events dispatch differently in the case of all
|
||||
* privileged XUL documents. Events that fire in an iframe propagate up to the parent
|
||||
* frame. This does not happen when HTML is in the mix. Only return the toolbox if
|
||||
* it matches the proper case of a XUL iframe inside of a XUL document.
|
||||
*
|
||||
* In addition to the XUL case, if the panel uses the toolbox's ReactDOM instance,
|
||||
* this patch needs to be applied as well. This is the case for the inspector.
|
||||
*
|
||||
* @param {HTMLElement} node - The DOM node inside of an iframe.
|
||||
* @return {XULDocument|null} The toolbox.xul document, or null.
|
||||
*/
|
||||
function getToolboxDocIfXulOnly(node) {
|
||||
// This execution context doesn't know about XULDocuments, so don't get the toolbox.
|
||||
if (typeof XULDocument !== "function") {
|
||||
return null;
|
||||
}
|
||||
|
||||
let doc = node.ownerDocument;
|
||||
const inspectorUrl = "chrome://devtools/content/inspector/inspector.xhtml";
|
||||
const netMonitorUrl = "chrome://devtools/content/netmonitor/netmonitor.xhtml";
|
||||
const webConsoleUrl = "chrome://devtools/content/webconsole/webconsole.xhtml";
|
||||
|
||||
while (doc instanceof XULDocument ||
|
||||
doc.location.href === inspectorUrl ||
|
||||
doc.location.href === netMonitorUrl ||
|
||||
doc.location.href === webConsoleUrl) {
|
||||
const {frameElement} = doc.defaultView;
|
||||
|
||||
if (!frameElement) {
|
||||
// We're at the root element, and no toolbox was found.
|
||||
return null;
|
||||
}
|
||||
|
||||
doc = frameElement.parentElement.ownerDocument;
|
||||
if (doc.documentURI === "about:devtools-toolbox") {
|
||||
return doc;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* When accessing proxied functions, the instance becomes unbound to the method. This
|
||||
* utility either passes a value through if it's not a function, or automatically binds a
|
||||
* function and caches that bound function for repeated calls.
|
||||
*/
|
||||
function functionLazyBinder() {
|
||||
const boundFunctions = {};
|
||||
|
||||
return (target, name) => {
|
||||
if (typeof target[name] === "function") {
|
||||
// Lazily cache function bindings.
|
||||
if (boundFunctions[name]) {
|
||||
return boundFunctions[name];
|
||||
}
|
||||
boundFunctions[name] = target[name].bind(target);
|
||||
return boundFunctions[name];
|
||||
}
|
||||
return target[name];
|
||||
};
|
||||
}
|
||||
|
||||
// END MONKEY PATCH
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
ReactDOM = monkeyPatchReactDOM(ReactDOM);
|
||||
|
||||
var ReactDOM$2 = Object.freeze({
|
||||
default: ReactDOM
|
||||
});
|
||||
```
|
||||
|
163
devtools/client/shared/vendor/react-dom-dev.js
vendored
163
devtools/client/shared/vendor/react-dom-dev.js
vendored
@ -16051,169 +16051,6 @@ var foundDevTools = DOMRenderer.injectIntoDevTools({
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// START MONKEY PATCH
|
||||
/**
|
||||
* This section contains a monkey patch for React DOM, so that it functions correctly in
|
||||
* certain XUL situations. React centralizes events to specific DOM nodes by only
|
||||
* binding a single listener to the document of the page. It then captures these events,
|
||||
* and then uses a SyntheticEvent system to dispatch these throughout the page.
|
||||
*
|
||||
* In privileged XUL with a XUL iframe, and React in both documents, this system breaks.
|
||||
* By design, these XUL frames can still talk to each other, while in a normal HTML
|
||||
* situation, they would not be able to. The events from the XUL iframe propagate to the
|
||||
* parent document as well. This leads to the React event system incorrectly dispatching
|
||||
* TWO SyntheticEvents for for every ONE action.
|
||||
*
|
||||
* The fix here is trick React into thinking that the owning document for every node in
|
||||
* a XUL iframe to be the toolbox.xul. This is done by creating a Proxy object that
|
||||
* captures any usage of HTMLElement.ownerDocument, and then passing in the toolbox.xul
|
||||
* document rather than (for example) the netmonitor.xul document. React will then hook
|
||||
* up the event system correctly on the top level controlling document.
|
||||
*
|
||||
* @return {object} The proxied and monkey patched ReactDOM
|
||||
*/
|
||||
function monkeyPatchReactDOM(ReactDOM) {
|
||||
// This is the actual monkey patched function.
|
||||
const reactDomRender = monkeyPatchRender(ReactDOM);
|
||||
|
||||
// Proxied method calls might need to be bound, but do this lazily with caching.
|
||||
const lazyFunctionBinding = functionLazyBinder();
|
||||
|
||||
// Create a proxy, but the render property is not writable on the ReactDOM object, so
|
||||
// a direct proxy will fail with an error. Instead, create a proxy on a a blank object.
|
||||
// Pass on getting and setting behaviors.
|
||||
return new Proxy({}, {
|
||||
get: (target, name) => {
|
||||
if (name === "render") {
|
||||
return reactDomRender;
|
||||
}
|
||||
return lazyFunctionBinding(ReactDOM, name);
|
||||
},
|
||||
set: (target, name, value) => {
|
||||
ReactDOM[name] = value;
|
||||
return true;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a function that replaces the ReactDOM.render method. It does this by
|
||||
* creating a proxy for the dom node being mounted. This proxy rewrites the
|
||||
* "ownerDocument" property to point to the toolbox.xul document. This function
|
||||
* is only used for XUL iframes inside of a XUL document.
|
||||
*
|
||||
* @param {object} ReactDOM
|
||||
* @return {function} The patched ReactDOM.render function.
|
||||
*/
|
||||
function monkeyPatchRender(ReactDOM) {
|
||||
const elementProxyCache = new WeakMap();
|
||||
|
||||
return (...args) => {
|
||||
const container = args[1];
|
||||
const toolboxDoc = getToolboxDocIfXulOnly(container);
|
||||
|
||||
if (toolboxDoc) {
|
||||
// Re-use any existing cached HTMLElement proxies.
|
||||
let proxy = elementProxyCache.get(container);
|
||||
|
||||
if (!proxy) {
|
||||
// Proxied method calls need to be bound, but do this lazily.
|
||||
const lazyFunctionBinding = functionLazyBinder();
|
||||
|
||||
// Create a proxy to the container HTMLElement. If React tries to access the
|
||||
// ownerDocument, pass in the toolbox's document, as the event dispatching system
|
||||
// is rooted from the toolbox document.
|
||||
proxy = new Proxy(container, {
|
||||
get: function (target, name) {
|
||||
if (name === "ownerDocument") {
|
||||
return toolboxDoc;
|
||||
}
|
||||
return lazyFunctionBinding(target, name);
|
||||
}
|
||||
});
|
||||
|
||||
elementProxyCache.set(container, proxy);
|
||||
}
|
||||
|
||||
// Update the args passed to ReactDOM.render.
|
||||
args[1] = proxy;
|
||||
}
|
||||
|
||||
return ReactDOM.render.apply(this, args);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to access the containing toolbox XUL document, but only if all of the iframes
|
||||
* in the heirarchy are XUL documents. Events dispatch differently in the case of all
|
||||
* privileged XUL documents. Events that fire in an iframe propagate up to the parent
|
||||
* frame. This does not happen when HTML is in the mix. Only return the toolbox if
|
||||
* it matches the proper case of a XUL iframe inside of a XUL document.
|
||||
*
|
||||
* In addition to the XUL case, if the panel uses the toolbox's ReactDOM instance,
|
||||
* this patch needs to be applied as well. This is the case for the inspector.
|
||||
*
|
||||
* @param {HTMLElement} node - The DOM node inside of an iframe.
|
||||
* @return {XULDocument|null} The toolbox.xul document, or null.
|
||||
*/
|
||||
function getToolboxDocIfXulOnly(node) {
|
||||
// This execution context doesn't know about XULDocuments, so don't get the toolbox.
|
||||
if (typeof XULDocument !== "function") {
|
||||
return null;
|
||||
}
|
||||
|
||||
let doc = node.ownerDocument;
|
||||
const inspectorUrl = "chrome://devtools/content/inspector/inspector.xhtml";
|
||||
const netMonitorUrl = "chrome://devtools/content/netmonitor/netmonitor.xhtml";
|
||||
const webConsoleUrl = "chrome://devtools/content/webconsole/webconsole.xhtml";
|
||||
|
||||
while (doc instanceof XULDocument ||
|
||||
doc.location.href === inspectorUrl ||
|
||||
doc.location.href === netMonitorUrl ||
|
||||
doc.location.href === webConsoleUrl) {
|
||||
const {frameElement} = doc.defaultView;
|
||||
|
||||
if (!frameElement) {
|
||||
// We're at the root element, and no toolbox was found.
|
||||
return null;
|
||||
}
|
||||
|
||||
doc = frameElement.parentElement.ownerDocument;
|
||||
if (doc.documentURI === "about:devtools-toolbox") {
|
||||
return doc;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* When accessing proxied functions, the instance becomes unbound to the method. This
|
||||
* utility either passes a value through if it's not a function, or automatically binds a
|
||||
* function and caches that bound function for repeated calls.
|
||||
*/
|
||||
function functionLazyBinder() {
|
||||
const boundFunctions = {};
|
||||
|
||||
return (target, name) => {
|
||||
if (typeof target[name] === "function") {
|
||||
// Lazily cache function bindings.
|
||||
if (boundFunctions[name]) {
|
||||
return boundFunctions[name];
|
||||
}
|
||||
boundFunctions[name] = target[name].bind(target);
|
||||
return boundFunctions[name];
|
||||
}
|
||||
return target[name];
|
||||
};
|
||||
}
|
||||
|
||||
// END MONKEY PATCH
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
ReactDOM = monkeyPatchReactDOM(ReactDOM);
|
||||
|
||||
var ReactDOM$2 = Object.freeze({
|
||||
default: ReactDOM
|
||||
});
|
||||
|
163
devtools/client/shared/vendor/react-dom.js
vendored
163
devtools/client/shared/vendor/react-dom.js
vendored
@ -12918,169 +12918,6 @@ var foundDevTools = DOMRenderer.injectIntoDevTools({
|
||||
rendererPackageName: 'react-dom'
|
||||
});
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// START MONKEY PATCH
|
||||
/**
|
||||
* This section contains a monkey patch for React DOM, so that it functions correctly in
|
||||
* certain XUL situations. React centralizes events to specific DOM nodes by only
|
||||
* binding a single listener to the document of the page. It then captures these events,
|
||||
* and then uses a SyntheticEvent system to dispatch these throughout the page.
|
||||
*
|
||||
* In privileged XUL with a XUL iframe, and React in both documents, this system breaks.
|
||||
* By design, these XUL frames can still talk to each other, while in a normal HTML
|
||||
* situation, they would not be able to. The events from the XUL iframe propagate to the
|
||||
* parent document as well. This leads to the React event system incorrectly dispatching
|
||||
* TWO SyntheticEvents for for every ONE action.
|
||||
*
|
||||
* The fix here is trick React into thinking that the owning document for every node in
|
||||
* a XUL iframe to be the toolbox.xul. This is done by creating a Proxy object that
|
||||
* captures any usage of HTMLElement.ownerDocument, and then passing in the toolbox.xul
|
||||
* document rather than (for example) the netmonitor.xul document. React will then hook
|
||||
* up the event system correctly on the top level controlling document.
|
||||
*
|
||||
* @return {object} The proxied and monkey patched ReactDOM
|
||||
*/
|
||||
function monkeyPatchReactDOM(ReactDOM) {
|
||||
// This is the actual monkey patched function.
|
||||
const reactDomRender = monkeyPatchRender(ReactDOM);
|
||||
|
||||
// Proxied method calls might need to be bound, but do this lazily with caching.
|
||||
const lazyFunctionBinding = functionLazyBinder();
|
||||
|
||||
// Create a proxy, but the render property is not writable on the ReactDOM object, so
|
||||
// a direct proxy will fail with an error. Instead, create a proxy on a a blank object.
|
||||
// Pass on getting and setting behaviors.
|
||||
return new Proxy({}, {
|
||||
get: (target, name) => {
|
||||
if (name === "render") {
|
||||
return reactDomRender;
|
||||
}
|
||||
return lazyFunctionBinding(ReactDOM, name);
|
||||
},
|
||||
set: (target, name, value) => {
|
||||
ReactDOM[name] = value;
|
||||
return true;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a function that replaces the ReactDOM.render method. It does this by
|
||||
* creating a proxy for the dom node being mounted. This proxy rewrites the
|
||||
* "ownerDocument" property to point to the toolbox.xul document. This function
|
||||
* is only used for XUL iframes inside of a XUL document.
|
||||
*
|
||||
* @param {object} ReactDOM
|
||||
* @return {function} The patched ReactDOM.render function.
|
||||
*/
|
||||
function monkeyPatchRender(ReactDOM) {
|
||||
const elementProxyCache = new WeakMap();
|
||||
|
||||
return (...args) => {
|
||||
const container = args[1];
|
||||
const toolboxDoc = getToolboxDocIfXulOnly(container);
|
||||
|
||||
if (toolboxDoc) {
|
||||
// Re-use any existing cached HTMLElement proxies.
|
||||
let proxy = elementProxyCache.get(container);
|
||||
|
||||
if (!proxy) {
|
||||
// Proxied method calls need to be bound, but do this lazily.
|
||||
const lazyFunctionBinding = functionLazyBinder();
|
||||
|
||||
// Create a proxy to the container HTMLElement. If React tries to access the
|
||||
// ownerDocument, pass in the toolbox's document, as the event dispatching system
|
||||
// is rooted from the toolbox document.
|
||||
proxy = new Proxy(container, {
|
||||
get: function (target, name) {
|
||||
if (name === "ownerDocument") {
|
||||
return toolboxDoc;
|
||||
}
|
||||
return lazyFunctionBinding(target, name);
|
||||
}
|
||||
});
|
||||
|
||||
elementProxyCache.set(container, proxy);
|
||||
}
|
||||
|
||||
// Update the args passed to ReactDOM.render.
|
||||
args[1] = proxy;
|
||||
}
|
||||
|
||||
return ReactDOM.render.apply(this, args);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to access the containing toolbox XUL document, but only if all of the iframes
|
||||
* in the heirarchy are XUL documents. Events dispatch differently in the case of all
|
||||
* privileged XUL documents. Events that fire in an iframe propagate up to the parent
|
||||
* frame. This does not happen when HTML is in the mix. Only return the toolbox if
|
||||
* it matches the proper case of a XUL iframe inside of a XUL document.
|
||||
*
|
||||
* In addition to the XUL case, if the panel uses the toolbox's ReactDOM instance,
|
||||
* this patch needs to be applied as well. This is the case for the inspector.
|
||||
*
|
||||
* @param {HTMLElement} node - The DOM node inside of an iframe.
|
||||
* @return {XULDocument|null} The toolbox.xul document, or null.
|
||||
*/
|
||||
function getToolboxDocIfXulOnly(node) {
|
||||
// This execution context doesn't know about XULDocuments, so don't get the toolbox.
|
||||
if (typeof XULDocument !== "function") {
|
||||
return null;
|
||||
}
|
||||
|
||||
let doc = node.ownerDocument;
|
||||
const inspectorUrl = "chrome://devtools/content/inspector/inspector.xhtml";
|
||||
const netMonitorUrl = "chrome://devtools/content/netmonitor/netmonitor.xhtml";
|
||||
const webConsoleUrl = "chrome://devtools/content/webconsole/webconsole.xhtml";
|
||||
|
||||
while (doc instanceof XULDocument ||
|
||||
doc.location.href === inspectorUrl ||
|
||||
doc.location.href === netMonitorUrl ||
|
||||
doc.location.href === webConsoleUrl) {
|
||||
const {frameElement} = doc.defaultView;
|
||||
|
||||
if (!frameElement) {
|
||||
// We're at the root element, and no toolbox was found.
|
||||
return null;
|
||||
}
|
||||
|
||||
doc = frameElement.parentElement.ownerDocument;
|
||||
if (doc.documentURI === "about:devtools-toolbox") {
|
||||
return doc;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* When accessing proxied functions, the instance becomes unbound to the method. This
|
||||
* utility either passes a value through if it's not a function, or automatically binds a
|
||||
* function and caches that bound function for repeated calls.
|
||||
*/
|
||||
function functionLazyBinder() {
|
||||
const boundFunctions = {};
|
||||
|
||||
return (target, name) => {
|
||||
if (typeof target[name] === "function") {
|
||||
// Lazily cache function bindings.
|
||||
if (boundFunctions[name]) {
|
||||
return boundFunctions[name];
|
||||
}
|
||||
boundFunctions[name] = target[name].bind(target);
|
||||
return boundFunctions[name];
|
||||
}
|
||||
return target[name];
|
||||
};
|
||||
}
|
||||
|
||||
// END MONKEY PATCH
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
ReactDOM = monkeyPatchReactDOM(ReactDOM);
|
||||
|
||||
var ReactDOM$2 = Object.freeze({
|
||||
default: ReactDOM
|
||||
});
|
||||
|
@ -162,6 +162,7 @@ skip-if = (e10s && (os == 'win' || os == 'mac')) # Bug 1243976
|
||||
[browser_console.js]
|
||||
[browser_console_addonsdk_loader_exception.js]
|
||||
[browser_console_certificate_imminent_distrust.js]
|
||||
disabled=bug 1439378 to re-enable due to nss cert/key db upgrade issue
|
||||
[browser_console_clear_method.js]
|
||||
[browser_console_clear_on_reload.js]
|
||||
[browser_console_click_focus.js]
|
||||
|
@ -152,8 +152,9 @@ this.DevToolsShim = {
|
||||
return;
|
||||
}
|
||||
|
||||
let {scratchpads, browserConsole} = session;
|
||||
let hasDevToolsData = browserConsole || (scratchpads && scratchpads.length);
|
||||
let {scratchpads, browserConsole, browserToolbox} = session;
|
||||
let hasDevToolsData = browserConsole || browserToolbox ||
|
||||
(scratchpads && scratchpads.length);
|
||||
if (!hasDevToolsData) {
|
||||
// Do not initialize DevTools unless there is DevTools specific data in the session.
|
||||
return;
|
||||
|
@ -35,7 +35,6 @@
|
||||
#include "nsIDOMFileList.h"
|
||||
#include "nsIDOMMouseEvent.h"
|
||||
#include "nsIFormControl.h"
|
||||
#include "nsIDOMHTMLInputElement.h"
|
||||
#include "nsIImageLoadingContent.h"
|
||||
#include "nsIWebNavigation.h"
|
||||
#include "nsIPresShell.h"
|
||||
|
@ -1126,9 +1126,6 @@ waitForAllPaints(() => {
|
||||
|
||||
div.style.display = '';
|
||||
|
||||
// We need to wait a frame to unapply display:none style.
|
||||
await waitForNextFrame();
|
||||
|
||||
var markers = await observeStyling(5);
|
||||
is(markers.length, 5,
|
||||
'Script animations restored from "display: none" state should update ' +
|
||||
@ -1163,12 +1160,14 @@ waitForAllPaints(() => {
|
||||
|
||||
div.style.display = '';
|
||||
|
||||
// We need to wait a frame to unapply display:none style.
|
||||
await waitForNextFrame();
|
||||
var markers = await observeStyling(1);
|
||||
is(markers.length, 1,
|
||||
'Script animations restored from "display: none" state should update ' +
|
||||
'styles soon');
|
||||
|
||||
ok(SpecialPowers.wrap(animation).isRunningOnCompositor,
|
||||
'Opacity script animations restored from "display: none" should be ' +
|
||||
'run on the compositor');
|
||||
'run on the compositor in the next frame');
|
||||
|
||||
await ensureElementRemoval(div);
|
||||
});
|
||||
|
@ -135,7 +135,6 @@
|
||||
#include "nsIDOMDocumentType.h"
|
||||
#include "nsIDOMElement.h"
|
||||
#include "nsIDOMHTMLFormElement.h"
|
||||
#include "nsIDOMHTMLInputElement.h"
|
||||
#include "nsIDOMNode.h"
|
||||
#include "nsIDOMNodeList.h"
|
||||
#include "nsIDOMWindowUtils.h"
|
||||
@ -1060,7 +1059,7 @@ nsContentUtils::Atob(const nsAString& aAsciiBase64String,
|
||||
}
|
||||
|
||||
bool
|
||||
nsContentUtils::IsAutocompleteEnabled(nsIDOMHTMLInputElement* aInput)
|
||||
nsContentUtils::IsAutocompleteEnabled(mozilla::dom::HTMLInputElement* aInput)
|
||||
{
|
||||
NS_PRECONDITION(aInput, "aInput should not be null!");
|
||||
|
||||
@ -1068,8 +1067,7 @@ nsContentUtils::IsAutocompleteEnabled(nsIDOMHTMLInputElement* aInput)
|
||||
aInput->GetAutocomplete(autocomplete);
|
||||
|
||||
if (autocomplete.IsEmpty()) {
|
||||
nsCOMPtr<nsIDOMHTMLFormElement> form;
|
||||
aInput->GetForm(getter_AddRefs(form));
|
||||
auto* form = aInput->GetForm();
|
||||
if (!form) {
|
||||
return true;
|
||||
}
|
||||
|
@ -73,7 +73,6 @@ class nsIDocumentLoaderFactory;
|
||||
class nsIDOMDocument;
|
||||
class nsIDOMDocumentFragment;
|
||||
class nsIDOMEvent;
|
||||
class nsIDOMHTMLInputElement;
|
||||
class nsIDOMNode;
|
||||
class nsIDragSession;
|
||||
class nsIEventTarget;
|
||||
@ -135,6 +134,7 @@ struct CustomElementDefinition;
|
||||
class DocumentFragment;
|
||||
class Element;
|
||||
class EventTarget;
|
||||
class HTMLInputElement;
|
||||
class IPCDataTransfer;
|
||||
class IPCDataTransferItem;
|
||||
struct LifecycleCallbackArgs;
|
||||
@ -2634,7 +2634,7 @@ public:
|
||||
* @param aInput the input element to check. NOTE: aInput can't be null.
|
||||
* @return whether the input element has autocomplete enabled.
|
||||
*/
|
||||
static bool IsAutocompleteEnabled(nsIDOMHTMLInputElement* aInput);
|
||||
static bool IsAutocompleteEnabled(mozilla::dom::HTMLInputElement* aInput);
|
||||
|
||||
enum AutocompleteAttrState : uint8_t
|
||||
{
|
||||
|
@ -115,7 +115,6 @@
|
||||
#include "nsFocusManager.h"
|
||||
|
||||
// for radio group stuff
|
||||
#include "nsIDOMHTMLInputElement.h"
|
||||
#include "nsIRadioVisitor.h"
|
||||
#include "nsIFormControl.h"
|
||||
|
||||
|
@ -18,13 +18,13 @@
|
||||
#include "nsGlobalWindow.h"
|
||||
#include "nsFocusManager.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsIDOMHTMLInputElement.h"
|
||||
#include "nsIControllers.h"
|
||||
#include "nsIController.h"
|
||||
#include "xpcpublic.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "mozilla/dom/TabParent.h"
|
||||
#include "mozilla/dom/HTMLTextAreaElement.h"
|
||||
#include "mozilla/dom/HTMLInputElement.h"
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
#include "nsXULElement.h"
|
||||
@ -238,8 +238,8 @@ nsWindowRoot::GetControllers(bool aForVisibleWindow,
|
||||
if (htmlTextArea)
|
||||
return htmlTextArea->GetControllers(aResult);
|
||||
|
||||
nsCOMPtr<nsIDOMHTMLInputElement> htmlInputElement =
|
||||
do_QueryInterface(focusedContent);
|
||||
HTMLInputElement* htmlInputElement =
|
||||
HTMLInputElement::FromContent(focusedContent);
|
||||
if (htmlInputElement)
|
||||
return htmlInputElement->GetControllers(aResult);
|
||||
|
||||
|
@ -5562,7 +5562,7 @@ CanvasRenderingContext2D::DrawWindow(nsGlobalWindowInner& aWindow, double aX,
|
||||
}
|
||||
|
||||
// Flush layout updates
|
||||
if (!(aFlags & nsIDOMCanvasRenderingContext2D::DRAWWINDOW_DO_NOT_FLUSH)) {
|
||||
if (!(aFlags & CanvasRenderingContext2DBinding::DRAWWINDOW_DO_NOT_FLUSH)) {
|
||||
nsContentUtils::FlushLayoutForTree(aWindow.AsInner()->GetOuterWindow());
|
||||
}
|
||||
|
||||
@ -5597,20 +5597,20 @@ CanvasRenderingContext2D::DrawWindow(nsGlobalWindowInner& aWindow, double aX,
|
||||
nsPresContext::CSSPixelsToAppUnits((float)aH));
|
||||
uint32_t renderDocFlags = (nsIPresShell::RENDER_IGNORE_VIEWPORT_SCROLLING |
|
||||
nsIPresShell::RENDER_DOCUMENT_RELATIVE);
|
||||
if (aFlags & nsIDOMCanvasRenderingContext2D::DRAWWINDOW_DRAW_CARET) {
|
||||
if (aFlags & CanvasRenderingContext2DBinding::DRAWWINDOW_DRAW_CARET) {
|
||||
renderDocFlags |= nsIPresShell::RENDER_CARET;
|
||||
}
|
||||
if (aFlags & nsIDOMCanvasRenderingContext2D::DRAWWINDOW_DRAW_VIEW) {
|
||||
if (aFlags & CanvasRenderingContext2DBinding::DRAWWINDOW_DRAW_VIEW) {
|
||||
renderDocFlags &= ~(nsIPresShell::RENDER_IGNORE_VIEWPORT_SCROLLING |
|
||||
nsIPresShell::RENDER_DOCUMENT_RELATIVE);
|
||||
}
|
||||
if (aFlags & nsIDOMCanvasRenderingContext2D::DRAWWINDOW_USE_WIDGET_LAYERS) {
|
||||
if (aFlags & CanvasRenderingContext2DBinding::DRAWWINDOW_USE_WIDGET_LAYERS) {
|
||||
renderDocFlags |= nsIPresShell::RENDER_USE_WIDGET_LAYERS;
|
||||
}
|
||||
if (aFlags & nsIDOMCanvasRenderingContext2D::DRAWWINDOW_ASYNC_DECODE_IMAGES) {
|
||||
if (aFlags & CanvasRenderingContext2DBinding::DRAWWINDOW_ASYNC_DECODE_IMAGES) {
|
||||
renderDocFlags |= nsIPresShell::RENDER_ASYNC_DECODE_IMAGES;
|
||||
}
|
||||
if (aFlags & nsIDOMCanvasRenderingContext2D::DRAWWINDOW_DO_NOT_FLUSH) {
|
||||
if (aFlags & CanvasRenderingContext2DBinding::DRAWWINDOW_DO_NOT_FLUSH) {
|
||||
renderDocFlags |= nsIPresShell::RENDER_DRAWWINDOW_NOT_FLUSHING;
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,6 @@
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include <vector>
|
||||
#include "nsIDOMCanvasRenderingContext2D.h"
|
||||
#include "nsICanvasRenderingContextInternal.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "nsColor.h"
|
||||
|
@ -9,7 +9,6 @@
|
||||
#include "nsIServiceManager.h"
|
||||
|
||||
#include "nsIConsoleService.h"
|
||||
#include "nsIDOMCanvasRenderingContext2D.h"
|
||||
#include "nsICanvasRenderingContextInternal.h"
|
||||
#include "nsIHTMLCollection.h"
|
||||
#include "mozilla/dom/HTMLCanvasElement.h"
|
||||
|
@ -7,8 +7,6 @@
|
||||
#ifndef mozilla_dom_ImageData_h
|
||||
#define mozilla_dom_ImageData_h
|
||||
|
||||
#include "nsIDOMCanvasRenderingContext2D.h"
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/dom/BindingUtils.h"
|
||||
#include "mozilla/dom/TypedArray.h"
|
||||
|
@ -1637,7 +1637,7 @@ HTMLFormElement::GetActionURL(nsIURI** aActionURL,
|
||||
"The originating element must be a submit form control!");
|
||||
#endif // DEBUG
|
||||
|
||||
nsCOMPtr<nsIDOMHTMLInputElement> inputElement = do_QueryInterface(aOriginatingElement);
|
||||
HTMLInputElement* inputElement = HTMLInputElement::FromContent(aOriginatingElement);
|
||||
if (inputElement) {
|
||||
inputElement->GetFormAction(action);
|
||||
} else {
|
||||
|
@ -18,7 +18,6 @@
|
||||
#include "nsAttrValueInlines.h"
|
||||
#include "nsCRTGlue.h"
|
||||
|
||||
#include "nsIDOMHTMLInputElement.h"
|
||||
#include "nsITextControlElement.h"
|
||||
#include "nsIDOMNSEditableElement.h"
|
||||
#include "nsIRadioVisitor.h"
|
||||
@ -258,13 +257,13 @@ public:
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
rv = nsContentUtils::DispatchTrustedEvent(mInputElement->OwnerDoc(),
|
||||
static_cast<nsIDOMHTMLInputElement*>(mInputElement.get()),
|
||||
static_cast<Element*>(mInputElement.get()),
|
||||
NS_LITERAL_STRING("input"), true,
|
||||
false);
|
||||
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "DispatchTrustedEvent failed");
|
||||
|
||||
rv = nsContentUtils::DispatchTrustedEvent(mInputElement->OwnerDoc(),
|
||||
static_cast<nsIDOMHTMLInputElement*>(mInputElement.get()),
|
||||
static_cast<Element*>(mInputElement.get()),
|
||||
NS_LITERAL_STRING("change"), true,
|
||||
false);
|
||||
|
||||
@ -760,7 +759,7 @@ nsColorPickerShownCallback::UpdateInternal(const nsAString& aColor,
|
||||
if (valueChanged) {
|
||||
mValueChanged = true;
|
||||
return nsContentUtils::DispatchTrustedEvent(mInput->OwnerDoc(),
|
||||
static_cast<nsIDOMHTMLInputElement*>(mInput.get()),
|
||||
static_cast<Element*>(mInput.get()),
|
||||
NS_LITERAL_STRING("input"), true,
|
||||
false);
|
||||
}
|
||||
@ -794,7 +793,7 @@ nsColorPickerShownCallback::Done(const nsAString& aColor)
|
||||
|
||||
if (mValueChanged) {
|
||||
rv = nsContentUtils::DispatchTrustedEvent(mInput->OwnerDoc(),
|
||||
static_cast<nsIDOMHTMLInputElement*>(mInput.get()),
|
||||
static_cast<Element*>(mInput.get()),
|
||||
NS_LITERAL_STRING("change"), true,
|
||||
false);
|
||||
}
|
||||
@ -1086,7 +1085,7 @@ UploadLastDir::Observe(nsISupports* aSubject, char const* aTopic, char16_t const
|
||||
|
||||
#ifdef ACCESSIBILITY
|
||||
//Helper method
|
||||
static nsresult FireEventForAccessibility(nsIDOMHTMLInputElement* aTarget,
|
||||
static nsresult FireEventForAccessibility(HTMLInputElement* aTarget,
|
||||
nsPresContext* aPresContext,
|
||||
EventMessage aEventMessage);
|
||||
#endif
|
||||
@ -1548,23 +1547,11 @@ HTMLInputElement::AfterClearForm(bool aUnbindOrDelete)
|
||||
}
|
||||
}
|
||||
|
||||
// nsIDOMHTMLInputElement
|
||||
|
||||
NS_IMETHODIMP
|
||||
HTMLInputElement::GetForm(nsIDOMHTMLFormElement** aForm)
|
||||
{
|
||||
return nsGenericHTMLFormElementWithState::GetForm(aForm);
|
||||
}
|
||||
|
||||
NS_IMPL_ACTION_ATTR(HTMLInputElement, FormAction, formaction)
|
||||
NS_IMPL_STRING_ATTR(HTMLInputElement, Name, name)
|
||||
NS_IMPL_BOOL_ATTR(HTMLInputElement, ReadOnly, readonly)
|
||||
|
||||
NS_IMETHODIMP
|
||||
void
|
||||
HTMLInputElement::GetAutocomplete(nsAString& aValue)
|
||||
{
|
||||
if (!DoesAutocompleteApply()) {
|
||||
return NS_OK;
|
||||
return;
|
||||
}
|
||||
|
||||
aValue.Truncate();
|
||||
@ -1573,7 +1560,6 @@ HTMLInputElement::GetAutocomplete(nsAString& aValue)
|
||||
mAutocompleteAttrState =
|
||||
nsContentUtils::SerializeAutocompleteAttribute(attributeVal, aValue,
|
||||
mAutocompleteAttrState);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
@ -1630,13 +1616,6 @@ HTMLInputElement::Height()
|
||||
return GetWidthHeightForImage(mCurrentRequest).height;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HTMLInputElement::GetIndeterminate(bool* aValue)
|
||||
{
|
||||
*aValue = Indeterminate();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
HTMLInputElement::SetIndeterminateInternal(bool aValue,
|
||||
bool aShouldInvalidate)
|
||||
@ -1653,11 +1632,10 @@ HTMLInputElement::SetIndeterminateInternal(bool aValue,
|
||||
UpdateState(true);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
void
|
||||
HTMLInputElement::SetIndeterminate(bool aValue)
|
||||
{
|
||||
SetIndeterminateInternal(aValue, true);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
@ -2408,7 +2386,7 @@ HTMLInputElement::OpenDateTimePicker(const DateTimeValue& aInitialValue)
|
||||
|
||||
mDateTimeInputBoxValue = new DateTimeValue(aInitialValue);
|
||||
nsContentUtils::DispatchChromeEvent(OwnerDoc(),
|
||||
static_cast<nsIDOMHTMLInputElement*>(this),
|
||||
static_cast<Element*>(this),
|
||||
NS_LITERAL_STRING("MozOpenDateTimePicker"),
|
||||
true, true);
|
||||
}
|
||||
@ -2422,7 +2400,7 @@ HTMLInputElement::UpdateDateTimePicker(const DateTimeValue& aValue)
|
||||
|
||||
mDateTimeInputBoxValue = new DateTimeValue(aValue);
|
||||
nsContentUtils::DispatchChromeEvent(OwnerDoc(),
|
||||
static_cast<nsIDOMHTMLInputElement*>(this),
|
||||
static_cast<Element*>(this),
|
||||
NS_LITERAL_STRING("MozUpdateDateTimePicker"),
|
||||
true, true);
|
||||
}
|
||||
@ -2435,7 +2413,7 @@ HTMLInputElement::CloseDateTimePicker()
|
||||
}
|
||||
|
||||
nsContentUtils::DispatchChromeEvent(OwnerDoc(),
|
||||
static_cast<nsIDOMHTMLInputElement*>(this),
|
||||
static_cast<Element*>(this),
|
||||
NS_LITERAL_STRING("MozCloseDateTimePicker"),
|
||||
true, true);
|
||||
}
|
||||
@ -2529,7 +2507,7 @@ HTMLInputElement::SetUserInput(const nsAString& aValue)
|
||||
}
|
||||
|
||||
nsContentUtils::DispatchTrustedEvent(OwnerDoc(),
|
||||
static_cast<nsIDOMHTMLInputElement*>(this),
|
||||
static_cast<Element*>(this),
|
||||
NS_LITERAL_STRING("input"), true,
|
||||
true);
|
||||
|
||||
@ -3110,13 +3088,6 @@ HTMLInputElement::SetValueChanged(bool aValueChanged)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HTMLInputElement::GetChecked(bool* aChecked)
|
||||
{
|
||||
*aChecked = Checked();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
HTMLInputElement::SetCheckedChanged(bool aCheckedChanged)
|
||||
{
|
||||
@ -3152,11 +3123,10 @@ HTMLInputElement::SetCheckedChangedInternal(bool aCheckedChanged)
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
void
|
||||
HTMLInputElement::SetChecked(bool aChecked)
|
||||
{
|
||||
DoSetChecked(aChecked, true, true);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
@ -3205,14 +3175,13 @@ void
|
||||
HTMLInputElement::RadioSetChecked(bool aNotify)
|
||||
{
|
||||
// Find the selected radio button so we can deselect it
|
||||
nsCOMPtr<nsIDOMHTMLInputElement> currentlySelected = GetSelectedRadioButton();
|
||||
HTMLInputElement* currentlySelected = GetSelectedRadioButton();
|
||||
|
||||
// Deselect the currently selected radio button
|
||||
if (currentlySelected) {
|
||||
// Pass true for the aNotify parameter since the currently selected
|
||||
// button is already in the document.
|
||||
static_cast<HTMLInputElement*>(currentlySelected.get())
|
||||
->SetCheckedInternal(false, true);
|
||||
currentlySelected->SetCheckedInternal(false, true);
|
||||
}
|
||||
|
||||
// Let the group know that we are now the One True Radio Button
|
||||
@ -3249,7 +3218,7 @@ HTMLInputElement::GetRadioGroupContainer() const
|
||||
return static_cast<nsDocument*>(GetUncomposedDoc());
|
||||
}
|
||||
|
||||
already_AddRefed<nsIDOMHTMLInputElement>
|
||||
HTMLInputElement*
|
||||
HTMLInputElement::GetSelectedRadioButton() const
|
||||
{
|
||||
nsIRadioGroupContainer* container = GetRadioGroupContainer();
|
||||
@ -3260,8 +3229,8 @@ HTMLInputElement::GetSelectedRadioButton() const
|
||||
nsAutoString name;
|
||||
GetAttr(kNameSpaceID_None, nsGkAtoms::name, name);
|
||||
|
||||
nsCOMPtr<nsIDOMHTMLInputElement> selected = container->GetCurrentRadioButton(name);
|
||||
return selected.forget();
|
||||
HTMLInputElement* selected = container->GetCurrentRadioButton(name);
|
||||
return selected;
|
||||
}
|
||||
|
||||
nsresult
|
||||
@ -3628,7 +3597,7 @@ HTMLInputElement::GetEventTargetParent(EventChainPreVisitor& aVisitor)
|
||||
aVisitor.mItemFlags |= NS_ORIGINAL_INDETERMINATE_VALUE;
|
||||
}
|
||||
|
||||
GetChecked(&originalCheckedValue);
|
||||
originalCheckedValue = Checked();
|
||||
DoSetChecked(!originalCheckedValue, true, true);
|
||||
mCheckedIsToggled = true;
|
||||
}
|
||||
@ -3636,8 +3605,8 @@ HTMLInputElement::GetEventTargetParent(EventChainPreVisitor& aVisitor)
|
||||
|
||||
case NS_FORM_INPUT_RADIO:
|
||||
{
|
||||
nsCOMPtr<nsIDOMHTMLInputElement> selectedRadioButton = GetSelectedRadioButton();
|
||||
aVisitor.mItemData = selectedRadioButton;
|
||||
HTMLInputElement* selectedRadioButton = GetSelectedRadioButton();
|
||||
aVisitor.mItemData = static_cast<Element*>(selectedRadioButton);
|
||||
|
||||
originalCheckedValue = mChecked;
|
||||
if (!originalCheckedValue) {
|
||||
@ -3982,7 +3951,7 @@ HTMLInputElement::SetValueOfRangeForUserEvent(Decimal aValue)
|
||||
|
||||
if (GetValueAsDecimal() != oldValue) {
|
||||
nsContentUtils::DispatchTrustedEvent(OwnerDoc(),
|
||||
static_cast<nsIDOMHTMLInputElement*>(this),
|
||||
static_cast<Element*>(this),
|
||||
NS_LITERAL_STRING("input"), true,
|
||||
false);
|
||||
}
|
||||
@ -4080,7 +4049,7 @@ HTMLInputElement::StepNumberControlForUserEvent(int32_t aDirection)
|
||||
nsTextEditorState::eSetValue_Notify);
|
||||
|
||||
nsContentUtils::DispatchTrustedEvent(OwnerDoc(),
|
||||
static_cast<nsIDOMHTMLInputElement*>(this),
|
||||
static_cast<Element*>(this),
|
||||
NS_LITERAL_STRING("input"), true,
|
||||
false);
|
||||
}
|
||||
@ -4271,8 +4240,9 @@ HTMLInputElement::PostHandleEvent(EventChainPostVisitor& aVisitor)
|
||||
// selected btn to TRUE. if it is a checkbox then set it to its
|
||||
// original value
|
||||
if (oldType == NS_FORM_INPUT_RADIO) {
|
||||
nsCOMPtr<nsIDOMHTMLInputElement> selectedRadioButton =
|
||||
do_QueryInterface(aVisitor.mItemData);
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(aVisitor.mItemData);
|
||||
HTMLInputElement* selectedRadioButton =
|
||||
HTMLInputElement::FromContentOrNull(content);
|
||||
if (selectedRadioButton) {
|
||||
selectedRadioButton->SetChecked(true);
|
||||
}
|
||||
@ -4291,11 +4261,11 @@ HTMLInputElement::PostHandleEvent(EventChainPostVisitor& aVisitor)
|
||||
} else {
|
||||
// Fire input event and then change event.
|
||||
nsContentUtils::DispatchTrustedEvent<InternalEditorInputEvent>
|
||||
(OwnerDoc(), static_cast<nsIDOMHTMLInputElement*>(this),
|
||||
(OwnerDoc(), static_cast<Element*>(this),
|
||||
eEditorInput, true, false);
|
||||
|
||||
nsContentUtils::DispatchTrustedEvent<WidgetEvent>
|
||||
(OwnerDoc(), static_cast<nsIDOMHTMLInputElement*>(this),
|
||||
(OwnerDoc(), static_cast<Element*>(this),
|
||||
eFormChange, true, false);
|
||||
#ifdef ACCESSIBILITY
|
||||
// Fire an event to notify accessibility
|
||||
@ -4306,8 +4276,9 @@ HTMLInputElement::PostHandleEvent(EventChainPostVisitor& aVisitor)
|
||||
FireEventForAccessibility(this, aVisitor.mPresContext,
|
||||
eFormRadioStateChange);
|
||||
// Fire event for the previous selected radio.
|
||||
nsCOMPtr<nsIDOMHTMLInputElement> previous =
|
||||
do_QueryInterface(aVisitor.mItemData);
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(aVisitor.mItemData);
|
||||
HTMLInputElement* previous =
|
||||
HTMLInputElement::FromContentOrNull(content);
|
||||
if (previous) {
|
||||
FireEventForAccessibility(previous, aVisitor.mPresContext,
|
||||
eFormRadioStateChange);
|
||||
@ -6022,7 +5993,7 @@ HTMLInputElement::GetControllers(ErrorResult& aRv)
|
||||
return mControllers;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsresult
|
||||
HTMLInputElement::GetControllers(nsIControllers** aResult)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aResult);
|
||||
@ -6216,13 +6187,13 @@ HTMLInputElement::SetSelectionDirection(const nsAString& aDirection, ErrorResult
|
||||
|
||||
#ifdef ACCESSIBILITY
|
||||
/*static*/ nsresult
|
||||
FireEventForAccessibility(nsIDOMHTMLInputElement* aTarget,
|
||||
FireEventForAccessibility(HTMLInputElement* aTarget,
|
||||
nsPresContext* aPresContext,
|
||||
EventMessage aEventMessage)
|
||||
{
|
||||
nsCOMPtr<mozilla::dom::Element> element = do_QueryInterface(aTarget);
|
||||
Element* element = static_cast<Element*>(aTarget);
|
||||
return nsContentUtils::DispatchTrustedEvent<WidgetEvent>
|
||||
(element->OwnerDoc(), aTarget, aEventMessage, true, true);
|
||||
(element->OwnerDoc(), element, aEventMessage, true, true);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -6526,7 +6497,7 @@ HTMLInputElement::IntrinsicState() const
|
||||
}
|
||||
|
||||
if (mType == NS_FORM_INPUT_RADIO) {
|
||||
nsCOMPtr<nsIDOMHTMLInputElement> selected = GetSelectedRadioButton();
|
||||
HTMLInputElement* selected = GetSelectedRadioButton();
|
||||
bool indeterminate = !selected && !mChecked;
|
||||
|
||||
if (indeterminate) {
|
||||
@ -7235,7 +7206,7 @@ HTMLInputElement::UpdateValueMissingValidityStateForRadio(bool aIgnoreSelf)
|
||||
"This should be called only for radio input types");
|
||||
|
||||
bool notify = mDoneCreating;
|
||||
nsCOMPtr<nsIDOMHTMLInputElement> selection = GetSelectedRadioButton();
|
||||
HTMLInputElement* selection = GetSelectedRadioButton();
|
||||
|
||||
aIgnoreSelf = aIgnoreSelf || !IsMutable();
|
||||
|
||||
|
@ -297,7 +297,7 @@ public:
|
||||
*
|
||||
* @return the selected button (or null).
|
||||
*/
|
||||
already_AddRefed<nsIDOMHTMLInputElement> GetSelectedRadioButton() const;
|
||||
HTMLInputElement* GetSelectedRadioButton() const;
|
||||
|
||||
virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
|
||||
bool aPreallocateChildren) const override;
|
||||
@ -482,7 +482,7 @@ public:
|
||||
SetHTMLAttr(nsGkAtoms::alt, aValue, aRv);
|
||||
}
|
||||
|
||||
// XPCOM GetAutocomplete() is OK
|
||||
void GetAutocomplete(nsAString& aValue);
|
||||
void SetAutocomplete(const nsAString& aValue, ErrorResult& aRv)
|
||||
{
|
||||
SetHTMLAttr(nsGkAtoms::autocomplete, aValue, aRv);
|
||||
@ -514,7 +514,7 @@ public:
|
||||
{
|
||||
return mChecked;
|
||||
}
|
||||
// XPCOM SetChecked() is OK
|
||||
void SetChecked(bool aChecked);
|
||||
|
||||
bool Disabled() const
|
||||
{
|
||||
@ -526,12 +526,9 @@ public:
|
||||
SetHTMLBoolAttr(nsGkAtoms::disabled, aValue, aRv);
|
||||
}
|
||||
|
||||
// XPCOM GetForm() is OK
|
||||
|
||||
FileList* GetFiles();
|
||||
void SetFiles(FileList* aFiles);
|
||||
|
||||
// XPCOM GetFormAction() is OK
|
||||
void SetFormAction(const nsAString& aValue, ErrorResult& aRv)
|
||||
{
|
||||
SetHTMLAttr(nsGkAtoms::formaction, aValue, aRv);
|
||||
@ -584,8 +581,7 @@ public:
|
||||
{
|
||||
return mIsDraggingRange;
|
||||
}
|
||||
|
||||
// XPCOM SetIndeterminate() is OK
|
||||
void SetIndeterminate(bool aValue);
|
||||
|
||||
void GetInputMode(nsAString& aValue);
|
||||
void SetInputMode(const nsAString& aValue, ErrorResult& aRv)
|
||||
@ -655,7 +651,10 @@ public:
|
||||
SetHTMLBoolAttr(nsGkAtoms::multiple, aValue, aRv);
|
||||
}
|
||||
|
||||
// XPCOM GetName() is OK
|
||||
void GetName(nsAString& aValue)
|
||||
{
|
||||
GetHTMLAttr(nsGkAtoms::name, aValue);
|
||||
}
|
||||
void SetName(const nsAString& aValue, ErrorResult& aRv)
|
||||
{
|
||||
SetHTMLAttr(nsGkAtoms::name, aValue, aRv);
|
||||
@ -860,6 +859,8 @@ public:
|
||||
}
|
||||
|
||||
nsIControllers* GetControllers(ErrorResult& aRv);
|
||||
// XPCOM adapter function widely used throughout code, leaving it as is.
|
||||
nsresult GetControllers(nsIControllers** aResult);
|
||||
|
||||
int32_t InputTextLength(CallerType aCallerType);
|
||||
|
||||
|
@ -19,7 +19,6 @@
|
||||
#include "nsContentCreatorFunctions.h"
|
||||
#include "nsTextControlFrame.h"
|
||||
#include "nsIControllers.h"
|
||||
#include "nsIDOMHTMLInputElement.h"
|
||||
#include "nsITransactionManager.h"
|
||||
#include "nsIControllerContext.h"
|
||||
#include "nsAttrValue.h"
|
||||
@ -884,7 +883,7 @@ DoCommandCallback(Command aCommand, void* aData)
|
||||
nsIContent *content = frame->GetContent();
|
||||
|
||||
nsCOMPtr<nsIControllers> controllers;
|
||||
nsCOMPtr<nsIDOMHTMLInputElement> input = do_QueryInterface(content);
|
||||
HTMLInputElement* input = HTMLInputElement::FromContent(content);
|
||||
if (input) {
|
||||
input->GetControllers(getter_AddRefs(controllers));
|
||||
} else {
|
||||
@ -1414,12 +1413,12 @@ nsTextEditorState::PrepareEditor(const nsAString *aValue)
|
||||
|
||||
if (!SuppressEventHandlers(presContext)) {
|
||||
nsCOMPtr<nsIControllers> controllers;
|
||||
nsCOMPtr<nsIDOMHTMLInputElement> inputElement =
|
||||
do_QueryInterface(mTextCtrlElement);
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(mTextCtrlElement);
|
||||
HTMLInputElement* inputElement =
|
||||
HTMLInputElement::FromContentOrNull(content);
|
||||
if (inputElement) {
|
||||
rv = inputElement->GetControllers(getter_AddRefs(controllers));
|
||||
} else {
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(mTextCtrlElement);
|
||||
HTMLTextAreaElement* textAreaElement =
|
||||
HTMLTextAreaElement::FromContentOrNull(content);
|
||||
|
||||
@ -2073,13 +2072,13 @@ nsTextEditorState::UnbindFromFrame(nsTextControlFrame* aFrame)
|
||||
if (!SuppressEventHandlers(mBoundFrame->PresContext()))
|
||||
{
|
||||
nsCOMPtr<nsIControllers> controllers;
|
||||
nsCOMPtr<nsIDOMHTMLInputElement> inputElement =
|
||||
do_QueryInterface(mTextCtrlElement);
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(mTextCtrlElement);
|
||||
HTMLInputElement* inputElement =
|
||||
HTMLInputElement::FromContentOrNull(content);
|
||||
if (inputElement)
|
||||
inputElement->GetControllers(getter_AddRefs(controllers));
|
||||
else
|
||||
{
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(mTextCtrlElement);
|
||||
HTMLTextAreaElement* textAreaElement =
|
||||
HTMLTextAreaElement::FromContentOrNull(content);
|
||||
if (textAreaElement) {
|
||||
|
@ -11,7 +11,6 @@ with Files("nsIDOMWebGLRenderingContext.idl"):
|
||||
BUG_COMPONENT = ("Core", "Canvas: WebGL")
|
||||
|
||||
XPIDL_SOURCES += [
|
||||
'nsIDOMCanvasRenderingContext2D.idl',
|
||||
'nsIDOMWebGLRenderingContext.idl',
|
||||
]
|
||||
|
||||
|
@ -1,33 +0,0 @@
|
||||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
/**
|
||||
* This interface remains only for the constants, for a context, use the
|
||||
* WebIDL/Paris bindings instead (CanvasRenderingContext2D.webidl).
|
||||
* The constants are used by CanvasRenderingContext2D::DrawWindow and are
|
||||
* used in WindowsPreviewPerTab.jsm and some extensions. The constants can
|
||||
* be referenced directly via a canvas context 2d rather than this interface,
|
||||
* and that should be preferred in new code.
|
||||
*/
|
||||
[uuid(4417cab7-c7eb-4e0c-b00a-c43842f0cba8)]
|
||||
interface nsIDOMCanvasRenderingContext2D : nsISupports
|
||||
{
|
||||
// Show the caret if appropriate when drawing
|
||||
const unsigned long DRAWWINDOW_DRAW_CARET = 0x01;
|
||||
// Don't flush pending layout notifications that could otherwise
|
||||
// be batched up
|
||||
const unsigned long DRAWWINDOW_DO_NOT_FLUSH = 0x02;
|
||||
// Draw scrollbars and scroll the viewport if they are present
|
||||
const unsigned long DRAWWINDOW_DRAW_VIEW = 0x04;
|
||||
// Use the widget layer manager if available. This means hardware
|
||||
// acceleration may be used, but it might actually be slower or
|
||||
// lower quality than normal. It will however more accurately reflect
|
||||
// the pixels rendered to the screen.
|
||||
const unsigned long DRAWWINDOW_USE_WIDGET_LAYERS = 0x08;
|
||||
// Don't synchronously decode images - draw what we have
|
||||
const unsigned long DRAWWINDOW_ASYNC_DECODE_IMAGES = 0x10;
|
||||
};
|
@ -23,16 +23,4 @@ interface nsIDOMHTMLFormElement;
|
||||
[uuid(64aeda0b-e9b5-4868-a4f9-e4776e32e733)]
|
||||
interface nsIDOMHTMLInputElement : nsISupports
|
||||
{
|
||||
readonly attribute DOMString autocomplete;
|
||||
attribute boolean checked;
|
||||
readonly attribute nsIDOMHTMLFormElement form;
|
||||
attribute DOMString formAction;
|
||||
|
||||
attribute boolean indeterminate;
|
||||
|
||||
attribute DOMString name;
|
||||
|
||||
attribute boolean readOnly;
|
||||
|
||||
readonly attribute nsIControllers controllers;
|
||||
};
|
||||
|
@ -2072,9 +2072,7 @@ ContentParent::LaunchSubprocess(ProcessPriority aInitialPriority /* = PROCESS_PR
|
||||
Unused << SendShareCodeCoverageMutex(CodeCoverageHandler::Get()->GetMutexHandle(procId));
|
||||
#endif
|
||||
|
||||
InitInternal(aInitialPriority,
|
||||
true, /* Setup off-main thread compositing */
|
||||
true /* Send registered chrome */);
|
||||
InitInternal(aInitialPriority);
|
||||
|
||||
ContentProcessManager::GetSingleton()->AddContentProcess(this);
|
||||
|
||||
@ -2168,9 +2166,7 @@ ContentParent::~ContentParent()
|
||||
}
|
||||
|
||||
void
|
||||
ContentParent::InitInternal(ProcessPriority aInitialPriority,
|
||||
bool aSetupOffMainThreadCompositing,
|
||||
bool aSendRegisteredChrome)
|
||||
ContentParent::InitInternal(ProcessPriority aInitialPriority)
|
||||
{
|
||||
Telemetry::Accumulate(Telemetry::CONTENT_PROCESS_LAUNCH_TIME_MS,
|
||||
static_cast<uint32_t>((TimeStamp::Now() - mLaunchTS)
|
||||
@ -2298,12 +2294,10 @@ ContentParent::InitInternal(ProcessPriority aInitialPriority,
|
||||
Unused << SendSetXPCOMProcessAttributes(xpcomInit, initialData, lnfCache,
|
||||
fontList);
|
||||
|
||||
if (aSendRegisteredChrome) {
|
||||
nsCOMPtr<nsIChromeRegistry> registrySvc = nsChromeRegistry::GetService();
|
||||
nsChromeRegistryChrome* chromeRegistry =
|
||||
static_cast<nsChromeRegistryChrome*>(registrySvc.get());
|
||||
chromeRegistry->SendRegisteredChrome(this);
|
||||
}
|
||||
nsCOMPtr<nsIChromeRegistry> registrySvc = nsChromeRegistry::GetService();
|
||||
nsChromeRegistryChrome* chromeRegistry =
|
||||
static_cast<nsChromeRegistryChrome*>(registrySvc.get());
|
||||
chromeRegistry->SendRegisteredChrome(this);
|
||||
|
||||
if (gAppData) {
|
||||
nsCString version(gAppData->version);
|
||||
@ -2336,41 +2330,37 @@ ContentParent::InitInternal(ProcessPriority aInitialPriority,
|
||||
// must come after the Open() call above.
|
||||
ProcessPriorityManager::SetProcessPriority(this, aInitialPriority);
|
||||
|
||||
if (aSetupOffMainThreadCompositing) {
|
||||
// NB: internally, this will send an IPC message to the child
|
||||
// process to get it to create the CompositorBridgeChild. This
|
||||
// message goes through the regular IPC queue for this
|
||||
// channel, so delivery will happen-before any other messages
|
||||
// we send. The CompositorBridgeChild must be created before any
|
||||
// PBrowsers are created, because they rely on the Compositor
|
||||
// already being around. (Creation is async, so can't happen
|
||||
// on demand.)
|
||||
GPUProcessManager* gpm = GPUProcessManager::Get();
|
||||
// NB: internally, this will send an IPC message to the child
|
||||
// process to get it to create the CompositorBridgeChild. This
|
||||
// message goes through the regular IPC queue for this
|
||||
// channel, so delivery will happen-before any other messages
|
||||
// we send. The CompositorBridgeChild must be created before any
|
||||
// PBrowsers are created, because they rely on the Compositor
|
||||
// already being around. (Creation is async, so can't happen
|
||||
// on demand.)
|
||||
GPUProcessManager* gpm = GPUProcessManager::Get();
|
||||
|
||||
Endpoint<PCompositorManagerChild> compositor;
|
||||
Endpoint<PImageBridgeChild> imageBridge;
|
||||
Endpoint<PVRManagerChild> vrBridge;
|
||||
Endpoint<PVideoDecoderManagerChild> videoManager;
|
||||
AutoTArray<uint32_t, 3> namespaces;
|
||||
Endpoint<PCompositorManagerChild> compositor;
|
||||
Endpoint<PImageBridgeChild> imageBridge;
|
||||
Endpoint<PVRManagerChild> vrBridge;
|
||||
Endpoint<PVideoDecoderManagerChild> videoManager;
|
||||
AutoTArray<uint32_t, 3> namespaces;
|
||||
|
||||
DebugOnly<bool> opened = gpm->CreateContentBridges(
|
||||
OtherPid(),
|
||||
&compositor,
|
||||
&imageBridge,
|
||||
&vrBridge,
|
||||
&videoManager,
|
||||
&namespaces);
|
||||
MOZ_ASSERT(opened);
|
||||
DebugOnly<bool> opened = gpm->CreateContentBridges(OtherPid(),
|
||||
&compositor,
|
||||
&imageBridge,
|
||||
&vrBridge,
|
||||
&videoManager,
|
||||
&namespaces);
|
||||
MOZ_ASSERT(opened);
|
||||
|
||||
Unused << SendInitRendering(
|
||||
Move(compositor),
|
||||
Move(imageBridge),
|
||||
Move(vrBridge),
|
||||
Move(videoManager),
|
||||
namespaces);
|
||||
Unused << SendInitRendering(Move(compositor),
|
||||
Move(imageBridge),
|
||||
Move(vrBridge),
|
||||
Move(videoManager),
|
||||
namespaces);
|
||||
|
||||
gpm->AddListener(this);
|
||||
}
|
||||
gpm->AddListener(this);
|
||||
|
||||
nsStyleSheetService *sheetService = nsStyleSheetService::GetInstance();
|
||||
if (sheetService) {
|
||||
|
@ -751,9 +751,7 @@ private:
|
||||
bool LaunchSubprocess(hal::ProcessPriority aInitialPriority = hal::PROCESS_PRIORITY_FOREGROUND);
|
||||
|
||||
// Common initialization after sub process launch or adoption.
|
||||
void InitInternal(ProcessPriority aPriority,
|
||||
bool aSetupOffMainThreadCompositing,
|
||||
bool aSendRegisteredChrome);
|
||||
void InitInternal(ProcessPriority aPriority);
|
||||
|
||||
virtual ~ContentParent();
|
||||
|
||||
|
39
dom/media/test/AutoplayTestUtils.js
Normal file
39
dom/media/test/AutoplayTestUtils.js
Normal file
@ -0,0 +1,39 @@
|
||||
function playAndPostResult(test_case, parent_window) {
|
||||
log("runTest " + test_case.name);
|
||||
|
||||
let element = document.createElement("video");
|
||||
element.preload = "auto";
|
||||
element.muted = test_case.muted;
|
||||
element.src = "short.mp4";
|
||||
element.id = "video";
|
||||
document.body.appendChild(element);
|
||||
|
||||
element.play().then(
|
||||
() => {
|
||||
parent_window.postMessage({played: true}, "*");
|
||||
},
|
||||
() => {
|
||||
parent_window.postMessage({played: false}, "*");
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function nextEvent(eventTarget, eventName) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
let f = function(event) {
|
||||
eventTarget.removeEventListener(eventName, f, false);
|
||||
resolve(event);
|
||||
};
|
||||
eventTarget.addEventListener(eventName, f, false);
|
||||
});
|
||||
}
|
||||
|
||||
function nextWindowMessage() {
|
||||
return nextEvent(window, "message");
|
||||
}
|
||||
|
||||
function log(msg) {
|
||||
var log_pane = document.body;
|
||||
log_pane.appendChild(document.createTextNode(msg));
|
||||
log_pane.appendChild(document.createElement("br"));
|
||||
}
|
21
dom/media/test/file_autoplay_policy_activation_frame.html
Normal file
21
dom/media/test/file_autoplay_policy_activation_frame.html
Normal file
@ -0,0 +1,21 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Autoplay policy frame</title>
|
||||
<script type="text/javascript" src="AutoplayTestUtils.js"></script>
|
||||
<style>
|
||||
video {
|
||||
width: 50%;
|
||||
height: 50%;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
nextWindowMessage().then(
|
||||
(event) => {
|
||||
playAndPostResult(event.data, event.source);
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
65
dom/media/test/file_autoplay_policy_activation_window.html
Normal file
65
dom/media/test/file_autoplay_policy_activation_window.html
Normal file
@ -0,0 +1,65 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Autoplay policy window</title>
|
||||
<style>
|
||||
video {
|
||||
width: 50%;
|
||||
height: 50%;
|
||||
}
|
||||
</style>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<script type="text/javascript" src="manifest.js"></script>
|
||||
<script type="text/javascript" src="AutoplayTestUtils.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<pre id="test">
|
||||
<script>
|
||||
|
||||
function testAutoplayInWindow(test_case, parent_window) {
|
||||
log("testAutoplayInWindow: " + test_case.name);
|
||||
playAndPostResult(test_case, parent_window);
|
||||
}
|
||||
|
||||
async function testAutoplayInChildFrame(test_case, parent_window) {
|
||||
log("testAutoplayInChildFrame: " + test_case.name);
|
||||
// Create a child iframe...
|
||||
var frame = document.createElement("iframe");
|
||||
var origin = test_case.same_origin_child
|
||||
? "http://mochi.test:8888" : "http://example.org";
|
||||
frame.src = origin + "/tests/dom/media/test/file_autoplay_policy_activation_frame.html";
|
||||
// Wait for it to load...
|
||||
document.body.appendChild(frame);
|
||||
await once(frame, "load");
|
||||
// Click the iframe to activate if appropriate.
|
||||
if (test_case.activated_child) {
|
||||
synthesizeMouseAtCenter(frame, {});
|
||||
}
|
||||
// Ask the child iframe to try to play video.
|
||||
frame.contentWindow.postMessage(test_case, "*");
|
||||
// Wait for the iframe to tell us whether it could play video.
|
||||
let result = await nextWindowMessage();
|
||||
// Report whether the iframe could play to the parent.
|
||||
parent_window.postMessage(result.data, "*");
|
||||
}
|
||||
|
||||
nextWindowMessage().then(
|
||||
(event) => {
|
||||
let test_case = event.data;
|
||||
// Click the window to activate if appropriate.
|
||||
if (test_case.activated_parent) {
|
||||
synthesizeMouseAtCenter(document.body, {});
|
||||
}
|
||||
let parent_window = event.source;
|
||||
if (test_case.same_origin_child === undefined) {
|
||||
testAutoplayInWindow(test_case, parent_window);
|
||||
} else {
|
||||
testAutoplayInChildFrame(test_case, parent_window);
|
||||
}
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -31,6 +31,7 @@ support-files =
|
||||
320x240.ogv^headers^
|
||||
448636.ogv
|
||||
448636.ogv^headers^
|
||||
AutoplayTestUtils.js
|
||||
A4.ogv
|
||||
A4.ogv^headers^
|
||||
VID_0001.ogg
|
||||
@ -437,6 +438,8 @@ support-files =
|
||||
dynamic_resource.sjs
|
||||
eme.js
|
||||
file_access_controls.html
|
||||
file_autoplay_policy_activation_window.html
|
||||
file_autoplay_policy_activation_frame.html
|
||||
flac-s24.flac
|
||||
flac-s24.flac^headers^
|
||||
flac-noheader-s16.flac
|
||||
@ -684,6 +687,8 @@ skip-if = true # bug 475110 - disabled since we don't play Wave files standalone
|
||||
skip-if = android_version == '15' || android_version == '17' || android_version == '22' # android(bug 1232305, bug 1232318, bug 1372457)
|
||||
[test_autoplay_policy.html]
|
||||
skip-if = android_version == '23' # bug 1424903
|
||||
[test_autoplay_policy_activation.html]
|
||||
skip-if = android_version == '23' # bug 1424903
|
||||
[test_buffered.html]
|
||||
skip-if = android_version == '15' || android_version == '22' # bug 1308388, android(bug 1232305)
|
||||
[test_bug448534.html]
|
||||
|
158
dom/media/test/test_autoplay_policy_activation.html
Normal file
158
dom/media/test/test_autoplay_policy_activation.html
Normal file
@ -0,0 +1,158 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Autoplay policy test</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
<script type="text/javascript" src="manifest.js"></script>
|
||||
<script type="text/javascript" src="AutoplayTestUtils.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<pre id="test">
|
||||
<script>
|
||||
|
||||
// Tests that videos can only play audibly in windows/frames
|
||||
// which have been activated by same-origin user gesture.
|
||||
|
||||
gTestPrefs.push(["media.autoplay.enabled", false],
|
||||
["media.autoplay.enabled.user-gestures-needed", true]);
|
||||
|
||||
SpecialPowers.pushPrefEnv({'set': gTestPrefs}, () => {
|
||||
runTest();
|
||||
});
|
||||
|
||||
let test_cases = [
|
||||
{
|
||||
name: "inaudible playback in unactivated same-origin iframe in activated parent allowed",
|
||||
muted: true,
|
||||
same_origin_child: true,
|
||||
activated_child: false,
|
||||
activated_parent: true,
|
||||
should_play: true,
|
||||
},
|
||||
|
||||
{
|
||||
name: "inaudible playback in unactivated same-origin iframe in unactivated parent allowed",
|
||||
muted: true,
|
||||
same_origin_child: true,
|
||||
activated_child: false,
|
||||
activated_parent: false,
|
||||
should_play: true,
|
||||
},
|
||||
|
||||
{
|
||||
name: "audible playback in unactivated same-origin iframe in activated parent allowed",
|
||||
muted: false,
|
||||
same_origin_child: true,
|
||||
activated_child: false,
|
||||
activated_parent: true,
|
||||
should_play: true,
|
||||
},
|
||||
|
||||
{
|
||||
name: "audible playback in unactivated same-origin iframe in unactivated parent blocked",
|
||||
muted: false,
|
||||
same_origin_child: true,
|
||||
activated_child: false,
|
||||
activated_parent: false,
|
||||
should_play: false,
|
||||
},
|
||||
|
||||
{
|
||||
name: "inaudible playback in unactivated cross-origin iframe in activated parent allowed",
|
||||
muted: true,
|
||||
same_origin_child: false,
|
||||
activated_child: false,
|
||||
activated_parent: true,
|
||||
should_play: true,
|
||||
},
|
||||
|
||||
{
|
||||
name: "inaudible playback in unactivated cross-origin iframe in unactivated parent allowed",
|
||||
muted: true,
|
||||
same_origin_child: false,
|
||||
activated_child: false,
|
||||
activated_parent: false,
|
||||
should_play: true,
|
||||
},
|
||||
|
||||
// TODO: This case fails, Firefox's behaviour needs to be fixed.
|
||||
// {
|
||||
// name: "audible playback in unactivated cross-origin iframe in activated parent blocked",
|
||||
// muted: false,
|
||||
// same_origin_child: false,
|
||||
// activated_child: false,
|
||||
// activated_parent: true,
|
||||
// should_play: false,
|
||||
// },
|
||||
|
||||
{
|
||||
name: "audible playback in unactivated cross-origin iframe in unactivated parent blocked",
|
||||
muted: false,
|
||||
same_origin_child: false,
|
||||
activated_child: false,
|
||||
activated_parent: false,
|
||||
should_play: false,
|
||||
},
|
||||
|
||||
{
|
||||
name: "audible playback in activated cross-origin iframe allowed",
|
||||
muted: false,
|
||||
same_origin_child: false,
|
||||
activated_child: true,
|
||||
activated_parent: false,
|
||||
should_play: true,
|
||||
},
|
||||
|
||||
{
|
||||
name: "audible playback in activated document allowed",
|
||||
muted: false,
|
||||
activated_parent: true,
|
||||
should_play: true,
|
||||
},
|
||||
|
||||
{
|
||||
name: "audible playback in unactivated document blocked",
|
||||
muted: false,
|
||||
activated_parent: false,
|
||||
should_play: false,
|
||||
},
|
||||
|
||||
{
|
||||
name: "inaudible playback in activated document allowed",
|
||||
muted: true,
|
||||
activated_parent: true,
|
||||
should_play: true,
|
||||
},
|
||||
|
||||
{
|
||||
name: "inaudible playback in unactivated document allowed",
|
||||
muted: true,
|
||||
activated_parent: false,
|
||||
should_play: true,
|
||||
},
|
||||
|
||||
];
|
||||
|
||||
let child_url = "file_autoplay_policy_activation_window.html";
|
||||
|
||||
async function runTest() {
|
||||
for (test_case of test_cases) {
|
||||
// Run each test in a new window, to ensure its user gesture
|
||||
// activation state isn't tainted by preceeding tests.
|
||||
let child = window.open(child_url, "", "width=500,height=500");
|
||||
await once(child, "load");
|
||||
child.postMessage(test_case, window.origin);
|
||||
let result = await nextWindowMessage();
|
||||
SimpleTest.is(result.data.played, test_case.should_play, test_case.name);
|
||||
child.close();
|
||||
}
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -106,6 +106,8 @@ skip-if = (android_version == '18') # android(Bug 1189784, timeouts on 4.3 emula
|
||||
skip-if = (android_version == '18') # android(Bug 1189784, timeouts on 4.3 emulator)
|
||||
[test_peerConnection_audioSynchronizationSources.html]
|
||||
skip-if = (android_version == '18') # android(Bug 1189784, timeouts on 4.3 emulator)
|
||||
[test_peerConnection_audioSynchronizationSourcesUnidirectional.html]
|
||||
skip-if = (android_version == '18') # android(Bug 1189784, timeouts on 4.3 emulator)
|
||||
[test_peerConnection_audioContributingSources.html]
|
||||
skip-if = (android_version == '18') # android(Bug 1189784, timeouts on 4.3 emulator)
|
||||
[test_peerConnection_checkPacketDumpHook.html]
|
||||
|
@ -29,16 +29,20 @@
|
||||
await waitForSyncSources(test);
|
||||
let receivers = [...test.pcRemote.getReceivers(),
|
||||
...test.pcLocal.getReceivers()];
|
||||
is(receivers.length, 2,
|
||||
`Expected number of receivers is 2. (${receivers.length})`);
|
||||
for (let recv of receivers) {
|
||||
let syncSources = recv.getSynchronizationSources();
|
||||
ok(syncSources,
|
||||
"Receiver has Synchronization sources " + JSON.stringify(syncSources));
|
||||
is(syncSources.length, 1, "Each receiver has only a single sync source");
|
||||
let source = recv.getSynchronizationSources()[0];
|
||||
ok(source.audioLevel,
|
||||
ok(source.audioLevel !== null,
|
||||
`Synchronization source has audio level. (${source.audioLevel})`);
|
||||
ok(source.audioLevel < 128,
|
||||
`Synchronization source audio level < 128. (${source.audioLevel})`);
|
||||
ok(source.audioLevel >= 0.0,
|
||||
`Synchronization source audio level >= 0.0 (${source.audioLevel})`);
|
||||
ok(source.audioLevel <= 1.0,
|
||||
`Synchronization source audio level <= 1.0 (${source.audioLevel})`);
|
||||
ok(source.timestamp,
|
||||
`Synchronization source has timestamp (${source.timestamp})`);
|
||||
ok(window.performance.now() + window.performance.timeOrigin -
|
||||
@ -54,12 +58,22 @@
|
||||
await waitForSyncSources(test);
|
||||
let receivers = [...test.pcRemote.getReceivers(),
|
||||
...test.pcLocal.getReceivers()];
|
||||
is(receivers.length, 2, "Expected number of receivers");
|
||||
for (let recv of receivers) {
|
||||
is(JSON.stringify(recv.getSynchronizationSources()),
|
||||
JSON.stringify(recv.getSynchronizationSources()),
|
||||
"Subsequent getSynchronizationSources calls are cached.");
|
||||
is(receivers.length, 2,
|
||||
`Expected number of receivers is 2. (${receivers.length})`);
|
||||
let sourceSets = [[],[]];
|
||||
for (let sourceSet of sourceSets) {
|
||||
for (let recv of receivers) {
|
||||
let sources = recv.getSynchronizationSources();
|
||||
ok(sources.length, 1,
|
||||
`Expected number of sources is 1. (${sources.length})`);
|
||||
sourceSet.push(sources);
|
||||
}
|
||||
// Busy wait 1s before trying again
|
||||
let endTime = performance.now() + 1000;
|
||||
while (performance.now() < endTime) {};
|
||||
}
|
||||
is(JSON.stringify(sourceSets[0]), JSON.stringify(sourceSets[1]),
|
||||
"Subsequent getSynchronizationSources calls are cached.");
|
||||
};
|
||||
|
||||
var test;
|
||||
|
@ -0,0 +1,54 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<script type="application/javascript" src="pc.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
createHTML({
|
||||
bug: "1439001",
|
||||
title: "Test audio unidirectional getSynchronizationSources"
|
||||
});
|
||||
|
||||
var waitForSyncSources = async (test) => {
|
||||
let receiver = test.pcRemote.getReceivers()[0];
|
||||
ok(receiver, "Remote has a receiver");
|
||||
// Wait for remote sync source
|
||||
while (receiver.getSynchronizationSources().length == 0) {
|
||||
await wait(250);
|
||||
}
|
||||
is(receiver.getSynchronizationSources().length, 1,
|
||||
"Remote receiver has a synchronization source");
|
||||
// Make sure local has no sync source
|
||||
is(test.pcLocal.getReceivers()[0].getSynchronizationSources().length, 0,
|
||||
"Local receiver has no synchronization source");
|
||||
};
|
||||
/*
|
||||
* Test to make sure that in unidirectional calls, the receiving end has
|
||||
* synchronization sources with audio levels, and the sending end has none.
|
||||
*/
|
||||
var testGetSynchronizationSourcesUnidirectional = async (test) => {
|
||||
await waitForSyncSources(test);
|
||||
let receiver = test.pcRemote.getReceivers()[0];
|
||||
let syncSources = receiver.getSynchronizationSources();
|
||||
ok(syncSources.length > 0,
|
||||
"Receiver has Synchronization sources " + JSON.stringify(syncSources));
|
||||
is(syncSources.length, 1, "Receiver has only a single sync source");
|
||||
let syncSource = syncSources[0];
|
||||
ok(syncSource.audioLevel !== undefined, "SynchronizationSource has audioLevel");
|
||||
};
|
||||
|
||||
var test;
|
||||
runNetworkTest(function(options) {
|
||||
test = new PeerConnectionTest(options);
|
||||
test.chain.insertAfter("PC_REMOTE_WAIT_FOR_MEDIA_FLOW",
|
||||
[testGetSynchronizationSourcesUnidirectional]);
|
||||
test.setMediaConstraints([{audio: true}], []);
|
||||
test.pcLocal.audioElementsOnly = true;
|
||||
test.run();
|
||||
});
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -163,7 +163,8 @@ QuotaUsageRequestChild::HandleResponse(const nsTArray<OriginUsage>& aResponse)
|
||||
|
||||
RefPtr<UsageResult> usageResult = new UsageResult(originUsage.origin(),
|
||||
originUsage.persisted(),
|
||||
originUsage.usage());
|
||||
originUsage.usage(),
|
||||
originUsage.lastAccessed());
|
||||
|
||||
usageResults.AppendElement(usageResult.forget());
|
||||
}
|
||||
|
@ -6979,6 +6979,8 @@ GetUsageOp::TraverseRepository(QuotaManager* aQuotaManager,
|
||||
originUsage->persisted() = persisted;
|
||||
}
|
||||
|
||||
originUsage->lastAccessed() = timestamp;
|
||||
|
||||
UsageInfo usageInfo;
|
||||
rv = GetUsageForOrigin(aQuotaManager,
|
||||
aPersistenceType,
|
||||
|
@ -13,6 +13,7 @@ struct OriginUsage
|
||||
nsCString origin;
|
||||
bool persisted;
|
||||
uint64_t usage;
|
||||
uint64_t lastAccessed;
|
||||
};
|
||||
|
||||
struct AllUsageResponse
|
||||
|
@ -12,10 +12,12 @@ namespace quota {
|
||||
|
||||
UsageResult::UsageResult(const nsACString& aOrigin,
|
||||
bool aPersisted,
|
||||
uint64_t aUsage)
|
||||
uint64_t aUsage,
|
||||
uint64_t aLastAccessed)
|
||||
: mOrigin(aOrigin)
|
||||
, mUsage(aUsage)
|
||||
, mPersisted(aPersisted)
|
||||
, mLastAccessed(aLastAccessed)
|
||||
{
|
||||
}
|
||||
|
||||
@ -47,6 +49,15 @@ UsageResult::GetUsage(uint64_t* aUsage)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
UsageResult::GetLastAccessed(uint64_t* aLastAccessed)
|
||||
{
|
||||
MOZ_ASSERT(aLastAccessed);
|
||||
|
||||
*aLastAccessed = mLastAccessed;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
OriginUsageResult::OriginUsageResult(uint64_t aUsage,
|
||||
uint64_t aFileUsage,
|
||||
uint64_t aLimit)
|
||||
|
@ -19,11 +19,13 @@ class UsageResult
|
||||
nsCString mOrigin;
|
||||
uint64_t mUsage;
|
||||
bool mPersisted;
|
||||
uint64_t mLastAccessed;
|
||||
|
||||
public:
|
||||
UsageResult(const nsACString& aOrigin,
|
||||
bool aPersisted,
|
||||
uint64_t aUsage);
|
||||
uint64_t aUsage,
|
||||
uint64_t aLastAccessed);
|
||||
|
||||
private:
|
||||
virtual ~UsageResult()
|
||||
|
@ -14,6 +14,8 @@ interface nsIQuotaUsageResult : nsISupports
|
||||
readonly attribute boolean persisted;
|
||||
|
||||
readonly attribute unsigned long long usage;
|
||||
|
||||
readonly attribute unsigned long long lastAccessed;
|
||||
};
|
||||
|
||||
[scriptable, function, uuid(96df03d2-116a-493f-bb0b-118c212a6b32)]
|
||||
|
@ -30,7 +30,6 @@
|
||||
#include "nsIContent.h"
|
||||
#include "nsIDOMComment.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsIDOMHTMLInputElement.h"
|
||||
#include "nsIDOMNode.h"
|
||||
#include "nsIDOMNodeList.h"
|
||||
#include "nsIDOMProcessingInstruction.h"
|
||||
@ -564,7 +563,7 @@ ResourceReader::OnWalkDOMNode(nsIDOMNode* aNode)
|
||||
return OnWalkSubframe(aNode);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMHTMLInputElement> nodeAsInput = do_QueryInterface(aNode);
|
||||
auto nodeAsInput = dom::HTMLInputElement::FromContent(content);
|
||||
if (nodeAsInput) {
|
||||
return OnWalkAttribute(aNode, "src");
|
||||
}
|
||||
|
@ -22,7 +22,6 @@
|
||||
#include "nsIControllers.h"
|
||||
#include "nsXULElement.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsIDOMHTMLInputElement.h"
|
||||
#include "nsFocusManager.h"
|
||||
#include "nsIFormControl.h"
|
||||
#include "nsIDOMEventListener.h"
|
||||
@ -48,6 +47,7 @@
|
||||
#include "mozilla/TextEvents.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/EventHandlerBinding.h"
|
||||
#include "mozilla/dom/HTMLInputElement.h"
|
||||
#include "mozilla/dom/HTMLTextAreaElement.h"
|
||||
#include "mozilla/dom/KeyboardEvent.h"
|
||||
#include "mozilla/dom/KeyboardEventBinding.h"
|
||||
@ -682,7 +682,7 @@ nsXBLPrototypeHandler::GetController(EventTarget* aTarget)
|
||||
}
|
||||
|
||||
if (!controllers) {
|
||||
nsCOMPtr<nsIDOMHTMLInputElement> htmlInputElement(do_QueryInterface(aTarget));
|
||||
HTMLInputElement* htmlInputElement = HTMLInputElement::FromContent(targetContent);
|
||||
if (htmlInputElement)
|
||||
htmlInputElement->GetControllers(getter_AddRefs(controllers));
|
||||
}
|
||||
|
@ -42,7 +42,6 @@
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsIDOMDocumentFragment.h"
|
||||
#include "nsIDOMElement.h"
|
||||
#include "nsIDOMHTMLInputElement.h"
|
||||
#include "nsIDOMNode.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIFile.h"
|
||||
|
@ -22,6 +22,7 @@
|
||||
// to be able to hold on to a GLContext.
|
||||
#include "mozilla/GenericRefCounted.h"
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
#include "mozilla/Path.h"
|
||||
|
||||
// This RefPtr class isn't ideal for usage in Azure, as it doesn't allow T**
|
||||
// outparams using the &-operator. But it will have to do as there's no easy
|
||||
@ -1534,6 +1535,7 @@ struct Config {
|
||||
|
||||
class GFX2D_API Factory
|
||||
{
|
||||
using char_type = filesystem::Path::value_type;
|
||||
public:
|
||||
static void Init(const Config& aConfig);
|
||||
static void ShutDown();
|
||||
@ -1698,7 +1700,7 @@ public:
|
||||
|
||||
|
||||
static already_AddRefed<DrawEventRecorder>
|
||||
CreateEventRecorderForFile(const char *aFilename);
|
||||
CreateEventRecorderForFile(const char_type* aFilename);
|
||||
|
||||
static void SetGlobalEventRecorder(DrawEventRecorder *aRecorder);
|
||||
|
||||
|
@ -35,7 +35,7 @@ DrawEventRecorderMemory::RecordEvent(const RecordedEvent &aEvent)
|
||||
aEvent.RecordToStream(mOutputStream);
|
||||
}
|
||||
|
||||
DrawEventRecorderFile::DrawEventRecorderFile(const char *aFilename)
|
||||
DrawEventRecorderFile::DrawEventRecorderFile(const char_type* aFilename)
|
||||
: mOutputStream(aFilename, ofstream::binary)
|
||||
{
|
||||
WriteHeader(mOutputStream);
|
||||
@ -59,7 +59,7 @@ DrawEventRecorderFile::IsOpen()
|
||||
}
|
||||
|
||||
void
|
||||
DrawEventRecorderFile::OpenNew(const char *aFilename)
|
||||
DrawEventRecorderFile::OpenNew(const char_type* aFilename)
|
||||
{
|
||||
MOZ_ASSERT(!mOutputStream.is_open());
|
||||
|
||||
|
@ -10,8 +10,7 @@
|
||||
#include "2D.h"
|
||||
#include "RecordedEvent.h"
|
||||
#include "RecordingTypes.h"
|
||||
#include <ostream>
|
||||
#include <fstream>
|
||||
#include "mozilla/FStream.h"
|
||||
|
||||
#include <unordered_set>
|
||||
#include <unordered_map>
|
||||
@ -129,9 +128,10 @@ protected:
|
||||
|
||||
class DrawEventRecorderFile : public DrawEventRecorderPrivate
|
||||
{
|
||||
using char_type = filesystem::Path::value_type;
|
||||
public:
|
||||
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DrawEventRecorderFile, override)
|
||||
explicit DrawEventRecorderFile(const char *aFilename);
|
||||
explicit DrawEventRecorderFile(const char_type* aFilename);
|
||||
~DrawEventRecorderFile();
|
||||
|
||||
void RecordEvent(const RecordedEvent &aEvent) override;
|
||||
@ -146,7 +146,7 @@ public:
|
||||
* objects it has recorded. This can be used with Close, so that a recording
|
||||
* can be processed in chunks. The file must not already be open.
|
||||
*/
|
||||
void OpenNew(const char *aFilename);
|
||||
void OpenNew(const char_type* aFilename);
|
||||
|
||||
/**
|
||||
* Closes the file so that it can be processed. The recorder does NOT forget
|
||||
@ -158,7 +158,7 @@ public:
|
||||
private:
|
||||
void Flush() override;
|
||||
|
||||
std::ofstream mOutputStream;
|
||||
mozilla::OFStream mOutputStream;
|
||||
};
|
||||
|
||||
typedef std::function<void(MemStream &aStream, std::vector<RefPtr<UnscaledFont>> &aUnscaledFonts)> SerializeResourcesFn;
|
||||
|
@ -1140,7 +1140,7 @@ Factory::CopyDataSourceSurface(DataSourceSurface* aSource,
|
||||
}
|
||||
|
||||
already_AddRefed<DrawEventRecorder>
|
||||
Factory::CreateEventRecorderForFile(const char *aFilename)
|
||||
Factory::CreateEventRecorderForFile(const char_type* aFilename)
|
||||
{
|
||||
return MakeAndAddRef<DrawEventRecorderFile>(aFilename);
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ class gfxVarReceiver;
|
||||
_(UseWebRenderProgramBinary, bool, false) \
|
||||
_(WebRenderDebugFlags, int32_t, 0) \
|
||||
_(ScreenDepth, int32_t, 0) \
|
||||
_(GREDirectory, nsCString, nsCString()) \
|
||||
_(GREDirectory, nsString, nsString()) \
|
||||
_(UseOMTP, bool, false) \
|
||||
_(AllowD3D11KeyedMutex, bool, false) \
|
||||
|
||||
|
@ -109,13 +109,13 @@ static PRLibrary* LoadApitraceLibrary()
|
||||
static PRLibrary*
|
||||
LoadLibraryForEGLOnWindows(const nsAString& filename)
|
||||
{
|
||||
nsAutoCString path(gfx::gfxVars::GREDirectory());
|
||||
nsAutoString path(gfx::gfxVars::GREDirectory());
|
||||
path.Append(PR_GetDirectorySeparator());
|
||||
path.Append(ToNewUTF8String(filename));
|
||||
path.Append(filename);
|
||||
|
||||
PRLibSpec lspec;
|
||||
lspec.type = PR_LibSpec_Pathname;
|
||||
lspec.value.pathname = path.get();
|
||||
lspec.type = PR_LibSpec_PathnameU;
|
||||
lspec.value.pathname_u = path.get();
|
||||
return PR_LoadLibraryWithFlags(lspec, PR_LD_LAZY | PR_LD_LOCAL);
|
||||
}
|
||||
|
||||
|
@ -77,6 +77,7 @@ union GfxVarValue
|
||||
gfxImageFormat;
|
||||
IntSize;
|
||||
nsCString;
|
||||
nsString;
|
||||
int32_t;
|
||||
};
|
||||
|
||||
|
@ -1139,18 +1139,16 @@ APZCTreeManager::ReceiveInputEvent(InputData& aEvent,
|
||||
});
|
||||
}
|
||||
|
||||
bool targetConfirmed = (hitResult != CompositorHitTestInfo::eInvisibleToHitTest)
|
||||
&& !(hitResult & CompositorHitTestInfo::eDispatchToContent);
|
||||
TargetConfirmationFlags confFlags{hitResult};
|
||||
bool apzDragEnabled = gfxPrefs::APZDragEnabled();
|
||||
if (apzDragEnabled && hitScrollbar) {
|
||||
// If scrollbar dragging is enabled and we hit a scrollbar, wait
|
||||
// for the main-thread confirmation because it contains drag metrics
|
||||
// that we need.
|
||||
targetConfirmed = false;
|
||||
confFlags.mTargetConfirmed = false;
|
||||
}
|
||||
result = mInputQueue->ReceiveInputEvent(
|
||||
apzc, targetConfirmed,
|
||||
mouseInput, aOutInputBlockId);
|
||||
apzc, confFlags, mouseInput, aOutInputBlockId);
|
||||
|
||||
// If we're starting an async scrollbar drag
|
||||
if (apzDragEnabled && startsDrag && hitScrollbarNode &&
|
||||
@ -1223,7 +1221,7 @@ APZCTreeManager::ReceiveInputEvent(InputData& aEvent,
|
||||
|
||||
result = mInputQueue->ReceiveInputEvent(
|
||||
apzc,
|
||||
/* aTargetConfirmed = */ !(hitResult & CompositorHitTestInfo::eDispatchToContent),
|
||||
TargetConfirmationFlags{hitResult},
|
||||
wheelInput, aOutInputBlockId);
|
||||
|
||||
// Update the out-parameters so they are what the caller expects.
|
||||
@ -1275,7 +1273,7 @@ APZCTreeManager::ReceiveInputEvent(InputData& aEvent,
|
||||
|
||||
result = mInputQueue->ReceiveInputEvent(
|
||||
apzc,
|
||||
/* aTargetConfirmed = */ !(hitResult & CompositorHitTestInfo::eDispatchToContent),
|
||||
TargetConfirmationFlags{hitResult},
|
||||
panInput, aOutInputBlockId);
|
||||
|
||||
// Update the out-parameters so they are what the caller expects.
|
||||
@ -1305,7 +1303,7 @@ APZCTreeManager::ReceiveInputEvent(InputData& aEvent,
|
||||
|
||||
result = mInputQueue->ReceiveInputEvent(
|
||||
apzc,
|
||||
/* aTargetConfirmed = */ !(hitResult & CompositorHitTestInfo::eDispatchToContent),
|
||||
TargetConfirmationFlags{hitResult},
|
||||
pinchInput, aOutInputBlockId);
|
||||
|
||||
// Update the out-parameters so they are what the caller expects.
|
||||
@ -1331,7 +1329,7 @@ APZCTreeManager::ReceiveInputEvent(InputData& aEvent,
|
||||
|
||||
result = mInputQueue->ReceiveInputEvent(
|
||||
apzc,
|
||||
/* aTargetConfirmed = */ !(hitResult & CompositorHitTestInfo::eDispatchToContent),
|
||||
TargetConfirmationFlags{hitResult},
|
||||
tapInput, aOutInputBlockId);
|
||||
|
||||
// Update the out-parameters so they are what the caller expects.
|
||||
@ -1415,7 +1413,7 @@ APZCTreeManager::ReceiveInputEvent(InputData& aEvent,
|
||||
// Dispatch the event to the input queue.
|
||||
result = mInputQueue->ReceiveInputEvent(
|
||||
targetApzc,
|
||||
/* aTargetConfirmed = */ true,
|
||||
TargetConfirmationFlags{true},
|
||||
keyInput, aOutInputBlockId);
|
||||
|
||||
// Any keyboard event that is dispatched to the input queue at this point
|
||||
@ -1589,7 +1587,7 @@ APZCTreeManager::ProcessTouchInput(MultiTouchInput& aInput,
|
||||
mApzcForInputBlock->GetGuid(aOutTargetGuid);
|
||||
uint64_t inputBlockId = 0;
|
||||
result = mInputQueue->ReceiveInputEvent(mApzcForInputBlock,
|
||||
/* aTargetConfirmed = */ !(mHitResultForInputBlock & CompositorHitTestInfo::eDispatchToContent),
|
||||
TargetConfirmationFlags{mHitResultForInputBlock},
|
||||
aInput, &inputBlockId);
|
||||
if (aOutInputBlockId) {
|
||||
*aOutInputBlockId = inputBlockId;
|
||||
@ -1674,7 +1672,7 @@ APZCTreeManager::ProcessTouchInputForScrollbarDrag(MultiTouchInput& aTouchInput,
|
||||
// only matters for the first event, which creates the drag block. For
|
||||
// that event, the correct value is false, since the drag block will, at the
|
||||
// earliest, be confirmed in the subsequent SetupScrollbarDrag() call.
|
||||
bool targetConfirmed = false;
|
||||
TargetConfirmationFlags targetConfirmed{false};
|
||||
|
||||
nsEventStatus result = mInputQueue->ReceiveInputEvent(mApzcForInputBlock,
|
||||
targetConfirmed, mouseInput, aOutInputBlockId);
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include <stdint.h> // for uint32_t
|
||||
#include "LayersTypes.h"
|
||||
#include "UnitTransforms.h"
|
||||
#include "mozilla/gfx/CompositorHitTestInfo.h"
|
||||
#include "mozilla/gfx/Point.h"
|
||||
#include "mozilla/EnumSet.h"
|
||||
#include "mozilla/FloatingPoint.h"
|
||||
@ -76,6 +77,22 @@ CompleteAsyncTransform(const AsyncTransformComponentMatrix& aMatrix)
|
||||
PixelCastJustification::MultipleAsyncTransforms);
|
||||
}
|
||||
|
||||
struct TargetConfirmationFlags {
|
||||
explicit TargetConfirmationFlags(bool aTargetConfirmed)
|
||||
: mTargetConfirmed(aTargetConfirmed)
|
||||
, mRequiresTargetConfirmation(false)
|
||||
{}
|
||||
|
||||
explicit TargetConfirmationFlags(gfx::CompositorHitTestInfo aHitTestInfo)
|
||||
: mTargetConfirmed(aHitTestInfo != gfx::CompositorHitTestInfo::eInvisibleToHitTest &&
|
||||
!(aHitTestInfo & gfx::CompositorHitTestInfo::eDispatchToContent))
|
||||
, mRequiresTargetConfirmation(aHitTestInfo & gfx::CompositorHitTestInfo::eRequiresTargetConfirmation)
|
||||
{}
|
||||
|
||||
bool mTargetConfirmed : 1;
|
||||
bool mRequiresTargetConfirmation : 1;
|
||||
};
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
||||
|
@ -23,10 +23,11 @@ namespace layers {
|
||||
static uint64_t sBlockCounter = InputBlockState::NO_BLOCK_ID + 1;
|
||||
|
||||
InputBlockState::InputBlockState(const RefPtr<AsyncPanZoomController>& aTargetApzc,
|
||||
bool aTargetConfirmed)
|
||||
TargetConfirmationFlags aFlags)
|
||||
: mTargetApzc(aTargetApzc)
|
||||
, mTargetConfirmed(aTargetConfirmed ? TargetConfirmationState::eConfirmed
|
||||
: TargetConfirmationState::eUnconfirmed)
|
||||
, mTargetConfirmed(aFlags.mTargetConfirmed ? TargetConfirmationState::eConfirmed
|
||||
: TargetConfirmationState::eUnconfirmed)
|
||||
, mRequiresTargetConfirmation(aFlags.mRequiresTargetConfirmation)
|
||||
, mBlockId(sBlockCounter++)
|
||||
, mTransformToApzc(aTargetApzc->GetTransformToThis())
|
||||
{
|
||||
@ -108,6 +109,12 @@ InputBlockState::HasReceivedRealConfirmedTarget() const
|
||||
mTargetConfirmed == TargetConfirmationState::eTimedOutAndMainThreadResponded;
|
||||
}
|
||||
|
||||
bool
|
||||
InputBlockState::ShouldDropEvents() const
|
||||
{
|
||||
return mRequiresTargetConfirmation && (mTargetConfirmed != TargetConfirmationState::eConfirmed);
|
||||
}
|
||||
|
||||
bool
|
||||
InputBlockState::IsDownchainOf(AsyncPanZoomController* aA, AsyncPanZoomController* aB) const
|
||||
{
|
||||
@ -159,8 +166,8 @@ InputBlockState::DispatchEvent(const InputData& aEvent) const
|
||||
}
|
||||
|
||||
CancelableBlockState::CancelableBlockState(const RefPtr<AsyncPanZoomController>& aTargetApzc,
|
||||
bool aTargetConfirmed)
|
||||
: InputBlockState(aTargetApzc, aTargetConfirmed)
|
||||
TargetConfirmationFlags aFlags)
|
||||
: InputBlockState(aTargetApzc, aFlags)
|
||||
, mPreventDefault(false)
|
||||
, mContentResponded(false)
|
||||
, mContentResponseTimerExpired(false)
|
||||
@ -230,6 +237,12 @@ CancelableBlockState::IsReadyForHandling() const
|
||||
return mContentResponded || mContentResponseTimerExpired;
|
||||
}
|
||||
|
||||
bool
|
||||
CancelableBlockState::ShouldDropEvents() const
|
||||
{
|
||||
return InputBlockState::ShouldDropEvents() || IsDefaultPrevented();
|
||||
}
|
||||
|
||||
void
|
||||
CancelableBlockState::RecordContentResponseTime()
|
||||
{
|
||||
@ -251,9 +264,9 @@ CancelableBlockState::RecordContentResponseTime()
|
||||
}
|
||||
|
||||
DragBlockState::DragBlockState(const RefPtr<AsyncPanZoomController>& aTargetApzc,
|
||||
bool aTargetConfirmed,
|
||||
TargetConfirmationFlags aFlags,
|
||||
const MouseInput& aInitialEvent)
|
||||
: CancelableBlockState(aTargetApzc, aTargetConfirmed)
|
||||
: CancelableBlockState(aTargetApzc, aFlags)
|
||||
, mReceivedMouseUp(false)
|
||||
{
|
||||
}
|
||||
@ -308,15 +321,15 @@ DragBlockState::Type()
|
||||
static uint64_t sLastWheelBlockId = InputBlockState::NO_BLOCK_ID;
|
||||
|
||||
WheelBlockState::WheelBlockState(const RefPtr<AsyncPanZoomController>& aTargetApzc,
|
||||
bool aTargetConfirmed,
|
||||
TargetConfirmationFlags aFlags,
|
||||
const ScrollWheelInput& aInitialEvent)
|
||||
: CancelableBlockState(aTargetApzc, aTargetConfirmed)
|
||||
: CancelableBlockState(aTargetApzc, aFlags)
|
||||
, mScrollSeriesCounter(0)
|
||||
, mTransactionEnded(false)
|
||||
{
|
||||
sLastWheelBlockId = GetBlockId();
|
||||
|
||||
if (aTargetConfirmed) {
|
||||
if (aFlags.mTargetConfirmed) {
|
||||
// Find the nearest APZC in the overscroll handoff chain that is scrollable.
|
||||
// If we get a content confirmation later that the apzc is different, then
|
||||
// content should have found a scrollable apzc, so we don't need to handle
|
||||
@ -543,13 +556,13 @@ WheelBlockState::EndTransaction()
|
||||
}
|
||||
|
||||
PanGestureBlockState::PanGestureBlockState(const RefPtr<AsyncPanZoomController>& aTargetApzc,
|
||||
bool aTargetConfirmed,
|
||||
TargetConfirmationFlags aFlags,
|
||||
const PanGestureInput& aInitialEvent)
|
||||
: CancelableBlockState(aTargetApzc, aTargetConfirmed)
|
||||
: CancelableBlockState(aTargetApzc, aFlags)
|
||||
, mInterrupted(false)
|
||||
, mWaitingForContentResponse(false)
|
||||
{
|
||||
if (aTargetConfirmed) {
|
||||
if (aFlags.mTargetConfirmed) {
|
||||
// Find the nearest APZC in the overscroll handoff chain that is scrollable.
|
||||
// If we get a content confirmation later that the apzc is different, then
|
||||
// content should have found a scrollable apzc, so we don't need to handle
|
||||
@ -643,8 +656,9 @@ PanGestureBlockState::SetNeedsToWaitForContentResponse(bool aWaitForContentRespo
|
||||
}
|
||||
|
||||
TouchBlockState::TouchBlockState(const RefPtr<AsyncPanZoomController>& aTargetApzc,
|
||||
bool aTargetConfirmed, TouchCounter& aCounter)
|
||||
: CancelableBlockState(aTargetApzc, aTargetConfirmed)
|
||||
TargetConfirmationFlags aFlags,
|
||||
TouchCounter& aCounter)
|
||||
: CancelableBlockState(aTargetApzc, aFlags)
|
||||
, mAllowedTouchBehaviorSet(false)
|
||||
, mDuringFastFling(false)
|
||||
, mSingleTapOccurred(false)
|
||||
@ -874,7 +888,7 @@ TouchBlockState::GetActiveTouchCount() const
|
||||
}
|
||||
|
||||
KeyboardBlockState::KeyboardBlockState(const RefPtr<AsyncPanZoomController>& aTargetApzc)
|
||||
: InputBlockState(aTargetApzc, true)
|
||||
: InputBlockState(aTargetApzc, TargetConfirmationFlags{true})
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -42,7 +42,7 @@ public:
|
||||
|
||||
static const uint64_t NO_BLOCK_ID = 0;
|
||||
|
||||
enum class TargetConfirmationState {
|
||||
enum class TargetConfirmationState : uint8_t {
|
||||
eUnconfirmed,
|
||||
eTimedOut,
|
||||
eTimedOutAndMainThreadResponded,
|
||||
@ -50,7 +50,7 @@ public:
|
||||
};
|
||||
|
||||
explicit InputBlockState(const RefPtr<AsyncPanZoomController>& aTargetApzc,
|
||||
bool aTargetConfirmed);
|
||||
TargetConfirmationFlags aFlags);
|
||||
virtual ~InputBlockState()
|
||||
{}
|
||||
|
||||
@ -83,6 +83,8 @@ public:
|
||||
bool IsTargetConfirmed() const;
|
||||
bool HasReceivedRealConfirmedTarget() const;
|
||||
|
||||
virtual bool ShouldDropEvents() const;
|
||||
|
||||
void SetScrolledApzc(AsyncPanZoomController* aApzc);
|
||||
AsyncPanZoomController* GetScrolledApzc() const;
|
||||
bool IsDownchainOfScrolledApzc(AsyncPanZoomController* aApzc) const;
|
||||
@ -110,6 +112,7 @@ private:
|
||||
private:
|
||||
RefPtr<AsyncPanZoomController> mTargetApzc;
|
||||
TargetConfirmationState mTargetConfirmed;
|
||||
bool mRequiresTargetConfirmation;
|
||||
const uint64_t mBlockId;
|
||||
|
||||
// The APZC that was actually scrolled by events in this input block.
|
||||
@ -143,7 +146,7 @@ class CancelableBlockState : public InputBlockState
|
||||
{
|
||||
public:
|
||||
CancelableBlockState(const RefPtr<AsyncPanZoomController>& aTargetApzc,
|
||||
bool aTargetConfirmed);
|
||||
TargetConfirmationFlags aFlags);
|
||||
|
||||
CancelableBlockState* AsCancelableBlock() override {
|
||||
return this;
|
||||
@ -204,6 +207,7 @@ public:
|
||||
*/
|
||||
virtual const char* Type() = 0;
|
||||
|
||||
bool ShouldDropEvents() const override;
|
||||
private:
|
||||
TimeStamp mContentResponseTimer;
|
||||
bool mPreventDefault;
|
||||
@ -218,7 +222,7 @@ class WheelBlockState : public CancelableBlockState
|
||||
{
|
||||
public:
|
||||
WheelBlockState(const RefPtr<AsyncPanZoomController>& aTargetApzc,
|
||||
bool aTargetConfirmed,
|
||||
TargetConfirmationFlags aFlags,
|
||||
const ScrollWheelInput& aEvent);
|
||||
|
||||
bool SetContentResponse(bool aPreventDefault) override;
|
||||
@ -302,7 +306,7 @@ class DragBlockState : public CancelableBlockState
|
||||
{
|
||||
public:
|
||||
DragBlockState(const RefPtr<AsyncPanZoomController>& aTargetApzc,
|
||||
bool aTargetConfirmed,
|
||||
TargetConfirmationFlags aFlags,
|
||||
const MouseInput& aEvent);
|
||||
|
||||
bool MustStayActive() override;
|
||||
@ -332,7 +336,7 @@ class PanGestureBlockState : public CancelableBlockState
|
||||
{
|
||||
public:
|
||||
PanGestureBlockState(const RefPtr<AsyncPanZoomController>& aTargetApzc,
|
||||
bool aTargetConfirmed,
|
||||
TargetConfirmationFlags aFlags,
|
||||
const PanGestureInput& aEvent);
|
||||
|
||||
bool SetContentResponse(bool aPreventDefault) override;
|
||||
@ -392,7 +396,8 @@ class TouchBlockState : public CancelableBlockState
|
||||
{
|
||||
public:
|
||||
explicit TouchBlockState(const RefPtr<AsyncPanZoomController>& aTargetApzc,
|
||||
bool aTargetConfirmed, TouchCounter& aTouchCounter);
|
||||
TargetConfirmationFlags aFlags,
|
||||
TouchCounter& aTouchCounter);
|
||||
|
||||
TouchBlockState *AsTouchBlock() override {
|
||||
return this;
|
||||
|
@ -30,7 +30,7 @@ InputQueue::~InputQueue() {
|
||||
|
||||
nsEventStatus
|
||||
InputQueue::ReceiveInputEvent(const RefPtr<AsyncPanZoomController>& aTarget,
|
||||
bool aTargetConfirmed,
|
||||
TargetConfirmationFlags aFlags,
|
||||
const InputData& aEvent,
|
||||
uint64_t* aOutInputBlockId) {
|
||||
APZThreadUtils::AssertOnControllerThread();
|
||||
@ -38,27 +38,27 @@ InputQueue::ReceiveInputEvent(const RefPtr<AsyncPanZoomController>& aTarget,
|
||||
switch (aEvent.mInputType) {
|
||||
case MULTITOUCH_INPUT: {
|
||||
const MultiTouchInput& event = aEvent.AsMultiTouchInput();
|
||||
return ReceiveTouchInput(aTarget, aTargetConfirmed, event, aOutInputBlockId);
|
||||
return ReceiveTouchInput(aTarget, aFlags, event, aOutInputBlockId);
|
||||
}
|
||||
|
||||
case SCROLLWHEEL_INPUT: {
|
||||
const ScrollWheelInput& event = aEvent.AsScrollWheelInput();
|
||||
return ReceiveScrollWheelInput(aTarget, aTargetConfirmed, event, aOutInputBlockId);
|
||||
return ReceiveScrollWheelInput(aTarget, aFlags, event, aOutInputBlockId);
|
||||
}
|
||||
|
||||
case PANGESTURE_INPUT: {
|
||||
const PanGestureInput& event = aEvent.AsPanGestureInput();
|
||||
return ReceivePanGestureInput(aTarget, aTargetConfirmed, event, aOutInputBlockId);
|
||||
return ReceivePanGestureInput(aTarget, aFlags, event, aOutInputBlockId);
|
||||
}
|
||||
|
||||
case MOUSE_INPUT: {
|
||||
const MouseInput& event = aEvent.AsMouseInput();
|
||||
return ReceiveMouseInput(aTarget, aTargetConfirmed, event, aOutInputBlockId);
|
||||
return ReceiveMouseInput(aTarget, aFlags, event, aOutInputBlockId);
|
||||
}
|
||||
|
||||
case KEYBOARD_INPUT: {
|
||||
// Every keyboard input must have a confirmed target
|
||||
MOZ_ASSERT(aTarget && aTargetConfirmed);
|
||||
MOZ_ASSERT(aTarget && aFlags.mTargetConfirmed);
|
||||
|
||||
const KeyboardInput& event = aEvent.AsKeyboardInput();
|
||||
return ReceiveKeyboardInput(aTarget, event, aOutInputBlockId);
|
||||
@ -75,7 +75,7 @@ InputQueue::ReceiveInputEvent(const RefPtr<AsyncPanZoomController>& aTarget,
|
||||
|
||||
nsEventStatus
|
||||
InputQueue::ReceiveTouchInput(const RefPtr<AsyncPanZoomController>& aTarget,
|
||||
bool aTargetConfirmed,
|
||||
TargetConfirmationFlags aFlags,
|
||||
const MultiTouchInput& aEvent,
|
||||
uint64_t* aOutInputBlockId) {
|
||||
TouchBlockState* block = nullptr;
|
||||
@ -93,7 +93,7 @@ InputQueue::ReceiveTouchInput(const RefPtr<AsyncPanZoomController>& aTarget,
|
||||
haveBehaviors |= mActiveTouchBlock->IsContentResponseTimerExpired();
|
||||
}
|
||||
|
||||
block = StartNewTouchBlock(aTarget, aTargetConfirmed, false);
|
||||
block = StartNewTouchBlock(aTarget, aFlags, false);
|
||||
INPQ_LOG("started new touch block %p id %" PRIu64 " for target %p\n",
|
||||
block, block->GetBlockId(), aTarget.get());
|
||||
|
||||
@ -168,7 +168,7 @@ InputQueue::ReceiveTouchInput(const RefPtr<AsyncPanZoomController>& aTarget,
|
||||
|
||||
nsEventStatus
|
||||
InputQueue::ReceiveMouseInput(const RefPtr<AsyncPanZoomController>& aTarget,
|
||||
bool aTargetConfirmed,
|
||||
TargetConfirmationFlags aFlags,
|
||||
const MouseInput& aEvent,
|
||||
uint64_t* aOutInputBlockId) {
|
||||
// On a new mouse down we can have a new target so we must force a new block
|
||||
@ -198,7 +198,7 @@ InputQueue::ReceiveMouseInput(const RefPtr<AsyncPanZoomController>& aTarget,
|
||||
|
||||
if (!block) {
|
||||
MOZ_ASSERT(newBlock);
|
||||
block = new DragBlockState(aTarget, aTargetConfirmed, aEvent);
|
||||
block = new DragBlockState(aTarget, aFlags, aEvent);
|
||||
|
||||
INPQ_LOG("started new drag block %p id %" PRIu64 " for %sconfirmed target %p\n",
|
||||
block, block->GetBlockId(), aTargetConfirmed ? "" : "un", aTarget.get());
|
||||
@ -227,7 +227,7 @@ InputQueue::ReceiveMouseInput(const RefPtr<AsyncPanZoomController>& aTarget,
|
||||
|
||||
nsEventStatus
|
||||
InputQueue::ReceiveScrollWheelInput(const RefPtr<AsyncPanZoomController>& aTarget,
|
||||
bool aTargetConfirmed,
|
||||
TargetConfirmationFlags aFlags,
|
||||
const ScrollWheelInput& aEvent,
|
||||
uint64_t* aOutInputBlockId) {
|
||||
WheelBlockState* block = mActiveWheelBlock.get();
|
||||
@ -243,7 +243,7 @@ InputQueue::ReceiveScrollWheelInput(const RefPtr<AsyncPanZoomController>& aTarge
|
||||
MOZ_ASSERT(!block || block->InTransaction());
|
||||
|
||||
if (!block) {
|
||||
block = new WheelBlockState(aTarget, aTargetConfirmed, aEvent);
|
||||
block = new WheelBlockState(aTarget, aFlags, aEvent);
|
||||
INPQ_LOG("started new scroll wheel block %p id %" PRIu64 " for target %p\n",
|
||||
block, block->GetBlockId(), aTarget.get());
|
||||
|
||||
@ -329,7 +329,7 @@ CanScrollTargetHorizontally(const PanGestureInput& aInitialEvent,
|
||||
|
||||
nsEventStatus
|
||||
InputQueue::ReceivePanGestureInput(const RefPtr<AsyncPanZoomController>& aTarget,
|
||||
bool aTargetConfirmed,
|
||||
TargetConfirmationFlags aFlags,
|
||||
const PanGestureInput& aEvent,
|
||||
uint64_t* aOutInputBlockId) {
|
||||
if (aEvent.mType == PanGestureInput::PANGESTURE_MAYSTART ||
|
||||
@ -355,11 +355,11 @@ InputQueue::ReceivePanGestureInput(const RefPtr<AsyncPanZoomController>& aTarget
|
||||
event.mType);
|
||||
event.mType = PanGestureInput::PANGESTURE_START;
|
||||
}
|
||||
block = new PanGestureBlockState(aTarget, aTargetConfirmed, event);
|
||||
block = new PanGestureBlockState(aTarget, aFlags, event);
|
||||
INPQ_LOG("started new pan gesture block %p id %" PRIu64 " for target %p\n",
|
||||
block, block->GetBlockId(), aTarget.get());
|
||||
|
||||
if (aTargetConfirmed &&
|
||||
if (aFlags.mTargetConfirmed &&
|
||||
event.mRequiresContentResponseIfCannotScrollHorizontallyInStartDirection &&
|
||||
!CanScrollTargetHorizontally(event, block)) {
|
||||
// This event may trigger a swipe gesture, depending on what our caller
|
||||
@ -446,7 +446,7 @@ uint64_t
|
||||
InputQueue::InjectNewTouchBlock(AsyncPanZoomController* aTarget)
|
||||
{
|
||||
TouchBlockState* block = StartNewTouchBlock(aTarget,
|
||||
/* aTargetConfirmed = */ true,
|
||||
TargetConfirmationFlags{true},
|
||||
/* aCopyPropertiesFromCurrent = */ true);
|
||||
INPQ_LOG("injecting new touch block %p with id %" PRIu64 " and target %p\n",
|
||||
block, block->GetBlockId(), aTarget);
|
||||
@ -456,10 +456,10 @@ InputQueue::InjectNewTouchBlock(AsyncPanZoomController* aTarget)
|
||||
|
||||
TouchBlockState*
|
||||
InputQueue::StartNewTouchBlock(const RefPtr<AsyncPanZoomController>& aTarget,
|
||||
bool aTargetConfirmed,
|
||||
TargetConfirmationFlags aFlags,
|
||||
bool aCopyPropertiesFromCurrent)
|
||||
{
|
||||
TouchBlockState* newBlock = new TouchBlockState(aTarget, aTargetConfirmed,
|
||||
TouchBlockState* newBlock = new TouchBlockState(aTarget, aFlags,
|
||||
mTouchCounter);
|
||||
if (aCopyPropertiesFromCurrent) {
|
||||
// We should never enter here without a current touch block, because this
|
||||
@ -730,14 +730,14 @@ InputQueue::ProcessQueue() {
|
||||
break;
|
||||
}
|
||||
|
||||
INPQ_LOG("processing input from block %p; preventDefault %d target %p\n",
|
||||
INPQ_LOG("processing input from block %p; preventDefault %d shouldDropEvents %d target %p\n",
|
||||
curBlock, cancelable && cancelable->IsDefaultPrevented(),
|
||||
curBlock->GetTargetApzc().get());
|
||||
curBlock->ShouldDropEvents(), curBlock->GetTargetApzc().get());
|
||||
RefPtr<AsyncPanZoomController> target = curBlock->GetTargetApzc();
|
||||
// target may be null here if the initial target was unconfirmed and then
|
||||
// we later got a confirmed null target. in that case drop the events.
|
||||
if (target) {
|
||||
if (cancelable && cancelable->IsDefaultPrevented()) {
|
||||
if (curBlock->ShouldDropEvents()) {
|
||||
if (curBlock->AsTouchBlock()) {
|
||||
target->ResetTouchInputState();
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ public:
|
||||
* return values from this function, including |aOutInputBlockId|.
|
||||
*/
|
||||
nsEventStatus ReceiveInputEvent(const RefPtr<AsyncPanZoomController>& aTarget,
|
||||
bool aTargetConfirmed,
|
||||
TargetConfirmationFlags aFlags,
|
||||
const InputData& aEvent,
|
||||
uint64_t* aOutInputBlockId);
|
||||
/**
|
||||
@ -140,7 +140,7 @@ private:
|
||||
~InputQueue();
|
||||
|
||||
TouchBlockState* StartNewTouchBlock(const RefPtr<AsyncPanZoomController>& aTarget,
|
||||
bool aTargetConfirmed,
|
||||
TargetConfirmationFlags aFlags,
|
||||
bool aCopyPropertiesFromCurrent);
|
||||
|
||||
/**
|
||||
@ -157,21 +157,21 @@ private:
|
||||
CancelableBlockState* aBlock);
|
||||
|
||||
nsEventStatus ReceiveTouchInput(const RefPtr<AsyncPanZoomController>& aTarget,
|
||||
bool aTargetConfirmed,
|
||||
TargetConfirmationFlags aFlags,
|
||||
const MultiTouchInput& aEvent,
|
||||
uint64_t* aOutInputBlockId);
|
||||
nsEventStatus ReceiveMouseInput(const RefPtr<AsyncPanZoomController>& aTarget,
|
||||
bool aTargetConfirmed,
|
||||
TargetConfirmationFlags aFlags,
|
||||
const MouseInput& aEvent,
|
||||
uint64_t* aOutInputBlockId);
|
||||
nsEventStatus ReceiveScrollWheelInput(const RefPtr<AsyncPanZoomController>& aTarget,
|
||||
bool aTargetConfirmed,
|
||||
TargetConfirmationFlags aFlags,
|
||||
const ScrollWheelInput& aEvent,
|
||||
uint64_t* aOutInputBlockId);
|
||||
nsEventStatus ReceivePanGestureInput(const RefPtr<AsyncPanZoomController>& aTarget,
|
||||
bool aTargetConfirmed,
|
||||
const PanGestureInput& aEvent,
|
||||
uint64_t* aOutInputBlockId);
|
||||
TargetConfirmationFlags aFlags,
|
||||
const PanGestureInput& aEvent,
|
||||
uint64_t* aOutInputBlockId);
|
||||
nsEventStatus ReceiveKeyboardInput(const RefPtr<AsyncPanZoomController>& aTarget,
|
||||
const KeyboardInput& aEvent,
|
||||
uint64_t* aOutInputBlockId);
|
||||
|
@ -217,7 +217,7 @@ public:
|
||||
}
|
||||
|
||||
nsEventStatus ReceiveInputEvent(const InputData& aEvent, uint64_t* aOutInputBlockId) {
|
||||
return GetInputQueue()->ReceiveInputEvent(this, !mWaitForMainThread, aEvent, aOutInputBlockId);
|
||||
return GetInputQueue()->ReceiveInputEvent(this, TargetConfirmationFlags{!mWaitForMainThread}, aEvent, aOutInputBlockId);
|
||||
}
|
||||
|
||||
void ContentReceivedInputBlock(uint64_t aInputBlockId, bool aPreventDefault) {
|
||||
|
@ -364,11 +364,8 @@ FPSCounter::WriteFrameTimeStamps()
|
||||
WriteFrameTimeStamps(fd);
|
||||
PR_Close(fd);
|
||||
|
||||
nsAutoCString path;
|
||||
rv = resultFile->GetNativePath(path);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
printf_stderr("Wrote FPS data to file: %s\n", path.get());
|
||||
printf_stderr("Wrote FPS data to file: %s\n",
|
||||
resultFile->HumanReadablePath().get());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -46,9 +46,15 @@ enum class CompositorHitTestInfo : uint16_t {
|
||||
// one (if set) or a horizontal one (if not set)
|
||||
eScrollbarVertical = 1 << 8,
|
||||
|
||||
// Events targeting this frame should only be processed if a target
|
||||
// confirmation is received from the main thread. If no such confirmation
|
||||
// is received within a timeout period, the event may be dropped.
|
||||
// Only meaningful in combination with eDispatchToContent.
|
||||
eRequiresTargetConfirmation = 1 << 9,
|
||||
|
||||
// Used for IPDL serialization. This bitmask should include all the bits
|
||||
// that are defined in the enum.
|
||||
ALL_BITS = (1 << 9) - 1,
|
||||
ALL_BITS = (1 << 10) - 1,
|
||||
};
|
||||
|
||||
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(CompositorHitTestInfo)
|
||||
|
@ -566,7 +566,7 @@ void RecordingPrefChanged(const char *aPrefName, void *aClosure)
|
||||
nsAutoString prefFileName;
|
||||
nsresult rv = Preferences::GetString("gfx.2d.recordingfile", prefFileName);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
fileName.Append(NS_ConvertUTF16toUTF8(prefFileName));
|
||||
CopyUTF16toUTF8(prefFileName, fileName);
|
||||
} else {
|
||||
nsCOMPtr<nsIFile> tmpFile;
|
||||
if (NS_FAILED(NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(tmpFile)))) {
|
||||
@ -578,12 +578,21 @@ void RecordingPrefChanged(const char *aPrefName, void *aClosure)
|
||||
if (NS_FAILED(rv))
|
||||
return;
|
||||
|
||||
#ifdef XP_WIN
|
||||
rv = tmpFile->GetPath(prefFileName);
|
||||
CopyUTF16toUTF8(prefFileName, fileName);
|
||||
#else
|
||||
rv = tmpFile->GetNativePath(fileName);
|
||||
#endif
|
||||
if (NS_FAILED(rv))
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef XP_WIN
|
||||
gPlatform->mRecorder = Factory::CreateEventRecorderForFile(prefFileName.BeginReading());
|
||||
#else
|
||||
gPlatform->mRecorder = Factory::CreateEventRecorderForFile(fileName.BeginReading());
|
||||
#endif
|
||||
printf_stderr("Recording to %s\n", fileName.get());
|
||||
Factory::SetGlobalEventRecorder(gPlatform->mRecorder);
|
||||
} else {
|
||||
@ -675,11 +684,11 @@ gfxPlatform::Init()
|
||||
nsCOMPtr<nsIFile> file;
|
||||
nsresult rv = NS_GetSpecialDirectory(NS_GRE_DIR, getter_AddRefs(file));
|
||||
if (NS_FAILED(rv)) {
|
||||
gfxVars::SetGREDirectory(nsCString());
|
||||
gfxVars::SetGREDirectory(nsString());
|
||||
} else {
|
||||
nsAutoCString nativePath;
|
||||
file->GetNativePath(nativePath);
|
||||
gfxVars::SetGREDirectory(nsCString(nativePath));
|
||||
nsAutoString path;
|
||||
file->GetPath(path);
|
||||
gfxVars::SetGREDirectory(nsString(path));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,7 @@
|
||||
*/
|
||||
|
||||
|
||||
/* fluent@0.6.0 */
|
||||
/* fluent@0.6.3 */
|
||||
|
||||
const { Localization } =
|
||||
ChromeUtils.import("resource://gre/modules/Localization.jsm", {});
|
||||
@ -31,36 +31,36 @@ const reOverlay = /<|&#?\w+;/;
|
||||
* Source: https://www.w3.org/TR/html5/text-level-semantics.html
|
||||
*/
|
||||
const LOCALIZABLE_ELEMENTS = {
|
||||
'http://www.w3.org/1999/xhtml': [
|
||||
'a', 'em', 'strong', 'small', 's', 'cite', 'q', 'dfn', 'abbr', 'data',
|
||||
'time', 'code', 'var', 'samp', 'kbd', 'sub', 'sup', 'i', 'b', 'u',
|
||||
'mark', 'ruby', 'rt', 'rp', 'bdi', 'bdo', 'span', 'br', 'wbr'
|
||||
"http://www.w3.org/1999/xhtml": [
|
||||
"a", "em", "strong", "small", "s", "cite", "q", "dfn", "abbr", "data",
|
||||
"time", "code", "var", "samp", "kbd", "sub", "sup", "i", "b", "u",
|
||||
"mark", "ruby", "rt", "rp", "bdi", "bdo", "span", "br", "wbr"
|
||||
],
|
||||
};
|
||||
|
||||
const LOCALIZABLE_ATTRIBUTES = {
|
||||
'http://www.w3.org/1999/xhtml': {
|
||||
global: ['title', 'aria-label', 'aria-valuetext', 'aria-moz-hint'],
|
||||
a: ['download'],
|
||||
area: ['download', 'alt'],
|
||||
"http://www.w3.org/1999/xhtml": {
|
||||
global: ["title", "aria-label", "aria-valuetext", "aria-moz-hint"],
|
||||
a: ["download"],
|
||||
area: ["download", "alt"],
|
||||
// value is special-cased in isAttrNameLocalizable
|
||||
input: ['alt', 'placeholder'],
|
||||
menuitem: ['label'],
|
||||
menu: ['label'],
|
||||
optgroup: ['label'],
|
||||
option: ['label'],
|
||||
track: ['label'],
|
||||
img: ['alt'],
|
||||
textarea: ['placeholder'],
|
||||
th: ['abbr']
|
||||
input: ["alt", "placeholder"],
|
||||
menuitem: ["label"],
|
||||
menu: ["label"],
|
||||
optgroup: ["label"],
|
||||
option: ["label"],
|
||||
track: ["label"],
|
||||
img: ["alt"],
|
||||
textarea: ["placeholder"],
|
||||
th: ["abbr"]
|
||||
},
|
||||
'http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul': {
|
||||
"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul": {
|
||||
global: [
|
||||
'accesskey', 'aria-label', 'aria-valuetext', 'aria-moz-hint', 'label'
|
||||
"accesskey", "aria-label", "aria-valuetext", "aria-moz-hint", "label"
|
||||
],
|
||||
key: ['key', 'keycode'],
|
||||
textbox: ['placeholder'],
|
||||
toolbarbutton: ['tooltiptext'],
|
||||
key: ["key", "keycode"],
|
||||
textbox: ["placeholder"],
|
||||
toolbarbutton: ["tooltiptext"],
|
||||
}
|
||||
};
|
||||
|
||||
@ -75,7 +75,7 @@ const LOCALIZABLE_ATTRIBUTES = {
|
||||
function overlayElement(targetElement, translation) {
|
||||
const value = translation.value;
|
||||
|
||||
if (typeof value === 'string') {
|
||||
if (typeof value === "string") {
|
||||
if (!reOverlay.test(value)) {
|
||||
// If the translation doesn't contain any markup skip the overlay logic.
|
||||
targetElement.textContent = value;
|
||||
@ -83,7 +83,8 @@ function overlayElement(targetElement, translation) {
|
||||
// Else parse the translation's HTML using an inert template element,
|
||||
// sanitize it and replace the targetElement's content.
|
||||
const templateElement = targetElement.ownerDocument.createElementNS(
|
||||
'http://www.w3.org/1999/xhtml', 'template');
|
||||
"http://www.w3.org/1999/xhtml", "template");
|
||||
// eslint-disable-next-line no-unsanitized/property
|
||||
templateElement.innerHTML = value;
|
||||
targetElement.appendChild(
|
||||
// The targetElement will be cleared at the end of sanitization.
|
||||
@ -92,9 +93,9 @@ function overlayElement(targetElement, translation) {
|
||||
}
|
||||
}
|
||||
|
||||
const explicitlyAllowed = targetElement.hasAttribute('data-l10n-attrs')
|
||||
? targetElement.getAttribute('data-l10n-attrs')
|
||||
.split(',').map(i => i.trim())
|
||||
const explicitlyAllowed = targetElement.hasAttribute("data-l10n-attrs")
|
||||
? targetElement.getAttribute("data-l10n-attrs")
|
||||
.split(",").map(i => i.trim())
|
||||
: null;
|
||||
|
||||
// Remove localizable attributes which may have been set by a previous
|
||||
@ -182,7 +183,7 @@ function sanitizeUsing(translationFragment, sourceElement) {
|
||||
|
||||
// SourceElement might have been already modified by shiftNamedElement.
|
||||
// Let's clear it to make sure other code doesn't rely on random leftovers.
|
||||
sourceElement.textContent = '';
|
||||
sourceElement.textContent = "";
|
||||
|
||||
return translationFragment;
|
||||
}
|
||||
@ -274,10 +275,10 @@ function isAttrNameLocalizable(name, element, explicitlyAllowed = null) {
|
||||
}
|
||||
|
||||
// Special case for value on HTML inputs with type button, reset, submit
|
||||
if (element.namespaceURI === 'http://www.w3.org/1999/xhtml' &&
|
||||
elemName === 'input' && attrName === 'value') {
|
||||
if (element.namespaceURI === "http://www.w3.org/1999/xhtml" &&
|
||||
elemName === "input" && attrName === "value") {
|
||||
const type = element.type.toLowerCase();
|
||||
if (type === 'submit' || type === 'button' || type === 'reset') {
|
||||
if (type === "submit" || type === "button" || type === "reset") {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -303,8 +304,8 @@ function shiftNamedElement(element, localName) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const L10NID_ATTR_NAME = 'data-l10n-id';
|
||||
const L10NARGS_ATTR_NAME = 'data-l10n-args';
|
||||
const L10NID_ATTR_NAME = "data-l10n-id";
|
||||
const L10NARGS_ATTR_NAME = "data-l10n-args";
|
||||
|
||||
const L10N_ELEMENT_QUERY = `[${L10NID_ATTR_NAME}]`;
|
||||
|
||||
@ -430,7 +431,7 @@ class DOMLocalization extends Localization {
|
||||
if (root === newRoot ||
|
||||
root.contains(newRoot) ||
|
||||
newRoot.contains(root)) {
|
||||
throw new Error('Cannot add a root that overlaps with existing root.');
|
||||
throw new Error("Cannot add a root that overlaps with existing root.");
|
||||
}
|
||||
}
|
||||
|
||||
@ -500,10 +501,10 @@ class DOMLocalization extends Localization {
|
||||
translateMutations(mutations) {
|
||||
for (const mutation of mutations) {
|
||||
switch (mutation.type) {
|
||||
case 'attributes':
|
||||
case "attributes":
|
||||
this.pendingElements.add(mutation.target);
|
||||
break;
|
||||
case 'childList':
|
||||
case "childList":
|
||||
for (const addedNode of mutation.addedNodes) {
|
||||
if (addedNode.nodeType === addedNode.ELEMENT_NODE) {
|
||||
if (addedNode.childElementCount) {
|
||||
@ -600,7 +601,7 @@ class DOMLocalization extends Localization {
|
||||
getTranslatables(element) {
|
||||
const nodes = Array.from(element.querySelectorAll(L10N_ELEMENT_QUERY));
|
||||
|
||||
if (typeof element.hasAttribute === 'function' &&
|
||||
if (typeof element.hasAttribute === "function" &&
|
||||
element.hasAttribute(L10NID_ATTR_NAME)) {
|
||||
nodes.push(element);
|
||||
}
|
||||
@ -625,4 +626,4 @@ class DOMLocalization extends Localization {
|
||||
}
|
||||
|
||||
this.DOMLocalization = DOMLocalization;
|
||||
this.EXPORTED_SYMBOLS = ['DOMLocalization'];
|
||||
this.EXPORTED_SYMBOLS = ["DOMLocalization"];
|
||||
|
@ -1,7 +1,7 @@
|
||||
const { AppConstants } = ChromeUtils.import("resource://gre/modules/AppConstants.jsm", {});
|
||||
const { Services } = ChromeUtils.import('resource://gre/modules/Services.jsm', {});
|
||||
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm", {});
|
||||
const { MessageContext } = ChromeUtils.import("resource://gre/modules/MessageContext.jsm", {});
|
||||
Components.utils.importGlobalProperties(["fetch"]); /* globals fetch */
|
||||
Cu.importGlobalProperties(["fetch"]);
|
||||
|
||||
/**
|
||||
* L10nRegistry is a localization resource management system for Gecko.
|
||||
@ -89,7 +89,7 @@ const L10nRegistry = {
|
||||
* @param {Array} resourceIds
|
||||
* @returns {AsyncIterator<MessageContext>}
|
||||
*/
|
||||
async * generateContexts(requestedLangs, resourceIds) {
|
||||
async* generateContexts(requestedLangs, resourceIds) {
|
||||
if (this.bootstrap !== null) {
|
||||
await this.bootstrap;
|
||||
}
|
||||
@ -109,7 +109,7 @@ const L10nRegistry = {
|
||||
throw new Error(`Source with name "${source.name}" already registered.`);
|
||||
}
|
||||
this.sources.set(source.name, source);
|
||||
Services.obs.notifyObservers(null, 'l10n:available-locales-changed', null);
|
||||
Services.locale.setAvailableLocales(this.getAvailableLocales());
|
||||
},
|
||||
|
||||
/**
|
||||
@ -126,7 +126,7 @@ const L10nRegistry = {
|
||||
}
|
||||
this.sources.set(source.name, source);
|
||||
this.ctxCache.clear();
|
||||
Services.obs.notifyObservers(null, 'l10n:available-locales-changed', null);
|
||||
Services.locale.setAvailableLocales(this.getAvailableLocales());
|
||||
},
|
||||
|
||||
/**
|
||||
@ -136,7 +136,7 @@ const L10nRegistry = {
|
||||
*/
|
||||
removeSource(sourceName) {
|
||||
this.sources.delete(sourceName);
|
||||
Services.obs.notifyObservers(null, 'l10n:available-locales-changed', null);
|
||||
Services.locale.setAvailableLocales(this.getAvailableLocales());
|
||||
},
|
||||
|
||||
/**
|
||||
@ -167,8 +167,8 @@ const L10nRegistry = {
|
||||
* @returns {String}
|
||||
*/
|
||||
function generateContextID(locale, sourcesOrder, resourceIds) {
|
||||
const sources = sourcesOrder.join(',');
|
||||
const ids = resourceIds.join(',');
|
||||
const sources = sourcesOrder.join(",");
|
||||
const ids = resourceIds.join(",");
|
||||
return `${locale}|${sources}|${ids}`;
|
||||
}
|
||||
|
||||
@ -219,7 +219,7 @@ async function* generateContextsForLocale(locale, sourcesOrder, resourceIds, res
|
||||
}
|
||||
}
|
||||
|
||||
const MSG_CONTEXT_OPTIONS = {
|
||||
const MSG_CONTEXT_OPTIONS = {
|
||||
// Temporarily disable bidi isolation due to Microsoft not supporting FSI/PDI.
|
||||
// See bug 1439018 for details.
|
||||
useIsolating: Services.prefs.getBoolPref("intl.l10n.enable-bidi-marks", false),
|
||||
@ -242,7 +242,7 @@ const MSG_CONTEXT_OPTIONS = {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Generates a single MessageContext by loading all resources
|
||||
@ -360,11 +360,9 @@ class FileSource {
|
||||
if (this.cache[fullPath].then) {
|
||||
return this.cache[fullPath];
|
||||
}
|
||||
} else {
|
||||
if (this.indexed) {
|
||||
} else if (this.indexed) {
|
||||
return Promise.reject(`The source has no resources for path "${fullPath}"`);
|
||||
}
|
||||
}
|
||||
return this.cache[fullPath] = L10nRegistry.load(fullPath).then(
|
||||
data => {
|
||||
return this.cache[fullPath] = data;
|
||||
@ -417,7 +415,7 @@ L10nRegistry.load = function(url) {
|
||||
if (!response.ok) {
|
||||
return Promise.reject(response.statusText);
|
||||
}
|
||||
return response.text()
|
||||
return response.text();
|
||||
});
|
||||
};
|
||||
|
||||
@ -425,4 +423,4 @@ this.L10nRegistry = L10nRegistry;
|
||||
this.FileSource = FileSource;
|
||||
this.IndexedFileSource = IndexedFileSource;
|
||||
|
||||
this.EXPORTED_SYMBOLS = ['L10nRegistry', 'FileSource', 'IndexedFileSource'];
|
||||
this.EXPORTED_SYMBOLS = ["L10nRegistry", "FileSource", "IndexedFileSource"];
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user