зеркало из https://github.com/mozilla/gecko-dev.git
Merge autoland to central, a=merge
MozReview-Commit-ID: GRzdZQPAUxX
This commit is contained in:
Коммит
b58de4b0cc
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче