Merge autoland to central, a=merge

MozReview-Commit-ID: GRzdZQPAUxX
This commit is contained in:
Wes Kocher 2017-03-15 14:05:40 -07:00
Родитель 571c1fd0ba a5a69068c1
Коммит b58de4b0cc
113 изменённых файлов: 2789 добавлений и 1123 удалений

Просмотреть файл

@ -1256,10 +1256,10 @@ pref("dom.debug.propagate_gesture_events_through_content", false);
// All the Geolocation preferences are here.
//
// Geolocation preferences for the RELEASE channel.
// Geolocation preferences for the RELEASE and "later" Beta channels.
// Some of these prefs are specified even though they are redundant; they are
// here for clarity and end-user experiments.
#ifdef RELEASE
#ifndef EARLY_BETA_OR_EARLIER
pref("geo.wifi.uri", "https://www.googleapis.com/geolocation/v1/geolocate?key=%GOOGLE_API_KEY%");
#ifdef XP_MACOSX

Просмотреть файл

@ -19,7 +19,7 @@ add_task(function* checkReturnToAboutHome() {
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, () => {
gBrowser.selectedTab = gBrowser.addTab(BAD_CERT);
browser = gBrowser.selectedBrowser;
certErrorLoaded = waitForCertErrorLoad(browser);
certErrorLoaded = BrowserTestUtils.waitForErrorPage(browser);
}, false);
info("Loading and waiting for the cert error");
@ -57,7 +57,7 @@ add_task(function* checkReturnToPreviousPage() {
let browser = gBrowser.selectedBrowser;
info("Loading and waiting for the cert error");
let certErrorLoaded = waitForCertErrorLoad(browser);
let certErrorLoaded = BrowserTestUtils.waitForErrorPage(browser);
BrowserTestUtils.loadURI(browser, BAD_CERT);
yield certErrorLoaded;
@ -92,7 +92,7 @@ add_task(function* checkBadStsCert() {
let browser = gBrowser.selectedBrowser;
info("Loading and waiting for the cert error");
let certErrorLoaded = waitForCertErrorLoad(browser);
let certErrorLoaded = BrowserTestUtils.waitForErrorPage(browser);
BrowserTestUtils.loadURI(browser, BAD_STS_CERT);
yield certErrorLoaded;
@ -128,7 +128,7 @@ add_task(function* checkWrongSystemTimeWarning() {
yield BrowserTestUtils.openNewForegroundTab(gBrowser, () => {
gBrowser.selectedTab = gBrowser.addTab(BAD_CERT);
browser = gBrowser.selectedBrowser;
certErrorLoaded = waitForCertErrorLoad(browser);
certErrorLoaded = BrowserTestUtils.waitForErrorPage(browser);
}, false);
info("Loading and waiting for the cert error");
@ -224,7 +224,7 @@ add_task(function* checkAdvancedDetails() {
yield BrowserTestUtils.openNewForegroundTab(gBrowser, () => {
gBrowser.selectedTab = gBrowser.addTab(BAD_CERT);
browser = gBrowser.selectedBrowser;
certErrorLoaded = waitForCertErrorLoad(browser);
certErrorLoaded = BrowserTestUtils.waitForErrorPage(browser);
}, false);
info("Loading and waiting for the cert error");
@ -286,7 +286,7 @@ add_task(function* checkAdvancedDetailsForHSTS() {
yield BrowserTestUtils.openNewForegroundTab(gBrowser, () => {
gBrowser.selectedTab = gBrowser.addTab(BAD_STS_CERT);
browser = gBrowser.selectedBrowser;
certErrorLoaded = waitForCertErrorLoad(browser);
certErrorLoaded = BrowserTestUtils.waitForErrorPage(browser);
}, false);
info("Loading and waiting for the cert error");
@ -355,7 +355,7 @@ add_task(function* checkUnknownIssuerLearnMoreLink() {
yield BrowserTestUtils.openNewForegroundTab(gBrowser, () => {
gBrowser.selectedTab = gBrowser.addTab(UNKNOWN_ISSUER);
browser = gBrowser.selectedBrowser;
certErrorLoaded = waitForCertErrorLoad(browser);
certErrorLoaded = BrowserTestUtils.waitForErrorPage(browser);
}, false);
info("Loading and waiting for the cert error");
@ -370,16 +370,6 @@ add_task(function* checkUnknownIssuerLearnMoreLink() {
yield BrowserTestUtils.removeTab(gBrowser.selectedTab);
});
function waitForCertErrorLoad(browser) {
return new Promise(resolve => {
info("Waiting for DOMContentLoaded event");
browser.addEventListener("DOMContentLoaded", function load() {
browser.removeEventListener("DOMContentLoaded", load, false, true);
resolve();
}, false, true);
});
}
function getCertChain(securityInfoAsString) {
let certChain = "";
const serhelper = Cc["@mozilla.org/network/serialization-helper;1"]

Просмотреть файл

@ -81,16 +81,16 @@ function dateToChromeTime(aDate) {
}
/**
* Insert bookmark items into specific folder.
* Converts an array of chrome bookmark objects into one our own places code
* understands.
*
* @param parentGuid
* GUID of the folder where items will be inserted
* @param items
* bookmark items to be inserted
* bookmark items to be inserted on this parent
* @param errorAccumulator
* function that gets called with any errors thrown so we don't drop them on the floor.
*/
function* insertBookmarkItems(parentGuid, items, errorAccumulator) {
function convertBookmarks(items, errorAccumulator) {
let itemsToInsert = [];
for (let item of items) {
try {
if (item.type == "url") {
@ -99,21 +99,18 @@ function* insertBookmarkItems(parentGuid, items, errorAccumulator) {
// messages to the console, so we avoid doing that.
continue;
}
yield MigrationUtils.insertBookmarkWrapper({
parentGuid, url: item.url, title: item.name
});
itemsToInsert.push({url: item.url, title: item.name});
} else if (item.type == "folder") {
let newFolderGuid = (yield MigrationUtils.insertBookmarkWrapper({
parentGuid, type: PlacesUtils.bookmarks.TYPE_FOLDER, title: item.name
})).guid;
yield insertBookmarkItems(newFolderGuid, item.children, errorAccumulator);
let folderItem = {type: PlacesUtils.bookmarks.TYPE_FOLDER, title: item.name};
folderItem.children = convertBookmarks(item.children, errorAccumulator);
itemsToInsert.push(folderItem);
}
} catch (e) {
Cu.reportError(e);
errorAccumulator(e);
} catch (ex) {
Cu.reportError(ex);
errorAccumulator(ex);
}
}
return itemsToInsert;
}
function ChromeProfileMigrator() {
@ -260,23 +257,8 @@ function GetBookmarksResource(aProfileFolder) {
return Task.spawn(function* () {
let gotErrors = false;
let errorGatherer = function() { gotErrors = true };
let jsonStream = yield new Promise((resolve, reject) => {
let options = {
uri: NetUtil.newURI(bookmarksFile),
loadUsingSystemPrincipal: true
};
NetUtil.asyncFetch(options, (inputStream, resultCode) => {
if (Components.isSuccessCode(resultCode)) {
resolve(inputStream);
} else {
reject(new Error("Could not read Bookmarks file"));
}
});
});
// Parse Chrome bookmark file that is JSON format
let bookmarkJSON = NetUtil.readInputStreamToString(
jsonStream, jsonStream.available(), { charset : "UTF-8" });
let bookmarkJSON = yield OS.File.read(bookmarksFile.path, {encoding: "UTF-8"});
let roots = JSON.parse(bookmarkJSON).roots;
// Importing bookmark bar items
@ -284,11 +266,12 @@ function GetBookmarksResource(aProfileFolder) {
roots.bookmark_bar.children.length > 0) {
// Toolbar
let parentGuid = PlacesUtils.bookmarks.toolbarGuid;
let bookmarks = convertBookmarks(roots.bookmark_bar.children, errorGatherer);
if (!MigrationUtils.isStartupMigration) {
parentGuid =
yield MigrationUtils.createImportedBookmarksFolder("Chrome", parentGuid);
}
yield insertBookmarkItems(parentGuid, roots.bookmark_bar.children, errorGatherer);
yield MigrationUtils.insertManyBookmarksWrapper(bookmarks, parentGuid);
}
// Importing bookmark menu items
@ -296,11 +279,12 @@ function GetBookmarksResource(aProfileFolder) {
roots.other.children.length > 0) {
// Bookmark menu
let parentGuid = PlacesUtils.bookmarks.menuGuid;
let bookmarks = convertBookmarks(roots.other.children, errorGatherer);
if (!MigrationUtils.isStartupMigration) {
parentGuid =
yield MigrationUtils.createImportedBookmarksFolder("Chrome", parentGuid);
parentGuid
= yield MigrationUtils.createImportedBookmarksFolder("Chrome", parentGuid);
}
yield insertBookmarkItems(parentGuid, roots.other.children, errorGatherer);
yield MigrationUtils.insertManyBookmarksWrapper(bookmarks, parentGuid);
}
if (gotErrors) {
throw new Error("The migration included errors.");

Просмотреть файл

@ -18,6 +18,8 @@ XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
XPCOMUtils.defineLazyModuleGetter(this, "ESEDBReader",
"resource:///modules/ESEDBReader.jsm");
Cu.importGlobalProperties(["URL"]);
const kEdgeRegistryRoot = "SOFTWARE\\Classes\\Local Settings\\Software\\" +
"Microsoft\\Windows\\CurrentVersion\\AppContainer\\Storage\\" +
"microsoft.microsoftedge_8wekyb3d8bbwe\\MicrosoftEdge";
@ -194,21 +196,18 @@ EdgeReadingListMigrator.prototype = {
}
let destFolderGuid = yield this._ensureReadingListFolder(parentGuid);
let exceptionThrown;
let bookmarks = [];
for (let item of readingListItems) {
let dateAdded = item.AddedDate || new Date();
yield MigrationUtils.insertBookmarkWrapper({
parentGuid: destFolderGuid, url: item.URL, title: item.Title, dateAdded
}).catch(ex => {
if (!exceptionThrown) {
exceptionThrown = ex;
}
Cu.reportError(ex);
});
}
if (exceptionThrown) {
throw exceptionThrown;
// Avoid including broken URLs:
try {
new URL(item.URL);
} catch (ex) {
continue;
}
bookmarks.push({ url: item.URL, title: item.Title, dateAdded });
}
yield MigrationUtils.insertManyBookmarksWrapper(readingListItems, destFolderGuid);
}),
_ensureReadingListFolder: Task.async(function*(parentGuid) {
@ -240,7 +239,7 @@ EdgeBookmarksMigrator.prototype = {
},
migrate(callback) {
this._migrateBookmarks(PlacesUtils.bookmarks.menuGuid).then(
this._migrateBookmarks().then(
() => callback(true),
ex => {
Cu.reportError(ex);
@ -249,64 +248,21 @@ EdgeBookmarksMigrator.prototype = {
);
},
_migrateBookmarks: Task.async(function*(rootGuid) {
let {bookmarks, folderMap} = this._fetchBookmarksFromDB();
if (!bookmarks.length) {
return;
}
yield this._importBookmarks(bookmarks, folderMap, rootGuid);
}),
_importBookmarks: Task.async(function*(bookmarks, folderMap, rootGuid) {
if (!MigrationUtils.isStartupMigration) {
rootGuid =
yield MigrationUtils.createImportedBookmarksFolder("Edge", rootGuid);
}
let exceptionThrown;
for (let bookmark of bookmarks) {
// If this is a folder, we might have created it already to put other bookmarks in.
if (bookmark.IsFolder && bookmark._guid) {
continue;
_migrateBookmarks: Task.async(function*() {
let {toplevelBMs, toolbarBMs} = this._fetchBookmarksFromDB();
if (toplevelBMs.length) {
let parentGuid = PlacesUtils.bookmarks.menuGuid;
if (!MigrationUtils.isStartupMigration) {
parentGuid = yield MigrationUtils.createImportedBookmarksFolder("Edge", parentGuid);
}
// If this is a folder, just create folders up to and including that folder.
// Otherwise, create folders until we have a parent for this bookmark.
// This avoids duplicating logic for the bookmarks bar.
let folderId = bookmark.IsFolder ? bookmark.ItemId : bookmark.ParentId;
let parentGuid = yield this._getGuidForFolder(folderId, folderMap, rootGuid).catch(ex => {
if (!exceptionThrown) {
exceptionThrown = ex;
}
Cu.reportError(ex);
});
// If this was a folder, we're done with this item
if (bookmark.IsFolder) {
continue;
}
if (!parentGuid) {
// If we couldn't sort out a parent, fall back to importing on the root:
parentGuid = rootGuid;
}
let placesInfo = {
parentGuid,
url: bookmark.URL,
dateAdded: bookmark.DateUpdated || new Date(),
title: bookmark.Title,
};
yield MigrationUtils.insertBookmarkWrapper(placesInfo).catch(ex => {
if (!exceptionThrown) {
exceptionThrown = ex;
}
Cu.reportError(ex);
});
yield MigrationUtils.insertManyBookmarksWrapper(toplevelBMs, parentGuid);
}
if (exceptionThrown) {
throw exceptionThrown;
if (toolbarBMs.length) {
let parentGuid = PlacesUtils.bookmarks.toolbarGuid;
if (!MigrationUtils.isStartupMigration) {
parentGuid = yield MigrationUtils.createImportedBookmarksFolder("Edge", parentGuid);
}
yield MigrationUtils.insertManyBookmarksWrapper(toolbarBMs, parentGuid);
}
}),
@ -331,44 +287,54 @@ EdgeBookmarksMigrator.prototype = {
return true;
};
let bookmarks = readTableFromEdgeDB(this.TABLE_NAME, columns, filterFn, this.db);
return {bookmarks, folderMap};
},
_getGuidForFolder: Task.async(function*(folderId, folderMap, rootGuid) {
// If the folderId is not known as a folder in the folder map, we assume
// we just need the root
if (!folderMap.has(folderId)) {
return rootGuid;
}
let folder = folderMap.get(folderId);
// If the folder already has a places guid, just return that.
if (folder._guid) {
return folder._guid;
}
// Hacks! The bookmarks bar is special:
if (folder.Title == "_Favorites_Bar_") {
let toolbarGuid = PlacesUtils.bookmarks.toolbarGuid;
if (!MigrationUtils.isStartupMigration) {
toolbarGuid =
yield MigrationUtils.createImportedBookmarksFolder("Edge", toolbarGuid);
let toplevelBMs = [], toolbarBMs = [];
for (let bookmark of bookmarks) {
let bmToInsert;
// Ignore invalid URLs:
if (!bookmark.IsFolder) {
try {
new URL(bookmark.URL);
} catch (ex) {
Cu.reportError(`Ignoring ${bookmark.URL} when importing from Edge because of exception: ${ex}`);
continue;
}
bmToInsert = {
dateAdded: bookmark.DateUpdated || new Date(),
title: bookmark.Title,
url: bookmark.URL,
};
} else /* bookmark.IsFolder */ {
// Ignore the favorites bar bookmark itself.
if (bookmark.Title == "_Favorites_Bar_") {
continue;
}
if (!bookmark._childrenRef) {
bookmark._childrenRef = [];
}
bmToInsert = {
title: bookmark.Title,
type: PlacesUtils.bookmarks.TYPE_FOLDER,
dateAdded: bookmark.DateUpdated || new Date(),
children: bookmark._childrenRef,
};
}
if (!folderMap.has(bookmark.ParentId)) {
toplevelBMs.push(bmToInsert);
} else {
let parent = folderMap.get(bookmark.ParentId);
if (parent.Title == "_Favorites_Bar_") {
toolbarBMs.push(bmToInsert);
continue;
}
if (!parent._childrenRef) {
parent._childrenRef = [];
}
parent._childrenRef.push(bmToInsert);
}
folder._guid = toolbarGuid;
return folder._guid;
}
// Otherwise, get the right parent guid recursively:
let parentGuid = yield this._getGuidForFolder(folder.ParentId, folderMap, rootGuid);
let folderInfo = {
title: folder.Title,
type: PlacesUtils.bookmarks.TYPE_FOLDER,
dateAdded: folder.DateUpdated || new Date(),
parentGuid,
};
// and add ourselves as a kid, and return the guid we got.
let parentBM = yield MigrationUtils.insertBookmarkWrapper(folderInfo);
folder._guid = parentBM.guid;
return folder._guid;
}),
return {toplevelBMs, toolbarBMs};
},
};
function EdgeProfileMigrator() {

Просмотреть файл

@ -377,12 +377,19 @@ Bookmarks.prototype = {
},
_migrateFolder: Task.async(function* (aSourceFolder, aDestFolderGuid) {
let bookmarks = yield this._getBookmarksInFolder(aSourceFolder);
if (bookmarks.length) {
yield MigrationUtils.insertManyBookmarksWrapper(bookmarks, aDestFolderGuid);
}
}),
_getBookmarksInFolder: Task.async(function* (aSourceFolder) {
// TODO (bug 741993): the favorites order is stored in the Registry, at
// HCU\Software\Microsoft\Windows\CurrentVersion\Explorer\MenuOrder\Favorites
// for IE, and in a similar location for Edge.
// Until we support it, bookmarks are imported in alphabetical order.
let entries = aSourceFolder.directoryEntries;
let succeeded = true;
let rv = [];
while (entries.hasMoreElements()) {
let entry = entries.getNext().QueryInterface(Ci.nsIFile);
try {
@ -391,27 +398,23 @@ Bookmarks.prototype = {
// Don't use isSymlink(), since it would throw for invalid
// lnk files pointing to URLs or to unresolvable paths.
if (entry.path == entry.target && entry.isDirectory()) {
let folderGuid;
if (entry.leafName == this._toolbarFolderName &&
entry.parent.equals(this._favoritesFolder)) {
let isBookmarksFolder = entry.leafName == this._toolbarFolderName &&
entry.parent.equals(this._favoritesFolder);
if (isBookmarksFolder && entry.isReadable()) {
// Import to the bookmarks toolbar.
folderGuid = PlacesUtils.bookmarks.toolbarGuid;
let folderGuid = PlacesUtils.bookmarks.toolbarGuid;
if (!MigrationUtils.isStartupMigration) {
folderGuid =
yield MigrationUtils.createImportedBookmarksFolder(this.importedAppLabel, folderGuid);
}
} else {
// Import to a new folder.
folderGuid = (yield MigrationUtils.insertBookmarkWrapper({
type: PlacesUtils.bookmarks.TYPE_FOLDER,
parentGuid: aDestFolderGuid,
title: entry.leafName
})).guid;
}
if (entry.isReadable()) {
// Recursively import the folder.
yield this._migrateFolder(entry, folderGuid);
} else if (entry.isReadable()) {
let childBookmarks = yield this._getBookmarksInFolder(entry);
rv.push({
type: PlacesUtils.bookmarks.TYPE_FOLDER,
title: entry.leafName,
children: childBookmarks,
});
}
} else {
// Strip the .url extension, to both check this is a valid link file,
@ -421,21 +424,14 @@ Bookmarks.prototype = {
let fileHandler = Cc["@mozilla.org/network/protocol;1?name=file"].
getService(Ci.nsIFileProtocolHandler);
let uri = fileHandler.readURLFile(entry);
let title = matches[1];
yield MigrationUtils.insertBookmarkWrapper({
parentGuid: aDestFolderGuid, url: uri, title
});
rv.push({url: uri, title: matches[1]});
}
}
} catch (ex) {
Components.utils.reportError("Unable to import " + this.importedAppLabel + " favorite (" + entry.leafName + "): " + ex);
succeeded = false;
}
}
if (!succeeded) {
throw new Error("Failed to import all bookmarks correctly.");
}
return rv;
}),
};

Просмотреть файл

@ -991,6 +991,20 @@ this.MigrationUtils = Object.freeze({
});
},
insertManyBookmarksWrapper(bookmarks, parent) {
let insertionPromise = PlacesUtils.bookmarks.insertTree({guid: parent, children: bookmarks});
return insertionPromise.then(insertedItems => {
this._importQuantities.bookmarks += insertedItems.length;
if (gKeepUndoData) {
let bmData = gUndoData.get("bookmarks");
for (let bm of insertedItems) {
let {parentGuid, guid, lastModified, type} = bm;
bmData.push({parentGuid, guid, lastModified, type});
}
}
}, ex => Cu.reportError(ex));
},
insertVisitsWrapper(places, options) {
this._importQuantities.history += places.length;
if (gKeepUndoData) {

Просмотреть файл

@ -27,6 +27,8 @@ XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
XPCOMUtils.defineLazyModuleGetter(this, "FormHistory",
"resource://gre/modules/FormHistory.jsm");
Cu.importGlobalProperties(["URL"]);
function Bookmarks(aBookmarksFile) {
this._file = aBookmarksFile;
}
@ -147,33 +149,38 @@ Bookmarks.prototype = {
// migrate the given array of safari bookmarks to the given places
// folder.
_migrateEntries: Task.async(function* (entries, parentGuid) {
for (let entry of entries) {
_migrateEntries(entries, parentGuid) {
let convertedEntries = this._convertEntries(entries);
return MigrationUtils.insertManyBookmarksWrapper(convertedEntries, parentGuid);
},
_convertEntries(entries) {
return entries.map(function(entry) {
let type = entry.get("WebBookmarkType");
if (type == "WebBookmarkTypeList" && entry.has("Children")) {
let title = entry.get("Title");
let newFolderGuid = (yield MigrationUtils.insertBookmarkWrapper({
parentGuid, type: PlacesUtils.bookmarks.TYPE_FOLDER, title
})).guid;
// Empty folders may not have a children array.
if (entry.has("Children"))
yield this._migrateEntries(entry.get("Children"), newFolderGuid, false);
} else if (type == "WebBookmarkTypeLeaf" && entry.has("URLString")) {
return {
title: entry.get("Title"),
type: PlacesUtils.bookmarks.TYPE_FOLDER,
children: this._convertEntries(entry.get("Children")),
};
}
if (type == "WebBookmarkTypeLeaf" && entry.has("URLString")) {
// Check we understand this URL before adding it:
let url = entry.get("URLString");
try {
new URL(url);
} catch (ex) {
Cu.reportError(`Ignoring ${url} when importing from Safari because of exception: ${ex}`);
return null;
}
let title;
if (entry.has("URIDictionary"))
title = entry.get("URIDictionary").get("title");
try {
yield MigrationUtils.insertBookmarkWrapper({
parentGuid, url: entry.get("URLString"), title
});
} catch (ex) {
Cu.reportError("Invalid Safari bookmark: " + ex);
}
return { url, title };
}
}
})
return null;
}).filter(e => !!e);
},
};
function History(aHistoryFile) {

Просмотреть файл

@ -0,0 +1,105 @@
"use strict";
Cu.import("resource://gre/modules/AppConstants.jsm");
add_task(function* () {
let rootDir = do_get_file("chromefiles/");
let pathId;
let subDirs = ["Google", "Chrome"];
if (AppConstants.platform == "macosx") {
subDirs.unshift("Application Support");
pathId = "ULibDir";
} else if (AppConstants.platform == "win") {
subDirs.push("User Data");
pathId = "LocalAppData";
} else {
subDirs = [".config", "google-chrome"];
pathId = "Home";
}
registerFakePath(pathId, rootDir);
let target = rootDir.clone();
// Pretend this is the default profile
subDirs.push("Default");
while (subDirs.length) {
target.append(subDirs.shift());
}
// We don't import osfile.jsm until after registering the fake path, because
// importing osfile will sometimes greedily fetch certain path identifiers
// from the dir service, which means they get cached, which means we can't
// register a fake path for them anymore.
Cu.import("resource://gre/modules/osfile.jsm"); /* globals OS */
yield OS.File.makeDir(target.path, {from: rootDir.parent.path, ignoreExisting: true});
target.append("Bookmarks");
yield OS.File.remove(target.path, {ignoreAbsent: true});
let bookmarksData = {roots: {bookmark_bar: {children: []}, other: {children: []}}};
const MAX_BMS = 100;
let barKids = bookmarksData.roots.bookmark_bar.children;
let menuKids = bookmarksData.roots.other.children;
let currentMenuKids = menuKids;
let currentBarKids = barKids;
for (let i = 0; i < MAX_BMS; i++) {
currentBarKids.push({
url: "https://www.chrome-bookmark-bar-bookmark" + i + ".com",
name: "bookmark " + i,
type: "url",
});
currentMenuKids.push({
url: "https://www.chrome-menu-bookmark" + i + ".com",
name: "bookmark for menu " + i,
type: "url",
});
if (i % 20 == 19) {
let nextFolder = {
name: "toolbar folder " + Math.ceil(i / 20),
type: "folder",
children: [],
};
currentBarKids.push(nextFolder);
currentBarKids = nextFolder.children;
nextFolder = {
name: "menu folder " + Math.ceil(i / 20),
type: "folder",
children: [],
};
currentMenuKids.push(nextFolder);
currentMenuKids = nextFolder.children;
}
}
yield OS.File.writeAtomic(target.path, JSON.stringify(bookmarksData), {encoding: "utf-8"});
let migrator = MigrationUtils.getMigrator("chrome");
// Sanity check for the source.
Assert.ok(migrator.sourceExists);
let itemsSeen = {bookmarks: 0, folders: 0};
let bmObserver = {
onItemAdded(aItemId, aParentId, aIndex, aItemType, aURI, aTitle) {
if (!aTitle.includes("Chrome")) {
itemsSeen[aItemType == PlacesUtils.bookmarks.TYPE_FOLDER ? "folders" : "bookmarks"]++;
}
},
onBeginUpdateBatch() {},
onEndUpdateBatch() {},
onItemRemoved() {},
onItemChanged() {},
onItemVisited() {},
onItemMoved() {},
};
PlacesUtils.bookmarks.addObserver(bmObserver, false);
const PROFILE = {
id: "Default",
name: "Default",
};
yield promiseMigration(migrator, MigrationUtils.resourceTypes.BOOKMARKS, PROFILE);
PlacesUtils.bookmarks.removeObserver(bmObserver);
Assert.equal(itemsSeen.bookmarks, 200, "Should have seen 200 bookmarks.");
Assert.equal(itemsSeen.folders, 10, "Should have seen 10 folders.");
Assert.equal(MigrationUtils._importQuantities.bookmarks, itemsSeen.bookmarks + itemsSeen.folders, "Telemetry reporting correct.");
});

Просмотреть файл

@ -7,6 +7,7 @@ support-files =
AppData/**
[test_automigration.js]
[test_Chrome_bookmarks.js]
[test_Chrome_cookies.js]
skip-if = os != "mac" # Relies on ULibDir
[test_Chrome_passwords.js]

Просмотреть файл

@ -91,7 +91,19 @@ AutofillProfileAutoCompleteSearch.prototype = {
this.log.debug("startSearch: for", searchString, "with input", formFillController.focusedInput);
let focusedInput = formFillController.focusedInput;
this.forceStop = false;
let info = this._serializeInfo(FormAutofillContent.getInputDetails(focusedInput));
let info = FormAutofillContent.getInputDetails(focusedInput);
if (!FormAutofillContent.savedFieldNames.has(info.fieldName)) {
let formHistory = Cc["@mozilla.org/autocomplete/search;1?name=form-history"]
.createInstance(Ci.nsIAutoCompleteSearch);
formHistory.startSearch(searchString, searchParam, previousResult, {
onSearchResult: (search, result) => {
listener.onSearchResult(this, result);
ProfileAutocomplete.setProfileAutoCompleteResult(result);
},
});
return;
}
this._getProfiles({info, searchString}).then((profiles) => {
if (this.forceStop) {
@ -142,12 +154,6 @@ AutofillProfileAutoCompleteSearch.prototype = {
Services.cpmm.sendAsyncMessage("FormAutofill:GetProfiles", data);
});
},
_serializeInfo(detail) {
let info = Object.assign({}, detail);
delete info.element;
return info;
},
};
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([AutofillProfileAutoCompleteSearch]);
@ -250,20 +256,39 @@ var FormAutofillContent = {
*/
_formsDetails: new WeakMap(),
/**
* @type {Set} Set of the fields with usable values in any saved profile.
*/
savedFieldNames: null,
init() {
FormAutofillUtils.defineLazyLogGetter(this, "FormAutofillContent");
Services.cpmm.addMessageListener("FormAutofill:enabledStatus", (result) => {
if (result.data) {
ProfileAutocomplete.ensureRegistered();
} else {
ProfileAutocomplete.ensureUnregistered();
}
});
Services.cpmm.addMessageListener("FormAutofill:enabledStatus", this);
Services.cpmm.addMessageListener("FormAutofill:savedFieldNames", this);
if (Services.cpmm.initialProcessData.autofillEnabled) {
ProfileAutocomplete.ensureRegistered();
}
this.savedFieldNames =
Services.cpmm.initialProcessData.autofillSavedFieldNames || new Set();
},
receiveMessage({name, data}) {
switch (name) {
case "FormAutofill:enabledStatus": {
if (data) {
ProfileAutocomplete.ensureRegistered();
} else {
ProfileAutocomplete.ensureUnregistered();
}
break;
}
case "FormAutofill:savedFieldNames": {
this.savedFieldNames = data;
}
}
},
/**

Просмотреть файл

@ -53,15 +53,10 @@ FormAutofillHandler.prototype = {
fieldDetails: null,
/**
* Returns information from the form about fields that can be autofilled, and
* populates the fieldDetails array on this object accordingly.
*
* @returns {Array<Object>} Serializable data structure that can be sent to the user
* interface, or null if the operation failed because the constraints
* on the allowed fields were not honored.
* Set fieldDetails from the form about fields that can be autofilled.
*/
collectFormFields() {
let autofillData = [];
this.fieldDetails = [];
for (let element of this.form.elements) {
// Exclude elements to which no autocomplete field has been assigned.
@ -77,28 +72,21 @@ FormAutofillHandler.prototype = {
f.fieldName == info.fieldName)) {
// A field with the same identifier already exists.
log.debug("Not collecting a field matching another with the same info:", info);
return null;
continue;
}
let inputFormat = {
let formatWithElement = {
section: info.section,
addressType: info.addressType,
contactType: info.contactType,
fieldName: info.fieldName,
element, // TODO: Apply Cu.getWeakReference and use get API for strong ref.
};
// Clone the inputFormat for caching the fields and elements together
let formatWithElement = Object.assign({}, inputFormat);
inputFormat.index = autofillData.length;
autofillData.push(inputFormat);
formatWithElement.element = element;
this.fieldDetails.push(formatWithElement);
}
log.debug("Collected details on", autofillData.length, "fields");
return autofillData;
log.debug("Collected details on", this.fieldDetails.length, "fields");
},
/**

Просмотреть файл

@ -85,6 +85,7 @@ FormAutofillParent.prototype = {
// Force to trigger the onStatusChanged function for setting listeners properly
// while initizlization
this._setStatus(this._getStatus());
this._updateSavedFieldNames();
},
observe(subject, topic, data) {
@ -115,6 +116,7 @@ FormAutofillParent.prototype = {
break;
}
this._updateSavedFieldNames();
let currentStatus = this._getStatus();
if (currentStatus !== this._enabled) {
this._setStatus(currentStatus);
@ -244,4 +246,29 @@ FormAutofillParent.prototype = {
target.sendAsyncMessage("FormAutofill:Profiles", profiles);
},
_updateSavedFieldNames() {
if (!Services.ppmm.initialProcessData.autofillSavedFieldNames) {
Services.ppmm.initialProcessData.autofillSavedFieldNames = new Set();
} else {
Services.ppmm.initialProcessData.autofillSavedFieldNames.clear();
}
this._profileStore.getAll().forEach((profile) => {
Object.keys(profile).forEach((fieldName) => {
if (!profile[fieldName]) {
return;
}
Services.ppmm.initialProcessData.autofillSavedFieldNames.add(fieldName);
});
});
// Remove the internal guid and metadata fields.
this._profileStore.INTERNAL_FIELDS.forEach((fieldName) => {
Services.ppmm.initialProcessData.autofillSavedFieldNames.delete(fieldName);
});
Services.ppmm.broadcastAsyncMessage("FormAutofill:savedFieldNames",
Services.ppmm.initialProcessData.autofillSavedFieldNames);
},
};

Просмотреть файл

@ -92,6 +92,9 @@ function ProfileStorage(path) {
}
ProfileStorage.prototype = {
// These fields are defined internally for each profile.
INTERNAL_FIELDS:
["guid", "timeCreated", "timeLastUsed", "timeLastModified", "timesUsed"],
/**
* Loads the profile data from file to memory.
*

Просмотреть файл

@ -24,13 +24,6 @@ const TESTCASES = [
<input id="country" autocomplete="country">
<input id="email" autocomplete="email">
<input id="tel" autocomplete="tel"></form>`,
returnedFormat: [
{"section": "", "addressType": "", "contactType": "", "fieldName": "street-address", "index": 0},
{"section": "", "addressType": "", "contactType": "", "fieldName": "address-level2", "index": 1},
{"section": "", "addressType": "", "contactType": "", "fieldName": "country", "index": 2},
{"section": "", "addressType": "", "contactType": "", "fieldName": "email", "index": 3},
{"section": "", "addressType": "", "contactType": "", "fieldName": "tel", "index": 4},
],
fieldDetails: [
{"section": "", "addressType": "", "contactType": "", "fieldName": "street-address", "element": {}},
{"section": "", "addressType": "", "contactType": "", "fieldName": "address-level2", "element": {}},
@ -48,13 +41,6 @@ const TESTCASES = [
<input id="country" autocomplete="shipping country">
<input id='email' autocomplete="shipping email">
<input id="tel" autocomplete="shipping tel"></form>`,
returnedFormat: [
{"section": "", "addressType": "shipping", "contactType": "", "fieldName": "street-address", "index": 0},
{"section": "", "addressType": "shipping", "contactType": "", "fieldName": "address-level2", "index": 1},
{"section": "", "addressType": "shipping", "contactType": "", "fieldName": "country", "index": 2},
{"section": "", "addressType": "shipping", "contactType": "", "fieldName": "email", "index": 3},
{"section": "", "addressType": "shipping", "contactType": "", "fieldName": "tel", "index": 4},
],
fieldDetails: [
{"section": "", "addressType": "shipping", "contactType": "", "fieldName": "street-address", "element": {}},
{"section": "", "addressType": "shipping", "contactType": "", "fieldName": "address-level2", "element": {}},
@ -72,13 +58,6 @@ const TESTCASES = [
<input id="country" autocomplete="shipping country">
<input id='email' autocomplete="shipping email">
<input id="tel" autocomplete="shipping tel"></form>`,
returnedFormat: [
{"section": "", "addressType": "shipping", "contactType": "", "fieldName": "street-address", "index": 0},
{"section": "", "addressType": "shipping", "contactType": "", "fieldName": "address-level2", "index": 1},
{"section": "", "addressType": "shipping", "contactType": "", "fieldName": "country", "index": 2},
{"section": "", "addressType": "shipping", "contactType": "", "fieldName": "email", "index": 3},
{"section": "", "addressType": "shipping", "contactType": "", "fieldName": "tel", "index": 4},
],
fieldDetails: [
{"section": "", "addressType": "shipping", "contactType": "", "fieldName": "street-address", "element": {}},
{"section": "", "addressType": "shipping", "contactType": "", "fieldName": "address-level2", "element": {}},
@ -100,8 +79,7 @@ for (let tc of TESTCASES) {
let form = doc.querySelector("form");
let handler = new FormAutofillHandler(form);
Assert.deepEqual(handler.collectFormFields(), testcase.returnedFormat,
"Check the format of form autofill were returned correctly");
handler.collectFormFields();
Assert.deepEqual(handler.fieldDetails, testcase.fieldDetails,
"Check the fieldDetails were set correctly");

Просмотреть файл

@ -25,6 +25,7 @@ add_task(function* test_enabledStatus_observe() {
let formAutofillParent = new FormAutofillParent();
sinon.stub(formAutofillParent, "_getStatus");
sinon.spy(formAutofillParent, "_setStatus");
sinon.stub(formAutofillParent, "_updateSavedFieldNames");
// _enabled = _getStatus() => No need to trigger onStatusChanged
formAutofillParent._enabled = true;

Просмотреть файл

@ -0,0 +1,89 @@
/*
* Test for keeping the valid fields information in initialProcessData.
*/
"use strict";
Cu.import("resource://formautofill/FormAutofillParent.jsm");
Cu.import("resource://formautofill/ProfileStorage.jsm");
add_task(function* test_profileSavedFieldNames_init() {
let formAutofillParent = new FormAutofillParent();
sinon.stub(formAutofillParent, "_updateSavedFieldNames");
formAutofillParent.init();
do_check_eq(formAutofillParent._updateSavedFieldNames.called, true);
formAutofillParent._uninit();
});
add_task(function* test_profileSavedFieldNames_observe() {
let formAutofillParent = new FormAutofillParent();
sinon.stub(formAutofillParent, "_updateSavedFieldNames");
// profile added => Need to trigger updateValidFields
formAutofillParent.observe(null, "formautofill-storage-changed", "add");
do_check_eq(formAutofillParent._updateSavedFieldNames.called, true);
// profile removed => Need to trigger updateValidFields
formAutofillParent._updateSavedFieldNames.reset();
formAutofillParent.observe(null, "formautofill-storage-changed", "remove");
do_check_eq(formAutofillParent._updateSavedFieldNames.called, true);
// profile updated => no need to trigger updateValidFields
formAutofillParent._updateSavedFieldNames.reset();
formAutofillParent.observe(null, "formautofill-storage-changed", "update");
do_check_eq(formAutofillParent._updateSavedFieldNames.called, false);
});
add_task(function* test_profileSavedFieldNames_update() {
let formAutofillParent = new FormAutofillParent();
formAutofillParent.init();
do_register_cleanup(function cleanup() {
Services.prefs.clearUserPref("browser.formautofill.enabled");
});
sinon.stub(formAutofillParent._profileStore, "getAll");
formAutofillParent._profileStore.getAll.returns([]);
// The set is empty if there's no profile in the store.
formAutofillParent._updateSavedFieldNames();
do_check_eq(Services.ppmm.initialProcessData.autofillSavedFieldNames.size, 0);
// 2 profiles with 4 valid fields.
let fakeStorage = [{
guid: "test-guid-1",
organization: "Sesame Street",
"street-address": "123 Sesame Street.",
tel: "1-345-345-3456",
email: "",
timeCreated: 0,
timeLastUsed: 0,
timeLastModified: 0,
timesUsed: 0,
}, {
guid: "test-guid-2",
organization: "Mozilla",
"street-address": "331 E. Evelyn Avenue",
tel: "1-650-903-0800",
country: "US",
timeCreated: 0,
timeLastUsed: 0,
timeLastModified: 0,
timesUsed: 0,
}];
formAutofillParent._profileStore.getAll.returns(fakeStorage);
formAutofillParent._updateSavedFieldNames();
let autofillSavedFieldNames = Services.ppmm.initialProcessData.autofillSavedFieldNames;
do_check_eq(autofillSavedFieldNames.size, 4);
do_check_eq(autofillSavedFieldNames.has("organization"), true);
do_check_eq(autofillSavedFieldNames.has("street-address"), true);
do_check_eq(autofillSavedFieldNames.has("tel"), true);
do_check_eq(autofillSavedFieldNames.has("email"), false);
do_check_eq(autofillSavedFieldNames.has("guid"), false);
do_check_eq(autofillSavedFieldNames.has("timeCreated"), false);
do_check_eq(autofillSavedFieldNames.has("timeLastUsed"), false);
do_check_eq(autofillSavedFieldNames.has("timeLastModified"), false);
do_check_eq(autofillSavedFieldNames.has("timesUsed"), false);
});

Просмотреть файл

@ -10,3 +10,5 @@ support-files =
[test_markAsAutofillField.js]
[test_profileAutocompleteResult.js]
[test_profileStorage.js]
[test_savedFieldNames.js]

Просмотреть файл

@ -1551,6 +1551,13 @@ class PPAPIInstance {
this.mm.addMessageListener("ppapipdf.js:hashchange", (evt) => {
this.notifyHashChange(evt.data.url);
});
this.mm.addMessageListener("ppapipdf.js:oncommand", (evt) => {
this.viewport.notify({
type: "command",
name: evt.data.name
});
});
}
notifyHashChange(url) {

Просмотреть файл

@ -594,6 +594,21 @@ class Viewport {
}
}
_handleCommand(name) {
switch(name) {
case 'cmd_selectAll':
this._doAction({
type: 'selectAll'
});
break;
case 'cmd_copy':
this._doAction({
type: 'getSelectedText'
})
break;
}
}
verifyPassword(password) {
this._doAction({
type: 'getPasswordComplete',
@ -614,12 +629,6 @@ class Viewport {
this._refresh();
}
break;
case 'copy':
this._doAction({
type: 'getSelectedText'
})
evt.preventDefault();
break;
}
}
@ -756,6 +765,9 @@ class Viewport {
case 'hashChange':
this._handleHashChange(message.hash);
break;
case 'command':
this._handleCommand(message.name);
break;
}
}
}

Просмотреть файл

@ -183,4 +183,35 @@ mm.addMessageListener("ppapipdf.js:save", () => {
});
});
// This class is created to transfer global XUL commands event we needed.
// The main reason we need to transfer it from sandbox side is that commands
// triggered from menu bar targets only the outmost iframe (which is sandbox
// itself) so we need to propagate it manually into the plugin's iframe.
class CommandController {
constructor() {
this.SUPPORTED_COMMANDS = ['cmd_copy', 'cmd_selectAll'];
containerWindow.controllers.insertControllerAt(0, this);
containerWindow.addEventListener('unload', this.terminate.bind(this));
}
terminate() {
containerWindow.controllers.removeController(this);
}
supportsCommand(cmd) {
return this.SUPPORTED_COMMANDS.includes(cmd);
}
isCommandEnabled(cmd) {
return this.SUPPORTED_COMMANDS.includes(cmd);
}
doCommand(cmd) {
mm.sendAsyncMessage("ppapipdf.js:oncommand", {name: cmd});
}
onEvent(evt) {}
};
var commandController = new CommandController();
mm.loadFrameScript("resource://ppapi.js/ppapi-instance.js", true);

Просмотреть файл

@ -163,3 +163,8 @@ span#hostname {
white-space: pre-wrap;
padding: 1em 0;
}
#cert_domain_link:not([href]) {
color: var(--in-content-page-color);
text-decoration: none;
}

Просмотреть файл

@ -10,19 +10,22 @@ support-files =
!/devtools/client/framework/test/shared-redux-head.js
[browser_memory_allocationStackDisplay_01.js]
skip-if = debug # bug 1219554
skip-if = debug # bug 1219554
[browser_memory_displays_01.js]
[browser_memory_clear_snapshots.js]
[browser_memory_diff_01.js]
[browser_memory_dominator_trees_01.js]
skip-if = coverage # bug 1347244
[browser_memory_dominator_trees_02.js]
skip-if = coverage # bug 1347244
[browser_memory_filter_01.js]
skip-if = coverage # bug 1347244
[browser_memory_individuals_01.js]
[browser_memory_keyboard.js]
[browser_memory_keyboard-snapshot-list.js]
[browser_memory_no_allocation_stacks.js]
[browser_memory_no_auto_expand.js]
skip-if = debug # bug 1219554
skip-if = debug # bug 1219554
[browser_memory_percents_01.js]
[browser_memory_refresh_does_not_leak.js]
[browser_memory_simple_01.js]

Просмотреть файл

@ -241,10 +241,6 @@ DOMInterfaces = {
'headerFile': 'nsCSSRules.h',
},
'CSSNamespaceRule': {
'nativeType': 'mozilla::css::NameSpaceRule',
},
'CSSPageRule': {
'nativeType': 'nsCSSPageRule',
'headerFile': 'nsCSSRules.h',

Просмотреть файл

@ -33,4 +33,16 @@ interface nsIDateTimeInputArea : nsISupports
* Set the current state of the picker, true if it's opened, false otherwise.
*/
void setPickerState(in boolean isOpen);
/**
* Set the attribute of the inner text boxes. Only "tabindex", "readonly",
* and "disabled" are allowed.
*/
void setEditAttribute(in DOMString name, in DOMString value);
/**
* Remove the attribute of the inner text boxes. Only "tabindex", "readonly",
* and "disabled" are allowed.
*/
void removeEditAttribute(in DOMString name);
};

Просмотреть файл

@ -234,6 +234,13 @@ def main(argv):
if read_all:
test_list = jittests.find_tests()
# If code coverage is enabled, exclude tests. (bug 1347245)
if os.getenv('GCOV_PREFIX') is not None:
if options.exclude:
options.exclude += ['asm.js/testSIMD.js']
else:
options.exclude = ['asm.js/testSIMD.js']
if options.exclude:
exclude_list = []
for exclude in options.exclude:

Просмотреть файл

@ -316,21 +316,25 @@ nsDateTimeControlFrame::CreateAnonymousContent(nsTArray<ContentInfo>& aElements)
NS_TrustedNewXULElement(getter_AddRefs(mInputAreaContent), nodeInfo.forget());
aElements.AppendElement(mInputAreaContent);
// Propogate our tabindex.
nsAutoString tabIndexStr;
if (mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::tabindex, tabIndexStr)) {
mInputAreaContent->SetAttr(kNameSpaceID_None, nsGkAtoms::tabindex,
tabIndexStr, false);
}
nsCOMPtr<nsIDateTimeInputArea> inputAreaContent =
do_QueryInterface(mInputAreaContent);
if (inputAreaContent) {
// Propogate our tabindex.
nsAutoString tabIndexStr;
if (mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::tabindex, tabIndexStr)) {
inputAreaContent->SetEditAttribute(NS_LITERAL_STRING("tabindex"),
tabIndexStr);
}
// Propagate our readonly state.
nsAutoString readonly;
if (mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::readonly, readonly)) {
mInputAreaContent->SetAttr(kNameSpaceID_None, nsGkAtoms::readonly, readonly,
false);
}
// Propagate our readonly state.
nsAutoString readonly;
if (mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::readonly, readonly)) {
inputAreaContent->SetEditAttribute(NS_LITERAL_STRING("readonly"),
readonly);
}
SyncDisabledState();
SyncDisabledState();
}
return NS_OK;
}
@ -347,12 +351,19 @@ nsDateTimeControlFrame::AppendAnonymousContentTo(nsTArray<nsIContent*>& aElement
void
nsDateTimeControlFrame::SyncDisabledState()
{
NS_ASSERTION(mInputAreaContent, "The input area content must exist!");
nsCOMPtr<nsIDateTimeInputArea> inputAreaContent =
do_QueryInterface(mInputAreaContent);
if (!inputAreaContent) {
return;
}
EventStates eventStates = mContent->AsElement()->State();
if (eventStates.HasState(NS_EVENT_STATE_DISABLED)) {
mInputAreaContent->SetAttr(kNameSpaceID_None, nsGkAtoms::disabled,
EmptyString(), true);
inputAreaContent->SetEditAttribute(NS_LITERAL_STRING("disabled"),
EmptyString());
} else {
mInputAreaContent->UnsetAttr(kNameSpaceID_None, nsGkAtoms::disabled, true);
inputAreaContent->RemoveEditAttribute(NS_LITERAL_STRING("disabled"));
}
}
@ -374,22 +385,28 @@ nsDateTimeControlFrame::AttributeChanged(int32_t aNameSpaceID,
// then we don't need to do anything since we are going to be reframed.
if (contentAsInputElem->GetType() == NS_FORM_INPUT_TIME ||
contentAsInputElem->GetType() == NS_FORM_INPUT_DATE) {
nsCOMPtr<nsIDateTimeInputArea> inputAreaContent =
do_QueryInterface(mInputAreaContent);
if (aAttribute == nsGkAtoms::value) {
nsCOMPtr<nsIDateTimeInputArea> inputAreaContent =
do_QueryInterface(mInputAreaContent);
if (inputAreaContent) {
nsContentUtils::AddScriptRunner(NewRunnableMethod(inputAreaContent,
&nsIDateTimeInputArea::NotifyInputElementValueChanged));
}
} else {
if (aModType == nsIDOMMutationEvent::REMOVAL) {
mInputAreaContent->UnsetAttr(aNameSpaceID, aAttribute, true);
if (inputAreaContent) {
nsAtomString name(aAttribute);
inputAreaContent->RemoveEditAttribute(name);
}
} else {
MOZ_ASSERT(aModType == nsIDOMMutationEvent::ADDITION ||
aModType == nsIDOMMutationEvent::MODIFICATION);
nsAutoString value;
mContent->GetAttr(aNameSpaceID, aAttribute, value);
mInputAreaContent->SetAttr(aNameSpaceID, aAttribute, value, true);
if (inputAreaContent) {
nsAtomString name(aAttribute);
nsAutoString value;
mContent->GetAttr(aNameSpaceID, aAttribute, value);
inputAreaContent->SetEditAttribute(name, value);
}
}
}
}

Просмотреть файл

@ -0,0 +1,20 @@
<!DOCTYPE html>
<body style="background-color: lime;">
<svg width="0" height="0">
<filter id="myFilter" filterUnits="objectBoundingBox" x="0" y="0" width="50%" height="50%">
<feMerge>
<feMergeNode/>
</feMerge>
</filter>
</svg>
<!-- This outer svg element should be totally covered by the next filtered outer svg element. -->
<svg style="position: fixed;" x="0" y ="0" width="120" height="120">
<rect x="10" y="10" width="100" height="100" fill="red"/>
</svg>
<svg filter="url(#myFilter)" style="position: fixed;" x="0" y ="0" width="240" height="240">
<rect x="10" y="10" width="100" height="100" fill="lime"/>
</svg>
</body>

Просмотреть файл

@ -0,0 +1,22 @@
<!DOCTYPE html>
<body style="background-color: lime;">
<svg width="0" height="0">
<filter id="myFilter" filterUnits="objectBoundingBox" x="0" y="0" width="50%" height="50%">
<feMerge>
<feMergeNode/>
</feMerge>
</filter>
</svg>
<svg style="position: fixed;" x="0" y ="0" width="400" height="400">
<!-- This filtered inner element should be covered by the next outer svg element. -->
<svg filter="url(#myFilter)" style="position: fixed;" x="0" y ="0" width="200" height="200">
<rect x="10" y="10" width="120" height="120" fill="red"/>
</svg>
</svg>
<svg style="position: fixed;" x="0" y ="0" width="120" height="120">
<rect x="10" y="10" width="100" height="100" fill="lime"/>
</svg>
</body>

Просмотреть файл

@ -83,6 +83,8 @@ fails == filter-marked-line-01.svg pass.svg # bug 477704
== filter-nested-filtering-02.svg pass.svg
== filter-patterned-rect-01.svg pass.svg
== filter-patterned-rect-02.svg pass.svg
== filter-region-01a.html pass.svg
== filter-region-01b.html pass.svg
== feColorMatrix-saturate-01.svg pass.svg

Просмотреть файл

@ -27,11 +27,40 @@ include moz-only/reftest-stylo.list
include svg-integration/reftest-stylo.list
== baseline-middle-01.svg baseline-middle-01.svg
skip-if(Android) pref(layout.css.mix-blend-mode.enabled,true) == blend-color-burn.svg blend-color-burn.svg
skip-if(Android) pref(layout.css.mix-blend-mode.enabled,true) == blend-color-dodge.svg blend-color-dodge.svg
skip-if(stylo) pref(layout.css.mix-blend-mode.enabled,true) == blend-color.svg blend-color.svg # Too intermittent
skip-if(Android) pref(layout.css.mix-blend-mode.enabled,true) == blend-darken.svg blend-darken.svg
skip-if(Android) pref(layout.css.mix-blend-mode.enabled,true) == blend-difference.svg blend-difference.svg
skip-if(Android) fuzzy-if(skiaContent,1,1600) pref(layout.css.mix-blend-mode.enabled,true) == blend-exclusion.svg blend-exclusion.svg
skip-if(stylo) pref(layout.css.mix-blend-mode.enabled,true) == blend-hard-light.svg blend-hard-light.svg # Too intermittent
skip-if(stylo) pref(layout.css.mix-blend-mode.enabled,true) == blend-hue.svg blend-hue.svg # Too intermittent
skip-if(Android) pref(layout.css.mix-blend-mode.enabled,true) == blend-layer-blend.svg blend-layer-blend.svg
skip-if(Android) pref(layout.css.mix-blend-mode.enabled,true) == blend-layer-filter.svg blend-layer-filter.svg
skip-if(Android) pref(layout.css.mix-blend-mode.enabled,true) == blend-layer-mask.svg blend-layer-mask.svg
skip-if(Android) pref(layout.css.mix-blend-mode.enabled,true) == blend-layer-opacity.svg blend-layer-opacity.svg
skip-if(Android) pref(layout.css.mix-blend-mode.enabled,true) == blend-lighten.svg blend-lighten.svg
skip-if(stylo) pref(layout.css.mix-blend-mode.enabled,true) == blend-luminosity.svg blend-luminosity.svg # Too intermittent
skip-if(stylo) skip-if(Android) pref(layout.css.mix-blend-mode.enabled,true) == blend-multiply-alpha.svg blend-multiply-alpha.svg
skip-if(Android) pref(layout.css.mix-blend-mode.enabled,true) == blend-multiply.svg blend-multiply.svg
pref(layout.css.mix-blend-mode.enabled,true) == blend-normal.svg blend-normal.svg
skip-if(Android) pref(layout.css.mix-blend-mode.enabled,true) == blend-overlay.svg blend-overlay.svg
skip-if(stylo) skip-if(Android) pref(layout.css.mix-blend-mode.enabled,true) == blend-saturation.svg blend-saturation.svg
skip-if(stylo) skip-if(Android) pref(layout.css.mix-blend-mode.enabled,true) == blend-screen.svg blend-screen.svg
skip-if(Android) pref(layout.css.mix-blend-mode.enabled,true) == blend-soft-light.svg blend-soft-light.svg
== blend-difference-stacking.html blend-difference-stacking.html
== border-radius-01.html border-radius-01.html
== clip-01.svg clip-01.svg
== clip-02a.svg clip-02a.svg
== clip-02b.svg clip-02b.svg
== clip-surface-clone-01.svg clip-surface-clone-01.svg
== clipPath-advanced-01.svg clipPath-advanced-01.svg
== clipPath-and-mask-on-outflowElement-01a.html clipPath-and-mask-on-outflowElement-01a.html
fails == clipPath-and-mask-on-outflowElement-01b.html clipPath-and-mask-on-outflowElement-01b.html
fuzzy-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu)||/^Windows\x20NT\x206\.[12]/.test(http.oscpu),1,5) fuzzy-if(OSX,1,6) fuzzy-if(skiaContent,1,630) == clipPath-and-shape-rendering-01.svg clipPath-and-shape-rendering-01.svg
== clipPath-and-transform-01.svg clipPath-and-transform-01.svg
== clipPath-basic-01.svg clipPath-basic-01.svg
@ -41,9 +70,16 @@ fuzzy-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu)||/^Windows\x20NT\x206\.[12]/
== clipPath-basic-05.svg clipPath-basic-05.svg
== clipPath-basic-06.svg clipPath-basic-06.svg
== clipPath-basic-07.svg clipPath-basic-07.svg
== clipPath-on-outflowElement-01a.html clipPath-on-outflowElement-01a.html
== clipPath-on-outflowElement-01b.html clipPath-on-outflowElement-01b.html
default-preferences pref(layout.css.clip-path-shapes.enabled,true)
fuzzy(1,32400) == clipPath-on-outflowElement-02a.html clipPath-on-outflowElement-02a.html
fuzzy(1,32400) == clipPath-on-outflowElement-02b.html clipPath-on-outflowElement-02b.html
default-preferences
== clipPath-winding-01.svg clipPath-winding-01.svg
== clip-surface-clone-01.svg clip-surface-clone-01.svg
== comments-in-pres-attrs.svg pass.svg
== conditions-01.svg conditions-01.svg
== conditions-02.svg conditions-02.svg
== conditions-03.svg conditions-03.svg
@ -52,12 +88,15 @@ fuzzy-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu)||/^Windows\x20NT\x206\.[12]/
== conditions-07.svg conditions-07.svg
fuzzy-if(skiaContent,1,320) == conditions-08.svg conditions-08.svg
== conditions-09.svg conditions-09.svg
== currentColor-01.svg currentColor-01.svg
== currentColor-02.svg currentColor-02.svg
== currentColor-03.svg currentColor-03.svg
== data-uri-with-filter-01.xhtml data-uri-with-filter-01.xhtml
== data-uri-with-gradient-01.xhtml data-uri-with-gradient-01.xhtml
== data-uri-with-pattern-01.xhtml data-uri-with-pattern-01.xhtml
== dynamic-attr-removal-1.svg dynamic-attr-removal-1.svg
== dynamic-attr-removal-2.svg dynamic-attr-removal-2.svg
== dynamic-attr-change-1.svg dynamic-attr-change-1.svg
@ -137,20 +176,14 @@ random == dynamic-use-nested-01b.svg dynamic-use-nested-01b.svg
== dynamic-viewBox-change-01.svg dynamic-viewBox-change-01.svg
== dynamic-viewBox-change-02.svg dynamic-viewBox-change-02.svg
== dynamic-viewBox-change-03.svg dynamic-viewBox-change-03.svg
== fragmentIdentifier-01.xhtml fragmentIdentifier-01.xhtml
== linked-filter-01.svg linked-filter-01.svg
== linked-pattern-01.svg linked-pattern-01.svg
== use-01.svg use-01.svg
== use-01-extref.svg use-01-extref.svg
== use-02-extref.svg use-02-extref.svg
== use-extref-dataURI-01.svg use-extref-dataURI-01.svg
== use-children.svg use-children.svg
== fallback-color-01a.svg fallback-color-01a.svg
== fallback-color-01b.svg fallback-color-01b.svg
== fallback-color-02a.svg fallback-color-02a.svg
== fallback-color-02b.svg fallback-color-02b.svg
== fallback-color-03.svg fallback-color-03.svg
fuzzy-if(skiaContent,1,2) == fallback-color-04.svg fallback-color-04.svg
== filter-basic-01.svg filter-basic-01.svg
== filter-basic-02.svg filter-basic-02.svg
== filter-basic-03.svg filter-basic-03.svg
@ -168,6 +201,7 @@ fails-if(Android) pref(security.fileuri.strict_origin_policy,true) == filter-ext
fails == filter-scaled-02.html filter-scaled-02.html
== filter-translated-01.svg filter-translated-01.svg
fuzzy-if(skiaContent,1,800000) == filters-and-group-opacity-01.svg filters-and-group-opacity-01.svg
== foreignObject-01.svg foreignObject-01.svg
== foreignObject-02.svg foreignObject-02.svg
== foreignObject-ancestor-style-change-01.svg foreignObject-ancestor-style-change-01.svg
@ -185,6 +219,7 @@ fuzzy-if(skiaContent,1,800000) == filters-and-group-opacity-01.svg filters-and-g
== foreignObject-fixedpos-02.html foreignObject-fixedpos-02.html
== foreignObject-dynamic-fixedpos-01.html foreignObject-dynamic-fixedpos-01.html
== foreignObject-vertical-01.svg foreignObject-vertical-01.svg
== fragmentIdentifier-01.xhtml fragmentIdentifier-01.xhtml
== g-transform-01.svg g-transform-01.svg
== getElementById-a-element-01.svg getElementById-a-element-01.svg
fuzzy-if(Android,9,980) fuzzy-if(skiaContent,3,32000) == gradient-live-01a.svg gradient-live-01a.svg
@ -192,6 +227,7 @@ fuzzy-if(Android,9,980) fuzzy-if(skiaContent,3,32000) == gradient-live-01b.svg g
fuzzy-if(Android,9,980) fuzzy-if(skiaContent,3,32000) == gradient-live-01c.svg gradient-live-01c.svg
fuzzy-if(Android,9,980) fuzzy-if(skiaContent,3,32000) == gradient-live-01d.svg gradient-live-01d.svg
== gradient-transform-01.svg gradient-transform-01.svg
== href-attr-change-restyles.svg href-attr-change-restyles.svg
== import-svg-01.html import-svg-01.html
== invalid-text-01.svg invalid-text-01.svg
== lang-attribute-01.svg lang-attribute-01.svg
@ -201,6 +237,10 @@ fuzzy-if(Android,9,980) fuzzy-if(skiaContent,3,32000) == gradient-live-01d.svg g
== linearGradient-basic-02.svg linearGradient-basic-02.svg
# off-by-one fuzziness expected. OS X is broken with bad aliasing though (bug 1023640).
fuzzy-if(cocoaWidget,15,19679) fuzzy-if(winWidget,1,8800) fuzzy-if(!cocoaWidget&&!winWidget,1,4000) fuzzy-if(skiaContent,1,5000) == linearGradient-basic-03.svg linearGradient-basic-03.svg
== linked-filter-01.svg linked-filter-01.svg
== linked-pattern-01.svg linked-pattern-01.svg
fuzzy-if(skiaContent,1,800000) == markers-and-group-opacity-01.svg markers-and-group-opacity-01.svg
== marker-attribute-01.svg marker-attribute-01.svg
== marker-effects-01.svg marker-effects-01.svg
@ -209,22 +249,30 @@ fuzzy-if(skiaContent,1,100) == marker-orientation-01.svg marker-orientation-01.s
fuzzy-if(skiaContent,1,5) pref(svg.marker-improvements.enabled,true) == marker-orientation-02.svg marker-orientation-02.svg
== marker-orientation-03.svg marker-orientation-03.svg
== marker-orientation-04.svg marker-orientation-04.svg
# fuzzy because of the differences between clipPath and mask clipping
fails == mask-and-clipPath.html mask-and-clipPath.html
== mask-and-clipPath-2.svg mask-and-clipPath-2.svg
== mask-basic-01.svg mask-basic-01.svg
fuzzy-if(skiaContent,1,10000) == mask-basic-02.svg mask-basic-02.svg
== mask-basic-03.svg mask-basic-03.svg
== mask-basic-04.svg mask-basic-04.svg
== mask-extref-dataURI-01.svg mask-extref-dataURI-01.svg
== mask-containing-masked-content-01.svg mask-containing-masked-content-01.svg
== mask-empty-size.svg mask-empty-size.svg
== mask-extref-dataURI-01.svg mask-extref-dataURI-01.svg
== mask-img.html mask-img.html
fails == mask-on-outflowElement-01a.html mask-on-outflowElement-01a.html
fails == mask-on-outflowElement-01b.html mask-on-outflowElement-01b.html
fuzzy(1,5000) == mask-opacity-01.svg mask-opacity-01.svg
== mask-transformed-01.svg mask-transformed-01.svg
== mask-transformed-02.svg mask-transformed-02.svg
== mask-transformed-child-01.svg mask-transformed-child-01.svg
# fuzzy because of the differences between clipPath and mask clipping
fails == mask-and-clipPath.html mask-and-clipPath.html
== mask-and-clipPath-2.svg mask-and-clipPath-2.svg
fuzzy-if(d2d||skiaContent,1,6400) == mask-type-01.svg mask-type-01.svg
fuzzy-if(d2d||skiaContent,1,6400) == mask-type-02.svg mask-type-02.svg
fuzzy-if(d2d||skiaContent,1,6400) == mask-type-03.svg mask-type-03.svg
fuzzy-if(d2d||skiaContent,1,6400) == mask-type-04.svg mask-type-04.svg
== nested-mask-mode.svg nested-mask-mode.svg
== nested-viewBox-01.svg nested-viewBox-01.svg
fuzzy-if(skiaContent,3,448000) == nesting-invalid-01.svg nesting-invalid-01.svg
fuzzy-if(d2d&&/^Windows\x20NT\x20(6\.1|10\.0)/.test(http.oscpu),63,168) fuzzy-if(cocoaWidget,1,122) fuzzy-if(skiaContent,2,1000) == non-scaling-stroke-01.svg non-scaling-stroke-01.svg
@ -265,8 +313,10 @@ fuzzy(23,60) fails-if(d2d) == path-01.svg path-01.svg
fuzzy-if(skiaContent,1,400) == path-06.svg path-06.svg
== path-07.svg path-07.svg
== path-08.svg path-08.svg
== pathLength-01.svg pathLength-01.svg
== pathLength-02.svg pathLength-02.svg
== pattern-basic-01.svg pattern-basic-01.svg
== pattern-invalid-01.svg pattern-invalid-01.svg
fuzzy-if(skiaContent,1,5) == pattern-live-01a.svg pattern-live-01a.svg
@ -277,39 +327,61 @@ fuzzy-if(skiaContent,1,5) == pattern-scale-01a.svg pattern-scale-01a.svg
fuzzy-if(skiaContent,3,5) == pattern-scale-01c.svg pattern-scale-01c.svg
== pattern-transform-presence-01.svg pattern-transform-presence-01.svg
== pattern-transformed-01.svg pattern-transformed-01.svg
== polygon-01.svg polygon-01.svg
== polygon-marker-01.svg polygon-marker-01.svg
== polygon-points-negative-01.svg polygon-points-negative-01.svg
== polyline-points-invalid-01.svg polyline-points-invalid-01.svg
== pseudo-classes-01.svg pseudo-classes-01.svg
# This test depends on :visited styles (which are asynchronous), so we run
# it in layout/style/test/test_visited_reftests.html instead of using the
# reftest harness.
== pseudo-classes-02.svg pseudo-classes-02.svg
== radialGradient-basic-01.svg radialGradient-basic-01.svg
== radialGradient-basic-02.svg radialGradient-basic-02.svg
fuzzy-if(cocoaWidget,4,15982) fuzzy-if(winWidget,4,92) fuzzy-if(skiaContent,4,60) == radialGradient-basic-03.svg radialGradient-basic-03.svg
== radialGradient-basic-04.svg radialGradient-basic-04.svg
fuzzy-if(skiaContent,1,3600) == rect-01.svg rect-01.svg
== rect-02.svg rect-02.svg
== rect-03.svg rect-03.svg
== rect-04.svg rect-04.svg
== rect-with-rx-and-ry-01.svg rect-with-rx-and-ry-01.svg
== rect-with-rx-or-ry-01.svg rect-with-rx-or-ry-01.svg
== rootElement-null-01.svg rootElement-null-01.svg
== script-empty-01.svg script-empty-01.svg
== selector-01.svg selector-01.svg
== stroke-dasharray-01.svg stroke-dasharray-01.svg
fuzzy-if(skiaContent,1,340) == stroke-dasharray-02.svg stroke-dasharray-02.svg
fuzzy-if(skiaContent,1,340) == stroke-dasharray-03.svg stroke-dasharray-03.svg
== stroke-dasharray-and-pathLength-01.svg stroke-dasharray-and-pathLength-01.svg
== stroke-dasharray-and-text-01.svg stroke-dasharray-and-text-01.svg
== stroke-dashoffset-01.svg stroke-dashoffset-01.svg
== stroke-dashoffset-and-pathLength-01.svg stroke-dashoffset-and-pathLength-01.svg
== stroke-linecap-circle-ellipse-01.svg stroke-linecap-circle-ellipse-01.svg
== stroke-linecap-circle-ellipse-dashed-01.svg stroke-linecap-circle-ellipse-dashed-01.svg
== stroke-linecap-round-w-zero-length-segs-01.svg stroke-linecap-round-w-zero-length-segs-01.svg
== stroke-linecap-round-w-zero-length-segs-02.svg stroke-linecap-round-w-zero-length-segs-02.svg
== stroke-linecap-square-w-zero-length-segs-01.svg stroke-linecap-square-w-zero-length-segs-01.svg
== stroke-linecap-square-w-zero-length-segs-02.svg stroke-linecap-square-w-zero-length-segs-02.svg
== stroke-width-percentage-01.svg stroke-width-percentage-01.svg
== stroke-width-percentage-02a.svg stroke-width-percentage-02a.svg
== stroke-width-percentage-02b.svg stroke-width-percentage-02b.svg
== stroke-width-percentage-03.xhtml stroke-width-percentage-03.xhtml
== style-property-on-script-element-01.svg style-property-on-script-element-01.svg
== style-without-type-attribute.svg style-without-type-attribute.svg
== svg-in-foreignObject-01.xhtml svg-in-foreignObject-01.xhtml
== svg-in-foreignObject-02.xhtml svg-in-foreignObject-02.xhtml
== switch-01.svg switch-01.svg
== suspend-01.svg suspend-01.svg
== suspend-02.svg suspend-02.svg
== suspend-03.svg suspend-03.svg
@ -318,9 +390,15 @@ fuzzy-if(skiaContent,1,3600) == rect-01.svg rect-01.svg
== suspend-06.svg suspend-06.svg
== suspend-07.svg suspend-07.svg
== suspend-08.svg suspend-08.svg
== svg-effects-area-unzoomed.xhtml svg-effects-area-unzoomed.xhtml
== svg-effects-area-zoomed-in.xhtml svg-effects-area-zoomed-in.xhtml
== svg-effects-area-zoomed-out.xhtml svg-effects-area-zoomed-out.xhtml
== svg-transform-01.svg svg-transform-01.svg
== svg-transform-02.svg svg-transform-02.svg
== symbol-01.svg symbol-01.svg
== text-font-size-01.svg text-font-size-01.svg
random-if(gtkWidget) == text-font-weight-01.svg text-font-weight-01.svg
== text-gradient-01.svg text-gradient-01.svg
@ -333,6 +411,7 @@ HTTP(..) == text-gradient-04.svg text-gradient-04.svg
# Tests for bug 546813: sanity-check using HTML text, then test SVG behavior.
== text-language-00.xhtml text-language-00.xhtml
random-if(gtkWidget) == text-language-01.xhtml text-language-01.xhtml
fuzzy-if(OSX==1007,6,2) fuzzy-if(OSX==1008,46,26) == text-layout-01.svg text-layout-01.svg
== text-layout-02.svg text-layout-02.svg
== text-layout-03.svg text-layout-03.svg
@ -341,34 +420,28 @@ fuzzy-if(OSX==1007,6,2) fuzzy-if(OSX==1008,46,26) == text-layout-01.svg text-lay
fuzzy-if(cocoaWidget&&layersGPUAccelerated,1,3) == text-layout-06.svg text-layout-06.svg
== text-layout-07.svg text-layout-07.svg
== text-layout-08.svg text-layout-08.svg
== text-scale-01.svg text-scale-01.svg
fuzzy-if(skiaContent,2,1000) HTTP(..) == text-scale-02.svg text-scale-02.svg
HTTP(..) == text-scale-03.svg text-scale-03.svg
== text-stroke-scaling-01.svg text-stroke-scaling-01.svg
== stroke-dasharray-01.svg stroke-dasharray-01.svg
fuzzy-if(skiaContent,1,340) == stroke-dasharray-02.svg stroke-dasharray-02.svg
fuzzy-if(skiaContent,1,340) == stroke-dasharray-03.svg stroke-dasharray-03.svg
== stroke-dasharray-and-pathLength-01.svg stroke-dasharray-and-pathLength-01.svg
== stroke-dasharray-and-text-01.svg stroke-dasharray-and-text-01.svg
== stroke-dashoffset-01.svg stroke-dashoffset-01.svg
== stroke-dashoffset-and-pathLength-01.svg stroke-dashoffset-and-pathLength-01.svg
== stroke-linecap-round-w-zero-length-segs-01.svg stroke-linecap-round-w-zero-length-segs-01.svg
== stroke-linecap-round-w-zero-length-segs-02.svg stroke-linecap-round-w-zero-length-segs-02.svg
== stroke-linecap-square-w-zero-length-segs-01.svg stroke-linecap-square-w-zero-length-segs-01.svg
== stroke-linecap-square-w-zero-length-segs-02.svg stroke-linecap-square-w-zero-length-segs-02.svg
== textPath-01.svg textPath-01.svg
== textPath-02.svg textPath-02.svg
fuzzy-if(skiaContent,1,610) == textPath-03.svg textPath-03.svg
== textPath-04.svg textPath-04.svg
== textPath-05.html textPath-05.html
== text-style-01a.svg text-style-01a.svg
== text-style-01b.svg text-style-01b.svg
== text-style-01c.svg text-style-01c.svg
== text-style-01d.svg text-style-01d.svg
== text-style-01e.svg text-style-01e.svg
== text-white-space-01.svg text-white-space-01.svg
== textPath-01.svg textPath-01.svg
== textPath-02.svg textPath-02.svg
fuzzy-if(skiaContent,1,610) == textPath-03.svg textPath-03.svg
== textPath-04.svg textPath-04.svg
== textPath-05.html textPath-05.html
== thin-stroke-01.svg thin-stroke-01.svg
== zero-stroke-01.svg zero-stroke-01.svg
== tspan-dxdy-01.svg tspan-dxdy-01.svg
== tspan-dxdy-02.svg tspan-dxdy-02.svg
== tspan-dxdy-03.svg tspan-dxdy-03.svg
@ -394,7 +467,24 @@ fuzzy-if(skiaContent,1,300) == tspan-xy-05.svg tspan-xy-05.svg
fuzzy-if(skiaContent,1,300) == tspan-xy-06.svg tspan-xy-06.svg
fuzzy-if(skiaContent,1,100) == tspan-xy-anchor-middle-01.svg tspan-xy-anchor-middle-01.svg
fuzzy-if(skiaContent,1,100) == tspan-xy-anchor-end-01.svg tspan-xy-anchor-end-01.svg
== use-01.svg use-01.svg
== use-01-extref.svg use-01-extref.svg
== use-02-extref.svg use-02-extref.svg
== use-extref-dataURI-01.svg use-extref-dataURI-01.svg
== use-children.svg use-children.svg
# test case for Fragment URLs
# https://drafts.csswg.org/css-values/#local-urls
== use-localRef-marker-01.svg use-localRef-marker-01.svg
== use-localRef-clipPath-01.svg use-localRef-clipPath-01.svg
== use-localRef-filter-01.svg use-localRef-filter-01.svg
== use-localRef-fill-01.svg use-localRef-fill-01.svg
== use-localRef-stroke-01.svg use-localRef-stroke-01.svg
== use-localRef-mask-01.svg use-localRef-mask-01.svg
== userSpaceOnUse-and-pattern-01.svg userSpaceOnUse-and-pattern-01.svg
== viewBox-and-pattern-01.svg viewBox-and-pattern-01.svg
== viewBox-and-pattern-02.svg viewBox-and-pattern-02.svg
== viewBox-and-pattern-03.svg viewBox-and-pattern-03.svg
@ -406,59 +496,4 @@ fuzzy-if(skiaContent,1,100) == tspan-xy-anchor-end-01.svg tspan-xy-anchor-end-01
== viewport-percent-graphic-user-01.svg viewport-percent-graphic-user-01.svg
== winding-01.svg winding-01.svg
== svg-effects-area-unzoomed.xhtml svg-effects-area-unzoomed.xhtml
== svg-effects-area-zoomed-in.xhtml svg-effects-area-zoomed-in.xhtml
== svg-effects-area-zoomed-out.xhtml svg-effects-area-zoomed-out.xhtml
== href-attr-change-restyles.svg href-attr-change-restyles.svg
== mask-img.html mask-img.html
skip-if(Android) pref(layout.css.mix-blend-mode.enabled,true) == blend-color-burn.svg blend-color-burn.svg
skip-if(Android) pref(layout.css.mix-blend-mode.enabled,true) == blend-color-dodge.svg blend-color-dodge.svg
skip-if(stylo) pref(layout.css.mix-blend-mode.enabled,true) == blend-color.svg blend-color.svg # Too intermittent
skip-if(Android) pref(layout.css.mix-blend-mode.enabled,true) == blend-darken.svg blend-darken.svg
skip-if(Android) pref(layout.css.mix-blend-mode.enabled,true) == blend-difference.svg blend-difference.svg
skip-if(Android) fuzzy-if(skiaContent,1,1600) pref(layout.css.mix-blend-mode.enabled,true) == blend-exclusion.svg blend-exclusion.svg
skip-if(stylo) pref(layout.css.mix-blend-mode.enabled,true) == blend-hard-light.svg blend-hard-light.svg # Too intermittent
skip-if(stylo) pref(layout.css.mix-blend-mode.enabled,true) == blend-hue.svg blend-hue.svg # Too intermittent
skip-if(Android) pref(layout.css.mix-blend-mode.enabled,true) == blend-layer-blend.svg blend-layer-blend.svg
skip-if(Android) pref(layout.css.mix-blend-mode.enabled,true) == blend-layer-filter.svg blend-layer-filter.svg
skip-if(Android) pref(layout.css.mix-blend-mode.enabled,true) == blend-layer-mask.svg blend-layer-mask.svg
skip-if(Android) pref(layout.css.mix-blend-mode.enabled,true) == blend-layer-opacity.svg blend-layer-opacity.svg
skip-if(Android) pref(layout.css.mix-blend-mode.enabled,true) == blend-lighten.svg blend-lighten.svg
skip-if(stylo) pref(layout.css.mix-blend-mode.enabled,true) == blend-luminosity.svg blend-luminosity.svg # Too intermittent
skip-if(stylo) skip-if(Android) pref(layout.css.mix-blend-mode.enabled,true) == blend-multiply-alpha.svg blend-multiply-alpha.svg
skip-if(Android) pref(layout.css.mix-blend-mode.enabled,true) == blend-multiply.svg blend-multiply.svg
pref(layout.css.mix-blend-mode.enabled,true) == blend-normal.svg blend-normal.svg
skip-if(Android) pref(layout.css.mix-blend-mode.enabled,true) == blend-overlay.svg blend-overlay.svg
skip-if(stylo) skip-if(Android) pref(layout.css.mix-blend-mode.enabled,true) == blend-saturation.svg blend-saturation.svg
skip-if(stylo) skip-if(Android) pref(layout.css.mix-blend-mode.enabled,true) == blend-screen.svg blend-screen.svg
skip-if(Android) pref(layout.css.mix-blend-mode.enabled,true) == blend-soft-light.svg blend-soft-light.svg
== blend-difference-stacking.html blend-difference-stacking.html
# test case for Fragment URLs
# https://drafts.csswg.org/css-values/#local-urls
== use-localRef-marker-01.svg use-localRef-marker-01.svg
== use-localRef-clipPath-01.svg use-localRef-clipPath-01.svg
== use-localRef-filter-01.svg use-localRef-filter-01.svg
== use-localRef-fill-01.svg use-localRef-fill-01.svg
== use-localRef-stroke-01.svg use-localRef-stroke-01.svg
== use-localRef-mask-01.svg use-localRef-mask-01.svg
fuzzy(1,5000) == mask-opacity-01.svg mask-opacity-01.svg
== clipPath-on-outflowElement-01a.html clipPath-on-outflowElement-01a.html
== clipPath-on-outflowElement-01b.html clipPath-on-outflowElement-01b.html
default-preferences pref(layout.css.clip-path-shapes.enabled,true)
fuzzy(1,32400) == clipPath-on-outflowElement-02a.html clipPath-on-outflowElement-02a.html
fuzzy(1,32400) == clipPath-on-outflowElement-02b.html clipPath-on-outflowElement-02b.html
default-preferences
fails == mask-on-outflowElement-01a.html mask-on-outflowElement-01a.html
fails == mask-on-outflowElement-01b.html mask-on-outflowElement-01b.html
== clipPath-and-mask-on-outflowElement-01a.html clipPath-and-mask-on-outflowElement-01a.html
fails == clipPath-and-mask-on-outflowElement-01b.html clipPath-and-mask-on-outflowElement-01b.html
== nested-mask-mode.svg nested-mask-mode.svg
== mask-empty-size.svg mask-empty-size.svg
== zero-stroke-01.svg zero-stroke-01.svg

Просмотреть файл

@ -25,12 +25,47 @@ include moz-only/reftest.list
# svg-integration tests (using svg effects in e.g. HTML)
include svg-integration/reftest.list
== background-svg-without-height.html background-ref.html
== background-svg-without-height-width.html background-ref.html
== background-svg-without-width.html background-ref.html
== baseline-middle-01.svg pass.svg
skip-if(Android) pref(layout.css.mix-blend-mode.enabled,true) == blend-color-burn.svg blend-color-burn-ref.svg
skip-if(Android) pref(layout.css.mix-blend-mode.enabled,true) == blend-color-dodge.svg blend-color-dodge-ref.svg
# pref(layout.css.mix-blend-mode.enabled,true) == blend-color.svg blend-color-ref.svg
skip-if(Android) pref(layout.css.mix-blend-mode.enabled,true) == blend-darken.svg blend-darken-ref.svg
skip-if(Android) pref(layout.css.mix-blend-mode.enabled,true) == blend-difference.svg blend-difference-ref.svg
skip-if(Android) fuzzy-if(skiaContent,1,1600) pref(layout.css.mix-blend-mode.enabled,true) == blend-exclusion.svg blend-exclusion-ref.svg
# pref(layout.css.mix-blend-mode.enabled,true) == blend-hard-light.svg blend-hard-light-ref.svg
# pref(layout.css.mix-blend-mode.enabled,true) == blend-hue.svg blend-hue-ref.svg
skip-if(Android) pref(layout.css.mix-blend-mode.enabled,true) == blend-layer-blend.svg blend-layer-blend-ref.svg
skip-if(Android) pref(layout.css.mix-blend-mode.enabled,true) == blend-layer-filter.svg blend-layer-filter-ref.svg
skip-if(Android) pref(layout.css.mix-blend-mode.enabled,true) == blend-layer-mask.svg blend-layer-mask-ref.svg
skip-if(Android) pref(layout.css.mix-blend-mode.enabled,true) == blend-layer-opacity.svg blend-layer-opacity-ref.svg
skip-if(Android) pref(layout.css.mix-blend-mode.enabled,true) == blend-lighten.svg blend-lighten-ref.svg
# pref(layout.css.mix-blend-mode.enabled,true) == blend-luminosity.svg blend-luminosity-ref.svg
#skip-if(Android) pref(layout.css.mix-blend-mode.enabled,true) == blend-multiply-alpha.svg blend-multiply-alpha-ref.svg
skip-if(Android) pref(layout.css.mix-blend-mode.enabled,true) == blend-multiply.svg blend-multiply-ref.svg
pref(layout.css.mix-blend-mode.enabled,true) == blend-normal.svg blend-normal-ref.svg
#skip-if(Android) pref(layout.css.mix-blend-mode.enabled,true) == blend-overlay.svg blend-overlay-ref.svg
#skip-if(Android) pref(layout.css.mix-blend-mode.enabled,true) == blend-saturation.svg blend-saturation-ref.svg
#skip-if(Android) pref(layout.css.mix-blend-mode.enabled,true) == blend-screen.svg blend-screen-ref.svg
#skip-if(Android) pref(layout.css.mix-blend-mode.enabled,true) == blend-soft-light.svg blend-soft-light-ref.svg
skip-if(Android) pref(layout.css.mix-blend-mode.enabled,true) fails-if(webrender) == blend-difference-stacking.html blend-difference-stacking-ref.html
== border-radius-01.html pass.svg
== clip-01.svg pass.svg
== clip-02a.svg clip-02-ref.svg
== clip-02b.svg clip-02-ref.svg
== clip-surface-clone-01.svg clip-surface-clone-01-ref.svg
== clip-use-element-01.svg pass.svg
== clip-use-element-02.svg pass.svg
== clipPath-advanced-01.svg pass.svg
== clipPath-and-mask-on-outflowElement-01a.html clipPath-on-outflowElement-01-ref.html
== clipPath-and-mask-on-outflowElement-01b.html clipPath-on-outflowElement-01-ref.html
fuzzy-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu)||/^Windows\x20NT\x206\.[12]/.test(http.oscpu),1,5) fuzzy-if(OSX,1,6) fuzzy-if(skiaContent,1,630) == clipPath-and-shape-rendering-01.svg clipPath-and-shape-rendering-01-ref.svg # bug 614840
== clipPath-and-transform-01.svg pass.svg
== clipPath-basic-01.svg pass.svg
@ -40,9 +75,16 @@ fuzzy-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu)||/^Windows\x20NT\x206\.[12]/
== clipPath-basic-05.svg pass.svg
== clipPath-basic-06.svg pass.svg
== clipPath-basic-07.svg pass.svg
== clipPath-on-outflowElement-01a.html clipPath-on-outflowElement-01-ref.html
== clipPath-on-outflowElement-01b.html clipPath-on-outflowElement-01-ref.html
default-preferences pref(layout.css.clip-path-shapes.enabled,true)
fuzzy(1,32400) == clipPath-on-outflowElement-02a.html clipPath-on-outflowElement-02-ref.html
fuzzy(1,32400) == clipPath-on-outflowElement-02b.html clipPath-on-outflowElement-02-ref.html
default-preferences
== clipPath-winding-01.svg pass.svg
== clip-surface-clone-01.svg clip-surface-clone-01-ref.svg
== comments-in-pres-attrs.svg pass.svg
== conditions-01.svg pass.svg
== conditions-02.svg pass.svg
== conditions-03.svg pass.svg
@ -51,12 +93,15 @@ fuzzy-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu)||/^Windows\x20NT\x206\.[12]/
== conditions-07.svg pass.svg
fuzzy-if(skiaContent,1,320) == conditions-08.svg conditions-08-ref.svg
== conditions-09.svg conditions-09-ref.svg
== currentColor-01.svg pass.svg
== currentColor-02.svg pass.svg
== currentColor-03.svg pass.svg
== data-uri-with-filter-01.xhtml data-uri-with-filter-01-ref.svg
== data-uri-with-gradient-01.xhtml data-uri-with-gradient-01-ref.svg
== data-uri-with-pattern-01.xhtml pass.svg
== dynamic-attr-removal-1.svg pass.svg
== dynamic-attr-removal-2.svg pass.svg
== dynamic-attr-change-1.svg pass.svg
@ -136,20 +181,14 @@ random == dynamic-use-nested-01b.svg dynamic-use-nested-01-ref.svg
== dynamic-viewBox-change-01.svg pass.svg
== dynamic-viewBox-change-02.svg pass.svg
== dynamic-viewBox-change-03.svg pass.svg
== fragmentIdentifier-01.xhtml pass.svg
== linked-filter-01.svg pass.svg
== linked-pattern-01.svg pass.svg
== use-01.svg pass.svg
== use-01-extref.svg pass.svg
== use-02-extref.svg use-02-extref-ref.svg
== use-extref-dataURI-01.svg pass.svg
== use-children.svg pass.svg
== fallback-color-01a.svg pass.svg
== fallback-color-01b.svg pass.svg
== fallback-color-02a.svg fallback-color-02-ref.svg
== fallback-color-02b.svg fallback-color-02-ref.svg
== fallback-color-03.svg pass.svg
fuzzy-if(skiaContent,1,2) == fallback-color-04.svg pass.svg
== filter-basic-01.svg pass.svg
== filter-basic-02.svg pass.svg
== filter-basic-03.svg pass.svg
@ -162,11 +201,14 @@ fails-if(Android) pref(security.fileuri.strict_origin_policy,true) == filter-ext
== filter-foreignObject-01.svg pass.svg
== filter-in-mask-01.svg pass.svg
== filter-invalidation-01.svg pass.svg
fuzzy(71,817) == filter-on-continuation-box-01.html filter-on-continuation-box-ref.html
== filter-result-01.svg filter-result-01-ref.svg
== filter-scaled-01.svg pass.svg
fuzzy-if(skiaContent,1,500) == filter-scaled-02.html filter-scaled-02-ref.html
== filter-translated-01.svg filter-translated-01-ref.svg
== filter-use-element-01.svg pass.svg
fuzzy-if(skiaContent,1,800000) == filters-and-group-opacity-01.svg filters-and-group-opacity-01-ref.svg
== foreignObject-01.svg pass.svg
== foreignObject-02.svg foreignObject-02-ref.svg
== foreignObject-ancestor-style-change-01.svg foreignObject-ancestor-style-change-01-ref.svg
@ -184,13 +226,19 @@ fuzzy-if(Android,18,600) == foreignObject-fixedpos-01.html foreignObject-dynamic
== foreignObject-fixedpos-02.html foreignObject-fixedpos-ref.html
== foreignObject-dynamic-fixedpos-01.html foreignObject-dynamic-abspos-01-ref.html
== foreignObject-vertical-01.svg foreignObject-vertical-01-ref.svg
== fragmentIdentifier-01.xhtml pass.svg
== g-transform-01.svg pass.svg
== getElementById-a-element-01.svg pass.svg
fuzzy-if(Android,9,980) fuzzy-if(skiaContent,3,32000) == gradient-live-01a.svg gradient-live-01-ref.svg
fuzzy-if(Android,9,980) fuzzy-if(skiaContent,3,32000) == gradient-live-01b.svg gradient-live-01-ref.svg
fuzzy-if(Android,9,980) fuzzy-if(skiaContent,3,32000) == gradient-live-01c.svg gradient-live-01-ref.svg
fuzzy-if(Android,9,980) fuzzy-if(skiaContent,3,32000) == gradient-live-01d.svg gradient-live-01-ref.svg
== gradient-transform-01.svg pass.svg
== href-attr-change-restyles.svg href-attr-change-restyles-ref.svg
fuzzy-if(skiaContent,1,550) == import-svg-01.html pass.svg
== invalid-text-01.svg pass.svg
== lang-attribute-01.svg pass.svg
@ -200,6 +248,10 @@ fuzzy-if(skiaContent,1,550) == import-svg-01.html pass.svg
== linearGradient-basic-02.svg pass.svg
# off-by-one fuzziness expected. OS X is broken with bad aliasing though (bug 1023640).
fuzzy-if(cocoaWidget,15,19679) fuzzy-if(winWidget,1,8800) fuzzy-if(!cocoaWidget&&!winWidget,1,4000) fuzzy-if(skiaContent,1,5000) == linearGradient-basic-03.svg linearGradient-basic-03-ref.svg
== linked-filter-01.svg pass.svg
== linked-pattern-01.svg pass.svg
fuzzy-if(skiaContent,1,800000) == markers-and-group-opacity-01.svg markers-and-group-opacity-01-ref.svg
== marker-attribute-01.svg pass.svg
== marker-effects-01.svg marker-effects-01-ref.svg
@ -208,27 +260,40 @@ fuzzy-if(skiaContent,1,100) == marker-orientation-01.svg marker-orientation-01-r
fuzzy-if(skiaContent,1,5) pref(svg.marker-improvements.enabled,true) == marker-orientation-02.svg marker-orientation-02-ref.svg
== marker-orientation-03.svg pass.svg
== marker-orientation-04.svg pass.svg
fuzzy(28,28) == mask-and-clipPath.html mask-and-clipPath-ref.html
== mask-and-clipPath-2.svg pass.svg
== mask-basic-01.svg pass.svg
fuzzy-if(skiaContent,1,10000) == mask-basic-02.svg mask-basic-02-ref.svg
== mask-basic-03.svg pass.svg
== mask-basic-04.svg pass.svg
== mask-extref-dataURI-01.svg pass.svg
== mask-containing-masked-content-01.svg pass.svg
== mask-contains-inner-svg-01.svg pass.svg
== mask-contains-inner-svg-02.svg pass.svg
== mask-empty-size.svg about:blank
== mask-extref-dataURI-01.svg pass.svg
== mask-img.html mask-img-ref.html
== mask-on-outflowElement-01a.html clipPath-on-outflowElement-01-ref.html
== mask-on-outflowElement-01b.html clipPath-on-outflowElement-01-ref.html
fuzzy(1,5000) == mask-opacity-01.svg mask-opacity-01-ref.svg
== mask-transformed-01.svg mask-transformed-01-ref.svg
== mask-transformed-02.svg pass.svg
== mask-transformed-child-01.svg mask-transformed-child-01-ref.svg
# fuzzy because of the differences between clipPath and mask clipping
fuzzy(28,28) == mask-and-clipPath.html mask-and-clipPath-ref.html
== mask-and-clipPath-2.svg pass.svg
fuzzy-if(d2d||skiaContent,1,6400) == mask-type-01.svg mask-type-01-ref.svg
fuzzy-if(d2d||skiaContent,1,6400) == mask-type-02.svg mask-type-01-ref.svg
fuzzy-if(d2d||skiaContent,1,6400) == mask-type-03.svg mask-type-01-ref.svg
fuzzy-if(d2d||skiaContent,1,6400) == mask-type-04.svg mask-type-01-ref.svg
== mask-use-element-01.svg pass.svg
!= nested-mask-mode.svg about:blank
== nested-viewBox-01.svg pass.svg
fuzzy-if(skiaContent,3,448000) == nesting-invalid-01.svg nesting-invalid-01-ref.svg
fuzzy-if(d2d&&/^Windows\x20NT\x20(6\.1|10\.0)/.test(http.oscpu),63,168) fuzzy-if(cocoaWidget,1,122) fuzzy-if(skiaContent,2,1000) == non-scaling-stroke-01.svg non-scaling-stroke-01-ref.svg # bug 1074161 for Win7 and OSX 10.8
fuzzy-if(gtkWidget,1,99) fuzzy-if(!contentSameGfxBackendAsCanvas,9,99) fuzzy-if(Android,9,586) == non-scaling-stroke-02.svg non-scaling-stroke-02-ref.svg
== non-scaling-stroke-03.svg non-scaling-stroke-03-ref.svg
== objectBoundingBox-and-clipPath.svg pass.svg
# Bug 588684
random-if(gtkWidget) == objectBoundingBox-and-fePointLight-01.svg objectBoundingBox-and-fePointLight-01-ref.svg
@ -240,12 +305,16 @@ random-if(gtkWidget) == objectBoundingBox-and-fePointLight-02.svg objectBounding
== objectBoundingBox-and-pattern-01c.svg objectBoundingBox-and-pattern-01-ref.svg
== objectBoundingBox-and-pattern-02.svg pass.svg
== objectBoundingBox-and-pattern-03.svg objectBoundingBox-and-pattern-03-ref.svg
== opacity-and-gradient-01.svg pass.svg
skip-if(d2d) fuzzy-if(cocoaWidget,1,99974) fuzzy-if(skiaContent,1,200000) == opacity-and-gradient-02.svg opacity-and-gradient-02-ref.svg
== opacity-and-pattern-01.svg pass.svg
fuzzy-if(skiaContent,1,10000) == opacity-and-transform-01.svg opacity-and-transform-01-ref.svg
fuzzy-if(Android,8,200) == outer-svg-border-and-padding-01.svg outer-svg-border-and-padding-01-ref.svg
== outline.html outline-ref.html
== overflow-on-outer-svg-01.svg overflow-on-outer-svg-01-ref.svg
== overflow-on-outer-svg-02a.xhtml overflow-on-outer-svg-02-ref.xhtml
== overflow-on-outer-svg-02b.xhtml overflow-on-outer-svg-02-ref.xhtml
@ -253,9 +322,14 @@ fuzzy-if(Android,8,200) == outer-svg-border-and-padding-01.svg outer-svg-border-
== overflow-on-outer-svg-02d.xhtml overflow-on-outer-svg-02-ref.xhtml
== overflow-on-outer-svg-03a.xhtml overflow-on-outer-svg-03-ref.xhtml
== overflow-on-outer-svg-03b.xhtml overflow-on-outer-svg-03-ref.xhtml
== paint-on-maskLayer-1a.html paint-on-maskLayer-1-ref.html
== paint-on-maskLayer-1b.html paint-on-maskLayer-1-ref.html
pref(layout.css.clip-path-shapes.enabled,true) == paint-on-maskLayer-1c.html paint-on-maskLayer-1-ref.html
pref(svg.paint-order.enabled,true) == paint-order-01.svg paint-order-01-ref.svg
pref(svg.paint-order.enabled,true) == paint-order-02.svg paint-order-02-ref.svg
pref(svg.paint-order.enabled,true) == paint-order-03.svg paint-order-03-ref.svg
#fuzzy(23,60) fails-if(d2d) == path-01.svg path-01-ref.svg
== path-02.svg pass.svg
== path-03.svg pass.svg
@ -264,8 +338,10 @@ pref(svg.paint-order.enabled,true) == paint-order-03.svg paint-order-03-ref.svg
fuzzy-if(skiaContent,1,400) == path-06.svg path-06-ref.svg
== path-07.svg path-07-ref.svg
== path-08.svg pass.svg
== pathLength-01.svg pass.svg
== pathLength-02.svg pass.svg
== pattern-basic-01.svg pass.svg
== pattern-invalid-01.svg pattern-invalid-01-ref.svg
fuzzy-if(skiaContent,1,5) == pattern-live-01a.svg pattern-live-01-ref.svg
@ -276,39 +352,61 @@ fuzzy-if(skiaContent,1,5) == pattern-scale-01a.svg pattern-scale-01-ref.svg
fuzzy-if(skiaContent,3,5) == pattern-scale-01c.svg pattern-scale-01-ref.svg
== pattern-transform-presence-01.svg pattern-transform-presence-01-ref.svg
== pattern-transformed-01.svg pattern-transformed-01-ref.svg
== polygon-01.svg polygon-01-ref.svg
== polygon-marker-01.svg pass.svg
== polygon-points-negative-01.svg pass.svg
== polyline-points-invalid-01.svg pass.svg
== pseudo-classes-01.svg pass.svg
# This test depends on :visited styles (which are asynchronous), so we run
# it in layout/style/test/test_visited_reftests.html instead of using the
# reftest harness.
# == pseudo-classes-02.svg pseudo-classes-02-ref.svg
== radialGradient-basic-01.svg pass.svg
== radialGradient-basic-02.svg pass.svg
fuzzy-if(cocoaWidget,4,15982) fuzzy-if(winWidget,4,92) fuzzy-if(skiaContent,4,60) == radialGradient-basic-03.svg radialGradient-basic-03-ref.svg
== radialGradient-basic-04.svg pass.svg
fuzzy-if(skiaContent,1,3600) == rect-01.svg pass.svg
== rect-02.svg pass.svg
== rect-03.svg pass.svg
== rect-04.svg pass.svg
== rect-with-rx-and-ry-01.svg pass.svg
== rect-with-rx-or-ry-01.svg rect-with-rx-or-ry-01-ref.svg
== rootElement-null-01.svg pass.svg
== script-empty-01.svg pass.svg
== selector-01.svg pass.svg
== stroke-dasharray-01.svg stroke-dasharray-01-ref.svg
fuzzy-if(skiaContent,1,340) == stroke-dasharray-02.svg pass.svg
fuzzy-if(skiaContent,1,340) == stroke-dasharray-03.svg pass.svg
== stroke-dasharray-and-pathLength-01.svg pass.svg
== stroke-dasharray-and-text-01.svg stroke-dasharray-and-text-01-ref.svg
== stroke-dashoffset-01.svg pass.svg
== stroke-dashoffset-and-pathLength-01.svg pass.svg
== stroke-linecap-circle-ellipse-01.svg stroke-linecap-circle-ellipse-01-ref.svg
== stroke-linecap-circle-ellipse-dashed-01.svg pass.svg
== stroke-linecap-round-w-zero-length-segs-01.svg pass.svg
== stroke-linecap-round-w-zero-length-segs-02.svg pass.svg
== stroke-linecap-square-w-zero-length-segs-01.svg pass.svg
== stroke-linecap-square-w-zero-length-segs-02.svg pass.svg
== stroke-width-percentage-01.svg pass.svg
== stroke-width-percentage-02a.svg stroke-width-percentage-02-ref.svg
== stroke-width-percentage-02b.svg stroke-width-percentage-02-ref.svg
== stroke-width-percentage-03.xhtml stroke-width-percentage-03-ref.xhtml
== style-property-on-script-element-01.svg pass.svg
== style-without-type-attribute.svg pass.svg
== svg-in-foreignObject-01.xhtml svg-in-foreignObject-01-ref.xhtml
fuzzy-if(skiaContent,1,2600) == svg-in-foreignObject-02.xhtml svg-in-foreignObject-01-ref.xhtml # reuse -01-ref.xhtml
== switch-01.svg pass.svg
== suspend-01.svg pass.svg
== suspend-02.svg pass.svg
== suspend-03.svg pass.svg
@ -317,9 +415,15 @@ fuzzy-if(skiaContent,1,2600) == svg-in-foreignObject-02.xhtml svg-in-foreignObje
== suspend-06.svg pass.svg
== suspend-07.svg pass.svg
== suspend-08.svg pass.svg
== svg-effects-area-unzoomed.xhtml svg-effects-area-unzoomed-ref.xhtml
== svg-effects-area-zoomed-in.xhtml svg-effects-area-zoomed-in-ref.xhtml
== svg-effects-area-zoomed-out.xhtml svg-effects-area-zoomed-out-ref.xhtml
== svg-transform-01.svg pass.svg
== svg-transform-02.svg pass.svg
== symbol-01.svg symbol-01-ref.svg
== text-font-size-01.svg pass.svg
random-if(gtkWidget) == text-font-weight-01.svg text-font-weight-01-ref.svg # bug 386713
== text-gradient-01.svg text-gradient-01-ref.svg
@ -343,31 +447,23 @@ fuzzy-if(cocoaWidget&&layersGPUAccelerated,1,3) == text-layout-06.svg text-layou
== text-scale-01.svg text-scale-01-ref.svg
fuzzy-if(skiaContent,2,1000) HTTP(..) == text-scale-02.svg text-scale-02-ref.svg
HTTP(..) == text-scale-03.svg text-scale-03-ref.svg
== text-stroke-scaling-01.svg text-stroke-scaling-01-ref.svg
== stroke-dasharray-01.svg stroke-dasharray-01-ref.svg
fuzzy-if(skiaContent,1,340) == stroke-dasharray-02.svg pass.svg
fuzzy-if(skiaContent,1,340) == stroke-dasharray-03.svg pass.svg
== stroke-dasharray-and-pathLength-01.svg pass.svg
== stroke-dasharray-and-text-01.svg stroke-dasharray-and-text-01-ref.svg
== stroke-dashoffset-01.svg pass.svg
== stroke-dashoffset-and-pathLength-01.svg pass.svg
== stroke-linecap-round-w-zero-length-segs-01.svg pass.svg
== stroke-linecap-round-w-zero-length-segs-02.svg pass.svg
== stroke-linecap-square-w-zero-length-segs-01.svg pass.svg
== stroke-linecap-square-w-zero-length-segs-02.svg pass.svg
== textPath-01.svg textPath-01-ref.svg
== textPath-02.svg pass.svg
fuzzy-if(skiaContent,1,610) == textPath-03.svg pass.svg
== textPath-04.svg pass.svg
== textPath-05.html pass.svg
== text-style-01a.svg text-style-01-ref.svg
== text-style-01b.svg text-style-01-ref.svg
== text-style-01c.svg text-style-01-ref.svg
== text-style-01d.svg text-style-01-ref.svg
== text-style-01e.svg text-style-01-ref.svg
== text-stroke-scaling-01.svg text-stroke-scaling-01-ref.svg
== textPath-01.svg textPath-01-ref.svg
== textPath-02.svg pass.svg
fuzzy-if(skiaContent,1,610) == textPath-03.svg pass.svg
== textPath-04.svg pass.svg
== textPath-05.html pass.svg
== text-white-space-01.svg text-white-space-01-ref.svg
== thin-stroke-01.svg pass.svg
== zero-stroke-01.svg pass.svg
== tspan-dxdy-01.svg tspan-dxdy-ref.svg
== tspan-dxdy-02.svg tspan-dxdy-ref.svg
== tspan-dxdy-03.svg tspan-dxdy-ref.svg
@ -393,7 +489,24 @@ fuzzy-if(skiaContent,1,300) == tspan-xy-05.svg tspan-xy-ref.svg
fuzzy-if(skiaContent,1,300) == tspan-xy-06.svg tspan-xy-ref.svg
fuzzy-if(skiaContent,1,100) == tspan-xy-anchor-middle-01.svg tspan-xy-anchor-middle-ref.svg
fuzzy-if(skiaContent,1,100) == tspan-xy-anchor-end-01.svg tspan-xy-anchor-end-ref.svg
== use-01.svg pass.svg
== use-01-extref.svg pass.svg
== use-02-extref.svg use-02-extref-ref.svg
== use-extref-dataURI-01.svg pass.svg
== use-children.svg pass.svg
# test case for Fragment URLs
# https://drafts.csswg.org/css-values/#local-urls
== use-localRef-marker-01.svg use-localRef-marker-01-ref.svg
== use-localRef-clipPath-01.svg use-localRef-clipPath-01-ref.svg
== use-localRef-filter-01.svg use-localRef-filter-01-ref.svg
== use-localRef-fill-01.svg use-localRef-fill-01-ref.svg
== use-localRef-stroke-01.svg use-localRef-stroke-01-ref.svg
== use-localRef-mask-01.svg use-localRef-mask-01-ref.svg
== userSpaceOnUse-and-pattern-01.svg userSpaceOnUse-and-pattern-01-ref.svg
== viewBox-and-pattern-01.svg pass.svg
== viewBox-and-pattern-02.svg pass.svg
== viewBox-and-pattern-03.svg pass.svg
@ -405,76 +518,4 @@ fuzzy-if(skiaContent,1,100) == tspan-xy-anchor-end-01.svg tspan-xy-anchor-end-re
== viewport-percent-graphic-user-01.svg pass.svg
== winding-01.svg pass.svg
== svg-effects-area-unzoomed.xhtml svg-effects-area-unzoomed-ref.xhtml
== svg-effects-area-zoomed-in.xhtml svg-effects-area-zoomed-in-ref.xhtml
== svg-effects-area-zoomed-out.xhtml svg-effects-area-zoomed-out-ref.xhtml
== href-attr-change-restyles.svg href-attr-change-restyles-ref.svg
== mask-img.html mask-img-ref.html
skip-if(Android) pref(layout.css.mix-blend-mode.enabled,true) == blend-color-burn.svg blend-color-burn-ref.svg
skip-if(Android) pref(layout.css.mix-blend-mode.enabled,true) == blend-color-dodge.svg blend-color-dodge-ref.svg
# pref(layout.css.mix-blend-mode.enabled,true) == blend-color.svg blend-color-ref.svg
skip-if(Android) pref(layout.css.mix-blend-mode.enabled,true) == blend-darken.svg blend-darken-ref.svg
skip-if(Android) pref(layout.css.mix-blend-mode.enabled,true) == blend-difference.svg blend-difference-ref.svg
skip-if(Android) fuzzy-if(skiaContent,1,1600) pref(layout.css.mix-blend-mode.enabled,true) == blend-exclusion.svg blend-exclusion-ref.svg
# pref(layout.css.mix-blend-mode.enabled,true) == blend-hard-light.svg blend-hard-light-ref.svg
# pref(layout.css.mix-blend-mode.enabled,true) == blend-hue.svg blend-hue-ref.svg
skip-if(Android) pref(layout.css.mix-blend-mode.enabled,true) == blend-layer-blend.svg blend-layer-blend-ref.svg
skip-if(Android) pref(layout.css.mix-blend-mode.enabled,true) == blend-layer-filter.svg blend-layer-filter-ref.svg
skip-if(Android) pref(layout.css.mix-blend-mode.enabled,true) == blend-layer-mask.svg blend-layer-mask-ref.svg
skip-if(Android) pref(layout.css.mix-blend-mode.enabled,true) == blend-layer-opacity.svg blend-layer-opacity-ref.svg
skip-if(Android) pref(layout.css.mix-blend-mode.enabled,true) == blend-lighten.svg blend-lighten-ref.svg
# pref(layout.css.mix-blend-mode.enabled,true) == blend-luminosity.svg blend-luminosity-ref.svg
#skip-if(Android) pref(layout.css.mix-blend-mode.enabled,true) == blend-multiply-alpha.svg blend-multiply-alpha-ref.svg
skip-if(Android) pref(layout.css.mix-blend-mode.enabled,true) == blend-multiply.svg blend-multiply-ref.svg
pref(layout.css.mix-blend-mode.enabled,true) == blend-normal.svg blend-normal-ref.svg
#skip-if(Android) pref(layout.css.mix-blend-mode.enabled,true) == blend-overlay.svg blend-overlay-ref.svg
#skip-if(Android) pref(layout.css.mix-blend-mode.enabled,true) == blend-saturation.svg blend-saturation-ref.svg
#skip-if(Android) pref(layout.css.mix-blend-mode.enabled,true) == blend-screen.svg blend-screen-ref.svg
#skip-if(Android) pref(layout.css.mix-blend-mode.enabled,true) == blend-soft-light.svg blend-soft-light-ref.svg
skip-if(Android) pref(layout.css.mix-blend-mode.enabled,true) == blend-difference-stacking.html blend-difference-stacking-ref.html
# test case for Fragment URLs
# https://drafts.csswg.org/css-values/#local-urls
== use-localRef-marker-01.svg use-localRef-marker-01-ref.svg
== use-localRef-clipPath-01.svg use-localRef-clipPath-01-ref.svg
== use-localRef-filter-01.svg use-localRef-filter-01-ref.svg
== use-localRef-fill-01.svg use-localRef-fill-01-ref.svg
== use-localRef-stroke-01.svg use-localRef-stroke-01-ref.svg
== use-localRef-mask-01.svg use-localRef-mask-01-ref.svg
fuzzy(1,5000) == mask-opacity-01.svg mask-opacity-01-ref.svg
== clipPath-on-outflowElement-01a.html clipPath-on-outflowElement-01-ref.html
== clipPath-on-outflowElement-01b.html clipPath-on-outflowElement-01-ref.html
default-preferences pref(layout.css.clip-path-shapes.enabled,true)
fuzzy(1,32400) == clipPath-on-outflowElement-02a.html clipPath-on-outflowElement-02-ref.html
fuzzy(1,32400) == clipPath-on-outflowElement-02b.html clipPath-on-outflowElement-02-ref.html
default-preferences
== mask-on-outflowElement-01a.html clipPath-on-outflowElement-01-ref.html
== mask-on-outflowElement-01b.html clipPath-on-outflowElement-01-ref.html
== clipPath-and-mask-on-outflowElement-01a.html clipPath-on-outflowElement-01-ref.html
== clipPath-and-mask-on-outflowElement-01b.html clipPath-on-outflowElement-01-ref.html
!= nested-mask-mode.svg about:blank
== mask-empty-size.svg about:blank
== paint-on-maskLayer-1a.html paint-on-maskLayer-1-ref.html
== paint-on-maskLayer-1b.html paint-on-maskLayer-1-ref.html
pref(layout.css.clip-path-shapes.enabled,true) == paint-on-maskLayer-1c.html paint-on-maskLayer-1-ref.html
fuzzy(71,817) == filter-on-continuation-box-01.html filter-on-continuation-box-ref.html
== mask-contains-inner-svg-01.svg pass.svg
== mask-contains-inner-svg-02.svg pass.svg
== mask-use-element-01.svg pass.svg
== clip-use-element-01.svg pass.svg
== clip-use-element-02.svg pass.svg
== filter-use-element-01.svg pass.svg
== background-svg-without-height.html background-ref.html
== background-svg-without-height-width.html background-ref.html
== background-svg-without-width.html background-ref.html
== zero-stroke-01.svg pass.svg

Просмотреть файл

@ -0,0 +1,51 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_CSSNamespaceRule_h
#define mozilla_dom_CSSNamespaceRule_h
#include "mozilla/css/Rule.h"
#include "mozilla/dom/CSSNamespaceRuleBinding.h"
class nsIAtom;
namespace mozilla {
namespace dom {
class CSSNamespaceRule : public css::Rule
{
protected:
using Rule::Rule;
public:
bool IsCCLeaf() const final {
return Rule::IsCCLeaf();
}
int32_t GetType() const final {
return Rule::NAMESPACE_RULE;
}
using Rule::GetType;
virtual nsIAtom* GetPrefix() const = 0;
virtual void GetURLSpec(nsString& aURLSpec) const = 0;
// WebIDL interfaces
uint16_t Type() const final {
return nsIDOMCSSRule::NAMESPACE_RULE;
}
size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const = 0;
JSObject* WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) final {
return CSSNamespaceRuleBinding::Wrap(aCx, this, aGivenProto);
}
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_CSSNamespaceRule_h

Просмотреть файл

@ -10,7 +10,7 @@
#include "mozilla/Attributes.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/css/Rule.h"
#include "mozilla/dom/CSSNamespaceRule.h"
#include "nsIDOMCSSRule.h"
@ -24,7 +24,7 @@ class nsIAtom;
namespace mozilla {
namespace css {
class NameSpaceRule final : public Rule
class NameSpaceRule final : public dom::CSSNamespaceRule
{
public:
NameSpaceRule(nsIAtom* aPrefix, const nsString& aURLSpec,
@ -37,28 +37,19 @@ public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_CSS_NAMESPACE_RULE_IMPL_CID)
NS_DECL_ISUPPORTS_INHERITED
virtual bool IsCCLeaf() const override;
#ifdef DEBUG
virtual void List(FILE* out = stdout, int32_t aIndent = 0) const override;
#endif
virtual int32_t GetType() const override;
using Rule::GetType;
virtual already_AddRefed<Rule> Clone() const override;
nsIAtom* GetPrefix() const { return mPrefix; }
void GetURLSpec(nsString& aURLSpec) const { aURLSpec = mURLSpec; }
nsIAtom* GetPrefix() const final { return mPrefix; }
void GetURLSpec(nsString& aURLSpec) const final { aURLSpec = mURLSpec; }
// WebIDL interface
uint16_t Type() const override;
void GetCssTextImpl(nsAString& aCssText) const override;
virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
override MOZ_MUST_OVERRIDE;
virtual JSObject* WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override;
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const final;
private:
nsCOMPtr<nsIAtom> mPrefix;

Просмотреть файл

@ -15,3 +15,4 @@ SERVO_ARC_TYPE(ImportRule, RawServoImportRule)
SERVO_ARC_TYPE(AnimationValue, RawServoAnimationValue)
SERVO_ARC_TYPE(MediaList, RawServoMediaList)
SERVO_ARC_TYPE(MediaRule, RawServoMediaRule)
SERVO_ARC_TYPE(NamespaceRule, RawServoNamespaceRule)

Просмотреть файл

@ -76,10 +76,6 @@ SERVO_BINDING_FUNC(Servo_StyleSet_FillKeyframesForName, bool,
SERVO_BINDING_FUNC(Servo_CssRules_ListTypes, void,
ServoCssRulesBorrowed rules,
nsTArrayBorrowed_uintptr_t result)
SERVO_BINDING_FUNC(Servo_CssRules_GetStyleRuleAt, RawServoStyleRuleStrong,
ServoCssRulesBorrowed rules, uint32_t index)
SERVO_BINDING_FUNC(Servo_CssRules_GetMediaRuleAt, RawServoMediaRuleStrong,
ServoCssRulesBorrowed rules, uint32_t index)
SERVO_BINDING_FUNC(Servo_CssRules_InsertRule, nsresult,
ServoCssRulesBorrowed rules,
RawServoStyleSheetBorrowed sheet, const nsACString* rule,
@ -88,25 +84,33 @@ SERVO_BINDING_FUNC(Servo_CssRules_DeleteRule, nsresult,
ServoCssRulesBorrowed rules, uint32_t index)
// CSS Rules
SERVO_BINDING_FUNC(Servo_StyleRule_Debug, void,
RawServoStyleRuleBorrowed rule, nsACString* result)
#define BASIC_RULE_FUNCS(type_) \
SERVO_BINDING_FUNC(Servo_CssRules_Get##type_##RuleAt, \
RawServo##type_##RuleStrong, \
ServoCssRulesBorrowed rules, uint32_t index) \
SERVO_BINDING_FUNC(Servo_##type_##Rule_Debug, void, \
RawServo##type_##RuleBorrowed rule, nsACString* result) \
SERVO_BINDING_FUNC(Servo_##type_##Rule_GetCssText, void, \
RawServo##type_##RuleBorrowed rule, nsAString* result)
BASIC_RULE_FUNCS(Style)
BASIC_RULE_FUNCS(Media)
BASIC_RULE_FUNCS(Namespace)
#undef BASIC_RULE_FUNCS
SERVO_BINDING_FUNC(Servo_StyleRule_GetStyle, RawServoDeclarationBlockStrong,
RawServoStyleRuleBorrowed rule)
SERVO_BINDING_FUNC(Servo_StyleRule_SetStyle, void,
RawServoStyleRuleBorrowed rule,
RawServoDeclarationBlockBorrowed declarations)
SERVO_BINDING_FUNC(Servo_StyleRule_GetCssText, void,
RawServoStyleRuleBorrowed rule, nsAString* result)
SERVO_BINDING_FUNC(Servo_StyleRule_GetSelectorText, void,
RawServoStyleRuleBorrowed rule, nsAString* result)
SERVO_BINDING_FUNC(Servo_MediaRule_Debug, void,
RawServoMediaRuleBorrowed rule, nsACString* result)
SERVO_BINDING_FUNC(Servo_MediaRule_GetMedia, RawServoMediaListStrong,
RawServoMediaRuleBorrowed rule)
SERVO_BINDING_FUNC(Servo_MediaRule_GetRules, ServoCssRulesStrong,
RawServoMediaRuleBorrowed rule)
SERVO_BINDING_FUNC(Servo_MediaRule_GetCssText, void,
RawServoMediaRuleBorrowed rule, nsAString* result)
SERVO_BINDING_FUNC(Servo_NamespaceRule_GetPrefix, nsIAtom*,
RawServoNamespaceRuleBorrowed rule)
SERVO_BINDING_FUNC(Servo_NamespaceRule_GetURI, nsIAtom*,
RawServoNamespaceRuleBorrowed rule)
// Animations API
SERVO_BINDING_FUNC(Servo_ParseProperty,

Просмотреть файл

@ -11,6 +11,7 @@
#include "mozilla/ServoBindings.h"
#include "mozilla/ServoStyleRule.h"
#include "mozilla/ServoMediaRule.h"
#include "mozilla/ServoNamespaceRule.h"
namespace mozilla {
@ -70,19 +71,18 @@ ServoCSSRuleList::GetRule(uint32_t aIndex)
if (rule <= kMaxRuleType) {
RefPtr<css::Rule> ruleObj = nullptr;
switch (rule) {
case nsIDOMCSSRule::STYLE_RULE: {
ruleObj = new ServoStyleRule(
Servo_CssRules_GetStyleRuleAt(mRawRules, aIndex).Consume());
break;
}
case nsIDOMCSSRule::MEDIA_RULE: {
ruleObj = new ServoMediaRule(
Servo_CssRules_GetMediaRuleAt(mRawRules, aIndex).Consume());
break;
#define CASE_RULE(const_, name_) \
case nsIDOMCSSRule::const_##_RULE: { \
ruleObj = new Servo##name_##Rule( \
Servo_CssRules_Get##name_##RuleAt(mRawRules, aIndex).Consume()); \
break; \
}
CASE_RULE(STYLE, Style)
CASE_RULE(MEDIA, Media)
CASE_RULE(NAMESPACE, Namespace)
#undef CASE_RULE
case nsIDOMCSSRule::FONT_FACE_RULE:
case nsIDOMCSSRule::KEYFRAMES_RULE:
case nsIDOMCSSRule::NAMESPACE_RULE:
// XXX create corresponding rules
default:
NS_WARNING("stylo: not implemented yet");

Просмотреть файл

@ -0,0 +1,73 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/ServoNamespaceRule.h"
#include "mozilla/ServoBindings.h"
using namespace mozilla::dom;
namespace mozilla {
ServoNamespaceRule::~ServoNamespaceRule()
{
}
NS_IMPL_ADDREF_INHERITED(ServoNamespaceRule, CSSNamespaceRule)
NS_IMPL_RELEASE_INHERITED(ServoNamespaceRule, CSSNamespaceRule)
NS_INTERFACE_MAP_BEGIN(ServoNamespaceRule)
NS_INTERFACE_MAP_END_INHERITING(CSSNamespaceRule)
#ifdef DEBUG
void
ServoNamespaceRule::List(FILE* out, int32_t aIndent) const
{
nsAutoCString str;
for (int32_t i = 0; i < aIndent; i++) {
str.AppendLiteral(" ");
}
Servo_NamespaceRule_Debug(mRawRule, &str);
fprintf_stderr(out, "%s\n", str.get());
}
#endif
already_AddRefed<css::Rule>
ServoNamespaceRule::Clone() const
{
// Rule::Clone is only used when CSSStyleSheetInner is cloned in
// preparation of being mutated. However, ServoStyleSheet never clones
// anything, so this method should never be called.
MOZ_ASSERT_UNREACHABLE("Shouldn't be cloning ServoNamespaceRule");
return nullptr;
}
nsIAtom*
ServoNamespaceRule::GetPrefix() const
{
return Servo_NamespaceRule_GetPrefix(mRawRule);
}
void
ServoNamespaceRule::GetURLSpec(nsString& aURLSpec) const
{
nsIAtom* atom = Servo_NamespaceRule_GetURI(mRawRule);
atom->ToString(aURLSpec);
}
void
ServoNamespaceRule::GetCssTextImpl(nsAString& aCssText) const
{
Servo_NamespaceRule_GetCssText(mRawRule, &aCssText);
}
size_t
ServoNamespaceRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
{
return aMallocSizeOf(this);
}
} // namespace mozilla

Просмотреть файл

@ -0,0 +1,47 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_ServoNamespaceRule_h
#define mozilla_ServoNamespaceRule_h
#include "mozilla/ServoBindingTypes.h"
#include "mozilla/dom/CSSNamespaceRule.h"
namespace mozilla {
class ServoNamespaceRule : public dom::CSSNamespaceRule
{
public:
explicit ServoNamespaceRule(already_AddRefed<RawServoNamespaceRule> aRule)
: CSSNamespaceRule(0, 0)
, mRawRule(Move(aRule))
{
}
NS_DECL_ISUPPORTS_INHERITED
#ifdef DEBUG
void List(FILE* out = stdout, int32_t aIndent = 0) const final;
#endif
already_AddRefed<Rule> Clone() const final;
nsIAtom* GetPrefix() const final;
void GetURLSpec(nsString& aURLSpec) const final;
// WebIDL interface
void GetCssTextImpl(nsAString& aCssText) const final;
size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const final;
private:
~ServoNamespaceRule();
RefPtr<RawServoNamespaceRule> mRawRule;
};
} // namespace mozilla
#endif // mozilla_ServoNamespaceRule_h

Просмотреть файл

@ -104,6 +104,7 @@ EXPORTS.mozilla += [
'ServoElementSnapshot.h',
'ServoMediaList.h',
'ServoMediaRule.h',
'ServoNamespaceRule.h',
'ServoPropPrefList.h',
'ServoSpecifiedValues.h',
'ServoStyleRule.h',
@ -128,6 +129,7 @@ EXPORTS.mozilla.dom += [
'CSS.h',
'CSSLexer.h',
'CSSMediaRule.h',
'CSSNamespaceRule.h',
'CSSRuleList.h',
'CSSValue.h',
'FontFace.h',
@ -218,6 +220,7 @@ UNIFIED_SOURCES += [
'ServoElementSnapshot.cpp',
'ServoMediaList.cpp',
'ServoMediaRule.cpp',
'ServoNamespaceRule.cpp',
'ServoSpecifiedValues.cpp',
'ServoStyleRule.cpp',
'ServoStyleSet.cpp',

Просмотреть файл

@ -34,7 +34,6 @@
#include "nsCSSParser.h"
#include "nsDOMClassInfoID.h"
#include "mozilla/dom/CSSStyleDeclarationBinding.h"
#include "mozilla/dom/CSSNamespaceRuleBinding.h"
#include "mozilla/dom/CSSImportRuleBinding.h"
#include "mozilla/dom/CSSSupportsRuleBinding.h"
#include "mozilla/dom/CSSMozDocumentRuleBinding.h"
@ -773,14 +772,14 @@ DocumentRule::AppendConditionText(nsAString& aCssText) const
NameSpaceRule::NameSpaceRule(nsIAtom* aPrefix, const nsString& aURLSpec,
uint32_t aLineNumber, uint32_t aColumnNumber)
: Rule(aLineNumber, aColumnNumber),
: CSSNamespaceRule(aLineNumber, aColumnNumber),
mPrefix(aPrefix),
mURLSpec(aURLSpec)
{
}
NameSpaceRule::NameSpaceRule(const NameSpaceRule& aCopy)
: Rule(aCopy),
: CSSNamespaceRule(aCopy),
mPrefix(aCopy.mPrefix),
mURLSpec(aCopy.mURLSpec)
{
@ -790,8 +789,8 @@ NameSpaceRule::~NameSpaceRule()
{
}
NS_IMPL_ADDREF_INHERITED(NameSpaceRule, Rule)
NS_IMPL_RELEASE_INHERITED(NameSpaceRule, Rule)
NS_IMPL_ADDREF_INHERITED(NameSpaceRule, CSSNamespaceRule)
NS_IMPL_RELEASE_INHERITED(NameSpaceRule, CSSNamespaceRule)
// QueryInterface implementation for NameSpaceRule
// If this ever gets its own cycle-collection bits, reevaluate our IsCCLeaf
@ -803,13 +802,7 @@ NS_INTERFACE_MAP_BEGIN(NameSpaceRule)
return NS_OK;
}
else
NS_INTERFACE_MAP_END_INHERITING(Rule)
bool
NameSpaceRule::IsCCLeaf() const
{
return Rule::IsCCLeaf();
}
NS_INTERFACE_MAP_END_INHERITING(CSSNamespaceRule)
#ifdef DEBUG
/* virtual */ void
@ -837,12 +830,6 @@ NameSpaceRule::List(FILE* out, int32_t aIndent) const
}
#endif
/* virtual */ int32_t
NameSpaceRule::GetType() const
{
return Rule::NAMESPACE_RULE;
}
/* virtual */ already_AddRefed<Rule>
NameSpaceRule::Clone() const
{
@ -850,12 +837,6 @@ NameSpaceRule::Clone() const
return clone.forget();
}
uint16_t
NameSpaceRule::Type() const
{
return nsIDOMCSSRule::NAMESPACE_RULE;
}
void
NameSpaceRule::GetCssTextImpl(nsAString& aCssText) const
{
@ -879,13 +860,6 @@ NameSpaceRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
// - mURLSpec
}
/* virtual */ JSObject*
NameSpaceRule::WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto)
{
return CSSNamespaceRuleBinding::Wrap(aCx, this, aGivenProto);
}
} // namespace css
} // namespace mozilla

Просмотреть файл

@ -536,7 +536,7 @@ nsMediaList::Matches(nsPresContext* aPresContext,
return mArray.IsEmpty();
}
already_AddRefed<MediaList>
already_AddRefed<dom::MediaList>
nsMediaList::Clone()
{
RefPtr<nsMediaList> result = new nsMediaList();

Просмотреть файл

@ -61,10 +61,6 @@ Any line which doesn't follow the format above would be ignored like comment.
* test_value_storage.html `animation` [280]
* test_any_dynamic.html: -moz-any pseudo class [2]
* CSSOM support:
* @namespace ##easy##
* test_at_rule_parse_serialize.html [1]
* test_bug765590.html [1]
* test_font_face_parser.html `@namespace` [1]
* @import
* test_bug221428.html [1]
* @media
@ -317,8 +313,6 @@ Any line which doesn't follow the format above would be ignored like comment.
* test_value_storage.html `-moz-element` [49]
* -moz-anchor-decoration value on text-decoration
* test_value_storage.html `-moz-anchor-decoration` [10]
* various values on -{webkit,moz}-user-select **need investigation**
* test_value_storage.html `user-select` [3]
* several prefixed values in cursor property
* test_value_storage.html `cursor` [4]
* moz-prefixed values of overflow shorthand bug 1330888

Просмотреть файл

@ -182,7 +182,9 @@ nsFilterInstance::nsFilterInstance(nsIFrame *aTargetFrame,
mTargetBBox = *aOverrideBBox;
} else {
MOZ_ASSERT(mTargetFrame, "Need to supply a frame when there's no aOverrideBBox");
mTargetBBox = nsSVGUtils::GetBBox(mTargetFrame);
mTargetBBox = nsSVGUtils::GetBBox(mTargetFrame,
nsSVGUtils::eUseFrameBoundsForOuterSVG |
nsSVGUtils::eBBoxIncludeFillGeometry);
}
// Compute user space to filter space transforms.

Просмотреть файл

@ -192,8 +192,8 @@ nsSVGIntegrationUtils::GetSVGCoordContextForNonSVGFrame(nsIFrame* aNonSVGFrame)
gfxRect
nsSVGIntegrationUtils::GetSVGBBoxForNonSVGFrame(nsIFrame* aNonSVGFrame)
{
NS_ASSERTION(!aNonSVGFrame->IsFrameOfType(nsIFrame::eSVG),
"SVG frames should not get here");
NS_ASSERTION(!(aNonSVGFrame->GetStateBits() & NS_FRAME_SVG_LAYOUT),
"Frames with SVG layout should not get here");
nsIFrame* firstFrame =
nsLayoutUtils::FirstContinuationOrIBSplitSibling(aNonSVGFrame);
// 'r' is in "user space":

Просмотреть файл

@ -1097,7 +1097,10 @@ nsSVGUtils::GetBBox(nsIFrame *aFrame, uint32_t aFlags)
}
gfxRect bbox;
nsISVGChildFrame *svg = do_QueryFrame(aFrame);
if (svg || aFrame->IsSVGText()) {
const bool hasSVGLayout = aFrame->GetStateBits() & NS_FRAME_SVG_LAYOUT;
if (hasSVGLayout || aFrame->IsSVGText() ||
// if we evaluate the following, |svg| can only be an outer-<svg> or null
(svg && !(aFlags & eUseFrameBoundsForOuterSVG))) {
// It is possible to apply a gradient, pattern, clipping path, mask or
// filter to text. When one of these facilities is applied to text
// the bounding box is the entire text element in all

Просмотреть файл

@ -403,7 +403,11 @@ public:
eBBoxIncludeStroke = 1 << 2,
eBBoxIncludeStrokeGeometry = 1 << 3,
eBBoxIncludeMarkers = 1 << 4,
eBBoxIncludeClipped = 1 << 5
eBBoxIncludeClipped = 1 << 5,
// Normally a getBBox call on outer-<svg> should only return the
// bounds of the elements children. This flag will cause the
// element's bounds to be returned instead.
eUseFrameBoundsForOuterSVG = 1 << 6
};
/**
* Get the SVG bbox (the SVG spec's simplified idea of bounds) of aFrame in

6
servo/Cargo.lock сгенерированный
Просмотреть файл

@ -1133,7 +1133,7 @@ dependencies = [
[[package]]
name = "html5ever"
version = "0.13.1"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"heapsize 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2252,7 +2252,7 @@ dependencies = [
"gfx_traits 0.0.1",
"heapsize 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize_derive 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"html5ever 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)",
"html5ever 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
"html5ever-atoms 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"hyper 0.9.18 (registry+https://github.com/rust-lang/crates.io-index)",
"hyper_serde 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
@ -3412,7 +3412,7 @@ dependencies = [
"checksum heartbeats-simple 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9ad003ce233955e9d95f2c69cde84e68302ba9ba4a673d351c9bff93c738aadc"
"checksum heartbeats-simple-sys 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e1a408c0011427cc0e0049f7861c70377819aedfc006e8c901b1c70fd98fb1a4"
"checksum hpack 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d2da7d3a34cf6406d9d700111b8eafafe9a251de41ae71d8052748259343b58"
"checksum html5ever 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d60508177ec4e5774a112efcf4d4d5f123cb00a43476fa5940b7da568371a165"
"checksum html5ever 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a3b2e982006a000535c1976213cd1baa3f455cd19335d50992ab219ffe1d3c06"
"checksum html5ever-atoms 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f9bd86e3b6a5a7933a272cc0a854f24e371f31576e585c0b41e8f857270c5134"
"checksum httparse 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a6e7a63e511f9edffbab707141fbb8707d1a3098615fb2adbd5769cdfcc9b17d"
"checksum hyper 0.9.18 (registry+https://github.com/rust-lang/crates.io-index)" = "1b9bf64f730d6ee4b0528a5f0a316363da9d8104318731509d4ccc86248f82b3"

Просмотреть файл

@ -108,7 +108,7 @@ use servo_config::opts;
use servo_config::prefs::PREFS;
use servo_rand::{Rng, SeedableRng, ServoRng, random};
use servo_remutex::ReentrantMutex;
use servo_url::ServoUrl;
use servo_url::{Host, ServoUrl};
use std::borrow::ToOwned;
use std::collections::{HashMap, VecDeque};
use std::iter::once;
@ -229,13 +229,13 @@ pub struct Constellation<Message, LTF, STF> {
/// event loop for each registered domain name (aka eTLD+1) in
/// each top-level frame. We store the event loops in a map
/// indexed by top-level frame id (as a `FrameId`) and registered
/// domain name (as a `String`) to event loops. This double
/// domain name (as a `Host`) to event loops. This double
/// indirection ensures that separate tabs do not share event
/// loops, even if the same domain is loaded in each.
/// It is important that scripts with the same eTLD+1
/// share an event loop, since they can use `document.domain`
/// to become same-origin, at which point they can share DOM objects.
event_loops: HashMap<FrameId, HashMap<String, Weak<EventLoop>>>,
event_loops: HashMap<FrameId, HashMap<Host, Weak<EventLoop>>>,
/// The set of all the pipelines in the browser.
/// (See the `pipeline` module for more details.)
@ -604,16 +604,18 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
None => self.root_frame_id,
};
debug!("Creating new pipeline {} in top-level frame {}.", pipeline_id, top_level_frame_id);
let (event_loop, host) = match sandbox {
IFrameSandboxState::IFrameSandboxed => (None, None),
IFrameSandboxState::IFrameUnsandboxed => match reg_host(&load_data.url) {
None => (None, None),
Some(host) => {
let event_loop = self.event_loops.get(&top_level_frame_id)
.and_then(|map| map.get(host))
.and_then(|map| map.get(&host))
.and_then(|weak| weak.upgrade());
match event_loop {
None => (None, Some(String::from(host))),
None => (None, Some(host)),
Some(event_loop) => (Some(event_loop.clone()), None),
}
},
@ -677,6 +679,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
};
if let Some(host) = host {
debug!("Adding new host entry {} for top-level frame {}.", host, top_level_frame_id);
self.event_loops.entry(top_level_frame_id)
.or_insert_with(HashMap::new)
.insert(host, Rc::downgrade(&pipeline.event_loop));

Просмотреть файл

@ -15,7 +15,7 @@
//! those cases are not present.
use servo_config::resource_files::read_resource_file;
use servo_url::ServoUrl;
use servo_url::{Host, ImmutableOrigin, ServoUrl};
use std::collections::HashSet;
use std::iter::FromIterator;
use std::str::from_utf8;
@ -146,6 +146,10 @@ pub fn is_reg_domain(domain: &str) -> bool {
/// Returns None if the URL has no host name.
/// Returns the registered suffix for the host name if it is a domain.
/// Leaves the host name alone if it is an IP address.
pub fn reg_host<'a>(url: &'a ServoUrl) -> Option<&'a str> {
url.domain().map(reg_suffix).or(url.host_str())
pub fn reg_host(url: &ServoUrl) -> Option<Host> {
match url.origin() {
ImmutableOrigin::Tuple(_, Host::Domain(domain), _) => Some(Host::Domain(String::from(reg_suffix(&*domain)))),
ImmutableOrigin::Tuple(_, ip, _) => Some(ip),
ImmutableOrigin::Opaque(_) => None,
}
}

Просмотреть файл

@ -45,7 +45,7 @@ fnv = "1.0"
gfx_traits = {path = "../gfx_traits"}
heapsize = "0.3.6"
heapsize_derive = "0.1"
html5ever = {version = "0.13", features = ["heap_size", "unstable"]}
html5ever = {version = "0.14", features = ["heap_size", "unstable"]}
html5ever-atoms = {version = "0.2", features = ["heap_size"]}
hyper = "0.9.9"
hyper_serde = "0.5"

Просмотреть файл

@ -10,7 +10,6 @@ use dom::bindings::codegen::Bindings::CSSStyleDeclarationBinding::CSSStyleDeclar
use dom::bindings::codegen::Bindings::DOMRectBinding::DOMRectMethods;
use dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods;
use dom::bindings::codegen::Bindings::ElementBinding::ElementMethods;
use dom::bindings::codegen::Bindings::LocationBinding::LocationMethods;
use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
use dom::bindings::conversions::{ConversionResult, FromJSValConvertible, jsstring_to_str};
use dom::bindings::inheritance::Castable;
@ -261,6 +260,6 @@ pub fn handle_request_animation_frame(documents: &Documents,
pub fn handle_reload(documents: &Documents,
id: PipelineId) {
if let Some(win) = documents.find_window(id) {
win.Location().Reload();
win.Location().reload_without_origin_check();
}
}

Просмотреть файл

@ -56,7 +56,7 @@ use dom::htmlbodyelement::HTMLBodyElement;
use dom::htmlcollection::{CollectionFilter, HTMLCollection};
use dom::htmlelement::HTMLElement;
use dom::htmlembedelement::HTMLEmbedElement;
use dom::htmlformelement::HTMLFormElement;
use dom::htmlformelement::{FormControl, FormControlElementHelpers, HTMLFormElement};
use dom::htmlheadelement::HTMLHeadElement;
use dom::htmlhtmlelement::HTMLHtmlElement;
use dom::htmliframeelement::HTMLIFrameElement;
@ -68,6 +68,7 @@ use dom::location::Location;
use dom::messageevent::MessageEvent;
use dom::mouseevent::MouseEvent;
use dom::node::{self, CloneChildrenFlag, Node, NodeDamage, window_from_node, IS_IN_DOC, LayoutNodeHelpers};
use dom::node::VecPreOrderInsertionHelper;
use dom::nodeiterator::NodeIterator;
use dom::nodelist::NodeList;
use dom::pagetransitionevent::PageTransitionEvent;
@ -103,6 +104,7 @@ use msg::constellation_msg::{FrameId, Key, KeyModifiers, KeyState};
use net_traits::{FetchResponseMsg, IpcSend, ReferrerPolicy};
use net_traits::CookieSource::NonHTTP;
use net_traits::CoreResourceMsg::{GetCookiesForUrl, SetCookiesForUrl};
use net_traits::pub_domains::is_pub_domain;
use net_traits::request::RequestInit;
use net_traits::response::HttpsState;
use num_traits::ToPrimitive;
@ -120,7 +122,7 @@ use servo_url::{ImmutableOrigin, MutableOrigin, ServoUrl};
use std::ascii::AsciiExt;
use std::borrow::ToOwned;
use std::cell::{Cell, Ref, RefMut};
use std::collections::{HashMap, VecDeque};
use std::collections::{HashMap, HashSet, VecDeque};
use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::default::Default;
use std::iter::once;
@ -313,6 +315,12 @@ pub struct Document {
dom_count: Cell<u32>,
/// Entry node for fullscreen.
fullscreen_element: MutNullableJS<Element>,
/// Map from ID to set of form control elements that have that ID as
/// their 'form' content attribute. Used to reset form controls
/// whenever any element with the same ID as the form attribute
/// is inserted or removed from the document.
/// See https://html.spec.whatwg.org/multipage/#form-owner
form_id_listener_map: DOMRefCell<HashMap<Atom, HashSet<JS<Element>>>>,
}
#[derive(JSTraceable, HeapSizeOf)]
@ -576,20 +584,26 @@ impl Document {
self,
to_unregister,
id);
let mut id_map = self.id_map.borrow_mut();
let is_empty = match id_map.get_mut(&id) {
None => false,
Some(elements) => {
let position = elements.iter()
.position(|element| &**element == to_unregister)
.expect("This element should be in registered.");
elements.remove(position);
elements.is_empty()
// Limit the scope of the borrow because id_map might be borrowed again by
// GetElementById through the following sequence of calls
// reset_form_owner_for_listeners -> reset_form_owner -> GetElementById
{
let mut id_map = self.id_map.borrow_mut();
let is_empty = match id_map.get_mut(&id) {
None => false,
Some(elements) => {
let position = elements.iter()
.position(|element| &**element == to_unregister)
.expect("This element should be in registered.");
elements.remove(position);
elements.is_empty()
}
};
if is_empty {
id_map.remove(&id);
}
};
if is_empty {
id_map.remove(&id);
}
self.reset_form_owner_for_listeners(&id);
}
/// Associate an element present in this document with the provided id.
@ -601,34 +615,34 @@ impl Document {
assert!(element.upcast::<Node>().is_in_doc());
assert!(!id.is_empty());
let mut id_map = self.id_map.borrow_mut();
let root = self.GetDocumentElement()
.expect("The element is in the document, so there must be a document \
element.");
match id_map.entry(id) {
Vacant(entry) => {
entry.insert(vec![JS::from_ref(element)]);
}
Occupied(entry) => {
let elements = entry.into_mut();
// Limit the scope of the borrow because id_map might be borrowed again by
// GetElementById through the following sequence of calls
// reset_form_owner_for_listeners -> reset_form_owner -> GetElementById
{
let mut id_map = self.id_map.borrow_mut();
let mut elements = id_map.entry(id.clone()).or_insert(Vec::new());
elements.insert_pre_order(element, root.r().upcast::<Node>());
}
self.reset_form_owner_for_listeners(&id);
}
let new_node = element.upcast::<Node>();
let mut head: usize = 0;
let root = root.upcast::<Node>();
for node in root.traverse_preorder() {
if let Some(elem) = node.downcast() {
if &*(*elements)[head] == elem {
head += 1;
}
if new_node == &*node || head == elements.len() {
break;
}
}
}
pub fn register_form_id_listener<T: ?Sized + FormControl>(&self, id: DOMString, listener: &T) {
let mut map = self.form_id_listener_map.borrow_mut();
let listener = listener.to_element();
let mut set = map.entry(Atom::from(id)).or_insert(HashSet::new());
set.insert(JS::from_ref(listener));
}
elements.insert(head, JS::from_ref(element));
pub fn unregister_form_id_listener<T: ?Sized + FormControl>(&self, id: DOMString, listener: &T) {
let mut map = self.form_id_listener_map.borrow_mut();
if let Occupied(mut entry) = map.entry(Atom::from(id)) {
entry.get_mut().remove(&JS::from_ref(listener.to_element()));
if entry.get().is_empty() {
entry.remove();
}
}
}
@ -1988,6 +2002,55 @@ impl LayoutDocumentHelpers for LayoutJS<Document> {
}
}
// https://html.spec.whatwg.org/multipage/#is-a-registrable-domain-suffix-of-or-is-equal-to
// The spec says to return a bool, we actually return an Option<Host> containing
// the parsed host in the successful case, to avoid having to re-parse the host.
fn get_registrable_domain_suffix_of_or_is_equal_to(host_suffix_string: &str, original_host: Host) -> Option<Host> {
// Step 1
if host_suffix_string.is_empty() {
return None;
}
// Step 2-3.
let host = match Host::parse(host_suffix_string) {
Ok(host) => host,
Err(_) => return None,
};
// Step 4.
if host != original_host {
// Step 4.1
let host = match host {
Host::Domain(ref host) => host,
_ => return None,
};
let original_host = match original_host {
Host::Domain(ref original_host) => original_host,
_ => return None,
};
// Step 4.2
let (prefix, suffix) = match original_host.len().checked_sub(host.len()) {
Some(index) => original_host.split_at(index),
None => return None,
};
if !prefix.ends_with(".") {
return None;
}
if suffix != host {
return None;
}
// Step 4.3
if is_pub_domain(host) {
return None;
}
}
// Step 5
Some(host)
}
/// https://url.spec.whatwg.org/#network-scheme
fn url_has_network_scheme(url: &ServoUrl) -> bool {
match url.scheme() {
@ -2101,6 +2164,7 @@ impl Document {
spurious_animation_frames: Cell::new(0),
dom_count: Cell::new(1),
fullscreen_element: MutNullableJS::new(None),
form_id_listener_map: Default::default(),
}
}
@ -2414,6 +2478,17 @@ impl Document {
}
}
}
fn reset_form_owner_for_listeners(&self, id: &Atom) {
let map = self.form_id_listener_map.borrow();
if let Some(listeners) = map.get(id) {
for listener in listeners {
listener.r().as_maybe_form_control()
.expect("Element must be a form control")
.reset_form_owner();
}
}
}
}
@ -2472,7 +2547,7 @@ impl DocumentMethods for Document {
false
}
// https://html.spec.whatwg.org/multipage/#relaxing-the-same-origin-restriction
// https://html.spec.whatwg.org/multipage/#dom-document-domain
fn Domain(&self) -> DOMString {
// Step 1.
if !self.has_browsing_context {
@ -2489,6 +2564,35 @@ impl DocumentMethods for Document {
}
}
// https://html.spec.whatwg.org/multipage/#dom-document-domain
fn SetDomain(&self, value: DOMString) -> ErrorResult {
// Step 1.
if !self.has_browsing_context {
return Err(Error::Security);
}
// TODO: Step 2. "If this Document object's active sandboxing
// flag set has its sandboxed document.domain browsing context
// flag set, then throw a "SecurityError" DOMException."
// Steps 3-4.
let effective_domain = match self.origin.effective_domain() {
Some(effective_domain) => effective_domain,
None => return Err(Error::Security),
};
// Step 5
let host = match get_registrable_domain_suffix_of_or_is_equal_to(&*value, effective_domain) {
None => return Err(Error::Security),
Some(host) => host,
};
// Step 6
self.origin.set_domain(host);
Ok(())
}
// https://html.spec.whatwg.org/multipage/#dom-document-referrer
fn Referrer(&self) -> DOMString {
match self.referrer {
@ -3396,6 +3500,9 @@ impl DocumentMethods for Document {
let entry_responsible_document = GlobalScope::entry().as_window().Document();
// This check is same-origin not same-origin-domain.
// https://github.com/whatwg/html/issues/2282
// https://github.com/whatwg/html/pull/2288
if !self.origin.same_origin(&entry_responsible_document.origin) {
// Step 4.
return Err(Error::Security);

Просмотреть файл

@ -19,6 +19,7 @@ use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
use dom::bindings::codegen::Bindings::WindowBinding::{ScrollBehavior, ScrollToOptions};
use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
use dom::bindings::codegen::UnionTypes::NodeOrString;
use dom::bindings::conversions::DerivedFrom;
use dom::bindings::error::{Error, ErrorResult, Fallible};
use dom::bindings::inheritance::{Castable, ElementTypeId, HTMLElementTypeId, NodeTypeId};
use dom::bindings::js::{JS, LayoutJS, MutNullableJS};
@ -44,6 +45,7 @@ use dom::htmlcollection::HTMLCollection;
use dom::htmlelement::HTMLElement;
use dom::htmlfieldsetelement::HTMLFieldSetElement;
use dom::htmlfontelement::{HTMLFontElement, HTMLFontElementLayoutHelpers};
use dom::htmlformelement::FormControlElementHelpers;
use dom::htmlhrelement::{HTMLHRElement, HTMLHRLayoutHelpers};
use dom::htmliframeelement::{HTMLIFrameElement, HTMLIFrameElementLayoutMethods};
use dom::htmlimageelement::{HTMLImageElement, LayoutHTMLImageElementHelpers};
@ -1360,6 +1362,14 @@ impl Element {
let document = document_from_node(self);
document.get_allow_fullscreen()
}
// https://html.spec.whatwg.org/multipage/#home-subtree
pub fn is_in_same_home_subtree<T>(&self, other: &T) -> bool
where T: DerivedFrom<Element> + DomObject
{
let other = other.upcast::<Element>();
self.root_element() == other.root_element()
}
}
impl ElementMethods for Element {
@ -2240,6 +2250,10 @@ impl VirtualMethods for Element {
s.bind_to_tree(tree_in_doc);
}
if let Some(f) = self.as_maybe_form_control() {
f.bind_form_control_to_tree();
}
if !tree_in_doc {
return;
}
@ -2255,6 +2269,10 @@ impl VirtualMethods for Element {
fn unbind_from_tree(&self, context: &UnbindContext) {
self.super_type().unwrap().unbind_from_tree(context);
if let Some(f) = self.as_maybe_form_control() {
f.unbind_form_control_from_tree();
}
if !context.tree_in_doc {
return;
}

Просмотреть файл

@ -4,8 +4,9 @@
use dom::bindings::codegen::Bindings::HistoryBinding;
use dom::bindings::codegen::Bindings::HistoryBinding::HistoryMethods;
use dom::bindings::codegen::Bindings::LocationBinding::LocationMethods;
use dom::bindings::codegen::Bindings::LocationBinding::LocationBinding::LocationMethods;
use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
use dom::bindings::error::Fallible;
use dom::bindings::inheritance::Castable;
use dom::bindings::js::{JS, Root};
use dom::bindings::reflector::{Reflector, reflect_dom_object};
@ -59,17 +60,17 @@ impl HistoryMethods for History {
}
// https://html.spec.whatwg.org/multipage/#dom-history-go
fn Go(&self, delta: i32) {
fn Go(&self, delta: i32) -> Fallible<()> {
let direction = if delta > 0 {
TraversalDirection::Forward(delta as usize)
} else if delta < 0 {
TraversalDirection::Back(-delta as usize)
} else {
self.window.Location().Reload();
return;
return self.window.Location().Reload();
};
self.traverse_history(direction);
Ok(())
}
// https://html.spec.whatwg.org/multipage/#dom-history-back

Просмотреть файл

@ -7,7 +7,7 @@ use dom::attr::Attr;
use dom::bindings::codegen::Bindings::HTMLButtonElementBinding;
use dom::bindings::codegen::Bindings::HTMLButtonElementBinding::HTMLButtonElementMethods;
use dom::bindings::inheritance::Castable;
use dom::bindings::js::Root;
use dom::bindings::js::{MutNullableJS, Root};
use dom::bindings::str::DOMString;
use dom::document::Document;
use dom::element::{AttributeMutation, Element};
@ -26,6 +26,7 @@ use dom::virtualmethods::VirtualMethods;
use dom_struct::dom_struct;
use html5ever_atoms::LocalName;
use std::cell::Cell;
use std::default::Default;
use style::element_state::*;
#[derive(JSTraceable, PartialEq, Copy, Clone)]
@ -40,7 +41,8 @@ enum ButtonType {
#[dom_struct]
pub struct HTMLButtonElement {
htmlelement: HTMLElement,
button_type: Cell<ButtonType>
button_type: Cell<ButtonType>,
form_owner: MutNullableJS<HTMLFormElement>,
}
impl HTMLButtonElement {
@ -51,7 +53,8 @@ impl HTMLButtonElement {
htmlelement:
HTMLElement::new_inherited_with_state(IN_ENABLED_STATE,
local_name, prefix, document),
button_type: Cell::new(ButtonType::Submit)
button_type: Cell::new(ButtonType::Submit),
form_owner: Default::default(),
}
}
@ -211,6 +214,9 @@ impl VirtualMethods for HTMLButtonElement {
self.button_type.set(ButtonType::Submit);
}
}
},
&local_name!("form") => {
self.form_attribute_mutated(mutation);
}
_ => {},
}
@ -237,7 +243,19 @@ impl VirtualMethods for HTMLButtonElement {
}
}
impl FormControl for HTMLButtonElement {}
impl FormControl for HTMLButtonElement {
fn form_owner(&self) -> Option<Root<HTMLFormElement>> {
self.form_owner.get()
}
fn set_form_owner(&self, form: Option<&HTMLFormElement>) {
self.form_owner.set(form);
}
fn to_element<'a>(&'a self) -> &'a Element {
self.upcast::<Element>()
}
}
impl Validatable for HTMLButtonElement {
fn is_instance_validatable(&self) -> bool {

Просмотреть файл

@ -6,7 +6,7 @@ use dom::attr::Attr;
use dom::bindings::codegen::Bindings::HTMLFieldSetElementBinding;
use dom::bindings::codegen::Bindings::HTMLFieldSetElementBinding::HTMLFieldSetElementMethods;
use dom::bindings::inheritance::{Castable, ElementTypeId, HTMLElementTypeId, NodeTypeId};
use dom::bindings::js::Root;
use dom::bindings::js::{MutNullableJS, Root};
use dom::bindings::str::DOMString;
use dom::document::Document;
use dom::element::{AttributeMutation, Element};
@ -19,11 +19,13 @@ use dom::validitystate::ValidityState;
use dom::virtualmethods::VirtualMethods;
use dom_struct::dom_struct;
use html5ever_atoms::LocalName;
use std::default::Default;
use style::element_state::*;
#[dom_struct]
pub struct HTMLFieldSetElement {
htmlelement: HTMLElement
htmlelement: HTMLElement,
form_owner: MutNullableJS<HTMLFormElement>,
}
impl HTMLFieldSetElement {
@ -33,7 +35,8 @@ impl HTMLFieldSetElement {
HTMLFieldSetElement {
htmlelement:
HTMLElement::new_inherited_with_state(IN_ENABLED_STATE,
local_name, prefix, document)
local_name, prefix, document),
form_owner: Default::default(),
}
}
@ -148,9 +151,24 @@ impl VirtualMethods for HTMLFieldSetElement {
}
}
},
&local_name!("form") => {
self.form_attribute_mutated(mutation);
},
_ => {},
}
}
}
impl FormControl for HTMLFieldSetElement {}
impl FormControl for HTMLFieldSetElement {
fn form_owner(&self) -> Option<Root<HTMLFormElement>> {
self.form_owner.get()
}
fn set_form_owner(&self, form: Option<&HTMLFormElement>) {
self.form_owner.set(form);
}
fn to_element<'a>(&'a self) -> &'a Element {
self.upcast::<Element>()
}
}

Просмотреть файл

@ -2,6 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::BlobBinding::BlobMethods;
use dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods;
use dom::bindings::codegen::Bindings::EventBinding::EventMethods;
@ -11,15 +12,14 @@ use dom::bindings::codegen::Bindings::HTMLFormElementBinding;
use dom::bindings::codegen::Bindings::HTMLFormElementBinding::HTMLFormElementMethods;
use dom::bindings::codegen::Bindings::HTMLInputElementBinding::HTMLInputElementMethods;
use dom::bindings::codegen::Bindings::HTMLTextAreaElementBinding::HTMLTextAreaElementMethods;
use dom::bindings::conversions::DerivedFrom;
use dom::bindings::inheritance::{Castable, ElementTypeId, HTMLElementTypeId, NodeTypeId};
use dom::bindings::js::{MutNullableJS, Root};
use dom::bindings::js::{JS, MutNullableJS, Root, RootedReference};
use dom::bindings::refcounted::Trusted;
use dom::bindings::reflector::DomObject;
use dom::bindings::str::DOMString;
use dom::blob::Blob;
use dom::document::Document;
use dom::element::Element;
use dom::element::{AttributeMutation, Element};
use dom::eventtarget::EventTarget;
use dom::file::File;
use dom::globalscope::GlobalScope;
@ -29,12 +29,16 @@ use dom::htmldatalistelement::HTMLDataListElement;
use dom::htmlelement::HTMLElement;
use dom::htmlfieldsetelement::HTMLFieldSetElement;
use dom::htmlformcontrolscollection::HTMLFormControlsCollection;
use dom::htmlimageelement::HTMLImageElement;
use dom::htmlinputelement::HTMLInputElement;
use dom::htmllabelelement::HTMLLabelElement;
use dom::htmllegendelement::HTMLLegendElement;
use dom::htmlobjectelement::HTMLObjectElement;
use dom::htmloutputelement::HTMLOutputElement;
use dom::htmlselectelement::HTMLSelectElement;
use dom::htmltextareaelement::HTMLTextAreaElement;
use dom::node::{Node, document_from_node, window_from_node};
use dom::node::{Node, PARSER_ASSOCIATED_FORM_OWNER, UnbindContext, VecPreOrderInsertionHelper};
use dom::node::{document_from_node, window_from_node};
use dom::validitystate::ValidationFlags;
use dom::virtualmethods::VirtualMethods;
use dom_struct::dom_struct;
@ -63,7 +67,8 @@ pub struct HTMLFormElement {
htmlelement: HTMLElement,
marked_for_reset: Cell<bool>,
elements: MutNullableJS<HTMLFormControlsCollection>,
generation_id: Cell<GenerationId>
generation_id: Cell<GenerationId>,
controls: DOMRefCell<Vec<JS<Element>>>,
}
impl HTMLFormElement {
@ -74,7 +79,8 @@ impl HTMLFormElement {
htmlelement: HTMLElement::new_inherited(local_name, prefix, document),
marked_for_reset: Cell::new(false),
elements: Default::default(),
generation_id: Cell::new(GenerationId(0))
generation_id: Cell::new(GenerationId(0)),
controls: DOMRefCell::new(Vec::new()),
}
}
@ -504,16 +510,14 @@ impl HTMLFormElement {
/// https://html.spec.whatwg.org/multipage/#constructing-the-form-data-set
/// Steps range from 1 to 3
fn get_unclean_dataset(&self, submitter: Option<FormSubmitter>) -> Vec<FormDatum> {
let node = self.upcast::<Node>();
// FIXME(#3553): This is an incorrect way of getting controls owned
// by the form, but good enough until html5ever lands
let controls = self.controls.borrow();
let mut data_set = Vec::new();
for child in node.traverse_preorder() {
for child in controls.iter() {
// Step 3.1: The field element is disabled.
match child.downcast::<Element>() {
Some(el) if !el.disabled_state() => (),
_ => continue,
if child.disabled_state() {
continue;
}
let child = child.upcast::<Node>();
// Step 3.1: The field element has a datalist element ancestor.
if child.ancestors()
@ -627,9 +631,10 @@ impl HTMLFormElement {
return;
}
// TODO: This is an incorrect way of getting controls owned
// by the form, but good enough until html5ever lands
for child in self.upcast::<Node>().traverse_preorder() {
let controls = self.controls.borrow();
for child in controls.iter() {
let child = child.upcast::<Node>();
match child.type_id() {
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLInputElement)) => {
child.downcast::<HTMLInputElement>().unwrap().reset();
@ -647,14 +652,27 @@ impl HTMLFormElement {
}
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLOutputElement)) => {
// Unimplemented
{}
}
_ => {}
}
};
}
self.marked_for_reset.set(false);
}
fn add_control<T: ?Sized + FormControl>(&self, control: &T) {
let root = self.upcast::<Element>().root_element();
let root = root.r().upcast::<Node>();
let mut controls = self.controls.borrow_mut();
controls.insert_pre_order(control.to_element(), root);
}
fn remove_control<T: ?Sized + FormControl>(&self, control: &T) {
let control = control.to_element();
let mut controls = self.controls.borrow_mut();
controls.iter().position(|c| c.r() == control)
.map(|idx| controls.remove(idx));
}
}
#[derive(JSTraceable, HeapSizeOf, Clone)]
@ -844,24 +862,139 @@ impl<'a> FormSubmitter<'a> {
}
}
pub trait FormControl: DerivedFrom<Element> + DomObject {
// FIXME: This is wrong (https://github.com/servo/servo/issues/3553)
// but we need html5ever to do it correctly
fn form_owner(&self) -> Option<Root<HTMLFormElement>> {
// https://html.spec.whatwg.org/multipage/#reset-the-form-owner
pub trait FormControl: DomObject {
fn form_owner(&self) -> Option<Root<HTMLFormElement>>;
fn set_form_owner(&self, form: Option<&HTMLFormElement>);
fn to_element<'a>(&'a self) -> &'a Element;
fn is_listed(&self) -> bool {
true
}
// https://html.spec.whatwg.org/multipage/#create-an-element-for-the-token
// Part of step 12.
// '..suppress the running of the reset the form owner algorithm
// when the parser subsequently attempts to insert the element..'
fn set_form_owner_from_parser(&self, form: &HTMLFormElement) {
let elem = self.to_element();
let owner = elem.get_string_attribute(&local_name!("form"));
if !owner.is_empty() {
let doc = document_from_node(elem);
let owner = doc.GetElementById(owner);
if let Some(ref o) = owner {
let maybe_form = o.downcast::<HTMLFormElement>();
if maybe_form.is_some() {
return maybe_form.map(Root::from_ref);
}
let node = elem.upcast::<Node>();
node.set_flag(PARSER_ASSOCIATED_FORM_OWNER, true);
form.add_control(self);
self.set_form_owner(Some(form));
}
// https://html.spec.whatwg.org/multipage/#reset-the-form-owner
fn reset_form_owner(&self) {
let elem = self.to_element();
let node = elem.upcast::<Node>();
let old_owner = self.form_owner();
let has_form_id = elem.has_attribute(&local_name!("form"));
let nearest_form_ancestor = node.ancestors()
.filter_map(Root::downcast::<HTMLFormElement>)
.next();
// Step 1
if old_owner.is_some() && !(self.is_listed() && has_form_id) {
if nearest_form_ancestor == old_owner {
return;
}
}
elem.upcast::<Node>().ancestors().filter_map(Root::downcast).next()
let new_owner = if self.is_listed() && has_form_id && elem.is_connected() {
// Step 3
let doc = document_from_node(node);
let form_id = elem.get_string_attribute(&local_name!("form"));
doc.GetElementById(form_id).and_then(Root::downcast::<HTMLFormElement>)
} else {
// Step 4
nearest_form_ancestor
};
if old_owner != new_owner {
if let Some(o) = old_owner {
o.remove_control(self);
}
let new_owner = new_owner.as_ref().map(|o| {
o.add_control(self);
o.r()
});
self.set_form_owner(new_owner);
}
}
// https://html.spec.whatwg.org/multipage/#association-of-controls-and-forms
fn form_attribute_mutated(&self, mutation: AttributeMutation) {
match mutation {
AttributeMutation::Set(_) => {
self.register_if_necessary();
},
AttributeMutation::Removed => {
self.unregister_if_necessary();
},
}
self.reset_form_owner();
}
// https://html.spec.whatwg.org/multipage/#association-of-controls-and-forms
fn register_if_necessary(&self) {
let elem = self.to_element();
let form_id = elem.get_string_attribute(&local_name!("form"));
let node = elem.upcast::<Node>();
if self.is_listed() && !form_id.is_empty() && node.is_in_doc() {
let doc = document_from_node(node);
doc.register_form_id_listener(form_id, self);
}
}
fn unregister_if_necessary(&self) {
let elem = self.to_element();
let form_id = elem.get_string_attribute(&local_name!("form"));
if self.is_listed() && !form_id.is_empty() {
let doc = document_from_node(elem.upcast::<Node>());
doc.unregister_form_id_listener(form_id, self);
}
}
// https://html.spec.whatwg.org/multipage/#association-of-controls-and-forms
fn bind_form_control_to_tree(&self) {
let elem = self.to_element();
let node = elem.upcast::<Node>();
// https://html.spec.whatwg.org/multipage/#create-an-element-for-the-token
// Part of step 12.
// '..suppress the running of the reset the form owner algorithm
// when the parser subsequently attempts to insert the element..'
let must_skip_reset = node.get_flag(PARSER_ASSOCIATED_FORM_OWNER);
node.set_flag(PARSER_ASSOCIATED_FORM_OWNER, false);
if !must_skip_reset {
self.form_attribute_mutated(AttributeMutation::Set(None));
}
}
// https://html.spec.whatwg.org/multipage/#association-of-controls-and-forms
fn unbind_form_control_from_tree(&self) {
let elem = self.to_element();
let has_form_attr = elem.has_attribute(&local_name!("form"));
let same_subtree = self.form_owner().map_or(true, |form| {
elem.is_in_same_home_subtree(&*form)
});
self.unregister_if_necessary();
// Since this control has been unregistered from the id->listener map
// in the previous step, reset_form_owner will not be invoked on it
// when the form owner element is unbound (i.e it is in the same
// subtree) if it appears later in the tree order. Hence invoke
// reset from here if this control has the form attribute set.
if !same_subtree || (self.is_listed() && has_form_attr) {
self.reset_form_owner();
}
}
fn get_form_attribute<InputFn, OwnerFn>(&self,
@ -870,7 +1003,7 @@ pub trait FormControl: DerivedFrom<Element> + DomObject {
owner: OwnerFn)
-> DOMString
where InputFn: Fn(&Self) -> DOMString,
OwnerFn: Fn(&HTMLFormElement) -> DOMString
OwnerFn: Fn(&HTMLFormElement) -> DOMString, Self: Sized
{
if self.to_element().has_attribute(attr) {
input(self)
@ -885,7 +1018,7 @@ pub trait FormControl: DerivedFrom<Element> + DomObject {
owner: OwnerFn)
-> bool
where InputFn: Fn(&Self) -> bool,
OwnerFn: Fn(&HTMLFormElement) -> bool
OwnerFn: Fn(&HTMLFormElement) -> bool, Self: Sized
{
if self.to_element().has_attribute(attr) {
input(self)
@ -894,10 +1027,6 @@ pub trait FormControl: DerivedFrom<Element> + DomObject {
}
}
fn to_element(&self) -> &Element {
self.upcast()
}
// XXXKiChjang: Implement these on inheritors
// fn candidate_for_validation(&self) -> bool;
// fn satisfies_constraints(&self) -> bool;
@ -914,6 +1043,69 @@ impl VirtualMethods for HTMLFormElement {
_ => self.super_type().unwrap().parse_plain_attribute(name, value),
}
}
fn unbind_from_tree(&self, context: &UnbindContext) {
self.super_type().unwrap().unbind_from_tree(context);
// Collect the controls to reset because reset_form_owner
// will mutably borrow self.controls
rooted_vec!(let mut to_reset);
to_reset.extend(self.controls.borrow().iter()
.filter(|c| !c.is_in_same_home_subtree(self))
.map(|c| c.clone()));
for control in to_reset.iter() {
control.as_maybe_form_control()
.expect("Element must be a form control")
.reset_form_owner();
}
}
}
pub trait FormControlElementHelpers {
fn as_maybe_form_control<'a>(&'a self) -> Option<&'a FormControl>;
}
impl FormControlElementHelpers for Element {
fn as_maybe_form_control<'a>(&'a self) -> Option<&'a FormControl> {
let node = self.upcast::<Node>();
match node.type_id() {
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLButtonElement)) => {
Some(self.downcast::<HTMLButtonElement>().unwrap() as &FormControl)
},
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLFieldSetElement)) => {
Some(self.downcast::<HTMLFieldSetElement>().unwrap() as &FormControl)
},
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLImageElement)) => {
Some(self.downcast::<HTMLImageElement>().unwrap() as &FormControl)
},
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLInputElement)) => {
Some(self.downcast::<HTMLInputElement>().unwrap() as &FormControl)
},
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLLabelElement)) => {
Some(self.downcast::<HTMLLabelElement>().unwrap() as &FormControl)
},
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLLegendElement)) => {
Some(self.downcast::<HTMLLegendElement>().unwrap() as &FormControl)
},
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLObjectElement)) => {
Some(self.downcast::<HTMLObjectElement>().unwrap() as &FormControl)
},
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLOutputElement)) => {
Some(self.downcast::<HTMLOutputElement>().unwrap() as &FormControl)
},
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLSelectElement)) => {
Some(self.downcast::<HTMLSelectElement>().unwrap() as &FormControl)
},
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTextAreaElement)) => {
Some(self.downcast::<HTMLTextAreaElement>().unwrap() as &FormControl)
},
_ => {
None
}
}
}
}
struct PlannedNavigation {

Просмотреть файл

@ -327,20 +327,6 @@ impl HTMLIFrameElement {
false
}
}
pub fn get_content_window(&self) -> Option<Root<Window>> {
self.pipeline_id.get()
.and_then(|pipeline_id| ScriptThread::find_document(pipeline_id))
.and_then(|document| {
let current_global = GlobalScope::current();
let current_document = current_global.as_window().Document();
if document.origin().same_origin(current_document.origin()) {
Some(Root::from_ref(document.window()))
} else {
None
}
})
}
}
pub trait HTMLIFrameElementLayoutMethods {
@ -512,15 +498,31 @@ impl HTMLIFrameElementMethods for HTMLIFrameElement {
// https://html.spec.whatwg.org/multipage/#dom-iframe-contentwindow
fn GetContentWindow(&self) -> Option<Root<BrowsingContext>> {
match self.get_content_window() {
Some(ref window) => Some(window.browsing_context()),
None => None
}
self.pipeline_id.get().and_then(|_| ScriptThread::find_browsing_context(self.frame_id))
}
// https://html.spec.whatwg.org/multipage/#dom-iframe-contentdocument
// https://html.spec.whatwg.org/multipage/#concept-bcc-content-document
fn GetContentDocument(&self) -> Option<Root<Document>> {
self.get_content_window().map(|window| window.Document())
// Step 1.
let pipeline_id = match self.pipeline_id.get() {
None => return None,
Some(pipeline_id) => pipeline_id,
};
// Step 2-3.
// Note that this lookup will fail if the document is dissimilar-origin,
// so we should return None in that case.
let document = match ScriptThread::find_document(pipeline_id) {
None => return None,
Some(document) => document,
};
// Step 4.
let current = GlobalScope::current().as_window().Document();
if !current.origin().same_origin_domain(document.origin()) {
return None;
}
// Step 5.
Some(document)
}
// Experimental mozbrowser implementation is based on the webidl

Просмотреть файл

@ -15,7 +15,7 @@ use dom::bindings::codegen::Bindings::MouseEventBinding::MouseEventMethods;
use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
use dom::bindings::error::Fallible;
use dom::bindings::inheritance::Castable;
use dom::bindings::js::{LayoutJS, Root};
use dom::bindings::js::{LayoutJS, MutNullableJS, Root};
use dom::bindings::refcounted::Trusted;
use dom::bindings::reflector::DomObject;
use dom::bindings::str::DOMString;
@ -26,6 +26,7 @@ use dom::event::Event;
use dom::eventtarget::EventTarget;
use dom::htmlareaelement::HTMLAreaElement;
use dom::htmlelement::HTMLElement;
use dom::htmlformelement::{FormControl, HTMLFormElement};
use dom::htmlmapelement::HTMLMapElement;
use dom::mouseevent::MouseEvent;
use dom::node::{Node, NodeDamage, document_from_node, window_from_node};
@ -78,6 +79,7 @@ pub struct HTMLImageElement {
htmlelement: HTMLElement,
current_request: DOMRefCell<ImageRequest>,
pending_request: DOMRefCell<ImageRequest>,
form_owner: MutNullableJS<HTMLFormElement>,
generation: Cell<u32>,
}
@ -384,6 +386,7 @@ impl HTMLImageElement {
metadata: None,
blocker: None,
}),
form_owner: Default::default(),
generation: Default::default(),
}
}
@ -689,6 +692,24 @@ impl VirtualMethods for HTMLImageElement {
}
}
impl FormControl for HTMLImageElement {
fn form_owner(&self) -> Option<Root<HTMLFormElement>> {
self.form_owner.get()
}
fn set_form_owner(&self, form: Option<&HTMLFormElement>) {
self.form_owner.set(form);
}
fn to_element<'a>(&'a self) -> &'a Element {
self.upcast::<Element>()
}
fn is_listed(&self) -> bool {
false
}
}
fn image_dimension_setter(element: &Element, attr: LocalName, value: u32) {
// This setter is a bit weird: the IDL type is unsigned long, but it's parsed as
// a dimension for rendering.

Просмотреть файл

@ -100,6 +100,7 @@ pub struct HTMLInputElement {
value_dirty: Cell<bool>,
filelist: MutNullableJS<FileList>,
form_owner: MutNullableJS<HTMLFormElement>,
}
#[derive(JSTraceable)]
@ -156,6 +157,7 @@ impl HTMLInputElement {
activation_state: DOMRefCell::new(InputActivationState::new()),
value_dirty: Cell::new(false),
filelist: MutNullableJS::new(None),
form_owner: Default::default(),
}
}
@ -1044,7 +1046,10 @@ impl VirtualMethods for HTMLInputElement {
el.set_read_write_state(!el.disabled_state());
}
}
}
},
&local_name!("form") => {
self.form_attribute_mutated(mutation);
},
_ => {},
}
}
@ -1163,7 +1168,19 @@ impl VirtualMethods for HTMLInputElement {
}
}
impl FormControl for HTMLInputElement {}
impl FormControl for HTMLInputElement {
fn form_owner(&self) -> Option<Root<HTMLFormElement>> {
self.form_owner.get()
}
fn set_form_owner(&self, form: Option<&HTMLFormElement>) {
self.form_owner.set(form);
}
fn to_element<'a>(&'a self) -> &'a Element {
self.upcast::<Element>()
}
}
impl Validatable for HTMLInputElement {
fn is_instance_validatable(&self) -> bool {

Просмотреть файл

@ -3,17 +3,18 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use dom::activation::{Activatable, ActivationSource, synthetic_click_activation};
use dom::attr::Attr;
use dom::bindings::codegen::Bindings::HTMLLabelElementBinding;
use dom::bindings::codegen::Bindings::HTMLLabelElementBinding::HTMLLabelElementMethods;
use dom::bindings::inheritance::Castable;
use dom::bindings::js::Root;
use dom::bindings::str::DOMString;
use dom::document::Document;
use dom::element::Element;
use dom::element::{AttributeMutation, Element};
use dom::event::Event;
use dom::eventtarget::EventTarget;
use dom::htmlelement::HTMLElement;
use dom::htmlformelement::{FormControl, HTMLFormElement};
use dom::htmlformelement::{FormControl, FormControlElementHelpers, HTMLFormElement};
use dom::node::{document_from_node, Node};
use dom::virtualmethods::VirtualMethods;
use dom_struct::dom_struct;
@ -22,7 +23,7 @@ use style::attr::AttrValue;
#[dom_struct]
pub struct HTMLLabelElement {
htmlelement: HTMLElement,
htmlelement: HTMLElement
}
impl HTMLLabelElement {
@ -31,7 +32,7 @@ impl HTMLLabelElement {
document: &Document) -> HTMLLabelElement {
HTMLLabelElement {
htmlelement:
HTMLElement::new_inherited(local_name, prefix, document)
HTMLElement::new_inherited(local_name, prefix, document),
}
}
@ -128,6 +129,16 @@ impl VirtualMethods for HTMLLabelElement {
_ => self.super_type().unwrap().parse_plain_attribute(name, value),
}
}
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) {
self.super_type().unwrap().attribute_mutated(attr, mutation);
match attr.local_name() {
&local_name!("form") => {
self.form_attribute_mutated(mutation);
},
_ => {},
}
}
}
impl HTMLLabelElement {
@ -140,4 +151,19 @@ impl HTMLLabelElement {
}
}
impl FormControl for HTMLLabelElement {}
impl FormControl for HTMLLabelElement {
fn form_owner(&self) -> Option<Root<HTMLFormElement>> {
self.GetControl().map(Root::upcast::<Element>).and_then(|elem| {
elem.as_maybe_form_control().and_then(|control| control.form_owner())
})
}
fn set_form_owner(&self, _: Option<&HTMLFormElement>) {
// Label is a special case for form owner, it reflects its control's
// form owner. Therefore it doesn't hold form owner itself.
}
fn to_element<'a>(&'a self) -> &'a Element {
self.upcast::<Element>()
}
}

Просмотреть файл

@ -6,7 +6,7 @@ use dom::bindings::codegen::Bindings::HTMLLegendElementBinding;
use dom::bindings::codegen::Bindings::HTMLLegendElementBinding::HTMLLegendElementMethods;
use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
use dom::bindings::inheritance::Castable;
use dom::bindings::js::Root;
use dom::bindings::js::{MutNullableJS, Root};
use dom::bindings::str::DOMString;
use dom::document::Document;
use dom::element::Element;
@ -21,6 +21,7 @@ use html5ever_atoms::LocalName;
#[dom_struct]
pub struct HTMLLegendElement {
htmlelement: HTMLElement,
form_owner: MutNullableJS<HTMLFormElement>,
}
impl HTMLLegendElement {
@ -28,7 +29,10 @@ impl HTMLLegendElement {
prefix: Option<DOMString>,
document: &Document)
-> HTMLLegendElement {
HTMLLegendElement { htmlelement: HTMLElement::new_inherited(local_name, prefix, document) }
HTMLLegendElement {
htmlelement: HTMLElement::new_inherited(local_name, prefix, document),
form_owner: Default::default(),
}
}
#[allow(unrooted_must_root)]
@ -83,4 +87,16 @@ impl HTMLLegendElementMethods for HTMLLegendElement {
}
}
impl FormControl for HTMLLegendElement {}
impl FormControl for HTMLLegendElement {
fn form_owner(&self) -> Option<Root<HTMLFormElement>> {
self.form_owner.get()
}
fn set_form_owner(&self, form: Option<&HTMLFormElement>) {
self.form_owner.set(form);
}
fn to_element<'a>(&'a self) -> &'a Element {
self.upcast::<Element>()
}
}

Просмотреть файл

@ -7,7 +7,7 @@ use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::HTMLObjectElementBinding;
use dom::bindings::codegen::Bindings::HTMLObjectElementBinding::HTMLObjectElementMethods;
use dom::bindings::inheritance::Castable;
use dom::bindings::js::Root;
use dom::bindings::js::{MutNullableJS, Root};
use dom::bindings::str::DOMString;
use dom::document::Document;
use dom::element::{AttributeMutation, Element};
@ -20,6 +20,7 @@ use dom::virtualmethods::VirtualMethods;
use dom_struct::dom_struct;
use html5ever_atoms::LocalName;
use net_traits::image::base::Image;
use std::default::Default;
use std::sync::Arc;
#[dom_struct]
@ -27,6 +28,7 @@ pub struct HTMLObjectElement {
htmlelement: HTMLElement,
#[ignore_heap_size_of = "Arc"]
image: DOMRefCell<Option<Arc<Image>>>,
form_owner: MutNullableJS<HTMLFormElement>,
}
impl HTMLObjectElement {
@ -37,6 +39,7 @@ impl HTMLObjectElement {
htmlelement:
HTMLElement::new_inherited(local_name, prefix, document),
image: DOMRefCell::new(None),
form_owner: Default::default(),
}
}
@ -114,9 +117,24 @@ impl VirtualMethods for HTMLObjectElement {
self.process_data_url();
}
},
&local_name!("form") => {
self.form_attribute_mutated(mutation);
},
_ => {},
}
}
}
impl FormControl for HTMLObjectElement {}
impl FormControl for HTMLObjectElement {
fn form_owner(&self) -> Option<Root<HTMLFormElement>> {
self.form_owner.get()
}
fn set_form_owner(&self, form: Option<&HTMLFormElement>) {
self.form_owner.set(form);
}
fn to_element<'a>(&'a self) -> &'a Element {
self.upcast::<Element>()
}
}

Просмотреть файл

@ -2,23 +2,27 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use dom::attr::Attr;
use dom::bindings::codegen::Bindings::HTMLOutputElementBinding;
use dom::bindings::codegen::Bindings::HTMLOutputElementBinding::HTMLOutputElementMethods;
use dom::bindings::inheritance::Castable;
use dom::bindings::js::Root;
use dom::bindings::js::{MutNullableJS, Root};
use dom::bindings::str::DOMString;
use dom::document::Document;
use dom::element::{AttributeMutation, Element};
use dom::htmlelement::HTMLElement;
use dom::htmlformelement::{FormControl, HTMLFormElement};
use dom::node::{Node, window_from_node};
use dom::nodelist::NodeList;
use dom::validitystate::ValidityState;
use dom::virtualmethods::VirtualMethods;
use dom_struct::dom_struct;
use html5ever_atoms::LocalName;
#[dom_struct]
pub struct HTMLOutputElement {
htmlelement: HTMLElement
htmlelement: HTMLElement,
form_owner: MutNullableJS<HTMLFormElement>,
}
impl HTMLOutputElement {
@ -27,7 +31,8 @@ impl HTMLOutputElement {
document: &Document) -> HTMLOutputElement {
HTMLOutputElement {
htmlelement:
HTMLElement::new_inherited(local_name, prefix, document)
HTMLElement::new_inherited(local_name, prefix, document),
form_owner: Default::default(),
}
}
@ -59,4 +64,32 @@ impl HTMLOutputElementMethods for HTMLOutputElement {
}
}
impl FormControl for HTMLOutputElement {}
impl VirtualMethods for HTMLOutputElement {
fn super_type<'b>(&'b self) -> Option<&'b VirtualMethods> {
Some(self.upcast::<HTMLElement>() as &VirtualMethods)
}
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) {
self.super_type().unwrap().attribute_mutated(attr, mutation);
match attr.local_name() {
&local_name!("form") => {
self.form_attribute_mutated(mutation);
},
_ => {},
}
}
}
impl FormControl for HTMLOutputElement {
fn form_owner(&self) -> Option<Root<HTMLFormElement>> {
self.form_owner.get()
}
fn set_form_owner(&self, form: Option<&HTMLFormElement>) {
self.form_owner.set(form);
}
fn to_element<'a>(&'a self) -> &'a Element {
self.upcast::<Element>()
}
}

Просмотреть файл

@ -32,6 +32,7 @@ use dom::validitystate::{ValidityState, ValidationFlags};
use dom::virtualmethods::VirtualMethods;
use dom_struct::dom_struct;
use html5ever_atoms::LocalName;
use std::default::Default;
use std::iter;
use style::attr::AttrValue;
use style::element_state::*;
@ -61,6 +62,7 @@ impl CollectionFilter for OptionsFilter {
pub struct HTMLSelectElement {
htmlelement: HTMLElement,
options: MutNullableJS<HTMLOptionsCollection>,
form_owner: MutNullableJS<HTMLFormElement>,
}
static DEFAULT_SELECT_SIZE: u32 = 0;
@ -73,7 +75,8 @@ impl HTMLSelectElement {
htmlelement:
HTMLElement::new_inherited_with_state(IN_ENABLED_STATE,
local_name, prefix, document),
options: Default::default()
options: Default::default(),
form_owner: Default::default(),
}
}
@ -344,19 +347,25 @@ impl VirtualMethods for HTMLSelectElement {
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) {
self.super_type().unwrap().attribute_mutated(attr, mutation);
if attr.local_name() == &local_name!("disabled") {
let el = self.upcast::<Element>();
match mutation {
AttributeMutation::Set(_) => {
el.set_disabled_state(true);
el.set_enabled_state(false);
},
AttributeMutation::Removed => {
el.set_disabled_state(false);
el.set_enabled_state(true);
el.check_ancestors_disabled_state_for_form_control();
match attr.local_name() {
&local_name!("disabled") => {
let el = self.upcast::<Element>();
match mutation {
AttributeMutation::Set(_) => {
el.set_disabled_state(true);
el.set_enabled_state(false);
},
AttributeMutation::Removed => {
el.set_disabled_state(false);
el.set_enabled_state(true);
el.check_ancestors_disabled_state_for_form_control();
}
}
}
},
&local_name!("form") => {
self.form_attribute_mutated(mutation);
},
_ => {},
}
}
@ -388,7 +397,19 @@ impl VirtualMethods for HTMLSelectElement {
}
}
impl FormControl for HTMLSelectElement {}
impl FormControl for HTMLSelectElement {
fn form_owner(&self) -> Option<Root<HTMLFormElement>> {
self.form_owner.get()
}
fn set_form_owner(&self, form: Option<&HTMLFormElement>) {
self.form_owner.set(form);
}
fn to_element<'a>(&'a self) -> &'a Element {
self.upcast::<Element>()
}
}
impl Validatable for HTMLSelectElement {
fn is_instance_validatable(&self) -> bool {

Просмотреть файл

@ -9,7 +9,7 @@ use dom::bindings::codegen::Bindings::HTMLTextAreaElementBinding;
use dom::bindings::codegen::Bindings::HTMLTextAreaElementBinding::HTMLTextAreaElementMethods;
use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
use dom::bindings::inheritance::Castable;
use dom::bindings::js::{LayoutJS, Root};
use dom::bindings::js::{LayoutJS, MutNullableJS, Root};
use dom::bindings::str::DOMString;
use dom::document::Document;
use dom::element::{AttributeMutation, Element};
@ -30,6 +30,7 @@ use html5ever_atoms::LocalName;
use ipc_channel::ipc::IpcSender;
use script_traits::ScriptMsg as ConstellationMsg;
use std::cell::Cell;
use std::default::Default;
use std::ops::Range;
use style::attr::AttrValue;
use style::element_state::*;
@ -43,6 +44,7 @@ pub struct HTMLTextAreaElement {
placeholder: DOMRefCell<DOMString>,
// https://html.spec.whatwg.org/multipage/#concept-textarea-dirty
value_changed: Cell<bool>,
form_owner: MutNullableJS<HTMLFormElement>,
}
pub trait LayoutHTMLTextAreaElementHelpers {
@ -116,6 +118,7 @@ impl HTMLTextAreaElement {
textinput: DOMRefCell::new(TextInput::new(
Lines::Multiple, DOMString::new(), chan, None, None, SelectionDirection::None)),
value_changed: Cell::new(false),
form_owner: Default::default(),
}
}
@ -342,7 +345,10 @@ impl VirtualMethods for HTMLTextAreaElement {
el.set_read_write_state(!el.disabled_state());
}
}
}
},
local_name!("form") => {
self.form_attribute_mutated(mutation);
},
_ => {},
}
}
@ -435,7 +441,19 @@ impl VirtualMethods for HTMLTextAreaElement {
}
}
impl FormControl for HTMLTextAreaElement {}
impl FormControl for HTMLTextAreaElement {
fn form_owner(&self) -> Option<Root<HTMLFormElement>> {
self.form_owner.get()
}
fn set_form_owner(&self, form: Option<&HTMLFormElement>) {
self.form_owner.set(form);
}
fn to_element<'a>(&'a self) -> &'a Element {
self.upcast::<Element>()
}
}
impl Validatable for HTMLTextAreaElement {}

Просмотреть файл

@ -5,6 +5,7 @@
use core::nonzero::NonZero;
use dom::bindings::codegen::Bindings::ImageDataBinding;
use dom::bindings::codegen::Bindings::ImageDataBinding::ImageDataMethods;
use dom::bindings::error::{Fallible, Error};
use dom::bindings::js::Root;
use dom::bindings::reflector::{Reflector, reflect_dom_object};
use dom::globalscope::GlobalScope;
@ -28,14 +29,7 @@ pub struct ImageData {
impl ImageData {
#[allow(unsafe_code)]
pub fn new(global: &GlobalScope, width: u32, height: u32, mut data: Option<Vec<u8>>) -> Root<ImageData> {
let imagedata = box ImageData {
reflector_: Reflector::new(),
width: width,
height: height,
data: Heap::default(),
};
let len = width * height * 4;
unsafe {
let cx = global.get_cx();
rooted!(in (cx) let mut js_object = ptr::null_mut());
@ -47,11 +41,88 @@ impl ImageData {
None => CreateWith::Length(len),
};
Uint8ClampedArray::create(cx, data, js_object.handle_mut()).unwrap();
(*imagedata).data.set(js_object.get());
Self::new_with_jsobject(global, width, Some(height), Some(js_object.get())).unwrap()
}
}
#[allow(unsafe_code)]
unsafe fn new_with_jsobject(global: &GlobalScope,
width: u32,
mut opt_height: Option<u32>,
opt_jsobject: Option<*mut JSObject>)
-> Fallible<Root<ImageData>> {
assert!(opt_jsobject.is_some() || opt_height.is_some());
if width == 0 {
return Err(Error::IndexSize);
}
reflect_dom_object(imagedata,
global, ImageDataBinding::Wrap)
// checking jsobject type and verifying (height * width * 4 == jsobject.byte_len())
if let Some(jsobject) = opt_jsobject {
let cx = global.get_cx();
typedarray!(in(cx) let array_res: Uint8ClampedArray = jsobject);
let mut array = try!(array_res
.map_err(|_| Error::Type("Argument to Image data is not an Uint8ClampedArray".to_owned())));
let byte_len = array.as_slice().len() as u32;
if byte_len % 4 != 0 {
return Err(Error::InvalidState);
}
let len = byte_len / 4;
if width == 0 || len % width != 0 {
return Err(Error::IndexSize);
}
let height = len / width;
if opt_height.map_or(false, |x| height != x) {
return Err(Error::IndexSize);
} else {
opt_height = Some(height);
}
}
let height = opt_height.unwrap();
if height == 0 {
return Err(Error::IndexSize);
}
let imagedata = box ImageData {
reflector_: Reflector::new(),
width: width,
height: height,
data: Heap::default(),
};
if let Some(jsobject) = opt_jsobject {
(*imagedata).data.set(jsobject);
} else {
let len = width * height * 4;
let cx = global.get_cx();
rooted!(in (cx) let mut array = ptr::null_mut());
Uint8ClampedArray::create(cx, CreateWith::Length(len), array.handle_mut()).unwrap();
(*imagedata).data.set(array.get());
}
Ok(reflect_dom_object(imagedata, global, ImageDataBinding::Wrap))
}
// https://html.spec.whatwg.org/multipage/#pixel-manipulation:dom-imagedata-3
#[allow(unsafe_code)]
pub fn Constructor(global: &GlobalScope, width: u32, height: u32) -> Fallible<Root<Self>> {
unsafe { Self::new_with_jsobject(global, width, Some(height), None) }
}
// https://html.spec.whatwg.org/multipage/#pixel-manipulation:dom-imagedata-4
#[allow(unsafe_code)]
#[allow(unused_variables)]
pub unsafe fn Constructor_(cx: *mut JSContext,
global: &GlobalScope,
jsobject: *mut JSObject,
width: u32,
opt_height: Option<u32>)
-> Fallible<Root<Self>> {
Self::new_with_jsobject(global, width, opt_height, Some(jsobject))
}
#[allow(unsafe_code)]

Просмотреть файл

@ -4,10 +4,12 @@
use dom::bindings::codegen::Bindings::LocationBinding;
use dom::bindings::codegen::Bindings::LocationBinding::LocationMethods;
use dom::bindings::error::{Error, ErrorResult};
use dom::bindings::codegen::Bindings::WindowBinding::WindowBinding::WindowMethods;
use dom::bindings::error::{Error, ErrorResult, Fallible};
use dom::bindings::js::{JS, Root};
use dom::bindings::reflector::{Reflector, reflect_dom_object};
use dom::bindings::str::{DOMString, USVString};
use dom::globalscope::GlobalScope;
use dom::urlhelper::UrlHelper;
use dom::window::Window;
use dom_struct::dom_struct;
@ -43,11 +45,27 @@ impl Location {
setter(&mut url, value);
self.window.load_url(url, false, false, None);
}
fn check_same_origin_domain(&self) -> ErrorResult {
let entry_document = GlobalScope::entry().as_window().Document();
let this_document = self.window.Document();
if entry_document.origin().same_origin_domain(this_document.origin()) {
Ok(())
} else {
Err(Error::Security)
}
}
// https://html.spec.whatwg.org/multipage/#dom-location-reload
pub fn reload_without_origin_check(&self) {
self.window.load_url(self.get_url(), true, true, None);
}
}
impl LocationMethods for Location {
// https://html.spec.whatwg.org/multipage/#dom-location-assign
fn Assign(&self, url: USVString) -> ErrorResult {
try!(self.check_same_origin_domain());
// TODO: per spec, we should use the _API base URL_ specified by the
// _entry settings object_.
let base_url = self.window.get_url();
@ -60,12 +78,15 @@ impl LocationMethods for Location {
}
// https://html.spec.whatwg.org/multipage/#dom-location-reload
fn Reload(&self) {
fn Reload(&self) -> ErrorResult {
try!(self.check_same_origin_domain());
self.window.load_url(self.get_url(), true, true, None);
Ok(())
}
// https://html.spec.whatwg.org/multipage/#dom-location-replace
fn Replace(&self, url: USVString) -> ErrorResult {
// Note: no call to self.check_same_origin_domain()
// TODO: per spec, we should use the _API base URL_ specified by the
// _entry settings object_.
let base_url = self.window.get_url();
@ -78,97 +99,124 @@ impl LocationMethods for Location {
}
// https://html.spec.whatwg.org/multipage/#dom-location-hash
fn Hash(&self) -> USVString {
UrlHelper::Hash(&self.get_url())
fn GetHash(&self) -> Fallible<USVString> {
try!(self.check_same_origin_domain());
Ok(UrlHelper::Hash(&self.get_url()))
}
// https://html.spec.whatwg.org/multipage/#dom-location-hash
fn SetHash(&self, mut value: USVString) {
fn SetHash(&self, mut value: USVString) -> ErrorResult {
if value.0.is_empty() {
value = USVString("#".to_owned());
}
try!(self.check_same_origin_domain());
self.set_url_component(value, UrlHelper::SetHash);
Ok(())
}
// https://html.spec.whatwg.org/multipage/#dom-location-host
fn Host(&self) -> USVString {
UrlHelper::Host(&self.get_url())
fn GetHost(&self) -> Fallible<USVString> {
try!(self.check_same_origin_domain());
Ok(UrlHelper::Host(&self.get_url()))
}
// https://html.spec.whatwg.org/multipage/#dom-location-host
fn SetHost(&self, value: USVString) {
fn SetHost(&self, value: USVString) -> ErrorResult {
try!(self.check_same_origin_domain());
self.set_url_component(value, UrlHelper::SetHost);
Ok(())
}
// https://html.spec.whatwg.org/multipage/#dom-location-origin
fn Origin(&self) -> USVString {
UrlHelper::Origin(&self.get_url())
fn GetOrigin(&self) -> Fallible<USVString> {
try!(self.check_same_origin_domain());
Ok(UrlHelper::Origin(&self.get_url()))
}
// https://html.spec.whatwg.org/multipage/#dom-location-hostname
fn Hostname(&self) -> USVString {
UrlHelper::Hostname(&self.get_url())
fn GetHostname(&self) -> Fallible<USVString> {
try!(self.check_same_origin_domain());
Ok(UrlHelper::Hostname(&self.get_url()))
}
// https://html.spec.whatwg.org/multipage/#dom-location-hostname
fn SetHostname(&self, value: USVString) {
fn SetHostname(&self, value: USVString) -> ErrorResult {
try!(self.check_same_origin_domain());
self.set_url_component(value, UrlHelper::SetHostname);
Ok(())
}
// https://html.spec.whatwg.org/multipage/#dom-location-href
fn Href(&self) -> USVString {
UrlHelper::Href(&self.get_url())
fn GetHref(&self) -> Fallible<USVString> {
try!(self.check_same_origin_domain());
Ok(UrlHelper::Href(&self.get_url()))
}
// https://html.spec.whatwg.org/multipage/#dom-location-href
fn SetHref(&self, value: USVString) {
if let Ok(url) = self.window.get_url().join(&value.0) {
self.window.load_url(url, false, false, None);
}
fn SetHref(&self, value: USVString) -> ErrorResult {
// Note: no call to self.check_same_origin_domain()
let url = match self.window.get_url().join(&value.0) {
Ok(url) => url,
Err(e) => return Err(Error::Type(format!("Couldn't parse URL: {}", e))),
};
self.window.load_url(url, false, false, None);
Ok(())
}
// https://html.spec.whatwg.org/multipage/#dom-location-pathname
fn Pathname(&self) -> USVString {
UrlHelper::Pathname(&self.get_url())
fn GetPathname(&self) -> Fallible<USVString> {
try!(self.check_same_origin_domain());
Ok(UrlHelper::Pathname(&self.get_url()))
}
// https://html.spec.whatwg.org/multipage/#dom-location-pathname
fn SetPathname(&self, value: USVString) {
fn SetPathname(&self, value: USVString) -> ErrorResult {
try!(self.check_same_origin_domain());
self.set_url_component(value, UrlHelper::SetPathname);
Ok(())
}
// https://html.spec.whatwg.org/multipage/#dom-location-port
fn Port(&self) -> USVString {
UrlHelper::Port(&self.get_url())
fn GetPort(&self) -> Fallible<USVString> {
try!(self.check_same_origin_domain());
Ok(UrlHelper::Port(&self.get_url()))
}
// https://html.spec.whatwg.org/multipage/#dom-location-port
fn SetPort(&self, value: USVString) {
fn SetPort(&self, value: USVString) -> ErrorResult {
try!(self.check_same_origin_domain());
self.set_url_component(value, UrlHelper::SetPort);
Ok(())
}
// https://html.spec.whatwg.org/multipage/#dom-location-protocol
fn Protocol(&self) -> USVString {
UrlHelper::Protocol(&self.get_url())
fn GetProtocol(&self) -> Fallible<USVString> {
try!(self.check_same_origin_domain());
Ok(UrlHelper::Protocol(&self.get_url()))
}
// https://html.spec.whatwg.org/multipage/#dom-location-protocol
fn SetProtocol(&self, value: USVString) {
fn SetProtocol(&self, value: USVString) -> ErrorResult {
try!(self.check_same_origin_domain());
self.set_url_component(value, UrlHelper::SetProtocol);
Ok(())
}
// https://html.spec.whatwg.org/multipage/#dom-location-href
fn Stringifier(&self) -> DOMString {
DOMString::from(self.Href().0)
fn Stringifier(&self) -> Fallible<DOMString> {
Ok(DOMString::from(try!(self.GetHref()).0))
}
// https://html.spec.whatwg.org/multipage/#dom-location-search
fn Search(&self) -> USVString {
UrlHelper::Search(&self.get_url())
fn GetSearch(&self) -> Fallible<USVString> {
try!(self.check_same_origin_domain());
Ok(UrlHelper::Search(&self.get_url()))
}
// https://html.spec.whatwg.org/multipage/#dom-location-search
fn SetSearch(&self, value: USVString) {
fn SetSearch(&self, value: USVString) -> ErrorResult {
try!(self.check_same_origin_domain());
self.set_url_component(value, UrlHelper::SetSearch);
Ok(())
}
}

Просмотреть файл

@ -162,7 +162,11 @@ bitflags! {
/// Whether any ancestor is a fragmentation container
const CAN_BE_FRAGMENTED = 0x40,
#[doc = "Specifies whether this node needs to be dirted when viewport size changed."]
const DIRTY_ON_VIEWPORT_SIZE_CHANGE = 0x80
const DIRTY_ON_VIEWPORT_SIZE_CHANGE = 0x80,
#[doc = "Specifies whether the parser has set an associated form owner for \
this element. Only applicable for form-associatable elements."]
const PARSER_ASSOCIATED_FORM_OWNER = 0x90,
}
}
@ -286,6 +290,11 @@ impl Node {
for node in child.traverse_preorder() {
// Out-of-document elements never have the descendants flag set.
node.set_flag(IS_IN_DOC | HAS_DIRTY_DESCENDANTS, false);
}
for node in child.traverse_preorder() {
// This needs to be in its own loop, because unbind_from_tree may
// rely on the state of IS_IN_DOC of the context node's descendants,
// e.g. when removing a <form>.
vtable_for(&&*node).unbind_from_tree(&context);
node.style_and_layout_data.get().map(|d| node.dispose(d));
}
@ -2656,3 +2665,41 @@ impl Into<LayoutElementType> for ElementTypeId {
}
}
/// Helper trait to insert an element into vector whose elements
/// are maintained in tree order
pub trait VecPreOrderInsertionHelper<T> {
fn insert_pre_order(&mut self, elem: &T, tree_root: &Node);
}
impl<T> VecPreOrderInsertionHelper<T> for Vec<JS<T>>
where T: DerivedFrom<Node> + DomObject
{
/// This algorithm relies on the following assumptions:
/// * any elements inserted in this vector share the same tree root
/// * any time an element is removed from the tree root, it is also removed from this array
/// * any time an element is moved within the tree, it is removed from this array and re-inserted
///
/// Under these assumptions, an element's tree-order position in this array can be determined by
/// performing a [preorder traversal](https://dom.spec.whatwg.org/#concept-tree-order) of the tree root's children,
/// and increasing the destination index in the array every time a node in the array is encountered during
/// the traversal.
fn insert_pre_order(&mut self, elem: &T, tree_root: &Node) {
if self.is_empty() {
self.push(JS::from_ref(elem));
return;
}
let elem_node = elem.upcast::<Node>();
let mut head: usize = 0;
for node in tree_root.traverse_preorder() {
let head_node = Root::upcast::<Node>(Root::from_ref(&*self[head]));
if head_node == node {
head += 1;
}
if elem_node == node.r() || head == self.len() {
break;
}
}
self.insert(head, JS::from_ref(elem));
}
}

Просмотреть файл

@ -15,12 +15,14 @@ use dom::comment::Comment;
use dom::document::Document;
use dom::documenttype::DocumentType;
use dom::element::{Element, ElementCreator};
use dom::htmlformelement::{FormControlElementHelpers, HTMLFormElement};
use dom::htmlscriptelement::HTMLScriptElement;
use dom::htmltemplateelement::HTMLTemplateElement;
use dom::node::Node;
use dom::processinginstruction::ProcessingInstruction;
use dom::virtualmethods::vtable_for;
use html5ever::Attribute;
use html5ever::QualName;
use html5ever::serialize::{AttrRef, Serializable, Serializer};
use html5ever::serialize::TraversalScope;
use html5ever::serialize::TraversalScope::{ChildrenOnly, IncludeNode};
@ -29,7 +31,6 @@ use html5ever::tokenizer::{Tokenizer as HtmlTokenizer, TokenizerOpts, TokenizerR
use html5ever::tokenizer::buffer_queue::BufferQueue;
use html5ever::tree_builder::{NodeOrText, QuirksMode};
use html5ever::tree_builder::{Tracer as HtmlTracer, TreeBuilder, TreeBuilderOpts, TreeSink};
use html5ever_atoms::QualName;
use js::jsapi::JSTracer;
use servo_url::ServoUrl;
use std::borrow::Cow;
@ -159,6 +160,13 @@ impl TreeSink for Sink {
}
}
fn same_tree(&self, x: JS<Node>, y: JS<Node>) -> bool {
let x = x.downcast::<Element>().expect("Element node expected");
let y = y.downcast::<Element>().expect("Element node expected");
x.is_in_same_home_subtree(y)
}
fn create_element(&mut self, name: QualName, attrs: Vec<Attribute>)
-> JS<Node> {
let elem = Element::create(name, None, &*self.document,
@ -176,17 +184,33 @@ impl TreeSink for Sink {
JS::from_ref(comment.upcast())
}
fn has_parent_node(&self, node: JS<Node>) -> bool {
node.GetParentNode().is_some()
}
fn associate_with_form(&mut self, target: JS<Node>, form: JS<Node>) {
let node = target;
let form = Root::downcast::<HTMLFormElement>(Root::from_ref(&*form))
.expect("Owner must be a form element");
let elem = node.downcast::<Element>();
let control = elem.as_ref().and_then(|e| e.as_maybe_form_control());
if let Some(control) = control {
control.set_form_owner_from_parser(&form);
} else {
// TODO remove this code when keygen is implemented.
assert!(node.NodeName() == "KEYGEN", "Unknown form-associatable element");
}
}
fn append_before_sibling(&mut self,
sibling: JS<Node>,
new_node: NodeOrText<JS<Node>>) -> Result<(), NodeOrText<JS<Node>>> {
// If there is no parent, return the node to the parser.
let parent = match sibling.GetParentNode() {
Some(p) => p,
None => return Err(new_node),
};
new_node: NodeOrText<JS<Node>>) {
let parent = sibling.GetParentNode()
.expect("append_before_sibling called on node without parent");
super::insert(&parent, Some(&*sibling), new_node);
Ok(())
}
fn parse_error(&mut self, msg: Cow<'static, str>) {

Просмотреть файл

@ -38,6 +38,7 @@ use dom::htmlmetaelement::HTMLMetaElement;
use dom::htmlobjectelement::HTMLObjectElement;
use dom::htmloptgroupelement::HTMLOptGroupElement;
use dom::htmloptionelement::HTMLOptionElement;
use dom::htmloutputelement::HTMLOutputElement;
use dom::htmlscriptelement::HTMLScriptElement;
use dom::htmlselectelement::HTMLSelectElement;
use dom::htmlstyleelement::HTMLStyleElement;
@ -212,6 +213,9 @@ pub fn vtable_for(node: &Node) -> &VirtualMethods {
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLOptionElement)) => {
node.downcast::<HTMLOptionElement>().unwrap() as &VirtualMethods
}
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLOutputElement)) => {
node.downcast::<HTMLOutputElement>().unwrap() as &VirtualMethods
}
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLScriptElement)) => {
node.downcast::<HTMLScriptElement>().unwrap() as &VirtualMethods
}

Просмотреть файл

@ -81,7 +81,7 @@ partial /*sealed*/ interface Document {
// resource metadata management
[/*PutForwards=href, */Unforgeable]
readonly attribute Location? location;
readonly attribute DOMString domain;
[SetterThrows] attribute DOMString domain;
readonly attribute DOMString referrer;
[Throws]
attribute DOMString cookie;

Просмотреть файл

@ -10,7 +10,7 @@ interface History {
readonly attribute unsigned long length;
// attribute ScrollRestoration scrollRestoration;
// readonly attribute any state;
void go(optional long delta = 0);
[Throws] void go(optional long delta = 0);
void back();
void forward();
// void pushState(any data, DOMString title, optional USVString? url = null);

Просмотреть файл

@ -9,9 +9,9 @@
* You are granted a license to use, reproduce and create derivative works of this document.
*/
//[Constructor(unsigned long sw, unsigned long sh),
//Constructor(Uint8ClampedArray data, unsigned long sw, optional unsigned long sh),
[Exposed=(Window,Worker)]
[Constructor(unsigned long sw, unsigned long sh),
Constructor(/* Uint8ClampedArray */ object data, unsigned long sw, optional unsigned long sh),
Exposed=(Window,Worker)]
interface ImageData {
//[Constant]
readonly attribute unsigned long width;

Просмотреть файл

@ -4,26 +4,24 @@
// https://html.spec.whatwg.org/multipage/#location
[Exposed=Window, Unforgeable] interface Location {
/*stringifier*/ attribute USVString href;
readonly attribute USVString origin;
attribute USVString protocol;
attribute USVString host;
attribute USVString hostname;
attribute USVString port;
attribute USVString pathname;
attribute USVString search;
attribute USVString hash;
/*stringifier*/ [Throws] attribute USVString href;
[Throws] readonly attribute USVString origin;
[Throws] attribute USVString protocol;
[Throws] attribute USVString host;
[Throws] attribute USVString hostname;
[Throws] attribute USVString port;
[Throws] attribute USVString pathname;
[Throws] attribute USVString search;
[Throws] attribute USVString hash;
[Throws]
void assign(USVString url);
[Throws]
void replace(USVString url);
void reload();
[Throws] void assign(USVString url);
[Throws] void replace(USVString url);
[Throws] void reload();
//[SameObject] readonly attribute USVString[] ancestorOrigins;
// This is only doing as well as gecko right now.
// https://github.com/servo/servo/issues/7590 is on file for
// adding attribute stringifier support.
stringifier;
[Throws] stringifier;
};

Просмотреть файл

@ -42,7 +42,7 @@ use dom::location::Location;
use dom::mediaquerylist::{MediaQueryList, WeakMediaQueryListVec};
use dom::messageevent::MessageEvent;
use dom::navigator::Navigator;
use dom::node::{Node, from_untrusted_node_address, window_from_node, NodeDamage};
use dom::node::{Node, NodeDamage, document_from_node, from_untrusted_node_address, window_from_node};
use dom::performance::Performance;
use dom::promise::Promise;
use dom::screen::Screen;
@ -528,7 +528,24 @@ impl WindowMethods for Window {
// https://html.spec.whatwg.org/multipage/#dom-frameelement
fn GetFrameElement(&self) -> Option<Root<Element>> {
self.browsing_context().frame_element().map(Root::from_ref)
// Steps 1-3.
let context = match self.browsing_context.get() {
None => return None,
Some(context) => context,
};
// Step 4-5.
let container = match context.frame_element() {
None => return None,
Some(container) => container,
};
// Step 6.
let container_doc = document_from_node(container);
let current_doc = GlobalScope::current().as_window().Document();
if !current_doc.origin().same_origin_domain(container_doc.origin()) {
return None;
}
// Step 7.
Some(Root::from_ref(container))
}
// https://html.spec.whatwg.org/multipage/#dom-navigator

Просмотреть файл

@ -27,7 +27,6 @@ use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::CSSStyleDeclarationBinding::CSSStyleDeclarationMethods;
use dom::bindings::codegen::Bindings::DocumentBinding::{DocumentMethods, DocumentReadyState};
use dom::bindings::codegen::Bindings::EventBinding::EventInit;
use dom::bindings::codegen::Bindings::LocationBinding::LocationMethods;
use dom::bindings::codegen::Bindings::TransitionEventBinding::TransitionEventInit;
use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
use dom::bindings::conversions::{ConversionResult, FromJSValConvertible, StringificationBehavior};
@ -644,6 +643,14 @@ impl ScriptThread {
}))
}
pub fn find_browsing_context(id: FrameId) -> Option<Root<BrowsingContext>> {
SCRIPT_THREAD_ROOT.with(|root| root.get().and_then(|script_thread| {
let script_thread = unsafe { &*script_thread };
script_thread.browsing_contexts.borrow().get(&id)
.map(|context| Root::from_ref(&**context))
}))
}
/// Creates a new script thread.
pub fn new(state: InitialScriptState,
port: Receiver<MainThreadScriptMsg>,
@ -1348,7 +1355,7 @@ impl ScriptThread {
/// Handles activity change message
fn handle_set_document_activity_msg(&self, id: PipelineId, activity: DocumentActivity) {
debug!("Setting activity of {} to be {:?}.", id, activity);
debug!("Setting activity of {} to be {:?} in {:?}.", id, activity, thread::current().name());
let document = self.documents.borrow().find_document(id);
if let Some(document) = document {
document.set_activity(activity);
@ -2101,7 +2108,7 @@ impl ScriptThread {
fn handle_reload(&self, pipeline_id: PipelineId) {
let window = self.documents.borrow().find_window(pipeline_id);
if let Some(window) = window {
window.Location().Reload();
window.Location().reload_without_origin_check();
}
}

Просмотреть файл

@ -113,29 +113,24 @@ pub fn handle_get_frame_id(documents: &Documents,
pipeline: PipelineId,
webdriver_frame_id: WebDriverFrameId,
reply: IpcSender<Result<Option<PipelineId>, ()>>) {
let window = match webdriver_frame_id {
let result = match webdriver_frame_id {
WebDriverFrameId::Short(_) => {
// This isn't supported yet
Ok(None)
},
WebDriverFrameId::Element(x) => {
match find_node_by_unique_id(documents, pipeline, x) {
Some(ref node) => {
match node.downcast::<HTMLIFrameElement>() {
Some(ref elem) => Ok(elem.get_content_window()),
None => Err(())
}
},
None => Err(())
}
find_node_by_unique_id(documents, pipeline, x)
.and_then(|node| node.downcast::<HTMLIFrameElement>().map(|elem| elem.pipeline_id()))
.ok_or(())
},
WebDriverFrameId::Parent => {
documents.find_window(pipeline).map(|window| window.parent()).ok_or(())
documents.find_window(pipeline)
.map(|window| window.parent_info().map(|(parent_id, _)| parent_id))
.ok_or(())
}
};
let frame_id = window.map(|x| x.map(|x| x.upcast::<GlobalScope>().pipeline_id()));
reply.send(frame_id).unwrap()
reply.send(result).unwrap()
}
pub fn handle_find_element_css(documents: &Documents, pipeline: PipelineId, selector: String,

Просмотреть файл

@ -8,7 +8,7 @@
#![allow(non_snake_case, missing_docs)]
use gecko_bindings::bindings::{RawServoMediaList, RawServoMediaRule};
use gecko_bindings::bindings::{RawServoMediaList, RawServoMediaRule, RawServoNamespaceRule};
use gecko_bindings::bindings::{RawServoStyleSheet, RawServoStyleRule, RawServoImportRule};
use gecko_bindings::bindings::{ServoComputedValues, ServoCssRules};
use gecko_bindings::structs::{RawServoAnimationValue, RawServoDeclarationBlock};
@ -17,7 +17,7 @@ use media_queries::MediaList;
use parking_lot::RwLock;
use properties::{ComputedValues, PropertyDeclarationBlock};
use properties::animated_properties::AnimationValue;
use stylesheets::{CssRules, Stylesheet, StyleRule, ImportRule, MediaRule};
use stylesheets::{CssRules, Stylesheet, StyleRule, ImportRule, MediaRule, NamespaceRule};
macro_rules! impl_arc_ffi {
($servo_type:ty => $gecko_type:ty [$addref:ident, $release:ident]) => {
@ -64,3 +64,6 @@ impl_arc_ffi!(RwLock<MediaList> => RawServoMediaList
impl_arc_ffi!(RwLock<MediaRule> => RawServoMediaRule
[Servo_MediaRule_AddRef, Servo_MediaRule_Release]);
impl_arc_ffi!(RwLock<NamespaceRule> => RawServoNamespaceRule
[Servo_NamespaceRule_AddRef, Servo_NamespaceRule_Release]);

Просмотреть файл

@ -4,6 +4,11 @@ pub use nsstring::{nsACString, nsAString, nsString};
type nsACString_internal = nsACString;
type nsAString_internal = nsAString;
use gecko_bindings::structs::mozilla::css::URLValue;
pub type RawServoNamespaceRuleStrong = ::gecko_bindings::sugar::ownership::Strong<RawServoNamespaceRule>;
pub type RawServoNamespaceRuleBorrowedOrNull<'a> = Option<&'a RawServoNamespaceRule>;
pub type RawServoNamespaceRuleBorrowed<'a> = &'a RawServoNamespaceRule;
enum RawServoNamespaceRuleVoid{ }
pub struct RawServoNamespaceRule(RawServoNamespaceRuleVoid);
use gecko_bindings::structs::RawGeckoDocument;
use gecko_bindings::structs::RawGeckoElement;
use gecko_bindings::structs::RawGeckoKeyframeList;
@ -1383,6 +1388,11 @@ extern "C" {
index: u32)
-> RawServoMediaRuleStrong;
}
extern "C" {
pub fn Servo_CssRules_GetNamespaceRuleAt(rules: ServoCssRulesBorrowed,
index: u32)
-> RawServoNamespaceRuleStrong;
}
extern "C" {
pub fn Servo_CssRules_InsertRule(rules: ServoCssRulesBorrowed,
sheet: RawServoStyleSheetBorrowed,
@ -1431,6 +1441,14 @@ extern "C" {
pub fn Servo_MediaRule_GetCssText(rule: RawServoMediaRuleBorrowed,
result: *mut nsAString_internal);
}
extern "C" {
pub fn Servo_NamespaceRule_Debug(rule: RawServoNamespaceRuleBorrowed,
result: *mut nsACString_internal);
}
extern "C" {
pub fn Servo_NamespaceRule_GetCssText(rule: RawServoNamespaceRuleBorrowed,
result: *mut nsAString_internal);
}
extern "C" {
pub fn Servo_ParseProperty(property: *const nsACString_internal,
value: *const nsACString_internal,

Просмотреть файл

@ -17,7 +17,7 @@ ${helpers.single_keyword("ime-mode", "auto normal active disabled inactive",
spec="https://drafts.csswg.org/css-ui/#input-method-editor")}
${helpers.single_keyword("-moz-user-select", "auto text none all element elements" +
" toggle tri_state -moz-all -moz-none -moz-text",
" toggle tri-state -moz-all -moz-none -moz-text",
products="gecko",
alias="-webkit-user-select",
gecko_ffi_name="mUserSelect",

Просмотреть файл

@ -28,6 +28,8 @@ use std::path::Path;
use std::sync::Arc;
use url::{Url, Position};
pub use url::Host;
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct ServoUrl(Arc<Url>);

Просмотреть файл

@ -33,8 +33,9 @@ use style::gecko_bindings::bindings;
use style::gecko_bindings::bindings::{RawGeckoKeyframeListBorrowed, RawGeckoKeyframeListBorrowedMut};
use style::gecko_bindings::bindings::{RawServoDeclarationBlockBorrowed, RawServoDeclarationBlockStrong};
use style::gecko_bindings::bindings::{RawServoMediaListBorrowed, RawServoMediaListStrong};
use style::gecko_bindings::bindings::{RawServoMediaRuleBorrowed, RawServoMediaRuleStrong};
use style::gecko_bindings::bindings::{RawServoStyleRuleBorrowed, RawServoStyleRuleStrong};
use style::gecko_bindings::bindings::{RawServoMediaRule, RawServoMediaRuleBorrowed};
use style::gecko_bindings::bindings::{RawServoNamespaceRule, RawServoNamespaceRuleBorrowed};
use style::gecko_bindings::bindings::{RawServoStyleRule, RawServoStyleRuleBorrowed};
use style::gecko_bindings::bindings::{RawServoStyleSetBorrowed, RawServoStyleSetOwned};
use style::gecko_bindings::bindings::{RawServoStyleSheetBorrowed, ServoComputedValuesBorrowed};
use style::gecko_bindings::bindings::{RawServoStyleSheetStrong, ServoComputedValuesStrong};
@ -76,7 +77,8 @@ use style::restyle_hints::{self, RestyleHint};
use style::selector_parser::PseudoElementCascadeType;
use style::sequential;
use style::string_cache::Atom;
use style::stylesheets::{CssRule, CssRules, ImportRule, MediaRule, Origin, Stylesheet, StyleRule};
use style::stylesheets::{CssRule, CssRules, ImportRule, MediaRule, NamespaceRule};
use style::stylesheets::{Origin, Stylesheet, StyleRule};
use style::stylesheets::StylesheetLoader as StyleStylesheetLoader;
use style::supports::parse_condition_or_declaration;
use style::thread_state;
@ -510,30 +512,6 @@ pub extern "C" fn Servo_CssRules_ListTypes(rules: ServoCssRulesBorrowed,
result.iter_mut().zip(iter).fold((), |_, (r, v)| *r = v);
}
#[no_mangle]
pub extern "C" fn Servo_CssRules_GetStyleRuleAt(rules: ServoCssRulesBorrowed, index: u32)
-> RawServoStyleRuleStrong {
let rules = RwLock::<CssRules>::as_arc(&rules).read();
match rules.0[index as usize] {
CssRule::Style(ref rule) => rule.clone().into_strong(),
_ => {
unreachable!("GetStyleRuleAt should only be called on a style rule");
}
}
}
#[no_mangle]
pub extern "C" fn Servo_CssRules_GetMediaRuleAt(rules: ServoCssRulesBorrowed, index: u32)
-> RawServoMediaRuleStrong {
let rules = RwLock::<CssRules>::as_arc(&rules).read();
match rules.0[index as usize] {
CssRule::Media(ref rule) => rule.clone().into_strong(),
_ => {
unreachable!("GetMediaRuleAt should only be called on a media rule");
}
}
}
#[no_mangle]
pub extern "C" fn Servo_CssRules_InsertRule(rules: ServoCssRulesBorrowed, sheet: RawServoStyleSheetBorrowed,
rule: *const nsACString, index: u32, nested: bool,
@ -559,11 +537,55 @@ pub extern "C" fn Servo_CssRules_DeleteRule(rules: ServoCssRulesBorrowed, index:
}
}
#[no_mangle]
pub extern "C" fn Servo_StyleRule_Debug(rule: RawServoStyleRuleBorrowed, result: *mut nsACString) {
let rule = RwLock::<StyleRule>::as_arc(&rule);
let result = unsafe { result.as_mut().unwrap() };
write!(result, "{:?}", *rule.read()).unwrap();
macro_rules! impl_basic_rule_funcs {
{ ($name:ident, $rule_type:ty, $raw_type:ty),
getter: $getter:ident,
debug: $debug:ident,
to_css: $to_css:ident,
} => {
#[no_mangle]
pub extern "C" fn $getter(rules: ServoCssRulesBorrowed, index: u32) -> Strong<$raw_type> {
let rules = RwLock::<CssRules>::as_arc(&rules).read();
match rules.0[index as usize] {
CssRule::$name(ref rule) => rule.clone().into_strong(),
_ => {
unreachable!(concat!(stringify!($getter), "should only be called ",
"on a ", stringify!($name), " rule"));
}
}
}
#[no_mangle]
pub extern "C" fn $debug(rule: &$raw_type, result: *mut nsACString) {
let rule = RwLock::<$rule_type>::as_arc(&rule);
let result = unsafe { result.as_mut().unwrap() };
write!(result, "{:?}", *rule.read()).unwrap();
}
#[no_mangle]
pub extern "C" fn $to_css(rule: &$raw_type, result: *mut nsAString) {
let rule = RwLock::<$rule_type>::as_arc(&rule);
rule.read().to_css(unsafe { result.as_mut().unwrap() }).unwrap();
}
}
}
impl_basic_rule_funcs! { (Style, StyleRule, RawServoStyleRule),
getter: Servo_CssRules_GetStyleRuleAt,
debug: Servo_StyleRule_Debug,
to_css: Servo_StyleRule_GetCssText,
}
impl_basic_rule_funcs! { (Media, MediaRule, RawServoMediaRule),
getter: Servo_CssRules_GetMediaRuleAt,
debug: Servo_MediaRule_Debug,
to_css: Servo_MediaRule_GetCssText,
}
impl_basic_rule_funcs! { (Namespace, NamespaceRule, RawServoNamespaceRule),
getter: Servo_CssRules_GetNamespaceRuleAt,
debug: Servo_NamespaceRule_Debug,
to_css: Servo_NamespaceRule_GetCssText,
}
#[no_mangle]
@ -580,25 +602,12 @@ pub extern "C" fn Servo_StyleRule_SetStyle(rule: RawServoStyleRuleBorrowed,
rule.write().block = declarations.clone();
}
#[no_mangle]
pub extern "C" fn Servo_StyleRule_GetCssText(rule: RawServoStyleRuleBorrowed, result: *mut nsAString) {
let rule = RwLock::<StyleRule>::as_arc(&rule);
rule.read().to_css(unsafe { result.as_mut().unwrap() }).unwrap();
}
#[no_mangle]
pub extern "C" fn Servo_StyleRule_GetSelectorText(rule: RawServoStyleRuleBorrowed, result: *mut nsAString) {
let rule = RwLock::<StyleRule>::as_arc(&rule);
rule.read().selectors.to_css(unsafe { result.as_mut().unwrap() }).unwrap();
}
#[no_mangle]
pub extern "C" fn Servo_MediaRule_Debug(rule: RawServoMediaRuleBorrowed, result: *mut nsACString) {
let rule = RwLock::<MediaRule>::as_arc(&rule);
let result = unsafe { result.as_mut().unwrap() };
write!(result, "{:?}", *rule.read()).unwrap();
}
#[no_mangle]
pub extern "C" fn Servo_MediaRule_GetMedia(rule: RawServoMediaRuleBorrowed) -> RawServoMediaListStrong {
let rule = RwLock::<MediaRule>::as_arc(&rule);
@ -612,9 +621,15 @@ pub extern "C" fn Servo_MediaRule_GetRules(rule: RawServoMediaRuleBorrowed) -> S
}
#[no_mangle]
pub extern "C" fn Servo_MediaRule_GetCssText(rule: RawServoMediaRuleBorrowed, result: *mut nsAString) {
let rule = RwLock::<MediaRule>::as_arc(&rule);
rule.read().to_css(unsafe { result.as_mut().unwrap() }).unwrap();
pub extern "C" fn Servo_NamespaceRule_GetPrefix(rule: RawServoNamespaceRuleBorrowed) -> *mut nsIAtom {
let rule = RwLock::<NamespaceRule>::as_arc(&rule);
rule.read().prefix.as_ref().unwrap_or(&atom!("")).as_ptr()
}
#[no_mangle]
pub extern "C" fn Servo_NamespaceRule_GetURI(rule: RawServoNamespaceRuleBorrowed) -> *mut nsIAtom {
let rule = RwLock::<NamespaceRule>::as_arc(&rule);
rule.read().url.0.as_ptr()
}
#[no_mangle]

Просмотреть файл

@ -15,7 +15,7 @@ extern crate parking_lot;
extern crate rayon;
extern crate selectors;
extern crate servo_url;
extern crate style;
#[macro_use] extern crate style;
extern crate style_traits;
#[allow(non_snake_case)]

Просмотреть файл

@ -21,7 +21,7 @@ fn test_moz_user_select() {
assert_roundtrip_with_context!(_moz_user_select::parse, "element");
assert_roundtrip_with_context!(_moz_user_select::parse, "elements");
assert_roundtrip_with_context!(_moz_user_select::parse, "toggle");
assert_roundtrip_with_context!(_moz_user_select::parse, "tri_state");
assert_roundtrip_with_context!(_moz_user_select::parse, "tri-state");
assert_roundtrip_with_context!(_moz_user_select::parse, "-moz-all");
assert_roundtrip_with_context!(_moz_user_select::parse, "-moz-none");
assert_roundtrip_with_context!(_moz_user_select::parse, "-moz-text");

Просмотреть файл

@ -15,7 +15,7 @@ extern crate parking_lot;
extern crate rayon;
extern crate selectors;
extern crate servo_url;
extern crate style;
#[macro_use] extern crate style;
extern crate style_traits;
mod sanity_checks;

Просмотреть файл

@ -89,14 +89,26 @@ qr-tests:
- xpcshell
ccov-code-coverage-tests:
- cppunit
- crashtest
- firefox-ui-functional-local
- firefox-ui-functional-remote
- gtest
- jittest
- jsreftest
- marionette
- mochitest
- mochitest-a11y
- mochitest-browser-chrome
- mochitest-chrome
- mochitest-clipboard
- mochitest-devtools-chrome
- mochitest-gpu
- mochitest-jetpack
- mochitest-media
- mochitest-webgl
- reftest
- reftest-no-accel
- web-platform-tests
- xpcshell

Просмотреть файл

@ -9,6 +9,10 @@ cppunit:
description: "CPP Unit Tests"
suite: cppunittest
treeherder-symbol: tc(Cpp)
instance-size:
by-test-platform:
linux64-ccov/opt: xlarge
default: default
e10s: false
docker-image: {"in-tree": "desktop1604-test"}
run-on-projects:
@ -174,9 +178,17 @@ firefox-ui-functional-local:
description: "Firefox-ui-tests functional run"
suite: "firefox-ui/functional local"
treeherder-symbol: tc-Fxfn-l(en-US)
instance-size:
by-test-platform:
linux64-ccov/opt: xlarge
default: default
max-run-time: 5400
tier: 1
docker-image: {"in-tree": "desktop1604-test"}
e10s:
by-test-platform:
linux64-ccov/opt: false
default: both
mozharness:
script: firefox_ui_tests/functional.py
config:
@ -190,9 +202,17 @@ firefox-ui-functional-remote:
description: "Firefox-ui-tests functional run"
suite: "firefox-ui/functional remote"
treeherder-symbol: tc-Fxfn-r(en-US)
instance-size:
by-test-platform:
linux64-ccov/opt: xlarge
default: default
max-run-time: 5400
tier: 2
docker-image: {"in-tree": "desktop1604-test"}
e10s:
by-test-platform:
linux64-ccov/opt: false
default: both
mozharness:
script: firefox_ui_tests/functional.py
config:
@ -233,6 +253,10 @@ jittest:
description: "JIT Test run"
suite: jittest/jittest-chunked
treeherder-symbol: tc(Jit)
instance-size:
by-test-platform:
linux64-ccov/opt: xlarge
default: default
e10s: false
docker-image: {"in-tree": "desktop1604-test"}
run-on-projects:
@ -449,6 +473,10 @@ mochitest-a11y:
description: "Mochitest a11y run"
suite: mochitest/a11y
treeherder-symbol: tc-M(a11y)
instance-size:
by-test-platform:
linux64-ccov/opt: xlarge
default: default
loopback-video: true
e10s: false
docker-image: {"in-tree": "desktop1604-test"}
@ -570,6 +598,7 @@ mochitest-chrome:
instance-size:
by-test-platform:
android.*: xlarge
linux64-ccov/opt: xlarge
default: default
chunks:
by-test-platform:
@ -619,6 +648,7 @@ mochitest-clipboard:
e10s:
by-test-platform:
macosx64/debug: true
linux64-ccov/opt: false
default: both
mozharness:
by-test-platform:
@ -708,6 +738,10 @@ mochitest-gpu:
description: "Mochitest GPU run"
suite: mochitest/gpu
treeherder-symbol: tc-M(gpu)
instance-size:
by-test-platform:
linux64-ccov/opt: xlarge
default: default
loopback-video: true
docker-image: {"in-tree": "desktop1604-test"}
run-on-projects:
@ -719,6 +753,7 @@ mochitest-gpu:
windows.*: both
android.*: false
macosx64/opt: both
linux64-ccov/opt: false
default: true
mozharness:
by-test-platform:
@ -753,6 +788,10 @@ mochitest-jetpack:
description: "Mochitest jetpack run"
suite: mochitest/jetpack-package
treeherder-symbol: tc-M(JP)
instance-size:
by-test-platform:
linux64-ccov/opt: xlarge
default: default
loopback-video: true
e10s: false
max-run-time: 5400
@ -789,10 +828,12 @@ mochitest-media:
e10s:
by-test-platform:
macosx64/debug: true
linux64-ccov/opt: false
default: both
instance-size:
by-test-platform:
android.*: xlarge
linux64-ccov/opt: xlarge
default: large
chunks:
by-test-platform:
@ -874,6 +915,7 @@ mochitest-webgl:
e10s:
by-test-platform:
macosx.*: true
linux64-ccov/opt: false
default: both
loopback-video: true
max-run-time:
@ -883,6 +925,7 @@ mochitest-webgl:
instance-size:
by-test-platform:
android.*: xlarge
linux64-ccov/opt: xlarge
default: default
# Bug 1296733: llvmpipe with mesa 9.2.1 lacks thread safety
allow-software-gl-layers: false
@ -1020,15 +1063,23 @@ reftest-no-accel:
description: "Reftest not accelerated run"
suite: reftest/reftest-no-accel
treeherder-symbol: tc-R(Ru)
instance-size:
by-test-platform:
linux64-ccov/opt: xlarge
default: default
docker-image: {"in-tree": "desktop1604-test"}
run-on-projects:
by-test-platform:
linux64-qr/.*: ['graphics', 'mozilla-central']
default: ['all']
chunks:
by-test-platform:
macosx.*: 1
default: 8
by-test-platform:
macosx.*: 1
default: 8
e10s:
by-test-platform:
linux64-ccov/opt: false
default: both
mozharness:
script: desktop_unittest.py
no-read-buildbot-config: true

Просмотреть файл

@ -44,7 +44,7 @@ def amend_taskgraph(taskgraph, label_to_taskid, to_add):
return taskgraph, label_to_taskid
def derive_misc_task(task, purpose, image, label_to_taskid):
def derive_misc_task(task, purpose, image, taskgraph, label_to_taskid):
"""Create the shell of a task that depends on `task` and on the given docker
image."""
label = '{}-{}'.format(purpose, task.label)
@ -80,24 +80,28 @@ def derive_misc_task(task, purpose, image, label_to_taskid):
'maxRunTime': 600,
}
}
dependencies = {
'parent': task.task_id,
'docker-image': image_taskid,
}
# only include the docker-image dependency here if it is actually in the
# taskgraph (has not been optimized). It is included in
# task_def['dependencies'] unconditionally.
dependencies = {'parent': task.task_id}
if image_taskid in taskgraph.tasks:
dependencies['docker-image'] = image_taskid
task = Task(kind='misc', label=label, attributes={}, task=task_def,
dependencies=dependencies)
task.task_id = slugid()
return task
def make_index_task(parent_task, label_to_taskid):
def make_index_task(parent_task, taskgraph, label_to_taskid):
index_paths = [r.split('.', 1)[1] for r in parent_task.task['routes']
if r.startswith('index.')]
parent_task.task['routes'] = [r for r in parent_task.task['routes']
if not r.startswith('index.')]
task = derive_misc_task(parent_task, 'index-task',
'index-task', label_to_taskid)
task = derive_misc_task(parent_task, 'index-task', 'index-task',
taskgraph, label_to_taskid)
task.task['scopes'] = [
'index:insert-task:{}'.format(path) for path in index_paths]
task.task['payload']['command'] = ['insert-indexes.js'] + index_paths
@ -120,7 +124,7 @@ def add_index_tasks(taskgraph, label_to_taskid):
for label, task in taskgraph.tasks.iteritems():
if len(task.task.get('routes', [])) <= MAX_ROUTES:
continue
added.append(make_index_task(task, label_to_taskid))
added.append(make_index_task(task, taskgraph, label_to_taskid))
if added:
taskgraph, label_to_taskid = amend_taskgraph(

Просмотреть файл

@ -2278,6 +2278,10 @@ toolbar#nav-bar {
options.e10s = False
mozinfo.update({"e10s": options.e10s}) # for test manifest parsing.
# Add flag to mozinfo to indicate that code coverage is enabled.
if os.getenv('GCOV_PREFIX') is not None:
mozinfo.update({"coverage": True})
self.setTestRoot(options)
# Despite our efforts to clean up servers started by this script, in practice

Просмотреть файл

@ -17,6 +17,10 @@ from mozharness.mozilla.testing.testbase import (
TestingMixin,
testing_config_options,
)
from mozharness.mozilla.testing.codecoverage import (
CodeCoverageMixin,
code_coverage_config_options
)
from mozharness.mozilla.vcstools import VCSToolsScript
@ -48,7 +52,8 @@ firefox_ui_tests_config_options = [
'dest': 'tag',
'help': 'Subset of tests to run (local, remote).',
}],
] + copy.deepcopy(testing_config_options)
] + copy.deepcopy(testing_config_options) \
+ copy.deepcopy(code_coverage_config_options)
# Command line arguments for update tests
firefox_ui_update_harness_config_options = [
@ -90,7 +95,7 @@ firefox_ui_update_config_options = firefox_ui_update_harness_config_options \
+ copy.deepcopy(firefox_ui_tests_config_options)
class FirefoxUITests(TestingMixin, VCSToolsScript):
class FirefoxUITests(TestingMixin, VCSToolsScript, CodeCoverageMixin):
# Needs to be overwritten in sub classes
cli_script = None
@ -243,6 +248,10 @@ class FirefoxUITests(TestingMixin, VCSToolsScript):
env.update({'MINIDUMP_STACKWALK': self.minidump_stackwalk_path})
env['RUST_BACKTRACE'] = '1'
# If code coverage is enabled, set GCOV_PREFIX env variable
if self.config.get('code_coverage'):
env['GCOV_PREFIX'] = self.gcov_dir
if self.config['allow_software_gl_layers']:
env['MOZ_LAYERS_ALLOW_SOFTWARE_GL'] = '1'

Просмотреть файл

@ -4,6 +4,8 @@ Cu.import("resource://gre/modules/Services.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Preferences",
"resource://gre/modules/Preferences.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "LightweightThemeManager",
"resource://gre/modules/LightweightThemeManager.jsm");
// WeakMap[Extension -> Theme]
let themeMap = new WeakMap();
@ -50,6 +52,7 @@ class Theme {
if (this.lwtStyles.headerURL &&
this.lwtStyles.accentcolor &&
this.lwtStyles.textcolor) {
LightweightThemeManager.fallbackThemeData = this.lwtStyles;
Services.obs.notifyObservers(null,
"lightweight-theme-styling-update",
JSON.stringify(this.lwtStyles));
@ -142,6 +145,7 @@ class Theme {
for (let icon of ICONS) {
lwtStyles.icons[`--${icon}--icon`] = "";
}
LightweightThemeManager.fallbackThemeData = null;
Services.obs.notifyObservers(null,
"lightweight-theme-styling-update",
JSON.stringify(lwtStyles));

Просмотреть файл

@ -8,6 +8,7 @@ module.exports = { // eslint-disable-line no-undef
},
"globals": {
"BrowserTestUtils": true,
"ExtensionTestUtils": false,
"XPCOMUtils": true,
},

Просмотреть файл

@ -1,3 +1,8 @@
[DEFAULT]
support-files =
head.js
[browser_ext_themes_chromeparity.js]
[browser_ext_themes_dynamic_updates.js]
[browser_ext_themes_lwtsupport.js]
[browser_ext_themes_persistence.js]

Просмотреть файл

@ -1,14 +1,5 @@
"use strict";
const BACKGROUND = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==";
const ACCENT_COLOR = "#a14040";
const TEXT_COLOR = "#fac96e";
function hexToRGB(hex) {
hex = parseInt((hex.indexOf("#") > -1 ? hex.substring(1) : hex), 16);
return [hex >> 16, (hex & 0x00FF00) >> 8, (hex & 0x0000FF)];
}
add_task(function* setup() {
yield SpecialPowers.pushPrefEnv({
set: [["extensions.webextensions.themes.enabled", true]],

Просмотреть файл

@ -0,0 +1,51 @@
"use strict";
// This test checks whether applied WebExtension themes are persisted and applied
// on newly opened windows.
add_task(function* setup() {
yield SpecialPowers.pushPrefEnv({
set: [["extensions.webextensions.themes.enabled", true]],
});
});
add_task(function* test_multiple_windows() {
let extension = ExtensionTestUtils.loadExtension({
manifest: {
"theme": {
"images": {
"headerURL": BACKGROUND,
},
"colors": {
"accentcolor": ACCENT_COLOR,
"textcolor": TEXT_COLOR,
},
},
},
});
yield extension.startup();
let docEl = window.document.documentElement;
let style = window.getComputedStyle(docEl);
Assert.ok(docEl.hasAttribute("lwtheme"), "LWT attribute should be set");
Assert.equal(docEl.getAttribute("lwthemetextcolor"), "bright",
"LWT text color attribute should be set");
Assert.equal(style.backgroundImage, 'url("' + BACKGROUND.replace(/"/g, '\\"') + '")',
"Expected background image");
// Now we'll open a new window to see if the theme is also applied there.
let window2 = yield BrowserTestUtils.openNewBrowserWindow();
docEl = window2.document.documentElement;
style = window2.getComputedStyle(docEl);
Assert.ok(docEl.hasAttribute("lwtheme"), "LWT attribute should be set");
Assert.equal(docEl.getAttribute("lwthemetextcolor"), "bright",
"LWT text color attribute should be set");
Assert.equal(style.backgroundImage, 'url("' + BACKGROUND.replace(/"/g, '\\"') + '")',
"Expected background image");
yield BrowserTestUtils.closeWindow(window2);
yield extension.unload();
});

Просмотреть файл

@ -0,0 +1,12 @@
/* exported BACKGROUND, ACCENT_COLOR, TEXT_COLOR, hexToRGB */
"use strict";
const BACKGROUND = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==";
const ACCENT_COLOR = "#a14040";
const TEXT_COLOR = "#fac96e";
function hexToRGB(hex) {
hex = parseInt((hex.indexOf("#") > -1 ? hex.substring(1) : hex), 16);
return [hex >> 16, (hex & 0x00FF00) >> 8, (hex & 0x0000FF)];
}

Просмотреть файл

@ -1,5 +1,5 @@
[flake8]
# See http://pep8.readthedocs.io/en/latest/intro.html#configuration
ignore = E121, E123, E126, E129, E133, E226, E241, E242, E704, W503, E402, E502, E128, E501, E713, E222, E201, E202, W602, E127, W601
ignore = E121, E123, E126, E129, E133, E226, E241, E242, E704, W503, E402, E128, E501, E713, E222, E201, E202, W602, E127, W601
max-line-length = 99
filename = *.py, +.lint

Просмотреть файл

@ -10270,7 +10270,7 @@
"SCROLL_INPUT_METHODS": {
"alert_emails": ["botond@mozilla.com"],
"bug_numbers": [1238137],
"expires_in_version": "55",
"expires_in_version": "60",
"kind": "enumerated",
"n_values": 64,
"description": "Count of scroll actions triggered by different input methods. See gfx/layers/apz/util/ScrollInputMethods.h for a list of possible values and their meanings."

Просмотреть файл

@ -1350,7 +1350,7 @@ TelemetryImpl::SnapshotSubsessionHistograms(bool clearSubsession,
JSContext *cx,
JS::MutableHandle<JS::Value> ret)
{
#if !defined(MOZ_WIDGET_GONK) && !defined(MOZ_WIDGET_ANDROID)
#if !defined(MOZ_WIDGET_ANDROID)
return TelemetryHistogram::CreateHistogramSnapshots(cx, ret, true,
clearSubsession);
#else

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше