MozReview-Commit-ID: DEm2JLplowg
This commit is contained in:
Wes Kocher 2017-04-28 16:46:56 -07:00
Родитель d1bac2da78 f1ae056d77
Коммит 63e9b2a680
203 изменённых файлов: 21455 добавлений и 20681 удалений

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

@ -83,6 +83,8 @@ devtools/client/canvasdebugger/**
devtools/client/commandline/**
devtools/client/debugger/**
devtools/client/framework/**
!devtools/client/framework/devtools.js
!devtools/client/framework/devtools-browser.js
!devtools/client/framework/selection.js
!devtools/client/framework/target*
!devtools/client/framework/toolbox*

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

@ -699,6 +699,8 @@ pref("browser.preferences.offlineGroup.enabled", false);
pref("browser.preferences.offlineGroup.enabled", true);
#endif
pref("browser.preferences.defaultPerformanceSettings.enabled", true);
pref("browser.download.show_plugins_in_list", true);
pref("browser.download.hide_plugins_without_extensions", true);
@ -1455,6 +1457,8 @@ pref("browser.translation.engine", "bing");
// Telemetry settings.
// Determines if Telemetry pings can be archived locally.
pref("toolkit.telemetry.archive.enabled", true);
// Enables sending the shutdown ping when Firefox shuts down.
pref("toolkit.telemetry.shutdownPingSender.enabled", true);
// Telemetry experiments settings.
pref("experiments.enabled", true);

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

@ -3488,23 +3488,41 @@ function getPEMString(cert) {
var PrintPreviewListener = {
_printPreviewTab: null,
_simplifiedPrintPreviewTab: null,
_tabBeforePrintPreview: null,
_simplifyPageTab: null,
_lastRequestedPrintPreviewTab: null,
_createPPBrowser() {
if (!this._tabBeforePrintPreview) {
this._tabBeforePrintPreview = gBrowser.selectedTab;
}
let browser = this._tabBeforePrintPreview.linkedBrowser;
let preferredRemoteType = browser.remoteType;
return gBrowser.loadOneTab("about:printpreview", {
inBackground: true,
preferredRemoteType,
sameProcessAsFrameLoader: browser.frameLoader
});
},
getPrintPreviewBrowser() {
if (!this._printPreviewTab) {
let browser = gBrowser.selectedBrowser;
let preferredRemoteType = browser.remoteType;
this._tabBeforePrintPreview = gBrowser.selectedTab;
this._printPreviewTab = gBrowser.loadOneTab("about:printpreview", {
inBackground: false,
preferredRemoteType,
sameProcessAsFrameLoader: browser.frameLoader
});
gBrowser.selectedTab = this._printPreviewTab;
this._printPreviewTab = this._createPPBrowser();
}
gBrowser._allowTabChange = true;
this._lastRequestedPrintPreviewTab = gBrowser.selectedTab = this._printPreviewTab;
gBrowser._allowTabChange = false;
return gBrowser.getBrowserForTab(this._printPreviewTab);
},
getSimplifiedPrintPreviewBrowser() {
if (!this._simplifiedPrintPreviewTab) {
this._simplifiedPrintPreviewTab = this._createPPBrowser();
}
gBrowser._allowTabChange = true;
this._lastRequestedPrintPreviewTab = gBrowser.selectedTab = this._simplifiedPrintPreviewTab;
gBrowser._allowTabChange = false;
return gBrowser.getBrowserForTab(this._simplifiedPrintPreviewTab);
},
createSimplifiedBrowser() {
let browser = this._tabBeforePrintPreview.linkedBrowser;
this._simplifyPageTab = gBrowser.loadOneTab("about:printpreview", {
@ -3527,8 +3545,8 @@ var PrintPreviewListener = {
onEnter() {
// We might have accidentally switched tabs since the user invoked print
// preview
if (gBrowser.selectedTab != this._printPreviewTab) {
gBrowser.selectedTab = this._printPreviewTab;
if (gBrowser.selectedTab != this._lastRequestedPrintPreviewTab) {
gBrowser.selectedTab = this._lastRequestedPrintPreviewTab;
}
gInPrintPreviewMode = true;
this._toggleAffectedChrome();
@ -3538,13 +3556,15 @@ var PrintPreviewListener = {
this._tabBeforePrintPreview = null;
gInPrintPreviewMode = false;
this._toggleAffectedChrome();
if (this._simplifyPageTab) {
gBrowser.removeTab(this._simplifyPageTab);
this._simplifyPageTab = null;
let tabsToRemove = ["_simplifyPageTab", "_printPreviewTab", "_simplifiedPrintPreviewTab"];
for (let tabProp of tabsToRemove) {
if (this[tabProp]) {
gBrowser.removeTab(this[tabProp]);
this[tabProp] = null;
}
}
gBrowser.removeTab(this._printPreviewTab);
gBrowser.deactivatePrintPreviewBrowsers();
this._printPreviewTab = null;
this._lastRequestedPrintPreviewTab = null;
},
_toggleAffectedChrome() {
gNavToolbox.collapsed = gInPrintPreviewMode;

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

@ -3401,7 +3401,7 @@
</getter>
<setter>
<![CDATA[
if (gNavToolbox.collapsed) {
if (gNavToolbox.collapsed && !this._allowTabChange) {
return this.mTabBox.selectedTab;
}
// Update the tab

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

@ -90,7 +90,9 @@ add_task(function* test_plaintext() {
"context-viewsource", true,
"context-viewinfo", true
];
yield test_contextmenu("#test-text", plainTextItems);
yield test_contextmenu("#test-text", plainTextItems, {
maybeScreenshotsPresent: true
});
});
add_task(function* test_link() {
@ -139,7 +141,9 @@ add_task(function* test_canvas() {
["context-viewimage", true,
"context-saveimage", true,
"context-selectall", true
]
], {
maybeScreenshotsPresent: true
}
);
});
@ -433,7 +437,9 @@ add_task(function* test_textarea_spellcheck() {
});
add_task(function* test_plaintext2() {
yield test_contextmenu("#test-text", plainTextItems);
yield test_contextmenu("#test-text", plainTextItems, {
maybeScreenshotsPresent: true
});
});
add_task(function* test_undo_add_to_dictionary() {
@ -569,7 +575,8 @@ add_task(function* test_pagemenu() {
let pagemenu = content.document.getElementById("test-pagemenu");
Assert.ok(!pagemenu.hasAttribute("hopeless"), "attribute got removed");
});
}
},
maybeScreenshotsPresent: true
});
});
@ -593,6 +600,7 @@ add_task(function* test_dom_full_screen() {
"context-viewinfo", true
],
{
maybeScreenshotsPresent: true,
shiftkey: true,
*preCheckContextMenuFn() {
yield pushPrefs(["full-screen-api.allow-trusted-requests-only", false],
@ -638,7 +646,8 @@ add_task(function* test_pagemenu2() {
"context-viewsource", true,
"context-viewinfo", true
],
{shiftkey: true}
{maybeScreenshotsPresent: true,
shiftkey: true}
);
});
@ -817,6 +826,7 @@ add_task(function* test_click_to_play_blocked_plugin() {
"context-viewinfo", true
],
{
maybeScreenshotsPresent: true,
*preCheckContextMenuFn() {
pushPrefs(["plugins.click_to_play", true]);
setTestPluginEnabledState(Ci.nsIPluginTag.STATE_CLICKTOPLAY);
@ -922,6 +932,7 @@ add_task(function* test_plaintext_sendpagetodevice() {
"context-viewinfo", true
];
yield test_contextmenu("#test-text", plainTextItemsWithSendPage, {
maybeScreenshotsPresent: true,
*onContextMenuShown() {
yield openMenuItemSubmenu("context-sendpagetodevice");
}

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

@ -174,9 +174,13 @@ add_task(function* test_tel_email_url_number_input() {
"context-paste", null, // ignore clipboard state
"context-delete", false,
"---", null,
"context-selectall", null],
{skipFocusChange: true}
);
"context-selectall", null], {
// XXX Bug 1345081. Currently the Screenshots menu option is shown for
// various text elements even though it is set to type "page". That bug
// should remove the need for next line.
maybeScreenshotsPresent: true,
skipFocusChange: true
});
}
});
@ -198,9 +202,13 @@ add_task(function* test_date_time_color_range_month_week_datetimelocal_input() {
"context-selectall", null,
"---", null,
"context-viewsource", true,
"context-viewinfo", true],
{skipFocusChange: true}
);
"context-viewinfo", true], {
// XXX Bug 1345081. Currently the Screenshots menu option is shown for
// various text elements even though it is set to type "page". That bug
// should remove the need for next line.
maybeScreenshotsPresent: true,
skipFocusChange: true
});
}
});
@ -234,9 +242,13 @@ add_task(function* test_text_input_readonly() {
"context-paste", null, // ignore clipboard state
"context-delete", false,
"---", null,
"context-selectall", null],
{skipFocusChange: true}
);
"context-selectall", null], {
// XXX Bug 1345081. Currently the Screenshots menu option is shown for
// various text elements even though it is set to type "page". That bug
// should remove the need for next line.
maybeScreenshotsPresent: true,
skipFocusChange: true
});
});
add_task(function* test_cleanup() {

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

@ -69,7 +69,10 @@ function getVisibleMenuItems(aMenu, aData) {
item.id != "spell-add-dictionaries-main" &&
item.id != "context-savelinktopocket" &&
item.id != "fill-login-saved-passwords" &&
item.id != "fill-login-no-logins") {
item.id != "fill-login-no-logins" &&
// XXX Screenshots doesn't have an access key. This needs
// at least bug 1320462 fixing first.
item.id != "screenshots_mozilla_org_create-screenshot") {
ok(key, "menuitem " + item.id + " has an access key");
if (accessKeys[key])
ok(false, "menuitem " + item.id + " has same accesskey as " + accessKeys[key]);
@ -246,6 +249,9 @@ let lastElementSelector = null;
* to true if offsetX and offsetY are not provided
* waitForSpellCheck: wait until spellcheck is initialized before
* starting test
* maybeScreenshotsPresent: if true, the screenshots menu entry is
* expected to be present in the menu if
* screenshots is enabled, optional
* preCheckContextMenuFn: callback to run before opening menu
* onContextMenuShown: callback to run when the context menu is shown
* postCheckContextMenuFn: callback to run after opening menu
@ -315,6 +321,17 @@ function* test_contextmenu(selector, menuItems, options = {}) {
menuItems = menuItems.concat(inspectItems);
}
if (options.maybeScreenshotsPresent &&
!Services.prefs.getBoolPref("extensions.screenshots.disabled", false) &&
!Services.prefs.getBoolPref("extensions.screenshots.system-disabled", false)) {
let screenshotItems = [
"---", null,
"screenshots_mozilla_org_create-screenshot", true
];
menuItems = menuItems.concat(screenshotItems);
}
checkContextMenu(menuItems);
}

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

@ -76,6 +76,10 @@ var whitelist = new Set([
// Add-on API introduced in bug 1118285
{file: "resource://app/modules/NewTabURL.jsm"},
// browser/components/newtab bug 1355166
{file: "resource://app/modules/NewTabSearchProvider.jsm"},
{file: "resource://app/modules/NewTabWebChannel.jsm"},
// layout/mathml/nsMathMLChar.cpp
{file: "resource://gre/res/fonts/mathfontSTIXGeneral.properties"},
{file: "resource://gre/res/fonts/mathfontUnicode.properties"},

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

@ -267,6 +267,8 @@
{
"type": "object",
"name": "createData",
"optional": true,
"default": {},
"properties": {
"url": {
"description": "A URL or array of URLs to open as tabs in the window. Fully-qualified URLs must include a scheme (i.e. 'http://www.google.com', not 'www.google.com'). Relative URLs will be relative to the current page within the extension. Defaults to the New Tab Page.",

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

@ -23,7 +23,9 @@ add_task(function* testWindowCreate() {
}
async function createWindow(params, expected, keep = false) {
let window = await browser.windows.create(params);
let window = await browser.windows.create(...params);
// params is null when testing create without createData
params = params[0] || {};
for (let key of Object.keys(params)) {
if (key == "state" && os == "mac" && params.state == "normal") {
@ -54,13 +56,19 @@ add_task(function* testWindowCreate() {
try {
({os} = await browser.runtime.getPlatformInfo());
await createWindow({state: "maximized"}, {state: "STATE_MAXIMIZED"});
await createWindow({state: "minimized"}, {state: "STATE_MINIMIZED"});
await createWindow({state: "normal"}, {state: "STATE_NORMAL", hiddenChrome: []});
await createWindow({state: "fullscreen"}, {state: "STATE_FULLSCREEN"});
// Set the current window to state: "normal" because the test is failing on Windows
// where the current window is maximized.
let currentWindow = await browser.windows.getCurrent();
await browser.windows.update(currentWindow.id, {state: "normal"});
await createWindow([], {state: "STATE_NORMAL"});
await createWindow([{state: "maximized"}], {state: "STATE_MAXIMIZED"});
await createWindow([{state: "minimized"}], {state: "STATE_MINIMIZED"});
await createWindow([{state: "normal"}], {state: "STATE_NORMAL", hiddenChrome: []});
await createWindow([{state: "fullscreen"}], {state: "STATE_FULLSCREEN"});
let window = await createWindow(
{type: "popup"},
[{type: "popup"}],
{hiddenChrome: ["menubar", "toolbar", "location", "directories", "status", "extrachrome"],
chromeFlags: ["CHROME_OPENAS_DIALOG"]},
true);

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

@ -1,242 +0,0 @@
/* global
NewTabWebChannel,
NewTabPrefsProvider,
PlacesProvider,
PreviewProvider,
NewTabSearchProvider,
Preferences,
XPCOMUtils,
Task
*/
/* exported NewTabMessages */
"use strict";
const {utils: Cu} = Components;
Cu.import("resource://gre/modules/Preferences.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Task.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "PlacesProvider",
"resource:///modules/PlacesProvider.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "PreviewProvider",
"resource:///modules/PreviewProvider.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "NewTabPrefsProvider",
"resource:///modules/NewTabPrefsProvider.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "NewTabSearchProvider",
"resource:///modules/NewTabSearchProvider.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "NewTabWebChannel",
"resource:///modules/NewTabWebChannel.jsm");
this.EXPORTED_SYMBOLS = ["NewTabMessages"];
const PREF_ENABLED = "browser.newtabpage.remote";
const CURRENT_ENGINE = "browser-search-engine-modified";
// Action names are from the content's perspective. in from chrome == out from content
// Maybe replace the ACTION objects by a bi-directional Map a bit later?
const ACTIONS = {
inboundActions: [
"REQUEST_PREFS",
"REQUEST_THUMB",
"REQUEST_FRECENT",
"REQUEST_UISTRINGS",
"REQUEST_SEARCH_SUGGESTIONS",
"REQUEST_MANAGE_ENGINES",
"REQUEST_SEARCH_STATE",
"REQUEST_REMOVE_FORM_HISTORY",
"REQUEST_PERFORM_SEARCH",
"REQUEST_CYCLE_ENGINE",
],
prefs: {
inPrefs: "REQUEST_PREFS",
outPrefs: "RECEIVE_PREFS",
},
preview: {
inThumb: "REQUEST_THUMB",
outThumb: "RECEIVE_THUMB",
},
links: {
inFrecent: "REQUEST_FRECENT",
outFrecent: "RECEIVE_FRECENT",
outPlacesChange: "RECEIVE_PLACES_CHANGE",
},
search: {
inSearch: {
UIStrings: "REQUEST_UISTRINGS",
suggestions: "REQUEST_SEARCH_SUGGESTIONS",
manageEngines: "REQUEST_MANAGE_ENGINES",
state: "REQUEST_SEARCH_STATE",
removeFormHistory: "REQUEST_REMOVE_FORM_HISTORY",
performSearch: "REQUEST_PERFORM_SEARCH",
cycleEngine: "REQUEST_CYCLE_ENGINE"
},
outSearch: {
UIStrings: "RECEIVE_UISTRINGS",
suggestions: "RECEIVE_SEARCH_SUGGESTIONS",
state: "RECEIVE_SEARCH_STATE",
currentEngine: "RECEIVE_CURRENT_ENGINE"
},
}
};
let NewTabMessages = {
_prefs: {},
/** NEWTAB EVENT HANDLERS **/
handleContentRequest(actionName, {data, target}) {
switch (actionName) {
case ACTIONS.prefs.inPrefs:
// Return to the originator all newtabpage prefs
let results = NewTabPrefsProvider.prefs.newtabPagePrefs;
NewTabWebChannel.send(ACTIONS.prefs.outPrefs, results, target);
break;
case ACTIONS.preview.inThumb:
// Return to the originator a preview URL
PreviewProvider.getThumbnail(data).then(imgData => {
NewTabWebChannel.send(ACTIONS.preview.outThumb, {url: data, imgData}, target);
});
break;
case ACTIONS.links.inFrecent:
// Return to the originator the top frecent links
PlacesProvider.links.getLinks().then(links => {
NewTabWebChannel.send(ACTIONS.links.outFrecent, links, target);
});
break;
case ACTIONS.search.inSearch.UIStrings:
// Return to the originator all search strings to display
let strings = NewTabSearchProvider.search.searchSuggestionUIStrings;
NewTabWebChannel.send(ACTIONS.search.outSearch.UIStrings, strings, target);
break;
case ACTIONS.search.inSearch.suggestions:
// Return to the originator all search suggestions
Task.spawn(function*() {
try {
let {engineName, searchString} = data;
let suggestions = yield NewTabSearchProvider.search.asyncGetSuggestions(engineName, searchString, target);
NewTabWebChannel.send(ACTIONS.search.outSearch.suggestions, suggestions, target);
} catch (e) {
Cu.reportError(e);
}
});
break;
case ACTIONS.search.inSearch.manageEngines:
// Open about:preferences to manage search state
NewTabSearchProvider.search.manageEngines(target.browser);
break;
case ACTIONS.search.inSearch.state:
// Return the state of the search component (i.e current engine and visible engine details)
Task.spawn(function*() {
try {
let state = yield NewTabSearchProvider.search.asyncGetState();
NewTabWebChannel.broadcast(ACTIONS.search.outSearch.state, state);
} catch (e) {
Cu.reportError(e);
}
});
break;
case ACTIONS.search.inSearch.removeFormHistory:
// Remove a form history entry from the search component
let suggestion = data;
NewTabSearchProvider.search.removeFormHistory(target, suggestion);
break;
case ACTIONS.search.inSearch.performSearch:
// Perform a search
NewTabSearchProvider.search.asyncPerformSearch(target, data).catch(Cu.reportError);
break;
case ACTIONS.search.inSearch.cycleEngine:
// Set the new current engine
NewTabSearchProvider.search.asyncCycleEngine(data).catch(Cu.reportError);
break;
}
},
/*
* Broadcast places change to all open newtab pages
*/
handlePlacesChange(type, data) {
NewTabWebChannel.broadcast(ACTIONS.links.outPlacesChange, {type, data});
},
/*
* Broadcast current engine has changed to all open newtab pages
*/
_handleCurrentEngineChange(name, value) { // jshint unused: false
let engine = value;
NewTabWebChannel.broadcast(ACTIONS.search.outSearch.currentEngine, engine);
},
/*
* Broadcast preference changes to all open newtab pages
*/
handlePrefChange(actionName, value) {
let prefChange = {};
prefChange[actionName] = value;
NewTabWebChannel.broadcast(ACTIONS.prefs.outPrefs, prefChange);
},
_handleEnabledChange(prefName, value) {
if (prefName === PREF_ENABLED) {
if (this._prefs.enabled && !value) {
this.uninit();
} else if (!this._prefs.enabled && value) {
this.init();
}
}
},
init() {
this.handleContentRequest = this.handleContentRequest.bind(this);
this._handleEnabledChange = this._handleEnabledChange.bind(this);
this._handleCurrentEngineChange = this._handleCurrentEngineChange.bind(this);
PlacesProvider.links.init();
NewTabPrefsProvider.prefs.init();
NewTabSearchProvider.search.init();
NewTabWebChannel.init();
this._prefs.enabled = Preferences.get(PREF_ENABLED, false);
if (this._prefs.enabled) {
for (let action of ACTIONS.inboundActions) {
NewTabWebChannel.on(action, this.handleContentRequest);
}
NewTabPrefsProvider.prefs.on(PREF_ENABLED, this._handleEnabledChange);
NewTabSearchProvider.search.on(CURRENT_ENGINE, this._handleCurrentEngineChange);
for (let pref of NewTabPrefsProvider.newtabPagePrefSet) {
NewTabPrefsProvider.prefs.on(pref, this.handlePrefChange);
}
PlacesProvider.links.on("deleteURI", this.handlePlacesChange);
PlacesProvider.links.on("clearHistory", this.handlePlacesChange);
PlacesProvider.links.on("linkChanged", this.handlePlacesChange);
PlacesProvider.links.on("manyLinksChanged", this.handlePlacesChange);
}
},
uninit() {
this._prefs.enabled = Preferences.get(PREF_ENABLED, false);
if (this._prefs.enabled) {
NewTabPrefsProvider.prefs.off(PREF_ENABLED, this._handleEnabledChange);
NewTabSearchProvider.search.off(CURRENT_ENGINE, this._handleCurrentEngineChange);
for (let action of ACTIONS.inboundActions) {
NewTabWebChannel.off(action, this.handleContentRequest);
}
for (let pref of NewTabPrefsProvider.newtabPagePrefSet) {
NewTabPrefsProvider.prefs.off(pref, this.handlePrefChange);
}
}
NewTabPrefsProvider.prefs.uninit();
NewTabSearchProvider.search.uninit();
NewTabWebChannel.uninit();
}
};

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

@ -1,244 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
/* global XPCOMUtils, Services, PlacesUtils, EventEmitter */
/* global gLinks */
/* exported PlacesProvider */
"use strict";
this.EXPORTED_SYMBOLS = ["PlacesProvider"];
const {interfaces: Ci, utils: Cu} = Components;
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
"resource://gre/modules/PlacesUtils.jsm");
XPCOMUtils.defineLazyGetter(this, "EventEmitter", function() {
const {EventEmitter} = Cu.import("resource://gre/modules/EventEmitter.jsm", {});
return EventEmitter;
});
XPCOMUtils.defineLazyModuleGetter(this, "Task",
"resource://gre/modules/Task.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "NewTabUtils",
"resource://gre/modules/NewTabUtils.jsm");
// The maximum number of results PlacesProvider retrieves from history.
const HISTORY_RESULTS_LIMIT = 100;
/* Queries history to retrieve the most visited sites. Emits events when the
* history changes.
* Implements the EventEmitter interface.
*/
let Links = function Links() {
EventEmitter.decorate(this);
};
Links.prototype = {
/**
* Set this to change the maximum number of links the provider will provide.
*/
get maxNumLinks() {
// getter, so it can't be replaced dynamically
return HISTORY_RESULTS_LIMIT;
},
/**
* A set of functions called by @mozilla.org/browser/nav-historyservice
* All history events are emitted from this object.
*/
historyObserver: {
_batchProcessingDepth: 0,
_batchCalledFrecencyChanged: false,
/**
* Called by the history service.
*/
onBeginUpdateBatch() {
this._batchProcessingDepth += 1;
},
onEndUpdateBatch() {
this._batchProcessingDepth -= 1;
if (this._batchProcessingDepth == 0 && this._batchCalledFrecencyChanged) {
this.onManyFrecenciesChanged();
this._batchCalledFrecencyChanged = false;
}
},
onDeleteURI: function historyObserver_onDeleteURI(aURI) {
// let observers remove sensetive data associated with deleted visit
gLinks.emit("deleteURI", {
url: aURI.spec,
});
},
onClearHistory: function historyObserver_onClearHistory() {
gLinks.emit("clearHistory");
},
onFrecencyChanged: function historyObserver_onFrecencyChanged(aURI,
aNewFrecency, aGUID, aHidden, aLastVisitDate) { // jshint ignore:line
// If something is doing a batch update of history entries we don't want
// to do lots of work for each record. So we just track the fact we need
// to call onManyFrecenciesChanged() once the batch is complete.
if (this._batchProcessingDepth > 0) {
this._batchCalledFrecencyChanged = true;
return;
}
// The implementation of the query in getLinks excludes hidden and
// unvisited pages, so it's important to exclude them here, too.
if (!aHidden && aLastVisitDate &&
NewTabUtils.linkChecker.checkLoadURI(aURI.spec)) {
gLinks.emit("linkChanged", {
url: aURI.spec,
frecency: aNewFrecency,
lastVisitDate: aLastVisitDate,
type: "history",
});
}
},
onManyFrecenciesChanged: function historyObserver_onManyFrecenciesChanged() {
// Called when frecencies are invalidated and also when clearHistory is called
// See toolkit/components/places/tests/unit/test_frecency_observers.js
gLinks.emit("manyLinksChanged");
},
onVisit(aURI, aVisitId, aTime, aSessionId, aReferrerVisitId, aTransitionType,
aGuid, aHidden, aVisitCount, aTyped, aLastKnownTitle) {
// For new visits, if we're not batch processing, notify for a title update
if (!this._batchProcessingDepth && aVisitCount == 1 && aLastKnownTitle) {
this.onTitleChanged(aURI, aLastKnownTitle, aGuid);
}
},
onTitleChanged: function historyObserver_onTitleChanged(aURI, aNewTitle) {
if (NewTabUtils.linkChecker.checkLoadURI(aURI.spec)) {
gLinks.emit("linkChanged", {
url: aURI.spec,
title: aNewTitle
});
}
},
QueryInterface: XPCOMUtils.generateQI([Ci.nsINavHistoryObserver,
Ci.nsISupportsWeakReference])
},
/**
* Must be called before the provider is used.
* Makes it easy to disable under pref
*/
init: function PlacesProvider_init() {
try {
PlacesUtils.history.addObserver(this.historyObserver, true);
} catch (e) {
Cu.reportError(e);
}
},
/**
* Gets the current set of links delivered by this provider.
*
* @returns {Promise} Returns a promise with the array of links as payload.
*/
getLinks: Task.async(function*() {
// Select a single page per host with highest frecency, highest recency.
// Choose N top such pages. Note +rev_host, to turn off optimizer per :mak
// suggestion.
let sqlQuery = `SELECT url, title, frecency,
last_visit_date as lastVisitDate,
"history" as type
FROM moz_places
WHERE frecency in (
SELECT MAX(frecency) as frecency
FROM moz_places
WHERE hidden = 0 AND last_visit_date NOTNULL
GROUP BY +rev_host
ORDER BY frecency DESC
LIMIT :limit
)
GROUP BY rev_host HAVING MAX(lastVisitDate)
ORDER BY frecency DESC, lastVisitDate DESC, url`;
let links = yield this.executePlacesQuery(sqlQuery, {
columns: ["url", "title", "lastVisitDate", "frecency", "type"],
params: {limit: this.maxNumLinks}
});
return links.filter(link => NewTabUtils.linkChecker.checkLoadURI(link.url));
}),
/**
* Executes arbitrary query against places database
*
* @param {String} aSql
* SQL query to execute
* @param {Object} [optional] aOptions
* aOptions.columns - an array of column names. if supplied the returned
* items will consist of objects keyed on column names. Otherwise
* an array of raw values is returned in the select order
* aOptions.param - an object of SQL binding parameters
* aOptions.callback - a callback to handle query rows
*
* @returns {Promise} Returns a promise with the array of retrieved items
*/
executePlacesQuery: Task.async(function*(aSql, aOptions = {}) {
let {columns, params, callback} = aOptions;
let items = [];
let queryError = null;
let conn = yield PlacesUtils.promiseDBConnection();
yield conn.executeCached(aSql, params, aRow => {
try {
// check if caller wants to handle query raws
if (callback) {
callback(aRow);
} else {
// otherwise fill in the item and add items array
let item = null;
// if columns array is given construct an object
if (columns && Array.isArray(columns)) {
item = {};
columns.forEach(column => {
item[column] = aRow.getResultByName(column);
});
} else {
// if no columns - make an array of raw values
item = [];
for (let i = 0; i < aRow.numEntries; i++) {
item.push(aRow.getResultByIndex(i));
}
}
items.push(item);
}
} catch (e) {
queryError = e;
throw StopIteration;
}
});
if (queryError) {
throw new Error(queryError);
}
return items;
}),
};
/**
* Singleton that serves as the default link provider for the grid.
*/
const gLinks = new Links(); // jshint ignore:line
let PlacesProvider = {
links: gLinks,
};
// Kept only for backwards-compatibility
XPCOMUtils.defineLazyGetter(PlacesProvider, "LinkChecker",
() => NewTabUtils.linkChecker);

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

@ -14,13 +14,11 @@ XPCSHELL_TESTS_MANIFESTS += [
]
EXTRA_JS_MODULES += [
'NewTabMessages.jsm',
'NewTabPrefsProvider.jsm',
'NewTabRemoteResources.jsm',
'NewTabSearchProvider.jsm',
'NewTabURL.jsm',
'NewTabWebChannel.jsm',
'PlacesProvider.jsm',
'PreviewProvider.jsm'
]

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

@ -1,357 +0,0 @@
"use strict";
/* global XPCOMUtils, PlacesUtils, PlacesTestUtils, PlacesProvider, NetUtil */
/* global do_get_profile, run_next_test, add_task */
/* global equal, ok */
const {
utils: Cu,
interfaces: Ci,
} = Components;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "PlacesProvider",
"resource:///modules/PlacesProvider.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
"resource://gre/modules/PlacesUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "PlacesTestUtils",
"resource://testing-common/PlacesTestUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
"resource://gre/modules/NetUtil.jsm");
// ensure a profile exists
do_get_profile();
function run_test() {
PlacesProvider.links.init();
run_next_test();
}
// url prefix for test history population
const TEST_URL = "https://mozilla.com/";
// time when the test starts execution
const TIME_NOW = new Date();
// utility function to compute past timestap
function timeDaysAgo(numDays) {
return new Date(TIME_NOW - (numDays * 24 * 60 * 60 * 1000));
}
// utility function to make a visit for insetion into places db
function makeVisit(index, daysAgo, isTyped, domain = TEST_URL) {
let {
TRANSITION_TYPED,
TRANSITION_LINK
} = PlacesUtils.history;
return {
uri: NetUtil.newURI(`${domain}${index}`),
visitDate: timeDaysAgo(daysAgo),
transition: (isTyped) ? TRANSITION_TYPED : TRANSITION_LINK,
};
}
/** Test LinkChecker **/
add_task(function test_LinkChecker_securityCheck() {
let urls = [
{url: "javascript:alert('hello')", expected: false}, // jshint ignore:line
{url: "data:image/png;base64,XXX", expected: false},
{url: "about:newtab", expected: true},
{url: "https://example.com", expected: true},
{url: "ftp://example.com", expected: true},
{url: "file://home/file/image.png", expected: true},
{url: "resource:///modules/PlacesProvider.jsm", expected: true},
];
for (let {url, expected} of urls) {
let observed = PlacesProvider.LinkChecker.checkLoadURI(url);
equal(observed, expected, `can load "${url}"?`);
}
});
/** Test Provider **/
add_task(function* test_Links_getLinks() {
yield PlacesTestUtils.clearHistory();
let provider = PlacesProvider.links;
let links = yield provider.getLinks();
equal(links.length, 0, "empty history yields empty links");
// add a visit
let testURI = NetUtil.newURI("http://mozilla.com");
yield PlacesTestUtils.addVisits(testURI);
links = yield provider.getLinks();
equal(links.length, 1, "adding a visit yields a link");
equal(links[0].url, testURI.spec, "added visit corresponds to added url");
});
add_task(function* test_Links_getLinks_Order() {
yield PlacesTestUtils.clearHistory();
let provider = PlacesProvider.links;
// all four visits must come from different domains to avoid deduplication
let visits = [
makeVisit(0, 0, true, "http://bar.com/"), // frecency 200, today
makeVisit(1, 0, true, "http://foo.com/"), // frecency 200, today
makeVisit(2, 2, true, "http://buz.com/"), // frecency 200, 2 days ago
makeVisit(3, 2, false, "http://aaa.com/"), // frecency 10, 2 days ago, transition
];
let links = yield provider.getLinks();
equal(links.length, 0, "empty history yields empty links");
yield PlacesTestUtils.addVisits(visits);
links = yield provider.getLinks();
equal(links.length, visits.length, "number of links added is the same as obtain by getLinks");
for (let i = 0; i < links.length; i++) {
equal(links[i].url, visits[i].uri.spec, "links are obtained in the expected order");
}
});
add_task(function* test_Links_getLinks_Deduplication() {
yield PlacesTestUtils.clearHistory();
let provider = PlacesProvider.links;
// all for visits must come from different domains to avoid deduplication
let visits = [
makeVisit(0, 2, true, "http://bar.com/"), // frecency 200, 2 days ago
makeVisit(1, 0, true, "http://bar.com/"), // frecency 200, today
makeVisit(2, 0, false, "http://foo.com/"), // frecency 10, today
makeVisit(3, 0, true, "http://foo.com/"), // frecency 200, today
];
let links = yield provider.getLinks();
equal(links.length, 0, "empty history yields empty links");
yield PlacesTestUtils.addVisits(visits);
links = yield provider.getLinks();
equal(links.length, 2, "only two links must be left after deduplication");
equal(links[0].url, visits[1].uri.spec, "earliest link is present");
equal(links[1].url, visits[3].uri.spec, "most fresent link is present");
});
add_task(function* test_Links_onLinkChanged() {
let provider = PlacesProvider.links;
let url = "https://example.com/onFrecencyChanged1";
let linkChangedMsgCount = 0;
let linkChangedPromise = new Promise(resolve => {
let handler = (_, link) => { // jshint ignore:line
/* There are 2 linkChanged events:
* 1. visit insertion (-1 frecency by default)
* 2. frecency score update (after transition type calculation etc)
*/
if (link.url === url) {
equal(link.url, url, `expected url on linkChanged event`);
linkChangedMsgCount += 1;
if (linkChangedMsgCount === 2) {
ok(true, `all linkChanged events captured`);
provider.off("linkChanged", this);
resolve();
}
}
};
provider.on("linkChanged", handler);
});
// add a visit
let testURI = NetUtil.newURI(url);
yield PlacesUtils.history.insert({
url: testURI,
visits: [{ transition: PlacesUtils.history.TRANSITIONS.LINK }]
});
yield linkChangedPromise;
yield PlacesTestUtils.clearHistory();
});
add_task(function* test_Links_onClearHistory() {
let provider = PlacesProvider.links;
let clearHistoryPromise = new Promise(resolve => {
let handler = () => {
ok(true, `clearHistory event captured`);
provider.off("clearHistory", handler);
resolve();
};
provider.on("clearHistory", handler);
});
// add visits
for (let i = 0; i <= 10; i++) {
let url = `https://example.com/onClearHistory${i}`;
let testURI = NetUtil.newURI(url);
yield PlacesTestUtils.addVisits(testURI);
}
yield PlacesTestUtils.clearHistory();
yield clearHistoryPromise;
});
add_task(function* test_Links_onDeleteURI() {
let provider = PlacesProvider.links;
let testURL = "https://example.com/toDelete";
let deleteURIPromise = new Promise(resolve => {
let handler = (_, {url}) => { // jshint ignore:line
equal(testURL, url, "deleted url and expected url are the same");
provider.off("deleteURI", handler);
resolve();
};
provider.on("deleteURI", handler);
});
let testURI = NetUtil.newURI(testURL);
yield PlacesTestUtils.addVisits(testURI);
yield PlacesUtils.history.remove(testURL);
yield deleteURIPromise;
});
add_task(function* test_Links_onManyLinksChanged() {
let provider = PlacesProvider.links;
let promise = new Promise(resolve => {
let handler = () => {
ok(true);
provider.off("manyLinksChanged", handler);
resolve();
};
provider.on("manyLinksChanged", handler);
});
let testURL = "https://example.com/toDelete";
let testURI = NetUtil.newURI(testURL);
yield PlacesTestUtils.addVisits(testURI);
// trigger DecayFrecency
PlacesUtils.history.QueryInterface(Ci.nsIObserver).
observe(null, "idle-daily", "");
yield promise;
});
add_task(function* test_Links_execute_query() {
yield PlacesTestUtils.clearHistory();
let provider = PlacesProvider.links;
let visits = [
makeVisit(0, 0, true), // frecency 200, today
makeVisit(1, 0, true), // frecency 200, today
makeVisit(2, 2, true), // frecency 200, 2 days ago
makeVisit(3, 2, false), // frecency 10, 2 days ago, transition
];
yield PlacesTestUtils.addVisits(visits);
function testItemValue(results, index, value) {
equal(results[index][0], `${TEST_URL}${value}`, "raw url");
equal(results[index][1], `test visit for ${TEST_URL}${value}`, "raw title");
}
function testItemObject(results, index, columnValues) {
Object.keys(columnValues).forEach(name => {
equal(results[index][name], columnValues[name], "object name " + name);
});
}
// select all 4 records
let results = yield provider.executePlacesQuery("select url, title from moz_places");
equal(results.length, 4, "expect 4 items");
// check for insert order sequence
for (let i = 0; i < results.length; i++) {
testItemValue(results, i, i);
}
// test parameter passing
results = yield provider.executePlacesQuery(
"select url, title from moz_places limit :limit",
{params: {limit: 2}}
);
equal(results.length, 2, "expect 2 items");
for (let i = 0; i < results.length; i++) {
testItemValue(results, i, i);
}
// test extracting items by name
results = yield provider.executePlacesQuery(
"select url, title from moz_places limit :limit",
{columns: ["url", "title"], params: {limit: 4}}
);
equal(results.length, 4, "expect 4 items");
for (let i = 0; i < results.length; i++) {
testItemObject(results, i, {
"url": `${TEST_URL}${i}`,
"title": `test visit for ${TEST_URL}${i}`,
});
}
// test ordering
results = yield provider.executePlacesQuery(
"select url, title, last_visit_date, frecency from moz_places " +
"order by frecency DESC, last_visit_date DESC, url DESC limit :limit",
{columns: ["url", "title", "last_visit_date", "frecency"], params: {limit: 4}}
);
equal(results.length, 4, "expect 4 items");
testItemObject(results, 0, {url: `${TEST_URL}1`});
testItemObject(results, 1, {url: `${TEST_URL}0`});
testItemObject(results, 2, {url: `${TEST_URL}2`});
testItemObject(results, 3, {url: `${TEST_URL}3`});
// test callback passing
results = [];
function handleRow(aRow) {
results.push({
url: aRow.getResultByName("url"),
title: aRow.getResultByName("title"),
last_visit_date: aRow.getResultByName("last_visit_date"),
frecency: aRow.getResultByName("frecency")
});
}
yield provider.executePlacesQuery(
"select url, title, last_visit_date, frecency from moz_places " +
"order by frecency DESC, last_visit_date DESC, url DESC",
{callback: handleRow}
);
equal(results.length, 4, "expect 4 items");
testItemObject(results, 0, {url: `${TEST_URL}1`});
testItemObject(results, 1, {url: `${TEST_URL}0`});
testItemObject(results, 2, {url: `${TEST_URL}2`});
testItemObject(results, 3, {url: `${TEST_URL}3`});
// negative test cases
// bad sql
try {
yield provider.executePlacesQuery("select from moz");
do_throw("bad sql should've thrown");
} catch (e) {
do_check_true("expected failure - bad sql");
}
// missing bindings
try {
yield provider.executePlacesQuery("select * from moz_places limit :limit");
do_throw("bad sql should've thrown");
} catch (e) {
do_check_true("expected failure - missing bidning");
}
// non-existent column name
try {
yield provider.executePlacesQuery("select * from moz_places limit :limit",
{columns: ["no-such-column"], params: {limit: 4}});
do_throw("bad sql should've thrown");
} catch (e) {
do_check_true("expected failure - wrong column name");
}
// cleanup
yield PlacesTestUtils.clearHistory();
});

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

@ -7,4 +7,3 @@ skip-if = toolkit == 'android'
[test_NewTabPrefsProvider.js]
[test_NewTabSearchProvider.js]
[test_NewTabURL.js]
[test_PlacesProvider.js]

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

@ -27,7 +27,7 @@ XPCOMUtils.defineLazyServiceGetter(this, "AlertsService", "@mozilla.org/alerts-s
ExtensionsUI:false, Feeds:false,
FileUtils:false, FormValidationHandler:false, Integration:false,
LightweightThemeManager:false, LoginHelper:false, LoginManagerParent:false,
NetUtil:false, NewTabMessages:false, NewTabUtils:false, OS:false,
NetUtil:false, NewTabUtils:false, OS:false,
PageThumbs:false, PdfJs:false, PermissionUI:false, PlacesBackups:false,
PlacesUtils:false, PluralForm:false, PrivateBrowsingUtils:false,
ProcessHangMonitor:false, ReaderParent:false, RecentWindow:false,
@ -65,7 +65,6 @@ XPCOMUtils.defineLazyServiceGetter(this, "AlertsService", "@mozilla.org/alerts-s
["LoginHelper", "resource://gre/modules/LoginHelper.jsm"],
["LoginManagerParent", "resource://gre/modules/LoginManagerParent.jsm"],
["NetUtil", "resource://gre/modules/NetUtil.jsm"],
["NewTabMessages", "resource:///modules/NewTabMessages.jsm"],
["NewTabUtils", "resource://gre/modules/NewTabUtils.jsm"],
["OS", "resource://gre/modules/osfile.jsm"],
["PageThumbs", "resource://gre/modules/PageThumbs.jsm"],
@ -509,8 +508,6 @@ BrowserGlue.prototype = {
NewTabUtils.links.addProvider(DirectoryLinksProvider);
AboutNewTab.init();
NewTabMessages.init();
SessionStore.init();
BrowserUsageTelemetry.init();
BrowserUITelemetry.init();
@ -896,8 +893,8 @@ BrowserGlue.prototype = {
BrowserUsageTelemetry.uninit();
SelfSupportBackend.uninit();
PageThumbs.uninit();
NewTabMessages.uninit();
AboutNewTab.uninit();
NewTabUtils.uninit();
webrtcUI.uninit();
FormValidationHandler.uninit();
AutoCompletePopup.uninit();

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

@ -16,7 +16,8 @@ function searchBookmarks(aSearchString) {
tree.applyFilter(aSearchString,
[PlacesUtils.bookmarksMenuFolderId,
PlacesUtils.unfiledBookmarksFolderId,
PlacesUtils.toolbarFolderId]);
PlacesUtils.toolbarFolderId,
PlacesUtils.mobileFolderId]);
}
window.addEventListener("SidebarFocused",

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

@ -757,7 +757,8 @@ var PlacesSearchBox = {
if (this._folders.length == 0) {
this._folders.push(PlacesUtils.bookmarksMenuFolderId,
PlacesUtils.unfiledBookmarksFolderId,
PlacesUtils.toolbarFolderId);
PlacesUtils.toolbarFolderId,
PlacesUtils.mobileFolderId);
}
return this._folders;
},
@ -943,7 +944,8 @@ var PlacesQueryBuilder = {
filterCollection = "bookmarks";
folders.push(PlacesUtils.bookmarksMenuFolderId,
PlacesUtils.toolbarFolderId,
PlacesUtils.unfiledBookmarksFolderId);
PlacesUtils.unfiledBookmarksFolderId,
PlacesUtils.mobileFolderId);
break;
case "downloads":
filterCollection = "downloads";

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

@ -52,11 +52,11 @@
<!-- Update -->
<groupbox id="updateApp" data-category="paneAdvanced" hidden="true">
<caption><label>&updateApplication.label;</label></caption>
#ifdef MOZ_UPDATER
<description>&updateApplication.description;</description>
<hbox align="start">
<vbox flex="1">
#ifdef MOZ_UPDATER
<radiogroup id="updateRadioGroup" align="start">
<radiogroup id="updateRadioGroup">
<radio id="autoDesktop"
value="auto"
label="&updateAuto2.label;"
@ -68,19 +68,7 @@
label="&updateManual2.label;"
accesskey="&updateManual2.accesskey;"/>
</radiogroup>
#ifdef MOZ_MAINTENANCE_SERVICE
<checkbox id="useService"
label="&useService.label;"
accesskey="&useService.accesskey;"
preference="app.update.service.enabled"/>
#endif
#endif
<checkbox id="enableSearchUpdate"
label="&enableSearchUpdate2.label;"
accesskey="&enableSearchUpdate2.accesskey;"
preference="browser.search.update"/>
</vbox>
#ifdef MOZ_UPDATER
<spacer flex="1"/>
<vbox>
<button id="showUpdateHistory"
@ -89,6 +77,16 @@
accesskey="&updateHistory2.accesskey;"
preference="app.update.disable_button.showUpdateHistory"/>
</vbox>
#endif
</hbox>
#ifdef MOZ_MAINTENANCE_SERVICE
<checkbox id="useService"
label="&useService.label;"
accesskey="&useService.accesskey;"
preference="app.update.service.enabled"/>
#endif
#endif
<checkbox id="enableSearchUpdate"
label="&enableSearchUpdate2.label;"
accesskey="&enableSearchUpdate2.accesskey;"
preference="browser.search.update"/>
</groupbox>

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

@ -100,12 +100,10 @@
#endif
/>
</hbox>
<hbox>
<radio id="alwaysAsk"
value="false"
label="&alwaysAskWhere.label;"
accesskey="&alwaysAskWhere.accesskey;"/>
</hbox>
<radio id="alwaysAsk"
value="false"
label="&alwaysAskWhere.label;"
accesskey="&alwaysAskWhere.accesskey;"/>
</radiogroup>
</groupbox>

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

@ -65,6 +65,8 @@ var gMainPane = {
document.getElementById("engineList").view = gEngineView;
this.buildDefaultEngineDropDown();
this.buildContentProcessCountMenuList();
let addEnginesLink = document.getElementById("addEngines");
let searchEnginesURL = Services.wm.getMostRecentWindow("navigator:browser")
.BrowserSearch.searchEnginesURL;
@ -91,6 +93,25 @@ var gMainPane = {
});
this.updateSuggestsCheckbox();
let processCountPref =
document.getElementById("dom.ipc.processCount");
processCountPref.addEventListener("change", () => {
this.updateDefaultPerformanceSettingsPref();
});
let accelerationPref =
document.getElementById("layers.acceleration.disabled");
accelerationPref.addEventListener("change", () => {
this.updateDefaultPerformanceSettingsPref();
});
this.updateDefaultPerformanceSettingsPref();
let defaultPerformancePref =
document.getElementById("browser.preferences.defaultPerformanceSettings.enabled");
defaultPerformancePref.addEventListener("change", () => {
this.updatePerformanceSettingsBox();
});
this.updatePerformanceSettingsBox();
// set up the "use current page" label-changing listener
this._updateUseCurrentButton();
window.addEventListener("focus", this._updateUseCurrentButton.bind(this));
@ -792,6 +813,43 @@ var gMainPane = {
permanentPBLabel.hidden = urlbarSuggests.hidden || !permanentPB;
},
updateDefaultPerformanceSettingsPref() {
let defaultPerformancePref =
document.getElementById("browser.preferences.defaultPerformanceSettings.enabled");
let processCountPref = document.getElementById("dom.ipc.processCount");
let accelerationPref = document.getElementById("layers.acceleration.disabled");
if (processCountPref.value != processCountPref.defaultValue ||
accelerationPref.value != accelerationPref.defaultValue) {
defaultPerformancePref.value = false;
}
},
updatePerformanceSettingsBox() {
let defaultPerformancePref =
document.getElementById("browser.preferences.defaultPerformanceSettings.enabled");
let performanceSettings = document.getElementById("performanceSettings");
if (defaultPerformancePref.value) {
let processCountPref = document.getElementById("dom.ipc.processCount");
let accelerationPref = document.getElementById("layers.acceleration.disabled");
processCountPref.value = processCountPref.defaultValue;
accelerationPref.value = accelerationPref.defaultValue;
performanceSettings.hidden = true;
} else {
performanceSettings.hidden = false;
}
},
buildContentProcessCountMenuList() {
let processCountPref = document.getElementById("dom.ipc.processCount");
let bundlePreferences = document.getElementById("bundlePreferences");
let label = bundlePreferences.getFormattedString("defaultContentProcessCount",
[processCountPref.defaultValue]);
let contentProcessCount =
document.querySelector(`#contentProcessCount > menupopup >
menuitem[value="${processCountPref.defaultValue}"]`);
contentProcessCount.label = label;
},
buildDefaultEngineDropDown() {
// This is called each time something affects the list of engines.
let list = document.getElementById("defaultEngine");

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

@ -12,6 +12,8 @@
<stringbundle id="engineManagerBundle" src="chrome://browser/locale/engineManager.properties"/>
<stringbundle id="bundlePreferences" src="chrome://browser/locale/preferences.properties"/>
<preferences id="mainPreferences" hidden="true" data-category="paneGeneral">
#ifdef E10S_TESTING_ONLY
@ -177,10 +179,6 @@
<preference id="general.smoothScroll"
name="general.smoothScroll"
type="bool"/>
<preference id="layers.acceleration.disabled"
name="layers.acceleration.disabled"
type="bool"
inverted="true"/>
#ifdef XP_WIN
<preference id="gfx.direct2d.disabled"
name="gfx.direct2d.disabled"
@ -196,6 +194,19 @@
name="toolkit.telemetry.enabled"
type="bool"/>
#endif
<preference id="browser.preferences.defaultPerformanceSettings.enabled"
name="browser.preferences.defaultPerformanceSettings.enabled"
type="bool"/>
<preference id="dom.ipc.processCount"
name="dom.ipc.processCount"
type="int"/>
<preference id="layers.acceleration.disabled"
name="layers.acceleration.disabled"
type="bool"
inverted="true"/>
</preferences>
<hbox id="header-general"
@ -232,10 +243,8 @@
#ifdef HAVE_SHELL_SERVICE
<vbox id="defaultBrowserBox">
<hbox align="center">
<checkbox id="alwaysCheckDefault" preference="browser.shell.checkDefaultBrowser"
label="&alwaysCheckDefault2.label;" accesskey="&alwaysCheckDefault2.accesskey;"/>
</hbox>
<checkbox id="alwaysCheckDefault" preference="browser.shell.checkDefaultBrowser"
label="&alwaysCheckDefault2.label;" accesskey="&alwaysCheckDefault2.accesskey;"/>
<deck id="setDefaultPane">
<hbox align="center" class="indent">
<label id="isNotDefaultLabel" flex="1">&isNotDefault.label;</label>
@ -318,12 +327,14 @@
</groupbox>
<!-- Default Search Engine -->
<groupbox id="defaultEngineGroup" align="start" data-category="paneGeneral" data-subcategory="search">
<groupbox id="defaultEngineGroup" data-category="paneGeneral" data-subcategory="search">
<caption label="&defaultSearchEngine.label;"/>
<label>&chooseYourDefaultSearchEngine.label;</label>
<menulist id="defaultEngine">
<menupopup/>
</menulist>
<box align="start">
<menulist id="defaultEngine">
<menupopup/>
</menulist>
</box>
<checkbox id="suggestionsInSearchFieldsCheckbox"
label="&provideSearchSuggestions.label;"
accesskey="&provideSearchSuggestions.accesskey;"
@ -375,7 +386,7 @@
<!-- Tab preferences -->
<groupbox data-category="paneGeneral"
hidden="true" align="start">
hidden="true">
<caption><label>&tabsGroup.label;</label></caption>
<checkbox id="ctrlTabRecentlyUsedOrder" label="&ctrlTabRecentlyUsedOrder.label;"
@ -408,7 +419,7 @@
</groupbox>
<!-- Accessibility -->
<groupbox data-category="paneGeneral" id="accessibilityGroup" align="start">
<groupbox data-category="paneGeneral" id="accessibilityGroup">
<caption><label>&accessibility.label;</label></caption>
#ifdef XP_WIN
@ -464,14 +475,12 @@
label="&translateExceptions.label;"
accesskey="&translateExceptions.accesskey;"/>
</hbox>
<hbox>
<checkbox id="checkSpelling"
label="&checkUserSpelling.label;"
accesskey="&checkUserSpelling.accesskey;"
onsyncfrompreference="return gMainPane.readCheckSpelling();"
onsynctopreference="return gMainPane.writeCheckSpelling();"
preference="layout.spellcheckDefault"/>
</hbox>
<checkbox id="checkSpelling"
label="&checkUserSpelling.label;"
accesskey="&checkUserSpelling.accesskey;"
onsyncfrompreference="return gMainPane.readCheckSpelling();"
onsynctopreference="return gMainPane.writeCheckSpelling();"
preference="layout.spellcheckDefault"/>
</groupbox>
@ -539,7 +548,7 @@
</groupbox>
<!-- Browsing -->
<groupbox id="browsingGroup" align="start" data-category="paneGeneral">
<groupbox id="browsingGroup" data-category="paneGeneral">
<caption><label>&browsing.label;</label></caption>
<checkbox id="useAutoScroll"
@ -550,8 +559,37 @@
label="&useSmoothScrolling.label;"
accesskey="&useSmoothScrolling.accesskey;"
preference="general.smoothScroll"/>
<checkbox id="allowHWAccel"
label="&allowHWAccel.label;"
accesskey="&allowHWAccel.accesskey;"
preference="layers.acceleration.disabled"/>
</groupbox>
<!-- Performance -->
<groupbox id="performanceGroup" data-category="paneGeneral" hidden="true">
<caption><label>&performance.label;</label></caption>
<checkbox id="useRecommendedPerformanceSettings"
label="&useRecommendedPerformanceSettings.label;"
accesskey="&useRecommendedPerformanceSettings.accesskey;"
preference="browser.preferences.defaultPerformanceSettings.enabled"/>
<description class="indent">&useRecommendedPerformanceSettings.description;</description>
<vbox id="performanceSettings" class="indent" hidden="true">
<checkbox id="allowHWAccel"
label="&allowHWAccel.label;"
accesskey="&allowHWAccel.accesskey;"
preference="layers.acceleration.disabled"/>
<hbox align="center">
<label id="limitContentProcess" accesskey="&limitContentProcess.accesskey;" control="contentProcessCount">&limitContentProcess.label;</label>
<menulist id="contentProcessCount" preference="dom.ipc.processCount">
<menupopup>
<menuitem label="1" value="1"/>
<menuitem label="2" value="2"/>
<menuitem label="3" value="3"/>
<menuitem label="4" value="4"/>
<menuitem label="5" value="5"/>
<menuitem label="6" value="6"/>
<menuitem label="7" value="7"/>
</menupopup>
</menulist>
</hbox>
<description>&limitContentProcess.description;</description>
</vbox>
</groupbox>

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

@ -239,9 +239,9 @@ var gPrivacyPane = {
gPrivacyPane.toggleDoNotDisturbNotifications);
if (AlertsServiceDND) {
let notificationsDoNotDisturbRow =
document.getElementById("notificationsDoNotDisturbRow");
notificationsDoNotDisturbRow.removeAttribute("hidden");
let notificationsDoNotDisturbBox =
document.getElementById("notificationsDoNotDisturbBox");
notificationsDoNotDisturbBox.removeAttribute("hidden");
if (AlertsServiceDND.manualDoNotDisturb) {
let notificationsDoNotDisturb =
document.getElementById("notificationsDoNotDisturb");

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

@ -225,30 +225,26 @@
<vbox id="historyCustomPane">
<separator class="thin"/>
<vbox>
<vbox align="start">
<checkbox id="privateBrowsingAutoStart"
label="&privateBrowsingPermanent2.label;"
accesskey="&privateBrowsingPermanent2.accesskey;"
preference="browser.privatebrowsing.autostart"/>
</vbox>
<checkbox id="privateBrowsingAutoStart"
label="&privateBrowsingPermanent2.label;"
accesskey="&privateBrowsingPermanent2.accesskey;"
preference="browser.privatebrowsing.autostart"/>
<vbox class="indent">
<vbox align="start">
<checkbox id="rememberHistory"
label="&rememberHistory2.label;"
accesskey="&rememberHistory2.accesskey;"
preference="places.history.enabled"/>
<checkbox id="rememberForms"
label="&rememberSearchForm.label;"
accesskey="&rememberSearchForm.accesskey;"
preference="browser.formfill.enable"/>
</vbox>
<checkbox id="rememberHistory"
label="&rememberHistory2.label;"
accesskey="&rememberHistory2.accesskey;"
preference="places.history.enabled"/>
<checkbox id="rememberForms"
label="&rememberSearchForm.label;"
accesskey="&rememberSearchForm.accesskey;"
preference="browser.formfill.enable"/>
<hbox id="cookiesBox">
<checkbox id="acceptCookies" label="&acceptCookies.label;"
preference="network.cookie.cookieBehavior"
accesskey="&acceptCookies.accesskey;"
onsyncfrompreference="return gPrivacyPane.readAcceptCookies();"
onsynctopreference="return gPrivacyPane.writeAcceptCookies();"/>
<spacer flex="1" />
onsynctopreference="return gPrivacyPane.writeAcceptCookies();"
flex="1" />
<button id="cookieExceptions"
class="accessory-button"
label="&cookieExceptions.label;" accesskey="&cookieExceptions.accesskey;"
@ -293,8 +289,8 @@
<checkbox id="alwaysClear"
preference="privacy.sanitize.sanitizeOnShutdown"
label="&clearOnClose.label;"
accesskey="&clearOnClose.accesskey;"/>
<spacer flex="1"/>
accesskey="&clearOnClose.accesskey;"
flex="1" />
<button id="clearDataSettings"
class="accessory-button"
label="&clearOnCloseSettings.label;"
@ -314,8 +310,8 @@
<checkbox id="savePasswords"
label="&rememberLogins1.label;" accesskey="&rememberLogins1.accesskey;"
preference="signon.rememberSignons"
onsyncfrompreference="return gPrivacyPane.readSavePasswords();"/>
<spacer flex="1"/>
onsyncfrompreference="return gPrivacyPane.readSavePasswords();"
flex="1" />
<button id="passwordExceptions"
class="accessory-button"
label="&passwordExceptions.label;"
@ -332,8 +328,8 @@
<hbox id="masterPasswordBox">
<checkbox id="useMasterPassword"
label="&useMasterPassword.label;"
accesskey="&useMasterPassword.accesskey;"/>
<spacer flex="1"/>
accesskey="&useMasterPassword.accesskey;"
flex="1" />
</hbox>
<button id="changeMasterPassword"
class="accessory-button"
@ -366,17 +362,6 @@
control="trackingProtectionRadioGroup">
&trackingProtection.radioGroupLabel;
</description>
<radiogroup id="trackingProtectionRadioGroup" aria-labelledby="trackingProtectionDesc">
<radio value="always"
label="&trackingProtectionAlways.label;"
accesskey="&trackingProtectionAlways.accesskey;"/>
<radio value="private"
label="&trackingProtectionPrivate.label;"
accesskey="&trackingProtectionPrivate.accesskey;"/>
<radio value="never"
label="&trackingProtectionNever.label;"
accesskey="&trackingProtectionNever.accesskey;"/>
</radiogroup>
</vbox>
<spacer flex="1"/>
<vbox id="trackingProtectionAdvancedSettings">
@ -392,6 +377,17 @@
preference="pref.privacy.disable_button.change_blocklist"/>
</vbox>
</hbox>
<radiogroup id="trackingProtectionRadioGroup" aria-labelledby="trackingProtectionDesc">
<radio value="always"
label="&trackingProtectionAlways.label;"
accesskey="&trackingProtectionAlways.accesskey;"/>
<radio value="private"
label="&trackingProtectionPrivate.label;"
accesskey="&trackingProtectionPrivate.accesskey;"/>
<radio value="never"
label="&trackingProtectionNever.label;"
accesskey="&trackingProtectionNever.accesskey;"/>
</radiogroup>
</vbox>
<vbox id="trackingprotectionpbmbox">
<caption><label>&tracking.label;</label></caption>
@ -419,28 +415,17 @@
<!-- Pop-ups -->
<groupbox id="miscGroup" data-category="panePrivacy" hidden="true">
<caption><label>&popups.label;</label></caption>
<grid id="contentGrid">
<columns>
<column flex="1"/>
<column/>
</columns>
<rows id="contentRows-1">
<row id="popupPolicyRow">
<vbox align="start">
<checkbox id="popupPolicy" preference="dom.disable_open_during_load"
label="&blockPopups.label;" accesskey="&blockPopups.accesskey;"
onsyncfrompreference="return gPrivacyPane.updateButtons('popupPolicyButton',
'dom.disable_open_during_load');"/>
</vbox>
<hbox pack="end">
<button id="popupPolicyButton"
class="accessory-button"
label="&popupExceptions.label;"
accesskey="&popupExceptions.accesskey;"/>
</hbox>
</row>
</rows>
</grid>
<hbox align="start">
<checkbox id="popupPolicy" preference="dom.disable_open_during_load"
label="&blockPopups.label;" accesskey="&blockPopups.accesskey;"
onsyncfrompreference="return gPrivacyPane.updateButtons('popupPolicyButton',
'dom.disable_open_during_load');"
flex="1" />
<button id="popupPolicyButton"
class="accessory-button"
label="&popupExceptions.label;"
accesskey="&popupExceptions.accesskey;"/>
</hbox>
</groupbox>
<!-- Notifications -->
@ -453,7 +438,7 @@
</columns>
<rows>
<row id="notificationsPolicyRow" align="center">
<hbox align="start">
<hbox flex="1">
<label id="notificationsPolicy">&notificationsPolicyDesc3.label;</label>
<label id="notificationsPolicyLearnMore"
class="learnMore text-link"
@ -466,17 +451,15 @@
accesskey="&notificationsPolicyButton.accesskey;"/>
</hbox>
</row>
<row id="notificationsDoNotDisturbRow" hidden="true">
<vbox align="start">
<checkbox id="notificationsDoNotDisturb" label="&notificationsDoNotDisturb.label;"
accesskey="&notificationsDoNotDisturb.accesskey;"/>
<label id="notificationsDoNotDisturbDetails"
class="indent"
value="&notificationsDoNotDisturbDetails.value;"/>
</vbox>
</row>
</rows>
</grid>
<vbox id="notificationsDoNotDisturbBox" hidden="true">
<checkbox id="notificationsDoNotDisturb" label="&notificationsDoNotDisturb.label;"
accesskey="&notificationsDoNotDisturb.accesskey;"/>
<label id="notificationsDoNotDisturbDetails"
class="indent"
value="&notificationsDoNotDisturbDetails.value;"/>
</vbox>
</groupbox>
<!-- Location Bar -->
@ -508,8 +491,8 @@
label="&warnOnAddonInstall.label;"
accesskey="&warnOnAddonInstall.accesskey;"
preference="xpinstall.whitelist.required"
onsyncfrompreference="return gPrivacyPane.readWarnAddonInstall();"/>
<spacer flex="1"/>
onsyncfrompreference="return gPrivacyPane.readWarnAddonInstall();"
flex="1" />
<button id="addonExceptions"
class="accessory-button"
label="&addonExceptions.label;"
@ -517,18 +500,16 @@
</hbox>
<separator class="thin"/>
<vbox align="start">
<checkbox id="enableSafeBrowsing"
label="&enableSafeBrowsing.label;"
accesskey="&enableSafeBrowsing.accesskey;" />
<vbox class="indent">
<checkbox id="blockDownloads"
label="&blockDownloads.label;"
accesskey="&blockDownloads.accesskey;" />
<checkbox id="blockUncommonUnwanted"
label="&blockUncommonAndUnwanted.label;"
accesskey="&blockUncommonAndUnwanted.accesskey;" />
</vbox>
<checkbox id="enableSafeBrowsing"
label="&enableSafeBrowsing.label;"
accesskey="&enableSafeBrowsing.accesskey;" />
<vbox class="indent">
<checkbox id="blockDownloads"
label="&blockDownloads.label;"
accesskey="&blockDownloads.accesskey;" />
<checkbox id="blockUncommonUnwanted"
label="&blockUncommonAndUnwanted.label;"
accesskey="&blockUncommonAndUnwanted.accesskey;" />
</vbox>
</groupbox>
@ -557,11 +538,10 @@
<checkbox id="enableOCSP"
label="&enableOCSP.label;"
accesskey="&enableOCSP.accesskey;"
flex="1"
onsyncfrompreference="return gPrivacyPane.readEnableOCSP();"
onsynctopreference="return gPrivacyPane.writeEnableOCSP();"
preference="security.OCSP.enabled"/>
<spacer flex="1"/>
preference="security.OCSP.enabled"
flex="1" />
<vbox>
<button id="viewCertificatesButton"
class="accessory-button"
@ -644,13 +624,11 @@
icon="clear"
label="&clearCacheNow.label;" accesskey="&clearCacheNow.accesskey;"/>
</hbox>
<hbox>
<checkbox preference="browser.cache.disk.smart_size.enabled"
id="allowSmartSize"
onsyncfrompreference="return gPrivacyPane.readSmartSizeEnabled();"
label="&overrideSmartCacheSize.label;"
accesskey="&overrideSmartCacheSize.accesskey;"/>
</hbox>
<checkbox preference="browser.cache.disk.smart_size.enabled"
id="allowSmartSize"
onsyncfrompreference="return gPrivacyPane.readSmartSizeEnabled();"
label="&overrideSmartCacheSize.label;"
accesskey="&overrideSmartCacheSize.accesskey;"/>
<hbox align="center" class="indent">
<label id="useCacheBefore" control="cacheSize"
accesskey="&limitCacheSizeBefore.accesskey;">
@ -677,8 +655,8 @@
<checkbox id="offlineNotify"
label="&offlineStorageNotify.label;" accesskey="&offlineStorageNotify.accesskey;"
preference="browser.offline-apps.notify"
onsyncfrompreference="return gPrivacyPane.readOfflineNotify();"/>
<spacer flex="1"/>
onsyncfrompreference="return gPrivacyPane.readOfflineNotify();"
flex="1" />
<button id="offlineNotifyExceptions"
class="accessory-button"
label="&offlineStorageNotifyExceptions.label;"

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

@ -31,6 +31,7 @@ skip-if = true || !healthreport # Bug 1185403 for the "true"
[browser_layersacceleration.js]
[browser_masterpassword.js]
[browser_notifications_do_not_disturb.js]
[browser_performance.js]
[browser_permissions_urlFieldHidden.js]
[browser_proxy_backup.js]
[browser_privacypane_1.js]

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

@ -12,8 +12,8 @@ add_task(function*() {
is(prefs.selectedPane, "panePrivacy", "Privacy pane was selected");
let doc = gBrowser.contentDocument;
let notificationsDoNotDisturbRow = doc.getElementById("notificationsDoNotDisturbRow");
if (notificationsDoNotDisturbRow.hidden) {
let notificationsDoNotDisturbBox = doc.getElementById("notificationsDoNotDisturbBox");
if (notificationsDoNotDisturbBox.hidden) {
todo(false, "Do not disturb is not available on this platform");
return;
}

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

@ -0,0 +1,116 @@
SpecialPowers.pushPrefEnv({set: [
["browser.preferences.defaultPerformanceSettings.enabled", true],
["dom.ipc.processCount", 4],
["layers.acceleration.disabled", false],
]});
add_task(function*() {
let prefs = yield openPreferencesViaOpenPreferencesAPI("paneGeneral", {leaveOpen: true});
is(prefs.selectedPane, "paneGeneral", "General pane was selected");
let doc = gBrowser.contentDocument;
let useRecommendedPerformanceSettings = doc.querySelector("#useRecommendedPerformanceSettings");
is(Services.prefs.getBoolPref("browser.preferences.defaultPerformanceSettings.enabled"), true,
"pref value should be true before clicking on checkbox");
ok(useRecommendedPerformanceSettings.checked, "checkbox should be checked before clicking on checkbox");
useRecommendedPerformanceSettings.click();
let performanceSettings = doc.querySelector("#performanceSettings");
is(performanceSettings.hidden, false, "performance settings section is shown");
is(Services.prefs.getBoolPref("browser.preferences.defaultPerformanceSettings.enabled"), false,
"pref value should be false after clicking on checkbox");
ok(!useRecommendedPerformanceSettings.checked, "checkbox should not be checked after clicking on checkbox");
let allowHWAccel = doc.querySelector("#allowHWAccel");
is(Services.prefs.getBoolPref("layers.acceleration.disabled"), false,
"pref value should be false before clicking on checkbox");
ok(allowHWAccel.checked, "checkbox should be checked");
let contentProcessCount = doc.querySelector("#contentProcessCount");
is(Services.prefs.getIntPref("dom.ipc.processCount"), 4, "default pref value should be default value");
is(contentProcessCount.selectedItem.value, 4, "selected item should be the default one");
allowHWAccel.click();
is(Services.prefs.getBoolPref("layers.acceleration.disabled"), true,
"pref value should be true after clicking on checkbox");
ok(!allowHWAccel.checked, "checkbox should not be checked");
contentProcessCount.value = 7;
contentProcessCount.doCommand();
is(Services.prefs.getIntPref("dom.ipc.processCount"), 7, "pref value should be 7");
is(contentProcessCount.selectedItem.value, 7, "selected item should be 7");
allowHWAccel.click();
is(Services.prefs.getBoolPref("layers.acceleration.disabled"), false,
"pref value should be false after clicking on checkbox");
ok(allowHWAccel.checked, "checkbox should not be checked");
contentProcessCount.value = 4;
contentProcessCount.doCommand();
is(Services.prefs.getIntPref("dom.ipc.processCount"), 4, "pref value should be default value");
is(contentProcessCount.selectedItem.value, 4, "selected item should be default one");
is(performanceSettings.hidden, false, "performance settings section should be still shown");
Services.prefs.setBoolPref("browser.preferences.defaultPerformanceSettings.enabled", true);
yield BrowserTestUtils.removeTab(gBrowser.selectedTab);
});
add_task(function*() {
let prefs = yield openPreferencesViaOpenPreferencesAPI("paneGeneral", {leaveOpen: true});
is(prefs.selectedPane, "paneGeneral", "General pane was selected");
let doc = gBrowser.contentDocument;
let performanceSettings = doc.querySelector("#performanceSettings");
is(performanceSettings.hidden, true, "performance settings section should not be shown");
Services.prefs.setBoolPref("browser.preferences.defaultPerformanceSettings.enabled", false);
is(performanceSettings.hidden, false, "performance settings section should be shown");
Services.prefs.setBoolPref("browser.preferences.defaultPerformanceSettings.enabled", true);
yield BrowserTestUtils.removeTab(gBrowser.selectedTab);
});
add_task(function*() {
Services.prefs.setIntPref("dom.ipc.processCount", 7);
let prefs = yield openPreferencesViaOpenPreferencesAPI("paneGeneral", {leaveOpen: true});
is(prefs.selectedPane, "paneGeneral", "General pane was selected");
let doc = gBrowser.contentDocument;
let performanceSettings = doc.querySelector("#performanceSettings");
is(performanceSettings.hidden, false, "performance settings section should be shown");
let contentProcessCount = doc.querySelector("#contentProcessCount");
is(Services.prefs.getIntPref("dom.ipc.processCount"), 7, "pref value should be 7");
is(contentProcessCount.selectedItem.value, 7, "selected item should be 7");
Services.prefs.setBoolPref("browser.preferences.defaultPerformanceSettings.enabled", true);
yield BrowserTestUtils.removeTab(gBrowser.selectedTab);
});
add_task(function*() {
Services.prefs.setBoolPref("layers.acceleration.disabled", true);
let prefs = yield openPreferencesViaOpenPreferencesAPI("paneGeneral", {leaveOpen: true});
is(prefs.selectedPane, "paneGeneral", "General pane was selected");
let doc = gBrowser.contentDocument;
let performanceSettings = doc.querySelector("#performanceSettings");
is(performanceSettings.hidden, false, "performance settings section should be shown");
let allowHWAccel = doc.querySelector("#allowHWAccel");
is(Services.prefs.getBoolPref("layers.acceleration.disabled"), true,
"pref value is false");
ok(!allowHWAccel.checked, "checkbox should not be checked");
Services.prefs.setBoolPref("browser.preferences.defaultPerformanceSettings.enabled", true);
yield BrowserTestUtils.removeTab(gBrowser.selectedTab);
});

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

@ -109,6 +109,7 @@ add_task(function*() {
|| child.id == "languagesGroup"
|| child.id == "fontsGroup"
|| child.id == "browsingGroup"
|| child.id == "performanceGroup"
|| child.id == "header-general") {
is_element_visible(child, "Should be in general tab");
} else if (child.id) {

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

@ -16,9 +16,9 @@
"unpack": true
},
{
"version": "rustc 1.16.0 (30cf806ef 2017-03-10) repack with cargo 0.19.0-nightly (8326a3683 2017-04-19)",
"size": 112206132,
"digest": "9ec214f971676369be07b13f5638f9ae1fa12400488d898193fb7a6adbb73ecc120337b569b200bc07630ef9d661a75c2710537422b57eebd9053e60bdc771c5",
"version": "rustc 1.17.0 (56124baa9 2017-04-24) repack with cargo 0.19.0-beta.1 (03efb7fc8 2017-04-23)",
"size": 121925324,
"digest": "218ec1fd0a00b50fc3f0ce497d2bb9eb2230c1998a1c22cfe8f61ac44d9b57a081e12e8cd946e9d960a1683ed50d625d62f35f2db6fa6aab82454f96f32cd7b2",
"algorithm": "sha512",
"filename": "rustc.tar.xz",
"unpack": true

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

@ -16,9 +16,9 @@
"unpack": true
},
{
"version": "rustc 1.16.0 (30cf806ef 2017-03-10) repack with cargo 0.19.0-nightly (8326a3683 2017-04-19)",
"size": 112206132,
"digest": "9ec214f971676369be07b13f5638f9ae1fa12400488d898193fb7a6adbb73ecc120337b569b200bc07630ef9d661a75c2710537422b57eebd9053e60bdc771c5",
"version": "rustc 1.17.0 (56124baa9 2017-04-24) repack with cargo 0.19.0-beta.1 (03efb7fc8 2017-04-23)",
"size": 121925324,
"digest": "218ec1fd0a00b50fc3f0ce497d2bb9eb2230c1998a1c22cfe8f61ac44d9b57a081e12e8cd946e9d960a1683ed50d625d62f35f2db6fa6aab82454f96f32cd7b2",
"algorithm": "sha512",
"filename": "rustc.tar.xz",
"unpack": true

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

@ -16,9 +16,9 @@
"unpack": true
},
{
"version": "rustc 1.16.0 (30cf806ef 2017-03-10) repack with cargo 0.19.0-nightly (8326a3683 2017-04-19)",
"size": 112206132,
"digest": "9ec214f971676369be07b13f5638f9ae1fa12400488d898193fb7a6adbb73ecc120337b569b200bc07630ef9d661a75c2710537422b57eebd9053e60bdc771c5",
"version": "rustc 1.17.0 (56124baa9 2017-04-24) repack with cargo 0.19.0-beta.1 (03efb7fc8 2017-04-23)",
"size": 121925324,
"digest": "218ec1fd0a00b50fc3f0ce497d2bb9eb2230c1998a1c22cfe8f61ac44d9b57a081e12e8cd946e9d960a1683ed50d625d62f35f2db6fa6aab82454f96f32cd7b2",
"algorithm": "sha512",
"filename": "rustc.tar.xz",
"unpack": true

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

@ -16,9 +16,9 @@
"unpack": true
},
{
"version": "rustc 1.16.0 (30cf806ef 2017-03-10) repack with cargo 0.19.0-nightly (8326a3683 2017-04-19)",
"size": 112206132,
"digest": "9ec214f971676369be07b13f5638f9ae1fa12400488d898193fb7a6adbb73ecc120337b569b200bc07630ef9d661a75c2710537422b57eebd9053e60bdc771c5",
"version": "rustc 1.17.0 (56124baa9 2017-04-24) repack with cargo 0.19.0-beta.1 (03efb7fc8 2017-04-23)",
"size": 121925324,
"digest": "218ec1fd0a00b50fc3f0ce497d2bb9eb2230c1998a1c22cfe8f61ac44d9b57a081e12e8cd946e9d960a1683ed50d625d62f35f2db6fa6aab82454f96f32cd7b2",
"algorithm": "sha512",
"filename": "rustc.tar.xz",
"unpack": true

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

@ -24,9 +24,9 @@
"size": 12072532
},
{
"version": "rustc 1.16.0 (30cf806ef 2017-03-10) repack with cargo 0.19.0-nightly (8326a3683 2017-04-19)",
"size": 112206132,
"digest": "9ec214f971676369be07b13f5638f9ae1fa12400488d898193fb7a6adbb73ecc120337b569b200bc07630ef9d661a75c2710537422b57eebd9053e60bdc771c5",
"version": "rustc 1.17.0 (56124baa9 2017-04-24) repack with cargo 0.19.0-beta.1 (03efb7fc8 2017-04-23)",
"size": 121925324,
"digest": "218ec1fd0a00b50fc3f0ce497d2bb9eb2230c1998a1c22cfe8f61ac44d9b57a081e12e8cd946e9d960a1683ed50d625d62f35f2db6fa6aab82454f96f32cd7b2",
"algorithm": "sha512",
"filename": "rustc.tar.xz",
"unpack": true

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

@ -16,9 +16,9 @@
"unpack": true
},
{
"version": "rustc 1.16.0 (30cf806ef 2017-03-10) repack with cargo 0.19.0-nightly (8326a3683 2017-04-19)",
"size": 112206132,
"digest": "9ec214f971676369be07b13f5638f9ae1fa12400488d898193fb7a6adbb73ecc120337b569b200bc07630ef9d661a75c2710537422b57eebd9053e60bdc771c5",
"version": "rustc 1.17.0 (56124baa9 2017-04-24) repack with cargo 0.19.0-beta.1 (03efb7fc8 2017-04-23)",
"size": 121925324,
"digest": "218ec1fd0a00b50fc3f0ce497d2bb9eb2230c1998a1c22cfe8f61ac44d9b57a081e12e8cd946e9d960a1683ed50d625d62f35f2db6fa6aab82454f96f32cd7b2",
"algorithm": "sha512",
"filename": "rustc.tar.xz",
"unpack": true

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

@ -16,9 +16,9 @@
"unpack": true
},
{
"version": "rustc 1.16.0 (30cf806ef 2017-03-10) repack with cargo 0.19.0-nightly (8326a3683 2017-04-19)",
"size": 112206132,
"digest": "9ec214f971676369be07b13f5638f9ae1fa12400488d898193fb7a6adbb73ecc120337b569b200bc07630ef9d661a75c2710537422b57eebd9053e60bdc771c5",
"version": "rustc 1.17.0 (56124baa9 2017-04-24) repack with cargo 0.19.0-beta.1 (03efb7fc8 2017-04-23)",
"size": 121925324,
"digest": "218ec1fd0a00b50fc3f0ce497d2bb9eb2230c1998a1c22cfe8f61ac44d9b57a081e12e8cd946e9d960a1683ed50d625d62f35f2db6fa6aab82454f96f32cd7b2",
"algorithm": "sha512",
"filename": "rustc.tar.xz",
"unpack": true

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

@ -8,9 +8,9 @@
"unpack": true
},
{
"version": "rustc 1.16.0 (30cf806ef 2017-03-10) repack with cargo 0.19.0-nightly (8326a3683 2017-04-19)",
"size": 80381089,
"digest": "01bc5c4d25ffd16f51643d36449ca469eccc362b8315945edd9b7e174462659a3d5d4bd5d2738f449557254ba930ca0d70d22f8717b51ba36af68193bd3c39f7",
"version": "rustc 1.17.0 (56124baa9 2017-04-24) repack with cargo 0.19.0-beta.1 (03efb7fc8 2017-04-23)",
"size": 81913425,
"digest": "41a9dc3f1c0df56f125a4f16cac3635bd3cc2af7167388f54eb4346a599cd8be875475a87a8dd1720d52281ecd361a1050d9523f052f424bce686ba061af6d6c",
"algorithm": "sha512",
"filename": "rustc.tar.bz2",
"unpack": true

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

@ -42,9 +42,9 @@
"filename": "dmg.tar.xz"
},
{
"version": "rustc 1.16.0 (30cf806ef 2017-03-10) repack with cargo 0.19.0-nightly (8326a3683 2017-04-19)",
"size": 107393796,
"digest": "90dca0af2ddd14b8dc4414c8ece52498f8f96e98bb0e4c228e2af27d4f8bd7689dda5160a6994e514e516cb4851f26d94b1bf50456c4dd5c485eaa8b02ba9f95",
"version": "rustc 1.17.0 (56124baa9 2017-04-24) repack with cargo 0.19.0-beta.1 (03efb7fc8 2017-04-23)",
"size": 116855168,
"digest": "89e414870a398369c745e38e5ce757b98c8f0bbde0ea92ca9fa0a8a72d970e8575fe5493128c1b6b1134ed336c1a7265b1d1ea77fe3673e73a87d0b774f10fac",
"algorithm": "sha512",
"filename": "rustc.tar.xz",
"unpack": true

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

@ -8,9 +8,9 @@
"unpack": true
},
{
"version": "rustc 1.16.0 (30cf806ef 2017-03-10) repack with cargo 0.19.0-nightly (8326a3683 2017-04-19)",
"size": 80381089,
"digest": "01bc5c4d25ffd16f51643d36449ca469eccc362b8315945edd9b7e174462659a3d5d4bd5d2738f449557254ba930ca0d70d22f8717b51ba36af68193bd3c39f7",
"version": "rustc 1.17.0 (56124baa9 2017-04-24) repack with cargo 0.19.0-beta.1 (03efb7fc8 2017-04-23)",
"size": 81913425,
"digest": "41a9dc3f1c0df56f125a4f16cac3635bd3cc2af7167388f54eb4346a599cd8be875475a87a8dd1720d52281ecd361a1050d9523f052f424bce686ba061af6d6c",
"algorithm": "sha512",
"filename": "rustc.tar.bz2",
"unpack": true

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

@ -6,9 +6,9 @@
"filename": "mozmake.exe"
},
{
"version": "rustc 1.16.0 (30cf806ef 2017-03-10) repack with cargo 0.19.0-nightly (8326a3683 2017-04-19)",
"size": 68401632,
"digest": "d55a50d61f3dbd34e68daf985c95773f6f66fa9b88364eefde03d2b009f2f4e9df7e7e72006347bb4ba0f65ff5190b4b6367fde01e79827e10534cd03fe720df",
"version": "rustc 1.17.0 (56124baa9 2017-04-24) repack with cargo 0.19.0-beta.1 (03efb7fc8 2017-04-23)",
"size": 76516077,
"digest": "6ed02db3ae678fa222ee3680172dc0bc0f0cec735fbc17e67926d4960cb0f6693416d7da8dd2e91d84ba862d7add4ac36e37d7891270e10ed0540fca8b446b68",
"algorithm": "sha512",
"filename": "rustc.tar.bz2",
"unpack": true

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

@ -6,9 +6,9 @@
"filename": "mozmake.exe"
},
{
"version": "rustc 1.16.0 (30cf806ef 2017-03-10) repack with cargo 0.19.0-nightly (8326a3683 2017-04-19)",
"size": 68401632,
"digest": "d55a50d61f3dbd34e68daf985c95773f6f66fa9b88364eefde03d2b009f2f4e9df7e7e72006347bb4ba0f65ff5190b4b6367fde01e79827e10534cd03fe720df",
"version": "rustc 1.17.0 (56124baa9 2017-04-24) repack with cargo 0.19.0-beta.1 (03efb7fc8 2017-04-23)",
"size": 76516077,
"digest": "6ed02db3ae678fa222ee3680172dc0bc0f0cec735fbc17e67926d4960cb0f6693416d7da8dd2e91d84ba862d7add4ac36e37d7891270e10ed0540fca8b446b68",
"algorithm": "sha512",
"filename": "rustc.tar.bz2",
"unpack": true

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

@ -6,9 +6,9 @@
"filename": "mozmake.exe"
},
{
"version": "rustc 1.16.0 (30cf806ef 2017-03-10) repack with cargo 0.19.0-nightly (8326a3683 2017-04-19)",
"size": 68401632,
"digest": "d55a50d61f3dbd34e68daf985c95773f6f66fa9b88364eefde03d2b009f2f4e9df7e7e72006347bb4ba0f65ff5190b4b6367fde01e79827e10534cd03fe720df",
"version": "rustc 1.17.0 (56124baa9 2017-04-24) repack with cargo 0.19.0-beta.1 (03efb7fc8 2017-04-23)",
"size": 76516077,
"digest": "6ed02db3ae678fa222ee3680172dc0bc0f0cec735fbc17e67926d4960cb0f6693416d7da8dd2e91d84ba862d7add4ac36e37d7891270e10ed0540fca8b446b68",
"algorithm": "sha512",
"filename": "rustc.tar.bz2",
"unpack": true

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

@ -6,9 +6,9 @@
"filename": "mozmake.exe"
},
{
"version": "rustc 1.16.0 (30cf806ef 2017-03-10) repack with cargo 0.19.0-nightly (8326a3683 2017-04-19)",
"size": 73942095,
"digest": "22be87ae8b6aaf1016dc4a24858caadda47dabc6f44b5730b15489727c900ff7c12e01df8d12aa1775f4b83a4fae73a1c12f69fd15b2ab7fe2603a08637f187d",
"version": "rustc 1.17.0 (56124baa9 2017-04-24) repack with cargo 0.19.0-beta.1 (03efb7fc8 2017-04-23)",
"size": 83368214,
"digest": "2f1dda29e495e9707a0e22cde5c80525bd202be9a3381dd053edf08e1a54cd7fa4106e8f1cec336daaae62252ef02cf5b76079c0495a90f1ac0b823a16fd27dc",
"algorithm": "sha512",
"visibility": "public",
"filename": "rustc.tar.bz2",

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

@ -6,9 +6,9 @@
"filename": "mozmake.exe"
},
{
"version": "rustc 1.16.0 (30cf806ef 2017-03-10) repack with cargo 0.19.0-nightly (8326a3683 2017-04-19)",
"size": 73942095,
"digest": "22be87ae8b6aaf1016dc4a24858caadda47dabc6f44b5730b15489727c900ff7c12e01df8d12aa1775f4b83a4fae73a1c12f69fd15b2ab7fe2603a08637f187d",
"version": "rustc 1.17.0 (56124baa9 2017-04-24) repack with cargo 0.19.0-beta.1 (03efb7fc8 2017-04-23)",
"size": 83368214,
"digest": "2f1dda29e495e9707a0e22cde5c80525bd202be9a3381dd053edf08e1a54cd7fa4106e8f1cec336daaae62252ef02cf5b76079c0495a90f1ac0b823a16fd27dc",
"algorithm": "sha512",
"visibility": "public",
"filename": "rustc.tar.bz2",

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

@ -1,13 +1,13 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* globals PlacesProvider, PreviewProvider */
/* globals NewTabUtils, PreviewProvider */
"use strict";
const {utils: Cu} = Components;
const {actionTypes: at, actionCreators: ac} = Cu.import("resource://activity-stream/common/Actions.jsm", {});
Cu.import("resource:///modules/PlacesProvider.jsm");
Cu.import("resource://gre/modules/NewTabUtils.jsm");
Cu.import("resource:///modules/PreviewProvider.jsm");
const TOP_SITES_SHOWMORE_LENGTH = 12;
@ -31,7 +31,7 @@ this.TopSitesFeed = class TopSitesFeed {
this.store.dispatch(ac.BroadcastToContent(action));
}
async getLinksWithDefaults(action) {
let links = await PlacesProvider.links.getLinks();
let links = await NewTabUtils.activityStreamLinks.getTopSites();
if (!links) {
links = [];

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

@ -17,7 +17,7 @@ describe("Top Sites Feed", () => {
sandbox = globals.sandbox;
});
beforeEach(() => {
globals.set("PlacesProvider", {links: {getLinks: sandbox.spy(() => Promise.resolve(links))}});
globals.set("NewTabUtils", {activityStreamLinks: {getTopSites: sandbox.spy(() => Promise.resolve(links))}});
globals.set("PreviewProvider", {getThumbnail: sandbox.spy(() => Promise.resolve(FAKE_SCREENSHOT))});
feed = new TopSitesFeed();
feed.store = {dispatch: sinon.spy(), getState() { return {TopSites: {rows: Array(12).fill("site")}}; }};
@ -34,10 +34,10 @@ describe("Top Sites Feed", () => {
});
describe("#getLinksWithDefaults", () => {
it("should get the links from Places Provider", async () => {
it("should get the links from NewTabUtils", async () => {
const result = await feed.getLinksWithDefaults();
assert.deepEqual(result, links);
assert.calledOnce(global.PlacesProvider.links.getLinks);
assert.calledOnce(global.NewTabUtils.activityStreamLinks.getTopSites);
});
it("should add defaults if there are are not enough links", async () => {
links = [{url: "foo.com"}];
@ -50,7 +50,7 @@ describe("Top Sites Feed", () => {
assert.lengthOf(result, TOP_SITES_SHOWMORE_LENGTH);
assert.deepEqual(result, [...links, DEFAULT_TOP_SITES[0]]);
});
it("should not throw if PlacesProvider returns null", () => {
it("should not throw if NewTabUtils returns null", () => {
links = null;
assert.doesNotThrow(() => {
feed.getLinksWithDefaults(action);

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

@ -22,6 +22,9 @@ this.FormAutofillHeuristics = {
"family-name",
"organization",
"street-address",
"address-line1",
"address-line2",
"address-line3",
"address-level2",
"address-level1",
"postal-code",

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

@ -5,8 +5,9 @@
/*
* Implements an interface of the storage of Form Autofill.
*
* The data is stored in JSON format, without indentation, using UTF-8 encoding.
* With indentation applied, the file would look like this:
* The data is stored in JSON format, without indentation and the computed
* fields, using UTF-8 encoding. With indentation and computed fields applied,
* the schema would look like this:
*
* {
* version: 1,
@ -19,14 +20,20 @@
* additional-name,
* family-name,
* organization, // Company
* street-address, // (Multiline)
* address-level2, // City/Town
* address-level1, // Province (Standardized code if possible)
* street-address, // (Multiline)
* address-level2, // City/Town
* address-level1, // Province (Standardized code if possible)
* postal-code,
* country, // ISO 3166
* tel,
* email,
*
* // computed fields (These fields are not stored in the file as they are
* // generated at runtime.)
* address-line1,
* address-line2,
* address-line3,
*
* // metadata
* timeCreated, // in ms
* timeLastUsed, // in ms
@ -66,7 +73,6 @@ FormAutofillUtils.defineLazyLogGetter(this, this.EXPORTED_SYMBOLS[0]);
const SCHEMA_VERSION = 1;
// Name-related fields will be handled in follow-up bugs due to the complexity.
const VALID_FIELDS = [
"given-name",
"additional-name",
@ -128,7 +134,8 @@ ProfileStorage.prototype = {
log.debug("add:", profile);
this._store.ensureDataReady();
let profileToSave = this._normalizeProfile(profile);
let profileToSave = this._clone(profile);
this._normalizeProfile(profileToSave);
profileToSave.guid = gUUIDGenerator.generateUUID().toString()
.replace(/[{}-]/g, "").substring(0, 12);
@ -163,7 +170,9 @@ ProfileStorage.prototype = {
throw new Error("No matching profile.");
}
let profileToUpdate = this._normalizeProfile(profile);
let profileToUpdate = this._clone(profile);
this._normalizeProfile(profileToUpdate);
for (let field of VALID_FIELDS) {
if (profileToUpdate[field] !== undefined) {
profileFound[field] = profileToUpdate[field];
@ -234,7 +243,9 @@ ProfileStorage.prototype = {
}
// Profile is cloned to avoid accidental modifications from outside.
return this._clone(profileFound);
let clonedProfile = this._clone(profileFound);
this._computeFields(clonedProfile);
return clonedProfile;
},
/**
@ -248,7 +259,9 @@ ProfileStorage.prototype = {
this._store.ensureDataReady();
// Profiles are cloned to avoid accidental modifications from outside.
return this._store.data.profiles.map(this._clone);
let clonedProfiles = this._store.data.profiles.map(this._clone);
clonedProfiles.forEach(this._computeFields);
return clonedProfiles;
},
/**
@ -259,10 +272,21 @@ ProfileStorage.prototype = {
*/
getByFilter({info, searchString}) {
log.debug("getByFilter:", info, searchString);
this._store.ensureDataReady();
// Profiles are cloned to avoid accidental modifications from outside.
let result = this._findByFilter({info, searchString}).map(this._clone);
let lcSearchString = searchString.toLowerCase();
let result = this.getAll().filter(profile => {
// Return true if string is not provided and field exists.
// TODO: We'll need to check if the address is for billing or shipping.
// (Bug 1358941)
let name = profile[info.fieldName];
if (!searchString) {
return !!name;
}
return name.toLowerCase().startsWith(lcSearchString);
});
log.debug("getByFilter: Returning", result.length, "result(s)");
return result;
},
@ -275,25 +299,47 @@ ProfileStorage.prototype = {
return this._store.data.profiles.find(profile => profile.guid == guid);
},
_findByFilter({info, searchString}) {
let profiles = this._store.data.profiles;
let lcSearchString = searchString.toLowerCase();
_computeFields(profile) {
if (profile["street-address"]) {
let streetAddress = profile["street-address"].split("\n");
// TODO: we should prevent the dataloss by concatenating the rest of lines
// with a locale-specific character in the future (bug 1360114).
for (let i = 0; i < 3; i++) {
if (streetAddress[i]) {
profile["address-line" + (i + 1)] = streetAddress[i];
}
}
}
},
return profiles.filter(profile => {
// Return true if string is not provided and field exists.
// TODO: We'll need to check if the address is for billing or shipping.
let name = profile[info.fieldName];
if (!searchString) {
return !!name;
_normalizeAddress(profile) {
if (profile["address-line1"] || profile["address-line2"] ||
profile["address-line3"]) {
// Treat "street-address" as "address-line1" if it contains only one line
// and "address-line1" is omitted.
if (!profile["address-line1"] && profile["street-address"] &&
!profile["street-address"].includes("\n")) {
profile["address-line1"] = profile["street-address"];
delete profile["street-address"];
}
return name.toLowerCase().startsWith(lcSearchString);
});
// Remove "address-line*" but keep the values.
let addressLines = [1, 2, 3].map(i => {
let value = profile["address-line" + i];
delete profile["address-line" + i];
return value;
});
// Concatenate "address-line*" if "street-address" is omitted.
if (!profile["street-address"]) {
profile["street-address"] = addressLines.join("\n");
}
}
},
_normalizeProfile(profile) {
let result = {};
this._normalizeAddress(profile);
for (let key in profile) {
if (!VALID_FIELDS.includes(key)) {
throw new Error(`"${key}" is not a valid field.`);
@ -302,10 +348,7 @@ ProfileStorage.prototype = {
typeof profile[key] !== "number") {
throw new Error(`"${key}" contains invalid data type.`);
}
result[key] = profile[key];
}
return result;
},
_dataPostProcessor(data) {

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

@ -0,0 +1,173 @@
/**
* Tests the transform algorithm in profileStorage.
*/
"use strict";
Cu.import("resource://gre/modules/Task.jsm");
Cu.import("resource://formautofill/ProfileStorage.jsm");
const TEST_STORE_FILE_NAME = "test-profile.json";
const COMPUTE_TESTCASES = [
// Empty
{
description: "Empty profile",
profile: {
},
expectedResult: {
},
},
// Address
{
description: "\"street-address\" with single line",
profile: {
"street-address": "single line",
},
expectedResult: {
"street-address": "single line",
"address-line1": "single line",
},
},
{
description: "\"street-address\" with multiple lines",
profile: {
"street-address": "line1\nline2\nline3",
},
expectedResult: {
"street-address": "line1\nline2\nline3",
"address-line1": "line1",
"address-line2": "line2",
"address-line3": "line3",
},
},
{
description: "\"street-address\" with multiple lines but line2 is omitted",
profile: {
"street-address": "line1\n\nline3",
},
expectedResult: {
"street-address": "line1\n\nline3",
"address-line1": "line1",
"address-line2": "",
"address-line3": "line3",
},
},
{
description: "\"street-address\" with 4 lines",
profile: {
"street-address": "line1\nline2\nline3\nline4",
},
expectedResult: {
"street-address": "line1\nline2\nline3\nline4",
"address-line1": "line1",
"address-line2": "line2",
"address-line3": "line3",
},
},
];
const NORMALIZE_TESTCASES = [
// Empty
{
description: "Empty profile",
profile: {
},
expectedResult: {
},
},
// Address
{
description: "Has \"address-line1~3\" and \"street-address\" is omitted",
profile: {
"address-line1": "line1",
"address-line2": "line2",
"address-line3": "line3",
},
expectedResult: {
"street-address": "line1\nline2\nline3",
},
},
{
description: "Has both \"address-line1~3\" and \"street-address\"",
profile: {
"street-address": "street address",
"address-line1": "line1",
"address-line2": "line2",
"address-line3": "line3",
},
expectedResult: {
"street-address": "street address",
},
},
{
description: "Has \"address-line2~3\" and single-line \"street-address\"",
profile: {
"street-address": "street address",
"address-line2": "line2",
"address-line3": "line3",
},
expectedResult: {
"street-address": "street address\nline2\nline3",
},
},
{
description: "Has \"address-line2~3\" and multiple-line \"street-address\"",
profile: {
"street-address": "street address\nstreet address line 2",
"address-line2": "line2",
"address-line3": "line3",
},
expectedResult: {
"street-address": "street address\nstreet address line 2",
},
},
];
let do_check_profile_matches = (expectedProfile, profile) => {
for (let key in expectedProfile) {
do_check_eq(expectedProfile[key], profile[key] || "");
}
};
add_task(function* test_computeFields() {
let path = getTempFile(TEST_STORE_FILE_NAME).path;
let profileStorage = new ProfileStorage(path);
yield profileStorage.initialize();
COMPUTE_TESTCASES.forEach(testcase => profileStorage.add(testcase.profile));
yield profileStorage._saveImmediately();
profileStorage = new ProfileStorage(path);
yield profileStorage.initialize();
let profiles = profileStorage.getAll();
for (let i in profiles) {
do_print("Verify testcase: " + COMPUTE_TESTCASES[i].description);
do_check_profile_matches(COMPUTE_TESTCASES[i].expectedResult, profiles[i]);
}
});
add_task(function* test_normalizeProfile() {
let path = getTempFile(TEST_STORE_FILE_NAME).path;
let profileStorage = new ProfileStorage(path);
yield profileStorage.initialize();
NORMALIZE_TESTCASES.forEach(testcase => profileStorage.add(testcase.profile));
yield profileStorage._saveImmediately();
profileStorage = new ProfileStorage(path);
yield profileStorage.initialize();
let profiles = profileStorage.getAll();
for (let i in profiles) {
do_print("Verify testcase: " + NORMALIZE_TESTCASES[i].description);
do_check_profile_matches(NORMALIZE_TESTCASES[i].expectedResult, profiles[i]);
}
});

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

@ -15,3 +15,4 @@ support-files =
[test_profileAutocompleteResult.js]
[test_profileStorage.js]
[test_savedFieldNames.js]
[test_transformFields.js]

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

@ -23,8 +23,6 @@
<!ENTITY useAutoScroll.accesskey "a">
<!ENTITY useSmoothScrolling.label "Use smooth scrolling">
<!ENTITY useSmoothScrolling.accesskey "m">
<!ENTITY allowHWAccel.label "Use hardware acceleration when available">
<!ENTITY allowHWAccel.accesskey "r">
<!ENTITY checkUserSpelling.label "Check your spelling as you type">
<!ENTITY checkUserSpelling.accesskey "t">
@ -126,3 +124,17 @@
<!ENTITY viewCerts.accesskey "C">
<!ENTITY viewSecurityDevices.label "Security Devices">
<!ENTITY viewSecurityDevices.accesskey "D">
<!ENTITY performance.label "Performance">
<!ENTITY useRecommendedPerformanceSettings.label
"Use recommended performance settings">
<!ENTITY useRecommendedPerformanceSettings.description
"Recommended performance settings are tailored to your computer.">
<!ENTITY useRecommendedPerformanceSettings.accesskey
"U">
<!ENTITY limitContentProcess.label "Content process limit">
<!ENTITY limitContentProcess.description
"More content processes can make &brandShortName; more responsive when using multiple tabs, but will also consume more memory.">
<!ENTITY limitContentProcess.accesskey "L">
<!ENTITY allowHWAccel.label "Use hardware acceleration when available">
<!ENTITY allowHWAccel.accesskey "r">

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

@ -260,3 +260,6 @@ removeContainerButton2=Dont remove this Container
searchResults.sorryMessage=Sorry! No results were found for “%S”
# LOCALIZATION NOTE %S gets replaced with the browser name
searchResults.needHelp=Need help? Visit <html:a id="need-help-link">%S Support</html:a>
# LOCALIZATION NOTE %S is the default value of the `dom.ipc.processCount` pref.
defaultContentProcessCount=%S (default)

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

@ -14,10 +14,9 @@
const {Cc, Ci, Cu} = require("chrome");
const Services = require("Services");
const promise = require("promise");
const defer = require("devtools/shared/defer");
const Telemetry = require("devtools/client/shared/telemetry");
const { gDevTools } = require("./devtools");
const {gDevTools} = require("./devtools");
// Load target and toolbox lazily as they need gDevTools to be fully initialized
loader.lazyRequireGetter(this, "TargetFactory", "devtools/client/framework/target", true);
@ -68,7 +67,7 @@ var gDevToolsBrowser = exports.gDevToolsBrowser = {
* of there
*/
// used by browser-sets.inc, command
toggleToolboxCommand: function (gBrowser) {
toggleToolboxCommand(gBrowser) {
let target = TargetFactory.forTab(gBrowser.selectedTab);
let toolbox = gDevTools.getToolbox(target);
@ -84,7 +83,7 @@ var gDevToolsBrowser = exports.gDevToolsBrowser = {
* depending on their relevant prefs. It gets run when a window is registered,
* or when any of the devtools prefs change.
*/
updateCommandAvailability: function (win) {
updateCommandAvailability(win) {
let doc = win.document;
function toggleMenuItem(id, isEnabled) {
@ -124,10 +123,12 @@ var gDevToolsBrowser = exports.gDevToolsBrowser = {
// Enable Browser Toolbox?
let chromeEnabled = Services.prefs.getBoolPref("devtools.chrome.enabled");
let devtoolsRemoteEnabled = Services.prefs.getBoolPref("devtools.debugger.remote-enabled");
let devtoolsRemoteEnabled = Services.prefs.getBoolPref(
"devtools.debugger.remote-enabled");
let remoteEnabled = chromeEnabled && devtoolsRemoteEnabled;
toggleMenuItem("menu_browserToolbox", remoteEnabled);
toggleMenuItem("menu_browserContentToolbox", remoteEnabled && win.gMultiProcessBrowser);
toggleMenuItem("menu_browserContentToolbox",
remoteEnabled && win.gMultiProcessBrowser);
// Enable DevTools connection screen, if the preference allows this.
toggleMenuItem("menu_devtools_connect", devtoolsRemoteEnabled);
@ -138,7 +139,7 @@ var gDevToolsBrowser = exports.gDevToolsBrowser = {
* window to make it possible to change colors on elements in the browser (like gcli,
* or the splitter between the toolbox and web content).
*/
updateDevtoolsThemeAttribute: function(win) {
updateDevtoolsThemeAttribute(win) {
// Set an attribute on root element of each window to make it possible
// to change colors based on the selected devtools theme.
let devtoolsTheme = Services.prefs.getCharPref("devtools.theme");
@ -147,9 +148,12 @@ var gDevToolsBrowser = exports.gDevToolsBrowser = {
}
// Style gcli and the splitter between the toolbox and page content. This used to
// set the attribute on the browser's root node but that regressed tpaint: bug 1331449.
win.document.getElementById("browser-bottombox").setAttribute("devtoolstheme", devtoolsTheme);
win.document.getElementById("content").setAttribute("devtoolstheme", devtoolsTheme);
// set the attribute on the browser's root node but that regressed tpaint:
// bug 1331449.
win.document.getElementById("browser-bottombox")
.setAttribute("devtoolstheme", devtoolsTheme);
win.document.getElementById("content")
.setAttribute("devtoolstheme", devtoolsTheme);
// If the toolbox color changes and we have the opposite compact theme applied,
// change it to match. For example:
@ -161,14 +165,16 @@ var gDevToolsBrowser = exports.gDevToolsBrowser = {
let currentTheme = LightweightThemeManager.currentTheme;
let currentThemeID = currentTheme && currentTheme.id;
if (currentThemeID == COMPACT_LIGHT_ID && devtoolsTheme == "dark") {
LightweightThemeManager.currentTheme = LightweightThemeManager.getUsedTheme(COMPACT_DARK_ID);
LightweightThemeManager.currentTheme =
LightweightThemeManager.getUsedTheme(COMPACT_DARK_ID);
}
if (currentThemeID == COMPACT_DARK_ID && devtoolsTheme == "light") {
LightweightThemeManager.currentTheme = LightweightThemeManager.getUsedTheme(COMPACT_LIGHT_ID);
LightweightThemeManager.currentTheme =
LightweightThemeManager.getUsedTheme(COMPACT_LIGHT_ID);
}
},
observe: function (subject, topic, prefName) {
observe(subject, topic, prefName) {
switch (topic) {
case "browser-delayed-startup-finished":
this._registerBrowserWindow(subject);
@ -191,7 +197,7 @@ var gDevToolsBrowser = exports.gDevToolsBrowser = {
case "sdk:loader:destroy":
// This event is fired when the devtools loader unloads, which happens
// only when the add-on workflow ask devtools to be reloaded.
if (subject.wrappedJSObject == require('@loader/unload')) {
if (subject.wrappedJSObject == require("@loader/unload")) {
gDevToolsBrowser.destroy({ shuttingDown: false });
}
break;
@ -206,7 +212,7 @@ var gDevToolsBrowser = exports.gDevToolsBrowser = {
Services.prefs.setCharPref("devtools.theme", "light");
}
if (currentThemeID == COMPACT_DARK_ID && devtoolsTheme == "light") {
Services.prefs.setCharPref("devtools.theme", "dark");
Services.prefs.setCharPref("devtools.theme", "dark");
}
break;
}
@ -214,7 +220,7 @@ var gDevToolsBrowser = exports.gDevToolsBrowser = {
_prefObserverRegistered: false,
ensurePrefObserver: function () {
ensurePrefObserver() {
if (!this._prefObserverRegistered) {
this._prefObserverRegistered = true;
Services.prefs.addObserver("devtools.", this);
@ -237,29 +243,26 @@ var gDevToolsBrowser = exports.gDevToolsBrowser = {
*/
// Used when: - registering a new tool
// - new xul window, to add menu items
selectToolCommand: function (gBrowser, toolId) {
selectToolCommand(gBrowser, toolId) {
let target = TargetFactory.forTab(gBrowser.selectedTab);
let toolbox = gDevTools.getToolbox(target);
let toolDefinition = gDevTools.getToolDefinition(toolId);
if (toolbox &&
(toolbox.currentToolId == toolId ||
(toolId == "webconsole" && toolbox.splitConsole)))
{
(toolId == "webconsole" && toolbox.splitConsole))) {
toolbox.fireCustomKey(toolId);
if (toolDefinition.preventClosingOnKey || toolbox.hostType == Toolbox.HostType.WINDOW) {
if (toolDefinition.preventClosingOnKey ||
toolbox.hostType == Toolbox.HostType.WINDOW) {
toolbox.raise();
} else {
gDevTools.closeToolbox(target);
}
gDevTools.emit("select-tool-command", toolId);
} else {
gDevTools.showToolbox(target, toolId).then(() => {
let target = TargetFactory.forTab(gBrowser.selectedTab);
let toolbox = gDevTools.getToolbox(target);
toolbox.fireCustomKey(toolId);
gDevTools.showToolbox(target, toolId).then(newToolbox => {
newToolbox.fireCustomKey(toolId);
gDevTools.emit("select-tool-command", toolId);
});
}
@ -269,7 +272,7 @@ var gDevToolsBrowser = exports.gDevToolsBrowser = {
* Open a tab on "about:debugging", optionally pre-select a given tab.
*/
// Used by browser-sets.inc, command
openAboutDebugging: function (gBrowser, hash) {
openAboutDebugging(gBrowser, hash) {
let url = "about:debugging" + (hash ? "#" + hash : "");
gBrowser.selectedTab = gBrowser.addTab(url);
},
@ -278,7 +281,7 @@ var gDevToolsBrowser = exports.gDevToolsBrowser = {
* Open a tab to allow connects to a remote browser
*/
// Used by browser-sets.inc, command
openConnectScreen: function (gBrowser) {
openConnectScreen(gBrowser) {
gBrowser.selectedTab = gBrowser.addTab("chrome://devtools/content/framework/connect/connect.xhtml");
},
@ -287,7 +290,7 @@ var gDevToolsBrowser = exports.gDevToolsBrowser = {
*/
// Used by browser-sets.inc, command
// itself, webide widget
openWebIDE: function () {
openWebIDE() {
let win = Services.wm.getMostRecentWindow("devtools:webide");
if (win) {
win.focus();
@ -296,55 +299,49 @@ var gDevToolsBrowser = exports.gDevToolsBrowser = {
}
},
inspectNode: function (tab, node) {
async inspectNode(tab, node) {
let target = TargetFactory.forTab(tab);
// Generate a cross iframes query selector
let selectors = [];
while(node) {
while (node) {
selectors.push(findCssSelector(node));
node = node.ownerDocument.defaultView.frameElement;
}
return gDevTools.showToolbox(target, "inspector").then(toolbox => {
let inspector = toolbox.getCurrentPanel();
let toolbox = await gDevTools.showToolbox(target, "inspector");
let inspector = toolbox.getCurrentPanel();
// new-node-front tells us when the node has been selected, whether the
// browser is remote or not.
let onNewNode = inspector.selection.once("new-node-front");
// new-node-front tells us when the node has been selected, whether the
// browser is remote or not.
let onNewNode = inspector.selection.once("new-node-front");
// Evaluate the cross iframes query selectors
function querySelectors(nodeFront) {
let selector = selectors.pop();
if (!selector) {
return Promise.resolve(nodeFront);
}
return inspector.walker.querySelector(nodeFront, selector)
.then(node => {
if (selectors.length > 0) {
return inspector.walker.children(node).then(({ nodes }) => {
return nodes[0]; // This is the NodeFront for the document node inside the iframe
});
}
return node;
}).then(querySelectors);
// Evaluate the cross iframes query selectors
async function querySelectors(nodeFront) {
let selector = selectors.pop();
if (!selector) {
return nodeFront;
}
inspector.walker.getRootNode()
.then(querySelectors)
.then(node => {
// Select the final node
inspector.selection.setNodeFront(node, "browser-context-menu");
});
nodeFront = await inspector.walker.querySelector(nodeFront, selector);
if (selectors.length > 0) {
let { nodes } = await inspector.walker.children(nodeFront);
// This is the NodeFront for the document node inside the iframe
nodeFront = nodes[0];
}
return querySelectors(nodeFront);
}
let nodeFront = await inspector.walker.getRootNode();
nodeFront = await querySelectors(nodeFront);
// Select the final node
inspector.selection.setNodeFront(nodeFront, "browser-context-menu");
return onNewNode.then(() => {
// Now that the node has been selected, wait until the inspector is
// fully updated.
return inspector.once("inspector-updated");
});
});
await onNewNode;
// Now that the node has been selected, wait until the inspector is
// fully updated.
await inspector.once("inspector-updated");
},
_getContentProcessTarget: function (processId) {
_getContentProcessTarget(processId) {
// Create a DebuggerServer in order to connect locally to it
if (!DebuggerServer.initialized) {
DebuggerServer.init();
@ -382,7 +379,7 @@ var gDevToolsBrowser = exports.gDevToolsBrowser = {
},
// Used by menus.js
openContentProcessToolbox: function (gBrowser) {
openContentProcessToolbox(gBrowser) {
let { childCount } = Services.ppmm;
// Get the process message manager for the current tab
let mm = gBrowser.selectedBrowser.messageManager.processMessageManager;
@ -410,7 +407,7 @@ var gDevToolsBrowser = exports.gDevToolsBrowser = {
/**
* Install Developer widget
*/
installDeveloperWidget: function () {
installDeveloperWidget() {
let id = "developer-button";
let widget = CustomizableUI.getWidget(id);
if (widget && widget.provider == CustomizableUI.PROVIDER_API) {
@ -425,12 +422,11 @@ var gDevToolsBrowser = exports.gDevToolsBrowser = {
defaultArea: AppConstants.MOZ_DEV_EDITION ?
CustomizableUI.AREA_NAVBAR :
CustomizableUI.AREA_PANEL,
onViewShowing: function (aEvent) {
onViewShowing(event) {
// Populate the subview with whatever menuitems are in the developer
// menu. We skip menu elements, because the menu panel has no way
// of dealing with those right now.
let doc = aEvent.target.ownerDocument;
let win = doc.defaultView;
let doc = event.target.ownerDocument;
let menu = doc.getElementById("menuWebDeveloperPopup");
@ -446,7 +442,7 @@ var gDevToolsBrowser = exports.gDevToolsBrowser = {
clearSubview(developerItems);
fillSubviewFromMenuItems(itemsToDisplay, developerItems);
},
onBeforeCreated: function (doc) {
onBeforeCreated(doc) {
// Bug 1223127, CUI should make this easier to do.
if (doc.getElementById("PanelUI-developerItems")) {
return;
@ -465,7 +461,7 @@ var gDevToolsBrowser = exports.gDevToolsBrowser = {
* Install WebIDE widget
*/
// Used by itself
installWebIDEWidget: function () {
installWebIDEWidget() {
if (this.isWebIDEWidgetInstalled()) {
return;
}
@ -483,13 +479,13 @@ var gDevToolsBrowser = exports.gDevToolsBrowser = {
label: "devtools-webide-button2.label",
tooltiptext: "devtools-webide-button2.tooltiptext",
defaultArea: defaultArea,
onCommand: function (aEvent) {
onCommand(event) {
gDevToolsBrowser.openWebIDE();
}
});
},
isWebIDEWidgetInstalled: function () {
isWebIDEWidgetInstalled() {
let widgetWrapper = CustomizableUI.getWidget("webide-button");
return !!(widgetWrapper && widgetWrapper.provider == CustomizableUI.PROVIDER_API);
},
@ -502,7 +498,7 @@ var gDevToolsBrowser = exports.gDevToolsBrowser = {
/**
* Uninstall WebIDE widget
*/
uninstallWebIDEWidget: function () {
uninstallWebIDEWidget() {
if (this.isWebIDEWidgetInstalled()) {
CustomizableUI.removeWidgetFromArea("webide-button");
}
@ -513,7 +509,7 @@ var gDevToolsBrowser = exports.gDevToolsBrowser = {
* Move WebIDE widget to the navbar
*/
// Used by webide.js
moveWebIDEWidgetInNavbar: function () {
moveWebIDEWidgetInNavbar() {
CustomizableUI.addWidgetToArea("webide-button", CustomizableUI.AREA_NAVBAR);
},
@ -523,7 +519,7 @@ var gDevToolsBrowser = exports.gDevToolsBrowser = {
* @param {XULDocument} doc
* The document to which devtools should be hooked to.
*/
_registerBrowserWindow: function (win) {
_registerBrowserWindow(win) {
if (gDevToolsBrowser._trackedBrowserWindows.has(win)) {
return;
}
@ -558,13 +554,13 @@ var gDevToolsBrowser = exports.gDevToolsBrowser = {
* Hook the JS debugger tool to the "Debug Script" button of the slow script
* dialog.
*/
setSlowScriptDebugHandler: function DT_setSlowScriptDebugHandler() {
setSlowScriptDebugHandler() {
let debugService = Cc["@mozilla.org/dom/slow-script-debug;1"]
.getService(Ci.nsISlowScriptDebug);
let tm = Cc["@mozilla.org/thread-manager;1"].getService(Ci.nsIThreadManager);
function slowScriptDebugHandler(aTab, aCallback) {
let target = TargetFactory.forTab(aTab);
function slowScriptDebugHandler(tab, callback) {
let target = TargetFactory.forTab(tab);
gDevTools.showToolbox(target, "jsdebugger").then(toolbox => {
let threadClient = toolbox.threadClient;
@ -575,13 +571,13 @@ var gDevToolsBrowser = exports.gDevToolsBrowser = {
case "paused":
// When the debugger is already paused.
threadClient.resumeThenPause();
aCallback();
callback();
break;
case "attached":
// When the debugger is already open.
threadClient.interrupt(() => {
threadClient.resumeThenPause();
aCallback();
callback();
});
break;
case "resuming":
@ -589,7 +585,7 @@ var gDevToolsBrowser = exports.gDevToolsBrowser = {
threadClient.addOneTimeListener("resumed", () => {
threadClient.interrupt(() => {
threadClient.resumeThenPause();
aCallback();
callback();
});
});
break;
@ -600,8 +596,8 @@ var gDevToolsBrowser = exports.gDevToolsBrowser = {
});
}
debugService.activationHandler = function (aWindow) {
let chromeWindow = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
debugService.activationHandler = function (window) {
let chromeWindow = window.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShellTreeItem)
.rootTreeItem
@ -611,11 +607,13 @@ var gDevToolsBrowser = exports.gDevToolsBrowser = {
let setupFinished = false;
slowScriptDebugHandler(chromeWindow.gBrowser.selectedTab,
() => { setupFinished = true; });
() => {
setupFinished = true;
});
// Don't return from the interrupt handler until the debugger is brought
// up; no reason to continue executing the slow script.
let utils = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
let utils = window.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils);
utils.enterModalState();
while (!setupFinished) {
@ -624,23 +622,21 @@ var gDevToolsBrowser = exports.gDevToolsBrowser = {
utils.leaveModalState();
};
debugService.remoteActivationHandler = function (aBrowser, aCallback) {
let chromeWindow = aBrowser.ownerDocument.defaultView;
let tab = chromeWindow.gBrowser.getTabForBrowser(aBrowser);
debugService.remoteActivationHandler = function (browser, callback) {
let chromeWindow = browser.ownerDocument.defaultView;
let tab = chromeWindow.gBrowser.getTabForBrowser(browser);
chromeWindow.gBrowser.selected = tab;
function callback() {
aCallback.finishDebuggerStartup();
}
slowScriptDebugHandler(tab, callback);
slowScriptDebugHandler(tab, function () {
callback.finishDebuggerStartup();
});
};
},
/**
* Unset the slow script debug handler.
*/
unsetSlowScriptDebugHandler: function DT_unsetSlowScriptDebugHandler() {
unsetSlowScriptDebugHandler() {
let debugService = Cc["@mozilla.org/dom/slow-script-debug;1"]
.getService(Ci.nsISlowScriptDebug);
debugService.activationHandler = undefined;
@ -652,7 +648,7 @@ var gDevToolsBrowser = exports.gDevToolsBrowser = {
* @param {object} toolDefinition
* properties of the tool to add
*/
_addToolToWindows: function DT_addToolToWindows(toolDefinition) {
_addToolToWindows(toolDefinition) {
// No menu item or global shortcut is required for options panel.
if (!toolDefinition.inMenu) {
return;
@ -664,7 +660,9 @@ var gDevToolsBrowser = exports.gDevToolsBrowser = {
!Services.prefs.getBoolPref(toolDefinition.visibilityswitch)) {
return;
}
} catch (e) {}
} catch (e) {
// Prevent breaking everything if the pref doesn't exists.
}
// We need to insert the new tool in the right place, which means knowing
// the tool that comes before the tool that we're trying to add
@ -689,9 +687,9 @@ var gDevToolsBrowser = exports.gDevToolsBrowser = {
}
},
hasToolboxOpened: function (win) {
hasToolboxOpened(win) {
let tab = win.gBrowser.selectedTab;
for (let [target, toolbox] of gDevTools._toolboxes) {
for (let [target, ] of gDevTools._toolboxes) {
if (target.tab == tab) {
return true;
}
@ -703,9 +701,8 @@ var gDevToolsBrowser = exports.gDevToolsBrowser = {
* Update the "Toggle Tools" checkbox in the developer tools menu. This is
* called when a toolbox is created or destroyed.
*/
_updateMenuCheckbox: function DT_updateMenuCheckbox() {
_updateMenuCheckbox() {
for (let win of gDevToolsBrowser._trackedBrowserWindows) {
let hasToolbox = gDevToolsBrowser.hasToolboxOpened(win);
let menu = win.document.getElementById("menu_devToolbox");
@ -723,7 +720,7 @@ var gDevToolsBrowser = exports.gDevToolsBrowser = {
* @param {string} toolId
* id of the tool to remove
*/
_removeToolFromWindows: function DT_removeToolFromWindows(toolId) {
_removeToolFromWindows(toolId) {
for (let win of gDevToolsBrowser._trackedBrowserWindows) {
BrowserMenus.removeToolFromMenu(toolId, win.document);
}
@ -740,7 +737,7 @@ var gDevToolsBrowser = exports.gDevToolsBrowser = {
* @param {XULWindow} win
* The window containing the menu entry
*/
_forgetBrowserWindow: function (win) {
_forgetBrowserWindow(win) {
if (!gDevToolsBrowser._trackedBrowserWindows.has(win)) {
return;
}
@ -770,7 +767,7 @@ var gDevToolsBrowser = exports.gDevToolsBrowser = {
tabContainer.removeEventListener("TabUnpinned", this);
},
handleEvent: function (event) {
handleEvent(event) {
switch (event.type) {
case "TabOpen":
case "TabClose":
@ -803,7 +800,7 @@ var gDevToolsBrowser = exports.gDevToolsBrowser = {
}
},
_pingTelemetry: function () {
_pingTelemetry() {
let mean = function (arr) {
if (arr.length === 0) {
return 0;
@ -829,9 +826,9 @@ var gDevToolsBrowser = exports.gDevToolsBrowser = {
* some cleanups to speed it up. Otherwise everything need to be
* cleaned up in order to be able to load devtools again.
*/
destroy: function ({ shuttingDown }) {
destroy({ shuttingDown }) {
Services.prefs.removeObserver("devtools.", gDevToolsBrowser);
Services.obs.removeObserver(gDevToolsBrowser, "lightweight-theme-changed", false);
Services.obs.removeObserver(gDevToolsBrowser, "lightweight-theme-changed");
Services.obs.removeObserver(gDevToolsBrowser, "browser-delayed-startup-finished");
Services.obs.removeObserver(gDevToolsBrowser, "quit-application");
Services.obs.removeObserver(gDevToolsBrowser, "sdk:loader:destroy");

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

@ -6,8 +6,6 @@
const {Cu} = require("chrome");
const Services = require("Services");
const promise = require("promise");
const defer = require("devtools/shared/defer");
// Load gDevToolsBrowser toolbox lazily as they need gDevTools to be fully initialized
loader.lazyRequireGetter(this, "Toolbox", "devtools/client/framework/toolbox", true);
@ -46,7 +44,7 @@ function DevTools() {
// start registering all default tools and themes: create menuitems, keys, emit
// related events.
this.registerDefaults();
};
}
DevTools.prototype = {
// The windowtype of the main window, used in various tools. This may be set
@ -100,7 +98,7 @@ DevTools.prototype = {
* markup from |url|, and also the toolbox containing the panel.
* And returns an instance of ToolPanel (function|required)
*/
registerTool: function DT_registerTool(toolDefinition) {
registerTool(toolDefinition) {
let toolId = toolDefinition.id;
if (!toolId || FORBIDDEN_IDS.has(toolId)) {
@ -130,17 +128,16 @@ DevTools.prototype = {
* true to indicate that the call is due to app quit, so we should not
* cause a cascade of costly events
*/
unregisterTool: function DT_unregisterTool(tool, isQuitApplication) {
unregisterTool(tool, isQuitApplication) {
let toolId = null;
if (typeof tool == "string") {
toolId = tool;
tool = this._tools.get(tool);
}
else {
} else {
let {Deprecated} = Cu.import("resource://gre/modules/Deprecated.jsm", {});
Deprecated.warning("Deprecation WARNING: gDevTools.unregisterTool(tool) is deprecated. " +
"You should unregister a tool using its toolId: " +
"gDevTools.unregisterTool(toolId).");
Deprecated.warning("Deprecation WARNING: gDevTools.unregisterTool(tool) is " +
"deprecated. You should unregister a tool using its toolId: " +
"gDevTools.unregisterTool(toolId).");
toolId = tool.id;
}
this._tools.delete(toolId);
@ -153,19 +150,19 @@ DevTools.prototype = {
/**
* Sorting function used for sorting tools based on their ordinals.
*/
ordinalSort: function DT_ordinalSort(d1, d2) {
ordinalSort(d1, d2) {
let o1 = (typeof d1.ordinal == "number") ? d1.ordinal : MAX_ORDINAL;
let o2 = (typeof d2.ordinal == "number") ? d2.ordinal : MAX_ORDINAL;
return o1 - o2;
},
getDefaultTools: function DT_getDefaultTools() {
getDefaultTools() {
return DefaultTools.sort(this.ordinalSort);
},
getAdditionalTools: function DT_getAdditionalTools() {
getAdditionalTools() {
let tools = [];
for (let [key, value] of this._tools) {
for (let [, value] of this._tools) {
if (DefaultTools.indexOf(value) == -1) {
tools.push(value);
}
@ -186,7 +183,7 @@ DevTools.prototype = {
* @return {ToolDefinition|null} tool
* The ToolDefinition for the id or null.
*/
getToolDefinition: function DT_getToolDefinition(toolId) {
getToolDefinition(toolId) {
let tool = this._tools.get(toolId);
if (!tool) {
return null;
@ -206,7 +203,7 @@ DevTools.prototype = {
* @return {Map} tools
* A map of the the tool definitions registered in this instance
*/
getToolDefinitionMap: function DT_getToolDefinitionMap() {
getToolDefinitionMap() {
let tools = new Map();
for (let [id, definition] of this._tools) {
@ -226,7 +223,7 @@ DevTools.prototype = {
* @return {Array} tools
* A sorted array of the tool definitions registered in this instance
*/
getToolDefinitionArray: function DT_getToolDefinitionArray() {
getToolDefinitionArray() {
let definitions = [];
for (let [id, definition] of this._tools) {
@ -260,7 +257,7 @@ DevTools.prototype = {
* is unapplied. The function takes the current iframe window
* and the new theme id as arguments (function)
*/
registerTheme: function DT_registerTheme(themeDefinition) {
registerTheme(themeDefinition) {
let themeId = themeDefinition.id;
if (!themeId) {
@ -283,13 +280,12 @@ DevTools.prototype = {
* @param {string|object} theme
* Definition or the id of the theme to unregister.
*/
unregisterTheme: function DT_unregisterTheme(theme) {
unregisterTheme(theme) {
let themeId = null;
if (typeof theme == "string") {
themeId = theme;
theme = this._themes.get(theme);
}
else {
} else {
themeId = theme.id;
}
@ -323,7 +319,7 @@ DevTools.prototype = {
* @return {ThemeDefinition|null} theme
* The ThemeDefinition for the id or null.
*/
getThemeDefinition: function DT_getThemeDefinition(themeId) {
getThemeDefinition(themeId) {
let theme = this._themes.get(themeId);
if (!theme) {
return null;
@ -337,7 +333,7 @@ DevTools.prototype = {
* @return {Map} themes
* A map of the the theme definitions registered in this instance
*/
getThemeDefinitionMap: function DT_getThemeDefinitionMap() {
getThemeDefinitionMap() {
let themes = new Map();
for (let [id, definition] of this._themes) {
@ -355,7 +351,7 @@ DevTools.prototype = {
* @return {Array} themes
* A sorted array of the theme definitions registered in this instance
*/
getThemeDefinitionArray: function DT_getThemeDefinitionArray() {
getThemeDefinitionArray() {
let definitions = [];
for (let [id, definition] of this._themes) {
@ -390,7 +386,6 @@ DevTools.prototype = {
showToolbox: Task.async(function* (target, toolId, hostType, hostOptions) {
let toolbox = this._toolboxes.get(target);
if (toolbox) {
if (hostType != null && toolbox.hostType != hostType) {
yield toolbox.switchHost(hostType);
}
@ -449,7 +444,7 @@ DevTools.prototype = {
* @return {Toolbox} toolbox
* The toolbox that is debugging the given target
*/
getToolbox: function DT_getToolbox(target) {
getToolbox(target) {
return this._toolboxes.get(target);
},
@ -482,17 +477,17 @@ DevTools.prototype = {
* some cleanups to speed it up. Otherwise everything need to be
* cleaned up in order to be able to load devtools again.
*/
destroy: function ({ shuttingDown }) {
destroy({ shuttingDown }) {
// Do not cleanup everything during firefox shutdown, but only when
// devtools are reloaded via the add-on contribution workflow.
if (!shuttingDown) {
for (let [target, toolbox] of this._toolboxes) {
for (let [, toolbox] of this._toolboxes) {
toolbox.destroy();
}
AboutDevTools.unregister();
}
for (let [key, tool] of this.getToolDefinitionMap()) {
for (let [key, ] of this.getToolDefinitionMap()) {
this.unregisterTool(key, true);
}
@ -508,7 +503,7 @@ DevTools.prototype = {
/**
* Iterator that yields each of the toolboxes.
*/
*[Symbol.iterator ]() {
* [Symbol.iterator ]() {
for (let toolbox of this._toolboxes) {
yield toolbox;
}

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

@ -143,6 +143,18 @@ networkMenu.sortedAsc=Sorted ascending
# in the network table toolbar, for any column that is sorted descending.
networkMenu.sortedDesc=Sorted descending
# LOCALIZATION NOTE (networkMenu.summary.tooltip.perf): A tooltip explaining
# what the perf button does
networkMenu.summary.tooltip.perf=Start performance analysis
# LOCALIZATION NOTE (networkMenu.summary.tooltip.domContentLoaded): A tooltip explaining
# what the DOMContentLoaded label displays
networkMenu.summary.tooltip.domContentLoaded=Time when “DOMContentLoad” event occurred
# LOCALIZATION NOTE (networkMenu.summary.tooltip.load): A tooltip explaining
# what the load label displays
networkMenu.summary.tooltip.load=Time when “load” event occurred
# LOCALIZATION NOTE (networkMenu.summary.requestsCount): This label is displayed
# in the network table footer providing the number of requests
# See: http://developer.mozilla.org/en/docs/Localization_and_Plurals
@ -152,14 +164,25 @@ networkMenu.summary.requestsCount=One request;%S requests
# in the network table footer when there are no requests
networkMenu.summary.requestsCountEmpty=No requests
# LOCALIZATION NOTE (networkMenu.summary.tooltip.requestsCount): A tooltip explaining
# what the requestsCount label displays
networkMenu.summary.tooltip.requestsCount=Number of requests
# LOCALIZATION NOTE (networkMenu.summary.transferred): This label is displayed
# in the network table footer providing the transferred size.
networkMenu.summary.transferred=%S / %S transferred
# LOCALIZATION NOTE (networkMenu.summary.tooltip.transferred): A tooltip explaining
# what the transferred label displays
networkMenu.summary.tooltip.transferred=Size/transferred size of all requests
# LOCALIZATION NOTE (networkMenu.summary.finish): This label is displayed
# in the network table footer providing the transfer time.
networkMenu.summary.finish=Finish: %S
# LOCALIZATION NOTE (networkMenu.summary.tooltip.finish): A tooltip explaining
# what the finish label displays
networkMenu.summary.tooltip.finish=Total time needed to load all requests
# LOCALIZATION NOTE (networkMenu.sizeB): This is the label displayed
# in the network menu specifying the size of a request (in bytes).
@ -196,6 +219,34 @@ networkMenu.sizeServiceWorker=service worker
# in the network menu specifying the time for a request to finish (in milliseconds).
networkMenu.totalMS=→ %S ms
# LOCALIZATION NOTE (netmonitor.waterfall.tooltip.total): This is part of the tooltip
# displayed in the requests waterfall for total time (in milliseconds).
netmonitor.waterfall.tooltip.total=Total %S ms
# LOCALIZATION NOTE (netmonitor.waterfall.tooltip.blocked): This is part of the tooltip
# displayed in the requests waterfall for blocked time (in milliseconds).
netmonitor.waterfall.tooltip.blocked=Blocked %S ms
# LOCALIZATION NOTE (netmonitor.waterfall.tooltip.dns): This is part of the tooltip
# displayed in the requests waterfall for dns time (in milliseconds).
netmonitor.waterfall.tooltip.dns=DNS %S ms
# LOCALIZATION NOTE (netmonitor.waterfall.tooltip.connect): This is part of the tooltip
# displayed in the requests waterfall for connect time (in milliseconds).
netmonitor.waterfall.tooltip.connect=Connect %S ms
# LOCALIZATION NOTE (netmonitor.waterfall.tooltip.send): This is part of the tooltip
# displayed in the requests waterfall for send time (in milliseconds).
netmonitor.waterfall.tooltip.send=Send %S ms
# LOCALIZATION NOTE (netmonitor.waterfall.tooltip.wait): This is part of the tooltip
# displayed in the requests waterfall for wait time (in milliseconds).
netmonitor.waterfall.tooltip.wait=Wait %S ms
# LOCALIZATION NOTE (netmonitor.waterfall.tooltip.receive): This is part of the tooltip
# displayed in the requests waterfall for receive time (in milliseiconds).
netmonitor.waterfall.tooltip.receive=Receive %S ms
# LOCALIZATION NOTE (networkMenu.millisecond): This is the label displayed
# in the network menu specifying timing interval divisions (in milliseconds).
networkMenu.millisecond=%S ms

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

@ -51,6 +51,37 @@
return NetMonitorController.shutdownNetMonitor();
}
};
// Implement support for chrome://devtools/content/netmonitor/index.html?type=tab&id=1234 URLs
// where 1234 is the tab id, you can retrieve from about:debugging#tabs links.
// Simply copy the id from about:devtools-toolbox?type=tab&id=1234 URLs.
// URL constructor doesn't support chrome: scheme
let href = window.location.href.replace(/chrome:/, "http://");
let url = new window.URL(href);
// If query parameters are given in a chrome tab, the inspector is running in standalone.
if (window.location.protocol === "chrome:" && url.search.length > 1) {
const { targetFromURL } = require("devtools/client/framework/target-from-url");
(async function () {
let target = await targetFromURL(url);
// Start the network event listening as it is done in the toolbox code
await target.activeConsole.startListeners([
"NetworkActivity",
]);
// Create a fake toolbox object
let toolbox = {
target,
viewSourceInDebugger() {
throw new Error("toolbox.viewSourceInDebugger is not implement from a tab");
}
};
window.Netmonitor.bootstrap({ toolbox });
})().catch(e => {
window.alert("Unable to start the network monitor:" + e.message + "\n" + e.stack);
});
}
</script>
</body>
</html>

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

@ -38,16 +38,17 @@ const RequestListColumnWaterfall = createClass({
render() {
let { firstRequestStartedMillis, item } = this.props;
const { boxes, tooltip } = timingBoxes(item);
return (
div({ className: "requests-list-column requests-list-waterfall" },
div({ className: "requests-list-column requests-list-waterfall", title: tooltip },
div({
className: "requests-list-timings",
style: {
paddingInlineStart: `${item.startedMillis - firstRequestStartedMillis}px`,
},
},
timingBoxes(item),
boxes,
)
)
);
@ -57,9 +58,10 @@ const RequestListColumnWaterfall = createClass({
function timingBoxes(item) {
let { eventTimings, fromCache, fromServiceWorker, totalTime } = item;
let boxes = [];
let tooltip = [];
if (fromCache || fromServiceWorker) {
return boxes;
return { boxes, tooltip };
}
if (eventTimings) {
@ -77,6 +79,7 @@ function timingBoxes(item) {
style: { width },
})
);
tooltip.push(L10N.getFormatStr("netmonitor.waterfall.tooltip." + key, width));
}
}
}
@ -90,9 +93,10 @@ function timingBoxes(item) {
title,
}, title)
);
tooltip.push(L10N.getFormatStr("netmonitor.waterfall.tooltip.total", totalTime));
}
return boxes;
return { boxes, tooltip: tooltip.join(", ") };
}
module.exports = RequestListColumnWaterfall;

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

@ -43,29 +43,35 @@ function StatusBar({ summary, openStatistics, timingMarkers }) {
div({ className: "devtools-toolbar devtools-status-bottom" },
button({
className: "devtools-button requests-list-network-summary-button",
title: L10N.getStr("networkMenu.summary.tooltip.perf"),
onClick: openStatistics,
},
div({ className: "summary-info-icon" }),
),
div({ className: "status-bar-label requests-list-network-summary-count" },
countText
),
div({
className: "status-bar-label requests-list-network-summary-count",
title: L10N.getStr("networkMenu.summary.tooltip.requestsCount"),
}, countText),
count !== 0 &&
div({ className: "status-bar-label requests-list-network-summary-transfer" },
transferText
),
div({
className: "status-bar-label requests-list-network-summary-transfer",
title: L10N.getStr("networkMenu.summary.tooltip.transferred"),
}, transferText),
count !== 0 &&
div({ className: "status-bar-label requests-list-network-summary-finish" },
finishText
),
div({
className: "status-bar-label requests-list-network-summary-finish",
title: L10N.getStr("networkMenu.summary.tooltip.finish"),
}, finishText),
DOMContentLoaded > -1 &&
div({ className: "status-bar-label dom-content-loaded" },
`DOMContentLoaded: ${getFormattedTime(DOMContentLoaded)}`
),
div({
className: "status-bar-label dom-content-loaded",
title: L10N.getStr("networkMenu.summary.tooltip.domContentLoaded"),
}, `DOMContentLoaded: ${getFormattedTime(DOMContentLoaded)}`),
load > -1 &&
div({ className: "status-bar-label load" },
`load: ${getFormattedTime(load)}`
),
div({
className: "status-bar-label load",
title: L10N.getStr("networkMenu.summary.tooltip.load"),
}, `load: ${getFormattedTime(load)}`),
)
);
}

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

@ -39,6 +39,9 @@ const HEADER_FILTERS = HEADERS
const FILTER_FLAGS = [
...HEADER_FILTERS,
"scheme",
"set-cookie-domain",
"set-cookie-name",
"set-cookie-value",
"mime-type",
"larger-than",
"is",
@ -117,6 +120,8 @@ function getSizeOrder(size) {
function isFlagFilterMatch(item, { type, value, negative }) {
let match = true;
let { responseCookies = { cookies: [] } } = item;
responseCookies = responseCookies.cookies || responseCookies;
switch (type) {
case "status-code":
match = item.status === value;
@ -177,6 +182,24 @@ function isFlagFilterMatch(item, { type, value, negative }) {
let scheme = new URL(item.url).protocol.replace(":", "").toLowerCase();
match = scheme === value;
break;
case "set-cookie-domain":
if (responseCookies.length > 0) {
let host = item.urlDetails.host;
let i = responseCookies.findIndex(c => {
let domain = c.hasOwnProperty("domain") ? c.domain : host;
return domain === value;
});
match = i > -1;
} else {
match = false;
}
break;
case "set-cookie-name":
match = responseCookies.findIndex(c => c.name.toLowerCase() === value) > -1;
break;
case "set-cookie-value":
match = responseCookies.findIndex(c => c.value.toLowerCase() === value) > -1;
break;
}
if (negative) {
return !match;

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

@ -61,7 +61,8 @@ return /******/ (function(modules) { // webpackBootstrap
parseURLEncodedText,
parseURLParams,
getSelectableInInspectorGrips,
maybeEscapePropertyName
maybeEscapePropertyName,
getGripPreviewItems
} = __webpack_require__(3);
module.exports = {
@ -72,7 +73,8 @@ return /******/ (function(modules) { // webpackBootstrap
maybeEscapePropertyName,
parseURLEncodedText,
parseURLParams,
getSelectableInInspectorGrips
getSelectableInInspectorGrips,
getGripPreviewItems
};
/***/ },
@ -576,13 +578,23 @@ return /******/ (function(modules) { // webpackBootstrap
// Event Grip
if (grip.preview && grip.preview.target) {
return [grip.preview.target];
let keys = Object.keys(grip.preview.properties);
let values = Object.values(grip.preview.properties);
return [grip.preview.target, ...keys, ...values];
}
// RegEx Grip
if (grip.displayString) {
return [grip.displayString];
}
// Generic Grip
if (grip.preview && grip.preview.ownProperties) {
let propertiesValues = Object.values(grip.preview.ownProperties).map(property => property.value || property);
let propertyKeys = Object.keys(grip.preview.ownProperties);
propertiesValues = propertiesValues.concat(propertyKeys);
// ArrayBuffer Grip
if (grip.preview.safeGetterValues) {
propertiesValues = propertiesValues.concat(Object.values(grip.preview.safeGetterValues).map(property => property.getterValue || property));
@ -596,7 +608,7 @@ return /******/ (function(modules) { // webpackBootstrap
/**
* Returns a new element wrapped with a component, props.objectLink if it exists,
* or a span if there are multiple childs, or directly the child if only one is passed.
* or a span if there are multiple children, or directly the child if only one is passed.
*
* @param {Object} props A Rep "props" object that may contain `objectLink`
* and `object` properties.
@ -639,7 +651,8 @@ return /******/ (function(modules) { // webpackBootstrap
getURLDisplayString,
getSelectableInInspectorGrips,
maybeEscapePropertyName,
safeObjectLink
safeObjectLink,
getGripPreviewItems
};
/***/ },

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

@ -20,26 +20,26 @@
}
@keyframes anim-simple {
from { color: black; }
to { color: white; }
from { color: rgb(0, 0, 0); }
to { color: rgb(255, 255, 255); }
}
@keyframes anim-simple-three {
from { color: black; }
50% { color: blue; }
to { color: white; }
from { color: rgb(0, 0, 0); }
50% { color: rgb(0, 0, 255); }
to { color: rgb(255, 255, 255); }
}
@keyframes anim-simple-timing {
from { color: black; animation-timing-function: linear; }
50% { color: blue; animation-timing-function: ease-in-out; }
to { color: white; animation-timing-function: step-end; }
from { color: rgb(0, 0, 0); animation-timing-function: linear; }
50% { color: rgb(0, 0, 255); animation-timing-function: ease-in-out; }
to { color: rgb(255, 255, 255); animation-timing-function: step-end; }
}
@keyframes anim-simple-timing-some {
from { color: black; animation-timing-function: linear; }
50% { color: blue; }
to { color: white; }
from { color: rgb(0, 0, 0); animation-timing-function: linear; }
50% { color: rgb(0, 0, 255); }
to { color: rgb(255, 255, 255); }
}
@keyframes anim-simple-shorthand {
@ -48,15 +48,15 @@
}
@keyframes anim-omit-to {
from { color: blue; }
from { color: rgb(0, 0, 255); }
}
@keyframes anim-omit-from {
to { color: blue; }
to { color: rgb(0, 0, 255); }
}
@keyframes anim-omit-from-to {
50% { color: blue; }
50% { color: rgb(0, 0, 255); }
}
@keyframes anim-partially-omit-to {
@ -67,29 +67,29 @@
}
@keyframes anim-different-props {
from { color: black; margin-top: 8px; }
25% { color: blue; }
from { color: rgb(0, 0, 0); margin-top: 8px; }
25% { color: rgb(0, 0, 255); }
75% { margin-top: 12px; }
to { color: white; margin-top: 16px }
to { color: rgb(255, 255, 255); margin-top: 16px }
}
@keyframes anim-different-props-and-easing {
from { color: black; margin-top: 8px; animation-timing-function: linear; }
25% { color: blue; animation-timing-function: step-end; }
from { color: rgb(0, 0, 0); margin-top: 8px; animation-timing-function: linear; }
25% { color: rgb(0, 0, 255); animation-timing-function: step-end; }
75% { margin-top: 12px; animation-timing-function: ease-in; }
to { color: white; margin-top: 16px }
to { color: rgb(255, 255, 255); margin-top: 16px }
}
@keyframes anim-merge-offset {
from { color: black; }
to { color: white; }
from { color: rgb(0, 0, 0); }
to { color: rgb(255, 255, 255); }
from { margin-top: 8px; }
to { margin-top: 16px; }
}
@keyframes anim-merge-offset-and-easing {
from { color: black; animation-timing-function: step-end; }
to { color: white; }
from { color: rgb(0, 0, 0); animation-timing-function: step-end; }
to { color: rgb(255, 255, 255); }
from { margin-top: 8px; animation-timing-function: linear; }
to { margin-top: 16px; }
from { font-size: 16px; animation-timing-function: step-end; }
@ -300,7 +300,7 @@ test(function(t) {
var div = addDiv(t);
div.style.animation = 'anim-omit-to 100s';
div.style.color = 'white';
div.style.color = 'rgb(255, 255, 255)';
var frames = getKeyframes(div);
assert_equals(frames.length, 2, "number of frames");
@ -322,7 +322,7 @@ test(function(t) {
var div = addDiv(t);
div.style.animation = 'anim-omit-from 100s';
div.style.color = 'white';
div.style.color = 'rgb(255, 255, 255)';
var frames = getKeyframes(div);
assert_equals(frames.length, 2, "number of frames");
@ -344,7 +344,7 @@ test(function(t) {
var div = addDiv(t);
div.style.animation = 'anim-omit-from-to 100s';
div.style.color = 'white';
div.style.color = 'rgb(255, 255, 255)';
var frames = getKeyframes(div);
assert_equals(frames.length, 3, "number of frames");
@ -570,7 +570,9 @@ test(function(t) {
test(function(t) {
var div = addDiv(t);
div.style.textShadow = '1px 1px 2px black, 0 0 16px blue, 0 0 3.2px blue';
div.style.textShadow = '1px 1px 2px rgb(0, 0, 0), ' +
'0 0 16px rgb(0, 0, 255), ' +
'0 0 3.2px rgb(0, 0, 255)';
div.style.animation = 'anim-text-shadow 100s';
var frames = getKeyframes(div);

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

@ -258,11 +258,6 @@ DOMInterfaces = {
'binaryNames': { 'ownerRule': 'DOMOwnerRule' },
},
'CSSSupportsRule': {
'nativeType': 'mozilla::CSSSupportsRule',
'headerFile': 'nsCSSRules.h',
},
'CSSValue': {
'concrete': False
},

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

@ -3713,6 +3713,7 @@ HTMLMediaElement::HTMLMediaElement(already_AddRefed<mozilla::dom::NodeInfo>& aNo
mDefaultPlaybackStartPosition(0.0),
mIsAudioTrackAudible(false),
mHasSuspendTaint(false),
mMediaTracksConstructed(false),
mVisibilityState(Visibility::UNTRACKED),
mErrorSink(new ErrorSink(this)),
mAudioChannelWrapper(new AudioChannelAgentCallback(this, mAudioChannel))
@ -7341,7 +7342,11 @@ HTMLMediaElement::GetDocument() const
void
HTMLMediaElement::ConstructMediaTracks(const MediaInfo* aInfo)
{
MOZ_ASSERT(aInfo);
if (mMediaTracksConstructed || !aInfo) {
return;
}
mMediaTracksConstructed = true;
AudioTrackList* audioList = AudioTracks();
if (audioList && aInfo->HasAudio()) {
@ -7366,15 +7371,15 @@ HTMLMediaElement::ConstructMediaTracks(const MediaInfo* aInfo)
void
HTMLMediaElement::RemoveMediaTracks()
{
AudioTrackList* audioList = AudioTracks();
if (audioList) {
audioList->RemoveTracks();
if (mAudioTrackList) {
mAudioTrackList->RemoveTracks();
}
VideoTrackList* videoList = VideoTracks();
if (videoList) {
videoList->RemoveTracks();
if (mVideoTrackList) {
mVideoTrackList->RemoveTracks();
}
mMediaTracksConstructed = false;
}
class MediaElementGMPCrashHelper : public GMPCrashHelper

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

@ -1747,6 +1747,10 @@ private:
// participate in video decoder suspending.
bool mHasSuspendTaint;
// True if audio tracks and video tracks are constructed and added into the
// track list, false if all tracks are removed from the track list.
bool mMediaTracksConstructed;
Visibility mVisibilityState;
UniquePtr<ErrorSink> mErrorSink;

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

@ -385,7 +385,6 @@ MediaDecoder::MediaDecoder(MediaDecoderOwner* aOwner)
, mPlaybackStatistics(new MediaChannelStatistics())
, mPinnedForSeek(false)
, mMinimizePreroll(false)
, mMediaTracksConstructed(false)
, mFiredMetadataLoaded(false)
, mIsDocumentVisible(false)
, mElementVisibility(Visibility::UNTRACKED)
@ -504,6 +503,9 @@ MediaDecoder::Shutdown()
mResource->Close();
}
// Ask the owner to remove its audio/video tracks.
GetOwner()->RemoveMediaTracks();
ChangeState(PLAY_STATE_SHUTDOWN);
mOwner = nullptr;
}
@ -774,7 +776,7 @@ void
MediaDecoder::OnMetadataUpdate(TimedMetadata&& aMetadata)
{
MOZ_ASSERT(NS_IsMainThread());
RemoveMediaTracks();
GetOwner()->RemoveMediaTracks();
MetadataLoaded(nsAutoPtr<MediaInfo>(new MediaInfo(*aMetadata.mInfo)),
Move(aMetadata.mTags),
MediaDecoderEventVisibility::Observable);
@ -797,7 +799,7 @@ MediaDecoder::MetadataLoaded(nsAutoPtr<MediaInfo> aInfo,
mMediaSeekable = aInfo->mMediaSeekable;
mMediaSeekableOnlyInBufferedRanges = aInfo->mMediaSeekableOnlyInBufferedRanges;
mInfo = aInfo.forget();
ConstructMediaTracks();
GetOwner()->ConstructMediaTracks(mInfo);
// Make sure the element and the frame (if any) are told about
// our new size.
@ -1164,9 +1166,9 @@ MediaDecoder::ChangeState(PlayState aState)
mPlayState = aState;
if (mPlayState == PLAY_STATE_PLAYING) {
ConstructMediaTracks();
GetOwner()->ConstructMediaTracks(mInfo);
} else if (IsEnded()) {
RemoveMediaTracks();
GetOwner()->RemoveMediaTracks();
}
}
@ -1709,32 +1711,6 @@ MediaDecoder::GetOwner() const
return mOwner;
}
void
MediaDecoder::ConstructMediaTracks()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_DIAGNOSTIC_ASSERT(!IsShutdown());
if (mMediaTracksConstructed || !mInfo) {
return;
}
GetOwner()->ConstructMediaTracks(mInfo);
mMediaTracksConstructed = true;
}
void
MediaDecoder::RemoveMediaTracks()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_DIAGNOSTIC_ASSERT(!IsShutdown());
GetOwner()->RemoveMediaTracks();
mMediaTracksConstructed = false;
}
MediaDecoderOwner::NextFrameStatus
MediaDecoder::NextFrameBufferedStatus()
{

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

@ -387,17 +387,6 @@ private:
// change. Call on the main thread only.
virtual void ChangeState(PlayState aState);
// Called from MetadataLoaded(). Ask its owner to create audio/video tracks
// and adds them to its owner's audio/video track list.
// Call on the main thread only.
void ConstructMediaTracks();
// Ask its owner to remove all audio tracks and video tracks that are
// previously added into the track list.
// Call on the main thread only.
void RemoveMediaTracks();
// Called when the video has completed playing.
// Call on the main thread only.
void PlaybackEnded();
@ -685,11 +674,6 @@ protected:
// or play the media again.
bool mMinimizePreroll;
// True if audio tracks and video tracks are constructed and added into the
// owenr's track list, false if all tracks are removed from the owner's track
// list.
bool mMediaTracksConstructed;
// True if we've already fired metadataloaded.
bool mFiredMetadataLoaded;

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

@ -1168,6 +1168,14 @@ class RTCPeerConnection {
this._impl.selectSsrc(receiver.track, ssrcIndex);
}
mozAddRIDExtension(receiver, extensionId) {
this._impl.addRIDExtension(receiver.track, extensionId);
}
mozAddRIDFilter(receiver, rid) {
this._impl.addRIDFilter(receiver.track, rid);
}
get localDescription() {
this._checkClosed();
let sdp = this._impl.localDescription;

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

@ -192,12 +192,10 @@ skip-if = toolkit == 'android'
skip-if = toolkit == 'android'
[test_peerConnection_scaleResolution.html]
skip-if = (android_version == '18') # android(Bug 1189784, timeouts on 4.3 emulator)
# disable test_peerConnection_simulcastOffer.html for Bug 1351590
#[test_peerConnection_simulcastOffer.html]
#skip-if = android_version # no simulcast support on android
# disable test_peerConnection_simulcastAnswer.html for Bug 1351531
#[test_peerConnection_simulcastAnswer.html]
#skip-if = android_version # no simulcast support on android
[test_peerConnection_simulcastOffer.html]
skip-if = android_version # no simulcast support on android
[test_peerConnection_simulcastAnswer.html]
skip-if = android_version # no simulcast support on android
#[test_peerConnection_relayOnly.html]
[test_peerConnection_callbacks.html]
skip-if = toolkit == 'android' # android(Bug 1189784, timeouts on 4.3 emulator)

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

@ -16,12 +16,20 @@
var test;
var pushPrefs = (...p) => SpecialPowers.pushPrefEnv({set: p});
function selectRecvSsrc(pc, index) {
function addRIDExtension(pc, extensionId) {
var receivers = pc._pc.getReceivers();
is(receivers.length, 1, "We have exactly one RTP receiver");
var receiver = receivers[0];
SpecialPowers.wrap(pc._pc).mozSelectSsrc(receiver, index);
SpecialPowers.wrap(pc._pc).mozAddRIDExtension(receiver, extensionId);
}
function selectRecvRID(pc, rid) {
var receivers = pc._pc.getReceivers();
is(receivers.length, 1, "We have exactly one RTP receiver");
var receiver = receivers[0];
SpecialPowers.wrap(pc._pc).mozAddRIDFilter(receiver, rid);
}
runNetworkTest(() =>
@ -76,11 +84,17 @@
}
]);
test.chain.insertAfter('PC_REMOTE_WAIT_FOR_MEDIA_FLOW',[
function PC_REMOTE_SET_RTP_FIRST_RID(test) {
// Cause pcLocal to filter out everything but the first SSRC. This
// lets only one of the simulcast streams through.
selectRecvSsrc(test.pcLocal, 0);
// do this after set remote description so the MediaPipeline
// has been created.
test.chain.insertAfter('PC_LOCAL_SET_REMOTE_DESCRIPTION',[
function PC_LOCAL_SET_RTP_FIRST_RID(test) {
var extmap_id = test._local_offer.sdp.match(
"a=extmap:([0-9+])/recvonly urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id");
ok(extmap_id, "Local offer has extmap id for simulcast: " + extmap_id[1]);
// Cause pcLocal to filter out everything but RID "bar", only
// allowing one of the simulcast streams through.
addRIDExtension(test.pcLocal, extmap_id[1]);
selectRecvRID(test.pcLocal, "bar");
}
]);
@ -101,9 +115,9 @@
is(vremote.videoHeight, vlocal.videoHeight / 2, "sink is 1/2 height of source");
},
function PC_LOCAL_SET_RTP_SECOND_RID(test) {
// Now, cause pcLocal to filter out everything but the second SSRC.
// This lets only the other simulcast stream through.
selectRecvSsrc(test.pcLocal, 1);
// Now, cause pcLocal to filter out everything but RID "foo", only
// allowing the other simulcast stream through.
selectRecvRID(test.pcLocal, "foo");
},
function PC_LOCAL_WAIT_FOR_SECOND_MEDIA_FLOW(test) {
return test.pcLocal.waitForMediaFlow();

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

@ -16,12 +16,20 @@
var test;
var pushPrefs = (...p) => SpecialPowers.pushPrefEnv({set: p});
function selectRecvSsrc(pc, index) {
function addRIDExtension(pc, extensionId) {
var receivers = pc._pc.getReceivers();
is(receivers.length, 1, "We have exactly one RTP receiver");
var receiver = receivers[0];
SpecialPowers.wrap(pc._pc).mozSelectSsrc(receiver, index);
SpecialPowers.wrap(pc._pc).mozAddRIDExtension(receiver, extensionId);
}
function selectRecvRID(pc, rid) {
var receivers = pc._pc.getReceivers();
is(receivers.length, 1, "We have exactly one RTP receiver");
var receiver = receivers[0];
SpecialPowers.wrap(pc._pc).mozAddRIDFilter(receiver, rid);
}
runNetworkTest(() =>
@ -68,11 +76,17 @@
}
]);
test.chain.insertAfter('PC_REMOTE_WAIT_FOR_MEDIA_FLOW',[
// do this after set local description so the MediaPipeline
// has been created.
test.chain.insertAfter('PC_REMOTE_SET_LOCAL_DESCRIPTION',[
function PC_REMOTE_SET_RTP_FIRST_RID(test) {
// Cause pcRemote to filter out everything but the first SSRC. This
// lets only one of the simulcast streams through.
selectRecvSsrc(test.pcRemote, 0);
var extmap_id = test.originalOffer.sdp.match(
"a=extmap:([0-9+])/sendonly urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id");
ok(extmap_id, "Original offer has extmap id for simulcast: " + extmap_id[1]);
// Cause pcRemote to filter out everything but RID "foo", only
// allowing one of the simulcast streams through.
addRIDExtension(test.pcRemote, extmap_id[1]);
selectRecvRID(test.pcRemote, "foo");
}
]);
@ -89,13 +103,13 @@
ok(vremote, "Should have remote video element for pcRemote");
ok(vlocal.videoWidth > 0, "source width is positive");
ok(vlocal.videoHeight > 0, "source height is positive");
is(vremote.videoWidth, vlocal.videoWidth / 2, "sink is 1/2 width of source");
is(vremote.videoHeight, vlocal.videoHeight / 2, "sink is 1/2 height of source");
is(vremote.videoWidth, vlocal.videoWidth, "sink is same width as source");
is(vremote.videoHeight, vlocal.videoHeight, "sink is same height as source");
},
function PC_REMOTE_SET_RTP_SECOND_RID(test) {
// Now, cause pcRemote to filter out everything but the second SSRC.
// This lets only the other simulcast stream through.
selectRecvSsrc(test.pcRemote, 1);
// Now, cause pcRemote to filter out everything but RID "bar", only
// allowing the other simulcast stream through.
selectRecvRID(test.pcRemote, "bar");
},
function PC_REMOTE_WAIT_FOR_SECOND_MEDIA_FLOW(test) {
return test.pcRemote.waitForMediaFlow();
@ -119,8 +133,8 @@
ok(vremote, "Should have remote video element for pcRemote");
ok(vlocal.videoWidth > 0, "source width is positive");
ok(vlocal.videoHeight > 0, "source height is positive");
is(vremote.videoWidth, vlocal.videoWidth, "sink is same width as source");
is(vremote.videoHeight, vlocal.videoHeight, "sink is same height as source");
is(vremote.videoWidth, vlocal.videoWidth / 2, "sink is 1/2 width of source");
is(vremote.videoHeight, vlocal.videoHeight / 2, "sink is 1/2 height of source");
},
]);

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

@ -44,7 +44,6 @@ skip-if = !crashreporter
skip-if = !crashreporter
[test_bug1028200-7.html]
skip-if = !crashreporter
[test_bug406541.html]
[test_bug532208.html]
[test_bug539565-1.html]
[test_bug539565-2.html]

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

@ -1,100 +0,0 @@
<!doctype html>
<html>
<head>
<title>Test for Bug 406541</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="plugin-utils.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
</head>
<body>
<script type="application/x-child-payload" id="child-payload">
// This is injected into the file:/// origin iframe, see below.
// appletA should spawn, appletB, with a codebase outside the temp directory,
// should not.
var appletA = document.createElement("applet");
var appletB = document.createElement("applet");
var appletC = document.createElement("applet");
appletA.type = appletB.type = appletC.type = "application/x-java-test";
appletB.setAttribute("codebase", "file:///");
appletC.setAttribute("codebase", "./subdir_bug406541/");
document.body.appendChild(appletA);
document.body.appendChild(appletB);
document.body.appendChild(appletC);
function isSpawned(plugin) {
try {
var x = plugin.getJavaCodebase();
return true;
} catch (e) {}
return false;
}
window.parent.postMessage({ "A": isSpawned(appletA),
"B": isSpawned(appletB),
"C": isSpawned(appletC) }, "*");
</script>
<script type="application/javascript">
SimpleTest.waitForExplicitFinish();
setTestPluginEnabledState(SpecialPowers.Ci.nsIPluginTag.STATE_ENABLED,
"Java Test Plug-in");
SpecialPowers.pushPrefEnv({ "set": [
['plugin.java.mime', 'application/x-java-test']
] }, runTest);
function runTest() {
// Create a empty file and point an iframe at it
var Cc = SpecialPowers.Cc;
var Ci = SpecialPowers.Ci;
var file = Cc["@mozilla.org/file/directory_service;1"]
.getService(Ci.nsIProperties)
.get("TmpD", Ci.nsIFile);
var subdir = Cc["@mozilla.org/file/directory_service;1"]
.getService(Ci.nsIProperties)
.get("TmpD", Ci.nsIFile);
file.append("test_bug406541.html");
file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0600);
subdir.append("subdir_bug406541");
subdir.createUnique(Ci.nsIFile.DIRECTORY_TYPE, 0600);
var i = document.createElement("iframe");
var loaded = false;
i.addEventListener("load", function initialLoad() {
if (!loaded) {
// Once loaded, use special powers to point it at the file
SpecialPowers.wrap(i.contentWindow).location.href = "file://" + file.path;
loaded = true;
} else {
// Inject the child-payload script to the file:/// origin. Let it test
// applet spawning and send the results in a postMessage. (Because I
// couldn't get SpecialPowers to let me touch applets cross-origin, then
// gave up.)
var innerdoc = SpecialPowers.wrap(i.contentWindow).document;
var s = innerdoc.createElement("script");
s.type = "text/javascript";
s.textContent = document.getElementById("child-payload").textContent;
var finished = false;
window.onmessage = function(message) {
ok(message.data.A, "Plugin A should spawn");
ok(!message.data.B, "Plugin B should NOT spawn");
ok(message.data.C, "Plugin C should spawn");
file.remove(false);
subdir.remove(false);
finished = true;
SimpleTest.finish();
};
innerdoc.body.appendChild(s);
SimpleTest.executeSoon(function() {
if (!finished) {
ok(finished, "Should have received callback by now");
SimpleTest.finish();
}
});
}
});
document.body.appendChild(i);
}
</script>
</body>
</html>

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

@ -9,6 +9,7 @@
interface ListBoxObject : BoxObject {
long getRowCount();
long getRowHeight();
long getNumberOfVisibleRows();
long getIndexOfFirstVisibleRow();

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

@ -64,6 +64,8 @@ interface PeerConnectionImpl {
sequence<MediaStream> getRemoteStreams();
void selectSsrc(MediaStreamTrack recvTrack, unsigned short ssrcIndex);
void addRIDExtension(MediaStreamTrack recvTrack, unsigned short extensionId);
void addRIDFilter(MediaStreamTrack recvTrack, DOMString rid);
/* As the ICE candidates roll in this one should be called each time
* in order to keep the candidate list up-to-date for the next SDP-related

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

@ -121,6 +121,10 @@ interface RTCPeerConnection : EventTarget {
[ChromeOnly]
void mozSelectSsrc(RTCRtpReceiver receiver, unsigned short ssrcIndex);
[ChromeOnly]
void mozAddRIDExtension(RTCRtpReceiver receiver, unsigned short extensionId);
[ChromeOnly]
void mozAddRIDFilter(RTCRtpReceiver receiver, DOMString rid);
void close ();
attribute EventHandler onnegotiationneeded;

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

@ -248,13 +248,15 @@ nsXBLResourceLoader::NotifyBoundElements()
if (shell) {
nsIFrame* childFrame = content->GetPrimaryFrame();
if (!childFrame) {
// Check to see if it's in the undisplayed content map.
//
// FIXME(emilio, bug 1359384): What about display: contents stuff?
// Looks like this would be inefficient in that case?
// Check to see if it's in the undisplayed content map, or the
// display: contents map.
nsStyleContext* sc =
shell->FrameManager()->GetUndisplayedContent(content);
if (!sc) {
sc = shell->FrameManager()->GetDisplayContentsStyleFor(content);
}
if (!sc) {
shell->PostRecreateFramesFor(content->AsElement());
}

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

@ -504,6 +504,9 @@ public:
/**
* Returns a DataSourceSurface with the same data as this one, but
* guaranteed to have surface->GetType() == SurfaceType::DATA.
*
* The returning surface might be null, because of OOM or gfx device reset.
* The caller needs to do null-check before using it.
*/
virtual already_AddRefed<DataSourceSurface> GetDataSurface() override;

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

@ -2713,6 +2713,7 @@ gfxFont::ShapeText(DrawTarget *aDrawTarget,
if (gfxPlatform::GetPlatform()->UseGraphiteShaping()) {
if (!mGraphiteShaper) {
mGraphiteShaper = MakeUnique<gfxGraphiteShaper>(this);
Telemetry::ScalarAdd(Telemetry::ScalarID::BROWSER_USAGE_GRAPHITE, 1);
}
ok = mGraphiteShaper->ShapeText(aDrawTarget, aText, aOffset, aLength,
aScript, aVertical, aRounding,

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

@ -16,7 +16,7 @@ struct nsCSSSelector;
// Defines for various style related constants
enum nsChangeHint {
enum nsChangeHint : uint32_t {
nsChangeHint_Empty = 0,
// change was visual only (e.g., COLOR=)
@ -472,7 +472,7 @@ NS_RemoveSubsumedHints(nsChangeHint aOurChange, nsChangeHint aHintsHandled)
* NOTE: When adding new restyle hints, please also add them to
* RestyleManager::RestyleHintToString.
*/
enum nsRestyleHint {
enum nsRestyleHint : uint32_t {
// Rerun selector matching on the element. If a new style context
// results, update the style contexts of descendants. (Irrelevant if
// eRestyle_Subtree is also set, since that implies a superset of the

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

@ -636,7 +636,7 @@ load 1233191.html
asserts-if(stylo,0-15) load 1271765.html # bug 1324684
asserts(2) load 1272983-1.html # bug 586628
asserts(2) load 1272983-2.html # bug 586628
asserts-if(stylo,2) load 1275059.html # Bug 1360221
load 1275059.html
load 1278007.html
load 1278080.html
load 1279814.html

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

@ -5526,7 +5526,7 @@ nsTextFrame::UpdateTextEmphasis(WritingMode aWM, PropertyProvider& aProvider)
nsStyleContext* styleContext = StyleContext();
bool isTextCombined = styleContext->IsTextCombined();
if (isTextCombined) {
styleContext = styleContext->GetParent();
styleContext = GetParent()->StyleContext();
}
RefPtr<nsFontMetrics> fm = nsLayoutUtils::
GetFontMetricsOfEmphasisMarks(styleContext, GetFontSizeInflation());

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

@ -354,7 +354,7 @@ static inline void PrintAsStringNewline(const char *s = nullptr) {
fflush (stderr);
}
static inline void PrintAsFormatString(const char *fmt, ...) {
static inline MOZ_FORMAT_PRINTF(1, 2) void PrintAsFormatString(const char *fmt, ...) {
va_list vl;
va_start(vl, fmt);
vfprintf (stderr, fmt, vl);
@ -368,7 +368,7 @@ static inline void PrintAsString(const mozilla::gfx::Rect& r) {}
static inline void PrintAsString(const mozilla::gfx::Float f) {}
static inline void PrintAsString(const char *s) {}
static inline void PrintAsStringNewline(const char *s = nullptr) {}
static inline void PrintAsFormatString(const char *fmt, ...) {}
static inline MOZ_FORMAT_PRINTF(1, 2) void PrintAsFormatString(const char *fmt, ...) {}
#endif
} // namespace mozilla

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

@ -756,10 +756,10 @@ fuzzy-if(OSX||winWidget,93,300) == css-writing-modes-3/float-vrl-006.xht css21/r
fuzzy-if(OSX||winWidget,93,300) == css-writing-modes-3/float-vrl-008.xht css21/reference/ref-filled-green-100px-square.xht
fuzzy-if(OSX||winWidget,93,300) == css-writing-modes-3/float-vrl-010.xht css21/reference/ref-filled-green-100px-square.xht
fuzzy-if(OSX||winWidget,93,300) == css-writing-modes-3/float-vrl-012.xht css21/reference/ref-filled-green-100px-square.xht
fails-if(stylo) != css-writing-modes-3/full-width-001.html css-writing-modes-3/reference/full-width-001-horizontal-notref.html
fails-if(stylo) != css-writing-modes-3/full-width-001.html css-writing-modes-3/reference/full-width-001-nofullwidth-notref.html
fails-if(stylo) != css-writing-modes-3/full-width-002.html css-writing-modes-3/reference/full-width-002-notcu-notref.html
fails-if(stylo) != css-writing-modes-3/full-width-002.html css-writing-modes-3/reference/full-width-002-horizontal-notref.html
!= css-writing-modes-3/full-width-001.html css-writing-modes-3/reference/full-width-001-horizontal-notref.html
!= css-writing-modes-3/full-width-001.html css-writing-modes-3/reference/full-width-001-nofullwidth-notref.html
!= css-writing-modes-3/full-width-002.html css-writing-modes-3/reference/full-width-002-notcu-notref.html
!= css-writing-modes-3/full-width-002.html css-writing-modes-3/reference/full-width-002-horizontal-notref.html
skip != css-writing-modes-3/full-width-003.html css-writing-modes-3/reference/full-width-002-notcu-notref.html
skip != css-writing-modes-3/full-width-003.html css-writing-modes-3/reference/full-width-002-horizontal-notref.html
fuzzy-if(OSX||winWidget,62,404) == css-writing-modes-3/height-width-inline-non-replaced-vlr-003.xht css21/reference/ref-filled-green-100px-square.xht
@ -937,15 +937,15 @@ fuzzy-if(OSX||winWidget,215,780) == css-writing-modes-3/text-baseline-vrl-002.xh
fuzzy-if(OSX||winWidget,215,780) == css-writing-modes-3/text-baseline-vrl-004.xht css-writing-modes-3/text-baseline-vrl-002-ref.xht
fuzzy-if(OSX||winWidget,215,780) == css-writing-modes-3/text-baseline-vrl-006.xht css-writing-modes-3/text-baseline-vrl-006-ref.xht
fuzzy-if(OSX,15,16) == css-writing-modes-3/text-combine-upright-decorations-001.html css-writing-modes-3/reference/text-combine-upright-decorations-001.html
fails-if(stylo) == css-writing-modes-3/text-combine-upright-inherit-all-001.html css-writing-modes-3/reference/text-combine-upright-inherit-all-001.html
fails-if(stylo) == css-writing-modes-3/text-combine-upright-inherit-all-002.html css-writing-modes-3/reference/text-combine-upright-inherit-all-002.html
fails-if(stylo) == css-writing-modes-3/text-combine-upright-layout-rules-001.html css-writing-modes-3/reference/text-combine-upright-layout-rules-001-ref.html
fails-if(stylo) == css-writing-modes-3/text-combine-upright-line-breaking-rules-001.html css-writing-modes-3/text-combine-upright-line-breaking-rules-001-ref.html
fuzzy(255,960) fails-if(stylo) == css-writing-modes-3/text-combine-upright-value-all-001.html css-writing-modes-3/reference/text-combine-upright-value-single-character.html
fuzzy(255,960) fails-if(stylo) == css-writing-modes-3/text-combine-upright-value-all-002.html css-writing-modes-3/reference/vertical-ahem-1x1-ref.html
fuzzy(255,960) fails-if(stylo) != css-writing-modes-3/text-combine-upright-value-all-002.html css-writing-modes-3/reference/horizontal-ahem-1x1-notref.html
fuzzy(255,960) fails-if(stylo) == css-writing-modes-3/text-combine-upright-value-all-003.html css-writing-modes-3/reference/vertical-ahem-1x1-ref.html
fuzzy(255,960) fails-if(stylo) != css-writing-modes-3/text-combine-upright-value-all-003.html css-writing-modes-3/reference/horizontal-ahem-1x1-notref.html
== css-writing-modes-3/text-combine-upright-inherit-all-001.html css-writing-modes-3/reference/text-combine-upright-inherit-all-001.html
== css-writing-modes-3/text-combine-upright-inherit-all-002.html css-writing-modes-3/reference/text-combine-upright-inherit-all-002.html
== css-writing-modes-3/text-combine-upright-layout-rules-001.html css-writing-modes-3/reference/text-combine-upright-layout-rules-001-ref.html
== css-writing-modes-3/text-combine-upright-line-breaking-rules-001.html css-writing-modes-3/text-combine-upright-line-breaking-rules-001-ref.html
fuzzy(255,960) == css-writing-modes-3/text-combine-upright-value-all-001.html css-writing-modes-3/reference/text-combine-upright-value-single-character.html
fuzzy(255,960) == css-writing-modes-3/text-combine-upright-value-all-002.html css-writing-modes-3/reference/vertical-ahem-1x1-ref.html
fuzzy(255,960) != css-writing-modes-3/text-combine-upright-value-all-002.html css-writing-modes-3/reference/horizontal-ahem-1x1-notref.html
fuzzy(255,960) == css-writing-modes-3/text-combine-upright-value-all-003.html css-writing-modes-3/reference/vertical-ahem-1x1-ref.html
fuzzy(255,960) != css-writing-modes-3/text-combine-upright-value-all-003.html css-writing-modes-3/reference/horizontal-ahem-1x1-notref.html
skip == css-writing-modes-3/text-combine-upright-value-digits2-001.html css-writing-modes-3/reference/text-combine-upright-value-single-character.html
skip == css-writing-modes-3/text-combine-upright-value-digits2-002.html css-writing-modes-3/reference/vertical-ahem-1x1-ref.html
skip != css-writing-modes-3/text-combine-upright-value-digits2-002.html css-writing-modes-3/reference/horizontal-ahem-1x1-notref.html

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

@ -14,8 +14,8 @@ skip-if(stylo) == ruby-inlinize-blocks-005.html ruby-inlinize-blocks-005-ref.htm
# Tests for ruby with text-combine-upright
fails-if(stylo) == ruby-text-combine-upright-001a.html ruby-text-combine-upright-001-ref.html
fails-if(stylo) == ruby-text-combine-upright-001b.html ruby-text-combine-upright-001-ref.html
fails-if(stylo) == ruby-text-combine-upright-002a.html ruby-text-combine-upright-002-ref.html
fails-if(stylo) == ruby-text-combine-upright-002b.html ruby-text-combine-upright-002-ref.html
== ruby-text-combine-upright-002a.html ruby-text-combine-upright-002-ref.html
== ruby-text-combine-upright-002b.html ruby-text-combine-upright-002-ref.html
# Tests for nested ruby
fails-if(stylo) == nested-ruby-pairing-001.html nested-ruby-pairing-001-ref.html

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

@ -2,14 +2,14 @@ default-preferences pref(layout.css.text-combine-upright.enabled,true)
== text-combine-upright-break-inside-001.html text-combine-upright-break-inside-001-ref.html
== text-combine-upright-break-inside-001a.html text-combine-upright-break-inside-001-ref.html
fails-if(stylo) == text-combine-upright-compression-001.html text-combine-upright-compression-001-ref.html
fails-if(stylo) == text-combine-upright-compression-002.html text-combine-upright-compression-002-ref.html
fails-if(stylo) == text-combine-upright-compression-003.html text-combine-upright-compression-003-ref.html
fails-if(stylo) == text-combine-upright-compression-004.html text-combine-upright-compression-004-ref.html
fails-if(stylo) == text-combine-upright-compression-005.html text-combine-upright-compression-005-ref.html
fails-if(stylo) == text-combine-upright-compression-005a.html text-combine-upright-compression-005-ref.html
fails-if(stylo) == text-combine-upright-compression-006.html text-combine-upright-compression-006-ref.html
fails-if(stylo) == text-combine-upright-compression-006a.html text-combine-upright-compression-006-ref.html
== text-combine-upright-compression-001.html text-combine-upright-compression-001-ref.html
== text-combine-upright-compression-002.html text-combine-upright-compression-002-ref.html
== text-combine-upright-compression-003.html text-combine-upright-compression-003-ref.html
== text-combine-upright-compression-004.html text-combine-upright-compression-004-ref.html
== text-combine-upright-compression-005.html text-combine-upright-compression-005-ref.html
== text-combine-upright-compression-005a.html text-combine-upright-compression-005-ref.html
== text-combine-upright-compression-006.html text-combine-upright-compression-006-ref.html
== text-combine-upright-compression-006a.html text-combine-upright-compression-006-ref.html
== text-combine-upright-compression-007.html text-combine-upright-compression-007-ref.html
== text-orientation-upright-directionality-001.html text-orientation-upright-directionality-001-ref.html

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

@ -0,0 +1,60 @@
/* -*- 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/dom/CSSSupportsRule.h"
#include "mozilla/dom/CSSSupportsRuleBinding.h"
using namespace mozilla::css;
namespace mozilla {
namespace dom {
NS_IMPL_ADDREF_INHERITED(CSSSupportsRule, css::ConditionRule)
NS_IMPL_RELEASE_INHERITED(CSSSupportsRule, css::ConditionRule)
// QueryInterface implementation for CSSSupportsRule
NS_INTERFACE_MAP_BEGIN(CSSSupportsRule)
NS_INTERFACE_MAP_ENTRY(nsIDOMCSSGroupingRule)
NS_INTERFACE_MAP_ENTRY(nsIDOMCSSConditionRule)
NS_INTERFACE_MAP_ENTRY(nsIDOMCSSSupportsRule)
NS_INTERFACE_MAP_END_INHERITING(ConditionRule)
// nsIDOMCSSGroupingRule methods
NS_IMETHODIMP
CSSSupportsRule::GetCssRules(nsIDOMCSSRuleList** aRuleList)
{
return GroupRule::GetCssRules(aRuleList);
}
NS_IMETHODIMP
CSSSupportsRule::InsertRule(const nsAString & aRule, uint32_t aIndex, uint32_t* _retval)
{
return GroupRule::InsertRule(aRule, aIndex, _retval);
}
NS_IMETHODIMP
CSSSupportsRule::DeleteRule(uint32_t aIndex)
{
return GroupRule::DeleteRule(aIndex);
}
void
CSSSupportsRule::SetConditionText(const nsAString& aConditionText,
ErrorResult& aRv)
{
aRv = SetConditionText(aConditionText);
}
/* virtual */ JSObject*
CSSSupportsRule::WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto)
{
return CSSSupportsRuleBinding::Wrap(aCx, this, aGivenProto);
}
} // namespace dom
} // namespace mozilla

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

@ -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_CSSSupportsRule_h
#define mozilla_dom_CSSSupportsRule_h
#include "mozilla/css/GroupRule.h"
#include "nsIDOMCSSSupportsRule.h"
namespace mozilla {
namespace dom {
class CSSSupportsRule : public css::ConditionRule
, public nsIDOMCSSSupportsRule
{
protected:
using ConditionRule::ConditionRule;
virtual ~CSSSupportsRule() {}
public:
NS_DECL_ISUPPORTS_INHERITED
int32_t GetType() const override { return css::Rule::SUPPORTS_RULE; }
using Rule::GetType;
// nsIDOMCSSGroupingRule interface
NS_DECL_NSIDOMCSSGROUPINGRULE
// nsIDOMCSSConditionRule interface
NS_IMETHOD SetConditionText(const nsAString& aConditionText) override = 0;
// nsIDOMCSSSupportsRule interface
NS_DECL_NSIDOMCSSSUPPORTSRULE
// WebIDL interface
uint16_t Type() const override { return nsIDOMCSSRule::SUPPORTS_RULE; }
// Our XPCOM GetConditionText is OK
void SetConditionText(const nsAString& aConditionText,
ErrorResult& aRv) final;
JSObject* WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_CSSSupportsRule_h

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

@ -18,3 +18,4 @@ SERVO_ARC_TYPE(MediaList, RawServoMediaList)
SERVO_ARC_TYPE(MediaRule, RawServoMediaRule)
SERVO_ARC_TYPE(NamespaceRule, RawServoNamespaceRule)
SERVO_ARC_TYPE(PageRule, RawServoPageRule)
SERVO_ARC_TYPE(SupportsRule, RawServoSupportsRule)

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

@ -98,10 +98,16 @@ SERVO_BINDING_FUNC(Servo_CssRules_DeleteRule, nsresult,
RawServo##type_##RuleBorrowed rule, nsACString* result) \
SERVO_BINDING_FUNC(Servo_##type_##Rule_GetCssText, void, \
RawServo##type_##RuleBorrowed rule, nsAString* result)
#define GROUP_RULE_FUNCS(type_) \
BASIC_RULE_FUNCS(type_) \
SERVO_BINDING_FUNC(Servo_##type_##Rule_GetRules, ServoCssRulesStrong, \
RawServo##type_##RuleBorrowed rule)
BASIC_RULE_FUNCS(Style)
BASIC_RULE_FUNCS(Media)
GROUP_RULE_FUNCS(Media)
BASIC_RULE_FUNCS(Namespace)
BASIC_RULE_FUNCS(Page)
GROUP_RULE_FUNCS(Supports)
#undef GROUP_RULE_FUNCS
#undef BASIC_RULE_FUNCS
SERVO_BINDING_FUNC(Servo_CssRules_GetFontFaceRuleAt, nsCSSFontFaceRule*,
ServoCssRulesBorrowed rules, uint32_t index)
@ -114,8 +120,6 @@ SERVO_BINDING_FUNC(Servo_StyleRule_GetSelectorText, void,
RawServoStyleRuleBorrowed rule, nsAString* result)
SERVO_BINDING_FUNC(Servo_MediaRule_GetMedia, RawServoMediaListStrong,
RawServoMediaRuleBorrowed rule)
SERVO_BINDING_FUNC(Servo_MediaRule_GetRules, ServoCssRulesStrong,
RawServoMediaRuleBorrowed rule)
SERVO_BINDING_FUNC(Servo_NamespaceRule_GetPrefix, nsIAtom*,
RawServoNamespaceRuleBorrowed rule)
SERVO_BINDING_FUNC(Servo_NamespaceRule_GetURI, nsIAtom*,
@ -125,6 +129,8 @@ SERVO_BINDING_FUNC(Servo_PageRule_GetStyle, RawServoDeclarationBlockStrong,
SERVO_BINDING_FUNC(Servo_PageRule_SetStyle, void,
RawServoPageRuleBorrowed rule,
RawServoDeclarationBlockBorrowed declarations)
SERVO_BINDING_FUNC(Servo_SupportsRule_GetConditionText, void,
RawServoSupportsRuleBorrowed rule, nsAString* result)
// Animations API
SERVO_BINDING_FUNC(Servo_ParseProperty,
@ -332,7 +338,8 @@ SERVO_BINDING_FUNC(Servo_ComputedValues_GetForAnonymousBox,
RawServoStyleSetBorrowed set)
SERVO_BINDING_FUNC(Servo_ComputedValues_Inherit, ServoComputedValuesStrong,
RawServoStyleSetBorrowed set,
ServoComputedValuesBorrowedOrNull parent_style)
ServoComputedValuesBorrowedOrNull parent_style,
mozilla::InheritTarget target)
// Initialize Servo components. Should be called exactly once at startup.
SERVO_BINDING_FUNC(Servo_Initialize, void,

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

@ -13,6 +13,7 @@
#include "mozilla/ServoMediaRule.h"
#include "mozilla/ServoNamespaceRule.h"
#include "mozilla/ServoPageRule.h"
#include "mozilla/ServoSupportsRule.h"
namespace mozilla {
@ -89,6 +90,7 @@ ServoCSSRuleList::GetRule(uint32_t aIndex)
CASE_RULE(MEDIA, Media)
CASE_RULE(NAMESPACE, Namespace)
CASE_RULE(PAGE, Page)
CASE_RULE(SUPPORTS, Supports)
#undef CASE_RULE
case nsIDOMCSSRule::FONT_FACE_RULE: {
// Returns a borrowed nsCSSFontFaceRule object directly, so we
@ -213,8 +215,9 @@ ServoCSSRuleList::FillStyleRuleHashtable(StyleRuleHashtable& aTable)
ServoStyleRule* castedRule = static_cast<ServoStyleRule*>(GetRule(i));
RawServoStyleRule* rawRule = castedRule->Raw();
aTable.Put(rawRule, castedRule);
} else if (type == nsIDOMCSSRule::MEDIA_RULE) {
ServoMediaRule* castedRule = static_cast<ServoMediaRule*>(GetRule(i));
} else if (type == nsIDOMCSSRule::MEDIA_RULE ||
type == nsIDOMCSSRule::SUPPORTS_RULE) {
GroupRule* castedRule = static_cast<GroupRule*>(GetRule(i));
// Call this method recursively on the ServoCSSRuleList in the rule.
ServoCSSRuleList* castedRuleList = static_cast<ServoCSSRuleList*>(

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

@ -366,7 +366,9 @@ ServoStyleSet::ResolveStyleForText(nsIContent* aTextNode,
const ServoComputedValues* parentComputedValues =
aParentContext->StyleSource().AsServoComputedValues();
RefPtr<ServoComputedValues> computedValues =
Servo_ComputedValues_Inherit(mRawSet.get(), parentComputedValues).Consume();
Servo_ComputedValues_Inherit(mRawSet.get(),
parentComputedValues,
InheritTarget::Text).Consume();
return GetContext(computedValues.forget(), aParentContext,
nsCSSAnonBoxes::mozText,
@ -377,9 +379,13 @@ ServoStyleSet::ResolveStyleForText(nsIContent* aTextNode,
already_AddRefed<nsStyleContext>
ServoStyleSet::ResolveStyleForFirstLetterContinuation(nsStyleContext* aParentContext)
{
const ServoComputedValues* parent = aParentContext->StyleSource().AsServoComputedValues();
const ServoComputedValues* parent =
aParentContext->StyleSource().AsServoComputedValues();
RefPtr<ServoComputedValues> computedValues =
Servo_ComputedValues_Inherit(mRawSet.get(), parent).Consume();
Servo_ComputedValues_Inherit(mRawSet.get(),
parent,
InheritTarget::FirstLetterContinuation)
.Consume();
MOZ_ASSERT(computedValues);
return GetContext(computedValues.forget(), aParentContext,
@ -399,7 +405,10 @@ ServoStyleSet::ResolveStyleForPlaceholder()
}
RefPtr<ServoComputedValues> computedValues =
Servo_ComputedValues_Inherit(mRawSet.get(), nullptr).Consume();
Servo_ComputedValues_Inherit(mRawSet.get(),
nullptr,
InheritTarget::PlaceholderFrame)
.Consume();
MOZ_ASSERT(computedValues);
RefPtr<nsStyleContext> retval =

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

@ -0,0 +1,96 @@
/* -*- 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/. */
/* representation of CSSSupportsRule for stylo */
#include "mozilla/ServoSupportsRule.h"
#include "mozilla/ServoBindings.h"
using namespace mozilla::dom;
namespace mozilla {
ServoSupportsRule::ServoSupportsRule(RefPtr<RawServoSupportsRule> aRawRule)
: CSSSupportsRule(Servo_SupportsRule_GetRules(aRawRule).Consume())
, mRawRule(Move(aRawRule))
{
}
ServoSupportsRule::~ServoSupportsRule()
{
}
NS_IMPL_ADDREF_INHERITED(ServoSupportsRule, CSSSupportsRule)
NS_IMPL_RELEASE_INHERITED(ServoSupportsRule, CSSSupportsRule)
// QueryInterface implementation for SupportsRule
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(ServoSupportsRule)
NS_INTERFACE_MAP_END_INHERITING(CSSSupportsRule)
/* virtual */ already_AddRefed<css::Rule>
ServoSupportsRule::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 ServoSupportsRule");
return nullptr;
}
/* virtual */ bool
ServoSupportsRule::UseForPresentation(nsPresContext* aPresContext,
nsMediaQueryResultCacheKey& aKey)
{
// GroupRule::UseForPresentation is only used in nsCSSRuleProcessor,
// so this should never be called.
MOZ_ASSERT_UNREACHABLE("Shouldn't be calling UseForPresentation");
return false;
}
#ifdef DEBUG
/* virtual */ void
ServoSupportsRule::List(FILE* out, int32_t aIndent) const
{
nsAutoCString str;
for (int32_t i = 0; i < aIndent; i++) {
str.AppendLiteral(" ");
}
Servo_SupportsRule_Debug(mRawRule, &str);
fprintf_stderr(out, "%s\n", str.get());
}
#endif
// nsIDOMCSSConditionRule methods
NS_IMETHODIMP
ServoSupportsRule::GetConditionText(nsAString& aConditionText)
{
Servo_SupportsRule_GetConditionText(mRawRule, &aConditionText);
return NS_OK;
}
NS_IMETHODIMP
ServoSupportsRule::SetConditionText(const nsAString& aConditionText)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* virtual */ void
ServoSupportsRule::GetCssTextImpl(nsAString& aCssText) const
{
Servo_SupportsRule_GetCssText(mRawRule, &aCssText);
}
/* virtual */ size_t
ServoSupportsRule::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)
const
{
// TODO Implement this!
return aMallocSizeOf(this);
}
} // namespace mozilla

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

@ -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/. */
/* representation of CSSSupportsRule for stylo */
#ifndef mozilla_ServoSupportsRule_h
#define mozilla_ServoSupportsRule_h
#include "mozilla/dom/CSSSupportsRule.h"
#include "mozilla/ServoBindingTypes.h"
namespace mozilla {
class ServoSupportsRule final : public dom::CSSSupportsRule
{
public:
explicit ServoSupportsRule(RefPtr<RawServoSupportsRule> aRawRule);
NS_DECL_ISUPPORTS_INHERITED
already_AddRefed<css::Rule> Clone() const override;
bool UseForPresentation(nsPresContext* aPresContext,
nsMediaQueryResultCacheKey& aKey) final;
#ifdef DEBUG
void List(FILE* out = stdout, int32_t aIndent = 0) const final;
#endif
RawServoSupportsRule* Raw() const { return mRawRule; }
// nsIDOMCSSConditionRule interface
NS_DECL_NSIDOMCSSCONDITIONRULE
// WebIDL interface
void GetCssTextImpl(nsAString& aCssText) const override;
using CSSSupportsRule::SetConditionText;
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)
const override;
private:
virtual ~ServoSupportsRule();
RefPtr<RawServoSupportsRule> mRawRule;
};
} // namespace mozilla
#endif // mozilla_ServoSupportsRule_h

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

@ -71,6 +71,8 @@ enum class UpdateAnimationsTasks : uint8_t {
CascadeResults = 1 << 3,
};
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(UpdateAnimationsTasks)
// The mode to use when parsing lengths.
enum class LengthParsingMode {
// In CSS, lengths must have units, except for zero values, where the unit can
@ -83,7 +85,16 @@ enum class LengthParsingMode {
SVG,
};
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(UpdateAnimationsTasks)
// The kind of style we're generating when requesting Servo to give us an
// inherited style.
enum class InheritTarget {
// We're requesting a text style.
Text,
// We're requesting a first-letter continuation frame style.
FirstLetterContinuation,
// We're requesting a style for a placeholder frame.
PlaceholderFrame,
};
} // namespace mozilla

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

@ -112,6 +112,7 @@ EXPORTS.mozilla += [
'ServoStyleRule.h',
'ServoStyleSet.h',
'ServoStyleSheet.h',
'ServoSupportsRule.h',
'ServoTypes.h',
'ServoUtils.h',
'SheetType.h',
@ -134,6 +135,7 @@ EXPORTS.mozilla.dom += [
'CSSNamespaceRule.h',
'CSSPageRule.h',
'CSSRuleList.h',
'CSSSupportsRule.h',
'CSSValue.h',
'FontFace.h',
'FontFaceSet.h',
@ -165,6 +167,7 @@ UNIFIED_SOURCES += [
'CSSPageRule.cpp',
'CSSRuleList.cpp',
'CSSStyleSheet.cpp',
'CSSSupportsRule.cpp',
'CSSVariableDeclarations.cpp',
'CSSVariableResolver.cpp',
'CSSVariableValues.cpp',
@ -231,6 +234,7 @@ UNIFIED_SOURCES += [
'ServoStyleRule.cpp',
'ServoStyleSet.cpp',
'ServoStyleSheet.cpp',
'ServoSupportsRule.cpp',
'StyleAnimationValue.cpp',
'StyleRule.cpp',
'StyleSheet.cpp',

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

@ -36,7 +36,6 @@
#include "nsDOMClassInfoID.h"
#include "mozilla/dom/CSSStyleDeclarationBinding.h"
#include "mozilla/dom/CSSImportRuleBinding.h"
#include "mozilla/dom/CSSSupportsRuleBinding.h"
#include "mozilla/dom/CSSMozDocumentRuleBinding.h"
#include "mozilla/dom/CSSFontFaceRuleBinding.h"
#include "mozilla/dom/CSSFontFeatureValuesRuleBinding.h"
@ -2272,7 +2271,7 @@ namespace mozilla {
CSSSupportsRule::CSSSupportsRule(bool aConditionMet,
const nsString& aCondition,
uint32_t aLineNumber, uint32_t aColumnNumber)
: css::ConditionRule(aLineNumber, aColumnNumber)
: dom::CSSSupportsRule(aLineNumber, aColumnNumber)
, mUseGroup(aConditionMet)
, mCondition(aCondition)
{
@ -2283,7 +2282,7 @@ CSSSupportsRule::~CSSSupportsRule()
}
CSSSupportsRule::CSSSupportsRule(const CSSSupportsRule& aCopy)
: css::ConditionRule(aCopy),
: dom::CSSSupportsRule(aCopy),
mUseGroup(aCopy.mUseGroup),
mCondition(aCopy.mCondition)
{
@ -2307,12 +2306,6 @@ CSSSupportsRule::List(FILE* out, int32_t aIndent) const
}
#endif
/* virtual */ int32_t
CSSSupportsRule::GetType() const
{
return Rule::SUPPORTS_RULE;
}
/* virtual */ already_AddRefed<mozilla::css::Rule>
CSSSupportsRule::Clone() const
{
@ -2332,16 +2325,7 @@ NS_IMPL_RELEASE_INHERITED(CSSSupportsRule, css::ConditionRule)
// QueryInterface implementation for CSSSupportsRule
NS_INTERFACE_MAP_BEGIN(CSSSupportsRule)
NS_INTERFACE_MAP_ENTRY(nsIDOMCSSGroupingRule)
NS_INTERFACE_MAP_ENTRY(nsIDOMCSSConditionRule)
NS_INTERFACE_MAP_ENTRY(nsIDOMCSSSupportsRule)
NS_INTERFACE_MAP_END_INHERITING(ConditionRule)
uint16_t
CSSSupportsRule::Type() const
{
return nsIDOMCSSRule::SUPPORTS_RULE;
}
NS_INTERFACE_MAP_END_INHERITING(dom::CSSSupportsRule)
void
CSSSupportsRule::GetCssTextImpl(nsAString& aCssText) const
@ -2351,25 +2335,6 @@ CSSSupportsRule::GetCssTextImpl(nsAString& aCssText) const
css::GroupRule::AppendRulesToCssText(aCssText);
}
// nsIDOMCSSGroupingRule methods
NS_IMETHODIMP
CSSSupportsRule::GetCssRules(nsIDOMCSSRuleList* *aRuleList)
{
return css::GroupRule::GetCssRules(aRuleList);
}
NS_IMETHODIMP
CSSSupportsRule::InsertRule(const nsAString & aRule, uint32_t aIndex, uint32_t* _retval)
{
return css::GroupRule::InsertRule(aRule, aIndex, _retval);
}
NS_IMETHODIMP
CSSSupportsRule::DeleteRule(uint32_t aIndex)
{
return css::GroupRule::DeleteRule(aIndex);
}
// nsIDOMCSSConditionRule methods
NS_IMETHODIMP
CSSSupportsRule::GetConditionText(nsAString& aConditionText)
@ -2384,13 +2349,6 @@ CSSSupportsRule::SetConditionText(const nsAString& aConditionText)
return NS_ERROR_NOT_IMPLEMENTED;
}
void
CSSSupportsRule::SetConditionText(const nsAString& aConditionText,
ErrorResult& aRv)
{
aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
}
/* virtual */ size_t
CSSSupportsRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
{
@ -2400,13 +2358,6 @@ CSSSupportsRule::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
return n;
}
/* virtual */ JSObject*
CSSSupportsRule::WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto)
{
return CSSSupportsRuleBinding::Wrap(aCx, this, aGivenProto);
}
} // namespace mozilla
// -------------------------------------------

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

@ -19,6 +19,7 @@
#include "mozilla/css/GroupRule.h"
#include "mozilla/dom/CSSMediaRule.h"
#include "mozilla/dom/CSSPageRule.h"
#include "mozilla/dom/CSSSupportsRule.h"
#include "nsAutoPtr.h"
#include "nsCSSPropertyID.h"
#include "nsCSSValue.h"
@ -446,8 +447,7 @@ private:
namespace mozilla {
class CSSSupportsRule final : public css::ConditionRule,
public nsIDOMCSSSupportsRule
class CSSSupportsRule final : public dom::CSSSupportsRule
{
public:
CSSSupportsRule(bool aConditionMet, const nsString& aCondition,
@ -458,35 +458,21 @@ public:
#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<mozilla::css::Rule> Clone() const override;
virtual bool UseForPresentation(nsPresContext* aPresContext,
nsMediaQueryResultCacheKey& aKey) override;
NS_DECL_ISUPPORTS_INHERITED
// nsIDOMCSSGroupingRule interface
NS_DECL_NSIDOMCSSGROUPINGRULE
// nsIDOMCSSConditionRule interface
NS_DECL_NSIDOMCSSCONDITIONRULE
// nsIDOMCSSSupportsRule interface
NS_DECL_NSIDOMCSSSUPPORTSRULE
// WebIDL interface
uint16_t Type() const override;
void GetCssTextImpl(nsAString& aCssText) const override;
// Our XPCOM GetConditionText is OK
virtual void SetConditionText(const nsAString& aConditionText,
ErrorResult& aRv) override;
using dom::CSSSupportsRule::SetConditionText;
virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const override;
virtual JSObject* WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override;
protected:
virtual ~CSSSupportsRule();

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

@ -631,49 +631,31 @@ private:
return newData; \
} \
/** \
* Always forward to the parent to grab the inherited style struct\
* we're a text node. \
* Also (conservatively) set the owning bit in the parent style \
* context if we're a text node. \
* \
* This causes the parent element's style context to cache any \
* inherited structs we request for a text node, which means we \
* don't have to compute change hints for the text node, as \
* handling the change on the parent element is sufficient. \
* \
* Note that adding the inherit bit is ok, because the struct \
* pointer returned by the parent and the child is owned by \
* Servo. This is fine if the pointers are the same (as it \
* should, read below), because both style context sources will \
* hold it. \
* Note, however, that we still need to request the style struct \
* of the text node itself, since we may run some fixups on it, \
* like for text-combine. \
* \
* In the case of a mishandled frame, we could end up with the \
* pointer to and old parent style, but that's fine too, since \
* the parent style context will remain alive until we reframe, \
* in which case we'll discard both style contexts. Also, we \
* hold a strong reference to the parent style context, which \
* makes it a non-issue. \
* This model is sound because for the fixed-up values to change, \
* other properties on the parent need to change too, and we'll \
* handle those change hints correctly. \
* \
* Also, note that the assertion below should be true, except \
* for those frames we still don't handle correctly, like \
* anonymous table wrappers, in which case the pointers will \
* differ. \
* \
* That means we're not going to restyle correctly text frames \
* of anonymous table wrappers, for example. It's kind of \
* embarrassing, but I think it's not worth it to add more \
* logic here unconditionally, given that's going to be fixed. \
* \
* TODO(emilio): Convert to a strong assertion once we support \
* all kinds of random frames. In fact, this can be a great \
* assertion to debug them. \
* TODO(emilio): Perhaps we should remove those fixups and handle \
* those in layout instead. Those fixups are kind of expensive \
* for style sharing, and computed style of text nodes is not \
* observable. If we do that, we could assert here that the \
* inherited structs of both are the same. \
*/ \
if (mPseudoTag == nsCSSAnonBoxes::mozText) { \
if (mPseudoTag == nsCSSAnonBoxes::mozText && aComputeData) { \
MOZ_ASSERT(mParent); \
const nsStyle##name_* data = \
mParent->DoGetStyle##name_<aComputeData>(); \
NS_WARNING_ASSERTION(!data || \
data == Servo_GetStyle##name_(mSource.AsServoComputedValues()), \
"bad data"); \
return data; \
mParent->AddStyleBit(NS_STYLE_INHERIT_BIT(name_)); \
} \
\
const bool needToCompute = !(mBits & NS_STYLE_INHERIT_BIT(name_));\

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

@ -61,7 +61,7 @@ to mochitest command.
* test_keyframes_rules.html [1]
* test_rules_out_of_sheets.html [1]
* \@support bug 1355394
* test_supports_rules.html [1]
* test_supports_rules.html [6]
* test_bug357614.html: case-insensitivity for old attrs in attr selector servo/servo#15006 [2]
* test_bug387615.html: servo/servo#15006 [1]
* test_bug397427.html: @import issue bug 1331291 and CSSOM support of @import [1]
@ -261,7 +261,7 @@ to mochitest command.
* test_rule_serialization.html [2]
* test_moz_document_rules.html [13]
* test_bug511909.html `@-moz-document` [4]
* test_condition_text.html: also \@supports [7]
* test_condition_text.html: also \@supports [11]
* getComputedStyle style doesn't contain custom properties bug 1336891
* test_variable_serialization_computed.html [35]
* test_variables.html `custom property name` [2]

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

@ -277,7 +277,8 @@ nsSVGMaskFrame::GetMaskForMaskedFrame(MaskParams& aParams)
}
RefPtr<DataSourceSurface> maskSurface = maskSnapshot->GetDataSurface();
DataSourceSurface::MappedSurface map;
if (!maskSurface->Map(DataSourceSurface::MapType::READ, &map)) {
if (!maskSurface ||
!maskSurface->Map(DataSourceSurface::MapType::READ, &map)) {
return MakePair(DrawResult::TEMPORARY_ERROR, RefPtr<SourceSurface>());
}

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

@ -75,6 +75,16 @@ ListBoxObject::GetRowCount()
return 0;
}
int32_t
ListBoxObject::GetRowHeight()
{
nsListBoxBodyFrame* body = GetListBoxBody(true);
if (body) {
return body->GetRowHeightPixels();
}
return 0;
}
int32_t
ListBoxObject::GetNumberOfVisibleRows()
{

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