MozReview-Commit-ID: AxmKwI9dnre
This commit is contained in:
Kartikaya Gupta 2017-03-21 09:21:34 -04:00
Родитель 8d50f9ae87 6fd1303c2a
Коммит 7fc02188d8
339 изменённых файлов: 25837 добавлений и 20840 удалений

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

@ -25,21 +25,4 @@ UnbindCacheEntriesFromDocument(
}
}
/**
* Clear the cache and shutdown the accessibles.
*/
template <class T>
static void
ClearCache(nsRefPtrHashtable<nsPtrHashKey<const void>, T>& aCache)
{
for (auto iter = aCache.Iter(); !iter.Done(); iter.Next()) {
T* accessible = iter.Data();
MOZ_ASSERT(accessible);
if (accessible && !accessible->IsDefunct()) {
accessible->Shutdown();
}
iter.Remove();
}
}
#endif

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

@ -483,7 +483,17 @@ DocAccessible::Shutdown()
mDependentIDsHash.Clear();
mNodeToAccessibleMap.Clear();
ClearCache(mAccessibleCache);
for (auto iter = mAccessibleCache.Iter(); !iter.Done(); iter.Next()) {
Accessible* accessible = iter.Data();
MOZ_ASSERT(accessible);
if (accessible && !accessible->IsDefunct()) {
// Unlink parent to avoid its cleaning overhead in shutdown.
accessible->mParent = nullptr;
accessible->Shutdown();
}
iter.Remove();
}
HyperTextAccessibleWrap::Shutdown();

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

@ -29,10 +29,6 @@ LOCAL_INCLUDES += [
'/xpcom/build',
]
USE_LIBS += [
'mozglue',
]
if CONFIG['LIBFUZZER']:
USE_LIBS += [ 'fuzzer' ]
LOCAL_INCLUDES += [

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

@ -3,11 +3,136 @@
* 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/. */
XPCOMUtils.defineLazyModuleGetter(this, "DeferredTask",
"resource://gre/modules/DeferredTask.jsm");
const TYPE_MAYBE_FEED = "application/vnd.mozilla.maybe.feed";
const TYPE_MAYBE_AUDIO_FEED = "application/vnd.mozilla.maybe.audio.feed";
const TYPE_MAYBE_VIDEO_FEED = "application/vnd.mozilla.maybe.video.feed";
const PREF_SHOW_FIRST_RUN_UI = "browser.feeds.showFirstRunUI";
const PREF_SELECTED_APP = "browser.feeds.handlers.application";
const PREF_SELECTED_WEB = "browser.feeds.handlers.webservice";
const PREF_SELECTED_ACTION = "browser.feeds.handler";
const PREF_SELECTED_READER = "browser.feeds.handler.default";
const PREF_VIDEO_SELECTED_APP = "browser.videoFeeds.handlers.application";
const PREF_VIDEO_SELECTED_WEB = "browser.videoFeeds.handlers.webservice";
const PREF_VIDEO_SELECTED_ACTION = "browser.videoFeeds.handler";
const PREF_VIDEO_SELECTED_READER = "browser.videoFeeds.handler.default";
const PREF_AUDIO_SELECTED_APP = "browser.audioFeeds.handlers.application";
const PREF_AUDIO_SELECTED_WEB = "browser.audioFeeds.handlers.webservice";
const PREF_AUDIO_SELECTED_ACTION = "browser.audioFeeds.handler";
const PREF_AUDIO_SELECTED_READER = "browser.audioFeeds.handler.default";
const PREF_UPDATE_DELAY = 2000;
const SETTABLE_PREFS = new Set([
PREF_VIDEO_SELECTED_ACTION,
PREF_AUDIO_SELECTED_ACTION,
PREF_SELECTED_ACTION,
PREF_VIDEO_SELECTED_READER,
PREF_AUDIO_SELECTED_READER,
PREF_SELECTED_READER,
PREF_VIDEO_SELECTED_WEB,
PREF_AUDIO_SELECTED_WEB,
PREF_SELECTED_WEB
]);
const EXECUTABLE_PREFS = new Set([
PREF_SELECTED_APP,
PREF_VIDEO_SELECTED_APP,
PREF_AUDIO_SELECTED_APP
]);
const VALID_ACTIONS = new Set(["ask", "reader", "bookmarks"]);
const VALID_READERS = new Set(["web", "client", "default", "bookmarks"]);
XPCOMUtils.defineLazyPreferenceGetter(this, "SHOULD_LOG",
"feeds.log", false);
function LOG(str) {
if (SHOULD_LOG)
dump("*** Feeds: " + str + "\n");
}
function getPrefActionForType(t) {
switch (t) {
case Ci.nsIFeed.TYPE_VIDEO:
return PREF_VIDEO_SELECTED_ACTION;
case Ci.nsIFeed.TYPE_AUDIO:
return PREF_AUDIO_SELECTED_ACTION;
default:
return PREF_SELECTED_ACTION;
}
}
function getPrefReaderForType(t) {
switch (t) {
case Ci.nsIFeed.TYPE_VIDEO:
return PREF_VIDEO_SELECTED_READER;
case Ci.nsIFeed.TYPE_AUDIO:
return PREF_AUDIO_SELECTED_READER;
default:
return PREF_SELECTED_READER;
}
}
function getPrefWebForType(t) {
switch (t) {
case Ci.nsIFeed.TYPE_VIDEO:
return PREF_VIDEO_SELECTED_WEB;
case Ci.nsIFeed.TYPE_AUDIO:
return PREF_AUDIO_SELECTED_WEB;
default:
return PREF_SELECTED_WEB;
}
}
function getPrefAppForType(t) {
switch (t) {
case Ci.nsIFeed.TYPE_VIDEO:
return PREF_VIDEO_SELECTED_APP;
case Ci.nsIFeed.TYPE_AUDIO:
return PREF_AUDIO_SELECTED_APP;
default:
return PREF_SELECTED_APP;
}
}
/**
* Maps a feed type to a maybe-feed mimetype.
*/
function getMimeTypeForFeedType(aFeedType) {
switch (aFeedType) {
case Ci.nsIFeed.TYPE_VIDEO:
return TYPE_MAYBE_VIDEO_FEED;
case Ci.nsIFeed.TYPE_AUDIO:
return TYPE_MAYBE_AUDIO_FEED;
default:
return TYPE_MAYBE_FEED;
}
}
/**
* The Feed Handler object manages discovery of RSS/ATOM feeds in web pages
* and shows UI when they are discovered.
*/
var FeedHandler = {
_prefChangeCallback: null,
/** Called when the user clicks on the Subscribe to This Page... menu item,
* or when the user clicks the feed button when the page contains multiple
* feeds.
@ -195,7 +320,8 @@ var FeedHandler = {
return file.leafName;
},
chooseClientApp(aTitle, aPrefName, aBrowser) {
_chooseClientApp(aTitle, aTypeName, aBrowser) {
const prefName = getPrefAppForType(aTypeName);
let fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
fp.init(window, aTitle, Ci.nsIFilePicker.modeOpen);
@ -222,7 +348,7 @@ var FeedHandler = {
}
if (fp.file.leafName != appName) {
Services.prefs.setComplexValue(aPrefName, Ci.nsILocalFile, selectedApp);
Services.prefs.setComplexValue(prefName, Ci.nsILocalFile, selectedApp);
aBrowser.messageManager.sendAsyncMessage("FeedWriter:SetApplicationLauncherMenuItem",
{ name: this._getFileDisplayName(selectedApp),
type: "SelectedAppMenuItem" });
@ -277,70 +403,240 @@ var FeedHandler = {
}
},
// nsISupports
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
Ci.nsISupportsWeakReference]),
init() {
window.messageManager.addMessageListener("FeedWriter:ChooseClientApp", this);
window.messageManager.addMessageListener("FeedWriter:RequestClientAppName", this);
window.messageManager.addMessageListener("FeedWriter:SetFeedCharPref", this);
window.messageManager.addMessageListener("FeedWriter:SetFeedComplexString", this);
window.messageManager.addMessageListener("FeedWriter:GetSubscriptionUI", this);
window.messageManager.addMessageListener("FeedWriter:SetFeedPrefsAndSubscribe", this);
window.messageManager.addMessageListener("FeedWriter:ShownFirstRun", this);
Services.ppmm.addMessageListener("FeedConverter:ExecuteClientApp", this);
const prefs = Services.prefs;
prefs.addObserver(PREF_SELECTED_ACTION, this, true);
prefs.addObserver(PREF_SELECTED_READER, this, true);
prefs.addObserver(PREF_SELECTED_WEB, this, true);
prefs.addObserver(PREF_VIDEO_SELECTED_ACTION, this, true);
prefs.addObserver(PREF_VIDEO_SELECTED_READER, this, true);
prefs.addObserver(PREF_VIDEO_SELECTED_WEB, this, true);
prefs.addObserver(PREF_AUDIO_SELECTED_ACTION, this, true);
prefs.addObserver(PREF_AUDIO_SELECTED_READER, this, true);
prefs.addObserver(PREF_AUDIO_SELECTED_WEB, this, true);
},
uninit() {
Services.ppmm.removeMessageListener("FeedConverter:ExecuteClientApp", this);
this._prefChangeCallback = null;
},
// nsIObserver
observe(subject, topic, data) {
if (topic == "nsPref:changed") {
LOG(`Pref changed ${data}`)
if (this._prefChangeCallback) {
this._prefChangeCallback.disarm();
}
// Multiple prefs are set at the same time, debounce to reduce noise
// This can happen in one feed and we want to message all feed pages
this._prefChangeCallback = new DeferredTask(() => {
this._prefChanged(data);
}, PREF_UPDATE_DELAY);
this._prefChangeCallback.arm();
}
},
_prefChanged(prefName) {
// Don't observe for PREF_*SELECTED_APP as user likely just picked one
// That is also handled by SetApplicationLauncherMenuItem call
// Rather than the others which happen on subscription
switch (prefName) {
case PREF_SELECTED_READER:
case PREF_SELECTED_WEB:
case PREF_VIDEO_SELECTED_READER:
case PREF_VIDEO_SELECTED_WEB:
case PREF_AUDIO_SELECTED_READER:
case PREF_AUDIO_SELECTED_WEB:
case PREF_SELECTED_ACTION:
case PREF_VIDEO_SELECTED_ACTION:
case PREF_AUDIO_SELECTED_ACTION:
const response = {
default: this._getReaderForType(Ci.nsIFeed.TYPE_FEED),
[Ci.nsIFeed.TYPE_AUDIO]: this._getReaderForType(Ci.nsIFeed.TYPE_AUDIO),
[Ci.nsIFeed.TYPE_VIDEO]: this._getReaderForType(Ci.nsIFeed.TYPE_VIDEO)
};
Services.mm.broadcastAsyncMessage("FeedWriter:PreferenceUpdated",
response);
break;
}
},
_initSubscriptionUIResponse(feedType) {
const wccr = Cc["@mozilla.org/embeddor.implemented/web-content-handler-registrar;1"].
getService(Ci.nsIWebContentConverterService);
const handlersRaw = wccr.getContentHandlers(getMimeTypeForFeedType(feedType));
const handlers = [];
for (let handler of handlersRaw) {
LOG(`Handler found: ${handler}`);
handlers.push({
name: handler.name,
uri: handler.uri
});
}
let showFirstRunUI = true;
// eslint-disable-next-line mozilla/use-default-preference-values
try {
showFirstRunUI = Services.prefs.getBoolPref(PREF_SHOW_FIRST_RUN_UI);
} catch (ex) { }
const response = { handlers, showFirstRunUI };
let selectedClientApp;
const feedTypePref = getPrefAppForType(feedType);
try {
selectedClientApp = Services.prefs.getComplexValue(feedTypePref, Ci.nsILocalFile);
} catch (ex) {
// Just do nothing, then we won't bother populating
}
let defaultClientApp = null;
try {
// This can sometimes not exist
defaultClientApp = Cc["@mozilla.org/browser/shell-service;1"]
.getService(Ci.nsIShellService)
.defaultFeedReader;
} catch (ex) {
// Just do nothing, then we don't bother populating
}
if (selectedClientApp && selectedClientApp.exists()) {
if (defaultClientApp && selectedClientApp.path != defaultClientApp.path) {
// Only set the default menu item if it differs from the selected one
response.defaultMenuItem = this._getFileDisplayName(defaultClientApp);
}
response.selectedMenuItem = this._getFileDisplayName(selectedClientApp);
}
response.reader = this._getReaderForType(feedType);
return response;
},
_setPref(aPrefName, aPrefValue, aIsComplex = false) {
LOG(`FeedWriter._setPref ${aPrefName}`);
// Ensure we have a pref that is settable
if (aPrefName && SETTABLE_PREFS.has(aPrefName)) {
if (aIsComplex) {
Services.prefs.setStringPref(aPrefName, aPrefValue);
} else {
Services.prefs.setCharPref(aPrefName, aPrefValue);
}
} else {
LOG(`FeedWriter._setPref ${aPrefName} not allowed`);
}
},
_getReaderForType(feedType) {
let prefs = Services.prefs;
let handler = "bookmarks";
let url;
// eslint-disable-next-line mozilla/use-default-preference-values
try {
handler = prefs.getCharPref(getPrefReaderForType(feedType));
} catch (ex) { }
if (handler === "web") {
try {
url = prefs.getStringPref(getPrefWebForType(feedType));
} catch (ex) {
LOG("FeedWriter._setSelectedHandler: invalid or no handler in prefs");
url = null;
}
}
const alwaysUse = this._getAlwaysUseState(feedType);
const action = prefs.getCharPref(getPrefActionForType(feedType));
return { handler, url, alwaysUse, action };
},
_getAlwaysUseState(feedType) {
try {
return Services.prefs.getCharPref(getPrefActionForType(feedType)) != "ask";
} catch (ex) { }
return false;
},
receiveMessage(msg) {
let handler;
switch (msg.name) {
case "FeedWriter:ChooseClientApp":
this.chooseClientApp(msg.data.title, msg.data.prefName, msg.target);
case "FeedWriter:GetSubscriptionUI":
const response = this._initSubscriptionUIResponse(msg.data.feedType);
msg.target.messageManager
.sendAsyncMessage("FeedWriter:GetSubscriptionUIResponse",
response);
break;
case "FeedWriter:RequestClientAppName":
let selectedClientApp;
try {
selectedClientApp = Services.prefs.getComplexValue(msg.data.feedTypePref, Ci.nsILocalFile);
} catch (ex) {
// Just do nothing, then we won't bother populating
}
let defaultClientApp = null;
try {
// This can sometimes not exist
defaultClientApp = Cc["@mozilla.org/browser/shell-service;1"]
.getService(Ci.nsIShellService)
.defaultFeedReader;
} catch (ex) {
// Just do nothing, then we don't bother populating
}
if (selectedClientApp && selectedClientApp.exists()) {
if (defaultClientApp && selectedClientApp.path != defaultClientApp.path) {
// Only set the default menu item if it differs from the selected one
msg.target.messageManager
.sendAsyncMessage("FeedWriter:SetApplicationLauncherMenuItem",
{ name: this._getFileDisplayName(defaultClientApp),
type: "DefaultAppMenuItem" });
}
msg.target.messageManager
.sendAsyncMessage("FeedWriter:SetApplicationLauncherMenuItem",
{ name: this._getFileDisplayName(selectedClientApp),
type: "SelectedAppMenuItem" });
}
case "FeedWriter:ChooseClientApp":
this._chooseClientApp(msg.data.title, msg.data.feedType, msg.target);
break;
case "FeedWriter:ShownFirstRun":
Services.prefs.setBoolPref("browser.feeds.showFirstRunUI", false);
Services.prefs.setBoolPref(PREF_SHOW_FIRST_RUN_UI, false);
break;
case "FeedWriter:SetFeedCharPref":
Services.prefs.setCharPref(msg.data.pref, msg.data.value);
break;
case "FeedWriter:SetFeedComplexString": {
Services.prefs.setStringPref(msg.data.pref, msg.data.value);
break;
}
case "FeedWriter:SetFeedPrefsAndSubscribe":
const settings = msg.data;
if (!settings.action || !VALID_ACTIONS.has(settings.action)) {
LOG(`Invalid action ${settings.action}`);
return;
}
if (!settings.reader || !VALID_READERS.has(settings.reader)) {
LOG(`Invalid reader ${settings.reader}`);
return;
}
const actionPref = getPrefActionForType(settings.feedType);
this._setPref(actionPref, settings.action);
const readerPref = getPrefReaderForType(settings.feedType);
this._setPref(readerPref, settings.reader);
handler = null;
switch (settings.reader) {
case "web":
// This is a web set URI by content using window.registerContentHandler()
// Lets make sure we know about it before setting it
const webPref = getPrefWebForType(settings.feedType);
let wccr = Cc["@mozilla.org/embeddor.implemented/web-content-handler-registrar;1"].
getService(Ci.nsIWebContentConverterService);
// If the user provided an invalid web URL this function won't give us a reference
handler = wccr.getWebContentHandlerByURI(getMimeTypeForFeedType(settings.feedType), settings.uri);
if (handler) {
this._setPref(webPref, settings.uri, true);
if (settings.useAsDefault) {
wccr.setAutoHandler(getMimeTypeForFeedType(settings.feedType), handler);
}
msg.target.messageManager
.sendAsyncMessage("FeedWriter:SetFeedPrefsAndSubscribeResponse",
{ redirect: handler.getHandlerURI(settings.feedLocation) });
} else {
LOG(`No handler found for web ${settings.feedType} ${settings.uri}`);
}
break;
default:
const feedService = Cc["@mozilla.org/browser/feeds/result-service;1"].
getService(Ci.nsIFeedResultService);
feedService.addToClientReader(settings.feedLocation,
settings.feedTitle,
settings.feedSubtitle,
settings.feedType,
settings.reader);
}
break;
case "FeedConverter:ExecuteClientApp":
this.executeClientApp(msg.data.spec, msg.data.title,
msg.data.subtitle, msg.data.feedHandler);
// Always check feedHandler is from a set array of executable prefs
if (EXECUTABLE_PREFS.has(msg.data.feedHandler)) {
this.executeClientApp(msg.data.spec, msg.data.title,
msg.data.subtitle, msg.data.feedHandler);
} else {
LOG(`FeedConverter:ExecuteClientApp - Will not exec ${msg.data.feedHandler}`);
}
break;
}
},

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

@ -473,7 +473,7 @@ XPCOMUtils.defineLazyGetter(gSyncUI, "_stringBundle", function() {
// XXXzpao these strings should probably be moved from /services to /browser... (bug 583381)
// but for now just make it work
return Services.strings.createBundle(
"chrome://weave/locale/services/sync.properties");
"chrome://weave/locale/sync.properties");
});
XPCOMUtils.defineLazyGetter(gSyncUI, "log", function() {

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

@ -15,7 +15,7 @@ Cu.import("resource://gre/modules/NotificationDB.jsm");
// lazy module getters
/* global AboutHome:false, AddonWatcher:false, AppConstants: false,
/* global AboutHome:false, AddonWatcher:false,
BrowserUITelemetry:false, BrowserUsageTelemetry:false, BrowserUtils:false,
CastingApps:false, CharsetMenu:false, Color:false, ContentSearch:false,
Deprecated:false, E10SUtils:false, FormValidationHandler:false,
@ -38,7 +38,6 @@ Cu.import("resource://gre/modules/NotificationDB.jsm");
[
["AboutHome", "resource:///modules/AboutHome.jsm"],
["AddonWatcher", "resource://gre/modules/AddonWatcher.jsm"],
["AppConstants", "resource://gre/modules/AppConstants.jsm"],
["BrowserUITelemetry", "resource:///modules/BrowserUITelemetry.jsm"],
["BrowserUsageTelemetry", "resource:///modules/BrowserUsageTelemetry.jsm"],
["BrowserUtils", "resource://gre/modules/BrowserUtils.jsm"],
@ -2572,8 +2571,13 @@ function URLBarSetURI(aURI) {
valid = !isBlankPageURL(uri.spec);
}
let isDifferentValidValue = valid && value != gURLBar.value;
gURLBar.value = value;
gURLBar.valueIsTyped = !valid;
if (isDifferentValidValue) {
gURLBar.selectionStart = gURLBar.selectionEnd = 0;
}
SetPageProxyState(valid ? "valid" : "invalid");
}
@ -6680,6 +6684,35 @@ function BrowserOpenSyncTabs() {
gSyncUI.openSyncedTabsPanel();
}
function ReportFalseDeceptiveSite() {
let docURI = gBrowser.selectedBrowser.documentURI;
let isPhishingPage =
docURI && docURI.spec.startsWith("about:blocked?e=deceptiveBlocked");
if (isPhishingPage) {
let mm = gBrowser.selectedBrowser.messageManager;
let onMessage = (message) => {
mm.removeMessageListener("DeceptiveBlockedDetails:Result", onMessage);
let reportUrl = gSafeBrowsing.getReportURL("PhishMistake", message.data.blockedInfo);
if (reportUrl) {
openUILinkIn(reportUrl, "tab");
} else {
let promptService = Cc["@mozilla.org/embedcomp/prompt-service;1"].
getService(Ci.nsIPromptService);
let bundle =
Services.strings.createBundle("chrome://browser/locale/safebrowsing/safebrowsing.properties");
promptService.alert(window,
bundle.GetStringFromName("errorReportFalseDeceptiveTitle"),
bundle.formatStringFromName("errorReportFalseDeceptiveMessage",
[message.data.blockedInfo.provider], 1));
}
}
mm.addMessageListener("DeceptiveBlockedDetails:Result", onMessage);
mm.sendAsyncMessage("DeceptiveBlockedDetails");
}
}
/**
* Format a URL
* eg:

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

@ -262,6 +262,35 @@ function getSerializedSecurityInfo(docShell) {
return serhelper.serializeToString(securityInfo);
}
function getSiteBlockedErrorDetails(docShell) {
let blockedInfo = {};
if (docShell.failedChannel) {
let classifiedChannel = docShell.failedChannel.
QueryInterface(Ci.nsIClassifiedChannel);
if (classifiedChannel) {
let httpChannel = docShell.failedChannel.QueryInterface(Ci.nsIHttpChannel);
let reportUri = httpChannel.URI.clone();
// Remove the query to avoid leaking sensitive data
if (reportUri instanceof Ci.nsIURL) {
reportUri.query = "";
}
blockedInfo = { list: classifiedChannel.matchedList,
provider: classifiedChannel.matchedProvider,
uri: reportUri.asciiSpec };
}
}
return blockedInfo;
}
addMessageListener("DeceptiveBlockedDetails", (message) => {
sendAsyncMessage("DeceptiveBlockedDetails:Result", {
blockedInfo: getSiteBlockedErrorDetails(docShell),
});
});
var AboutNetAndCertErrorListener = {
init(chromeGlobal) {
addMessageListener("CertErrorDetails", this);
@ -583,32 +612,13 @@ var ClickEventHandler = {
let docShell = ownerDoc.defaultView.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShell);
let blockedInfo = {};
if (docShell.failedChannel) {
let classifiedChannel = docShell.failedChannel.
QueryInterface(Ci.nsIClassifiedChannel);
if (classifiedChannel) {
let httpChannel = docShell.failedChannel.QueryInterface(Ci.nsIHttpChannel);
let reportUri = httpChannel.URI.clone();
// Remove the query to avoid leaking sensitive data
if (reportUri instanceof Ci.nsIURL) {
reportUri.query = "";
}
blockedInfo = { list: classifiedChannel.matchedList,
provider: classifiedChannel.matchedProvider,
uri: reportUri.asciiSpec };
}
}
sendAsyncMessage("Browser:SiteBlockedError", {
location: ownerDoc.location.href,
reason,
elementId: targetElement.getAttribute("id"),
isTopFrame: (ownerDoc.defaultView.parent === ownerDoc.defaultView),
blockedInfo
blockedInfo: getSiteBlockedErrorDetails(docShell),
});
},

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

@ -29,7 +29,7 @@
accesskey="&safeb.palm.notdeceptive.accesskey;"
insertbefore="aboutSeparator"
observes="reportPhishingErrorBroadcaster"
oncommand="openUILinkIn(gSafeBrowsing.getReportURL('PhishMistake'), 'tab');"
oncommand="ReportFalseDeceptiveSite();"
onclick="checkForMiddleClick(this, event);"/>
</menupopup>
</overlay>

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

@ -1,5 +1,9 @@
"use strict";
// Bug 1318389 - This test does a lot of window and tab manipulation,
// causing it to take a long time on debug.
requestLongerTimeout(2);
add_task(setupPrefsAndRecentWindowBehavior);
// Each of the test cases below is run twice: once for login-success and once

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

@ -6,7 +6,7 @@ var {Weave} = Cu.import("resource://services-sync/main.js", {});
var stringBundle = Cc["@mozilla.org/intl/stringbundle;1"]
.getService(Ci.nsIStringBundleService)
.createBundle("chrome://weave/locale/services/sync.properties");
.createBundle("chrome://weave/locale/sync.properties");
// ensure test output sees log messages.
Log.repository.getLogger("browserwindow.syncui").addAppender(new Log.DumpAppender());

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

@ -4,39 +4,31 @@
/* eslint-env mozilla/frame-script */
var testPage = "data:text/html,<body><style>:-moz-window-inactive { background-color: red; }</style><div id='area'></div></body>";
var testPage = "data:text/html;charset=utf-8,<body><style>:-moz-window-inactive { background-color: red; }</style><div id='area'></div></body>";
var colorChangeNotifications = 0;
var otherWindow;
var browser1, browser2;
function test() {
waitForExplicitFinish();
waitForFocus(reallyRunTests);
}
add_task(function* reallyRunTests() {
function reallyRunTests() {
let tab1 = yield BrowserTestUtils.openNewForegroundTab(gBrowser, testPage);
browser1 = tab1.linkedBrowser;
let tab1 = gBrowser.addTab();
let tab2 = gBrowser.addTab();
browser1 = gBrowser.getBrowserForTab(tab1);
browser2 = gBrowser.getBrowserForTab(tab2);
// This can't use openNewForegroundTab because if we focus tab2 now, we
// won't send a focus event during test 6, further down in this file.
let tab2 = gBrowser.addTab(testPage);
browser2 = tab2.linkedBrowser;
yield BrowserTestUtils.browserLoaded(browser2);
browser1.messageManager.loadFrameScript("data:,(" + childFunction.toString() + ")();", true);
browser2.messageManager.loadFrameScript("data:,(" + childFunction.toString() + ")();", true);
gURLBar.focus();
var loadCount = 0;
function check() {
// wait for both tabs to load
if (++loadCount != 2) {
return;
}
browser1.removeEventListener("load", check, true);
browser2.removeEventListener("load", check, true);
sendGetBackgroundRequest(true);
}
let testFinished = {};
testFinished.promise = new Promise(resolve => testFinished.resolve = resolve);
// The test performs four checks, using -moz-window-inactive on two child tabs.
// First, the initial state should be transparent. The second check is done
@ -74,7 +66,7 @@ function reallyRunTests() {
break;
case 8:
is(message.data.color, "rgba(0, 0, 0, 0)", "second window after tab switch");
finishTest();
testFinished.resolve();
break;
case 9:
ok(false, "too many color change notifications");
@ -97,16 +89,17 @@ function reallyRunTests() {
ok(message.data.ok, "Test:DeactivateEvent");
});
browser1.addEventListener("load", check, true);
browser2.addEventListener("load", check, true);
browser1.contentWindow.location = testPage;
browser2.contentWindow.location = testPage;
browser1.messageManager.loadFrameScript("data:,(" + childFunction.toString() + ")();", true);
browser2.messageManager.loadFrameScript("data:,(" + childFunction.toString() + ")();", true);
gBrowser.selectedTab = tab1;
}
// Start the test.
sendGetBackgroundRequest(true);
yield testFinished.promise;
yield BrowserTestUtils.removeTab(tab1);
yield BrowserTestUtils.removeTab(tab2);
otherWindow = null;
});
function sendGetBackgroundRequest(ifChanged) {
browser1.messageManager.sendAsyncMessage("Test:GetBackgroundColor", { ifChanged });
@ -114,19 +107,12 @@ function sendGetBackgroundRequest(ifChanged) {
}
function runOtherWindowTests() {
otherWindow = window.open("data:text/html,<body>Hi</body>", "", "chrome");
otherWindow = window.open("data:text/html;charset=utf-8,<body>Hi</body>", "", "chrome");
waitForFocus(function() {
sendGetBackgroundRequest(true);
}, otherWindow);
}
function finishTest() {
gBrowser.removeCurrentTab();
gBrowser.removeCurrentTab();
otherWindow = null;
finish();
}
function childFunction() {
let oldColor = null;

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

@ -13,7 +13,7 @@ skip-if = (os == "linux" && (debug || asan))
[browser_popupNotification_4.js]
skip-if = (os == "linux" && (debug || asan))
[browser_popupNotification_5.js]
skip-if = (os == "linux" && (debug || asan))
skip-if = true # bug 1332646
[browser_popupNotification_checkbox.js]
skip-if = (os == "linux" && (debug || asan))
[browser_popupNotification_keyboard.js]

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

@ -2,6 +2,8 @@
support-files =
head.js
[browser_all_files_referenced.js]
skip-if = debug # no point in running on both opt and debug, and will likely intermittently timeout on debug
[browser_misused_characters_in_strings.js]
support-files =
bug1262648_string_with_newlines.dtd

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

@ -0,0 +1,498 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
var isDevtools = SimpleTest.harnessParameters.subsuite == "devtools";
var gExceptionPaths = ["chrome://browser/content/defaultthemes/",
"chrome://browser/locale/searchplugins/"];
var whitelist = new Set([
// browser/extensions/pdfjs/content/PdfStreamConverter.jsm
{file: "chrome://pdf.js/locale/chrome.properties"},
{file: "chrome://pdf.js/locale/viewer.properties"},
// security/manager/pki/resources/content/device_manager.js
{file: "chrome://pippki/content/load_device.xul"},
// browser/modules/ReaderParent.jsm
{file: "chrome://browser/skin/reader-tour.png"},
{file: "chrome://browser/skin/reader-tour@2x.png"},
// Used by setting this url as a pref in about:config
{file: "chrome://browser/content/newtab/alternativeDefaultSites.json"},
// Add-on compat
{file: "chrome://browser/skin/devtools/common.css"},
{file: "chrome://global/content/XPCNativeWrapper.js"},
{file: "chrome://global/locale/brand.dtd"},
// The l10n build system can't package string files only for some platforms.
// See bug 1339424 for why this is hard to fix.
{file: "chrome://global/locale/fallbackMenubar.properties",
platforms: ["linux", "win"]},
{file: "chrome://global/locale/printPageSetup.dtd", platforms: ["macosx"]},
{file: "chrome://global/locale/printPreviewProgress.dtd",
platforms: ["macosx"]},
{file: "chrome://global/locale/printProgress.dtd", platforms: ["macosx"]},
{file: "chrome://global/locale/printdialog.dtd",
platforms: ["macosx", "win"]},
{file: "chrome://global/locale/printjoboptions.dtd",
platforms: ["macosx", "win"]},
// services/cloudsync/CloudSyncLocal.jsm
{file: "chrome://weave/locale/errors.properties"},
// devtools/client/inspector/bin/dev-server.js
{file: "chrome://devtools/content/inspector/markup/markup.xhtml",
isFromDevTools: true},
// Starting from here, files in the whitelist are bugs that need fixing.
// Bug 1339420
{file: "chrome://branding/content/icon128.png"},
// Bug 1339424 (wontfix?)
{file: "chrome://browser/locale/taskbar.properties",
platforms: ["linux", "macosx"]},
// Bug 1320156
{file: "chrome://browser/skin/Privacy-16.png", platforms: ["linux"]},
// Bug 1343584
{file: "chrome://browser/skin/click-to-play-warning-stripes.png"},
// Bug 1343824
{file: "chrome://browser/skin/customizableui/customize-illustration-rtl@2x.png",
platforms: ["linux", "win"]},
{file: "chrome://browser/skin/customizableui/customize-illustration@2x.png",
platforms: ["linux", "win"]},
{file: "chrome://browser/skin/customizableui/info-icon-customizeTip@2x.png",
platforms: ["linux", "win"]},
{file: "chrome://browser/skin/customizableui/panelarrow-customizeTip@2x.png",
platforms: ["linux", "win"]},
// Bug 1320058
{file: "chrome://browser/skin/preferences/saveFile.png", platforms: ["win"]},
// Bug 1348369
{file: "chrome://formautofill/content/editProfile.xhtml"},
// Bug 1316187
{file: "chrome://global/content/customizeToolbar.xul"},
// Bug 1343837
{file: "chrome://global/content/findUtils.js"},
// Bug 1343843
{file: "chrome://global/content/url-classifier/unittests.xul"},
// Bug 1343839
{file: "chrome://global/locale/headsUpDisplay.properties"},
// Bug 1348358
{file: "chrome://global/skin/arrow.css"},
{file: "chrome://global/skin/arrow/arrow-dn-sharp.gif",
platforms: ["linux", "win"]},
{file: "chrome://global/skin/arrow/arrow-down.png",
platforms: ["linux", "win"]},
{file: "chrome://global/skin/arrow/arrow-lft-sharp-end.gif"},
{file: "chrome://global/skin/arrow/arrow-lft-sharp.gif",
platforms: ["linux", "win"]},
{file: "chrome://global/skin/arrow/arrow-rit-sharp-end.gif"},
{file: "chrome://global/skin/arrow/arrow-rit-sharp.gif",
platforms: ["linux", "win"]},
{file: "chrome://global/skin/arrow/arrow-up-sharp.gif",
platforms: ["linux", "win"]},
{file: "chrome://global/skin/arrow/panelarrow-horizontal.svg",
platforms: ["linux"]},
{file: "chrome://global/skin/arrow/panelarrow-vertical.svg",
platforms: ["linux"]},
// Bug 1348529
{file: "chrome://global/skin/checkbox/cbox-check-dis.gif",
platforms: ["linux"]},
{file: "chrome://global/skin/checkbox/cbox-check.gif", platforms: ["linux"]},
// Bug 1348359
{file: "chrome://global/skin/dirListing/folder.png", platforms: ["linux"]},
{file: "chrome://global/skin/dirListing/local.png", platforms: ["linux", "win"]},
{file: "chrome://global/skin/dirListing/remote.png"},
{file: "chrome://global/skin/dirListing/up.png", platforms: ["linux"]},
// Bug 1348362
{file: "chrome://global/skin/icons/Close.gif", platforms: ["win"]},
{file: "chrome://global/skin/icons/Error.png", platforms: ["linux", "macosx"]},
{file: "chrome://global/skin/icons/Landscape.png", platforms: ["linux"]},
{file: "chrome://global/skin/icons/Minimize.gif", platforms: ["win"]},
{file: "chrome://global/skin/icons/Portrait.png", platforms: ["linux"]},
{file: "chrome://global/skin/icons/Print-preview.png", platforms: ["linux"]},
{file: "chrome://global/skin/icons/Question.png", platforms: ["linux"]},
{file: "chrome://global/skin/icons/Restore.gif", platforms: ["win"]},
{file: "chrome://global/skin/icons/Search-close.png", platforms: ["linux"]},
{file: "chrome://global/skin/icons/Search-glass.png", platforms: ["linux"]},
{file: "chrome://global/skin/icons/Warning.png", platforms: ["linux"]},
{file: "chrome://global/skin/icons/checkbox.png", platforms: ["macosx"]},
{file: "chrome://global/skin/icons/checkbox@2x.png", platforms: ["macosx"]},
{file: "chrome://global/skin/icons/close-inverted.png", platforms: ["linux"]},
{file: "chrome://global/skin/icons/close-inverted@2x.png", platforms: ["linux"]},
{file: "chrome://global/skin/icons/close.png", platforms: ["linux"]},
{file: "chrome://global/skin/icons/close@2x.png", platforms: ["linux"]},
{file: "chrome://global/skin/icons/collapse.png", platforms: ["linux"]},
{file: "chrome://global/skin/icons/error-64.png", platforms: ["linux", "win"]},
{file: "chrome://global/skin/icons/error-large.png", platforms: ["macosx"]},
{file: "chrome://global/skin/icons/expand.png", platforms: ["linux"]},
{file: "chrome://global/skin/icons/folder-item.png", platforms: ["linux"]},
{file: "chrome://global/skin/icons/question-large.png", platforms: ["macosx"]},
{file: "chrome://global/skin/icons/warning-32.png", platforms: ["macosx"]},
{file: "chrome://global/skin/icons/warning-64.png", platforms: ["linux", "win"]},
{file: "chrome://global/skin/icons/warning-large.png", platforms: ["linux"]},
{file: "chrome://global/skin/icons/windowControls.png", platforms: ["linux"]},
// Bug 1348521
{file: "chrome://global/skin/linkTree.css"},
// Bug 1348522
{file: "chrome://global/skin/media/clicktoplay-bgtexture.png"},
{file: "chrome://global/skin/media/videoClickToPlayButton.svg"},
// Bug 1348524
{file: "chrome://global/skin/notification/close.png", platforms: ["macosx"]},
// Bug 1348525
{file: "chrome://global/skin/splitter/grip-bottom.gif", platforms: ["linux"]},
{file: "chrome://global/skin/splitter/grip-left.gif", platforms: ["linux"]},
{file: "chrome://global/skin/splitter/grip-right.gif", platforms: ["linux"]},
{file: "chrome://global/skin/splitter/grip-top.gif", platforms: ["linux"]},
// Bug 1348526
{file: "chrome://global/skin/tree/sort-asc-classic.png", platforms: ["linux"]},
{file: "chrome://global/skin/tree/sort-asc.png", platforms: ["linux"]},
{file: "chrome://global/skin/tree/sort-dsc-classic.png", platforms: ["linux"]},
{file: "chrome://global/skin/tree/sort-dsc.png", platforms: ["linux"]},
// Bug 1344267
{file: "chrome://marionette/content/test_anonymous_content.xul"},
{file: "chrome://marionette/content/test_dialog.properties"},
{file: "chrome://marionette/content/test_dialog.xul"},
// Bug 1348532
{file: "chrome://mozapps/content/extensions/list.xul"},
// Bug 1348533
{file: "chrome://mozapps/skin/downloads/buttons.png", platforms: ["macosx"]},
{file: "chrome://mozapps/skin/downloads/downloadButtons.png", platforms: ["linux", "win"]},
// Bug 1348555
{file: "chrome://mozapps/skin/extensions/dictionaryGeneric-16.png"},
{file: "chrome://mozapps/skin/extensions/search.png", platforms: ["macosx"]},
{file: "chrome://mozapps/skin/extensions/themeGeneric-16.png"},
// Bug 1348556
{file: "chrome://mozapps/skin/plugins/pluginBlocked.png"},
// Bug 1348558
{file: "chrome://mozapps/skin/update/downloadButtons.png",
platforms: ["linux"]},
// Bug 1348559
{file: "chrome://pippki/content/resetpassword.xul"},
// Bug 1348562
{file: "chrome://devtools/skin/images/debugging-devices.svg",
isFromDevTools: true},
{file: "chrome://devtools/skin/images/fast-forward.svg",
isFromDevTools: true},
{file: "chrome://devtools/skin/images/firebug/spinner.png",
isFromDevTools: true},
{file: "chrome://devtools/skin/images/noise.png",
isFromDevTools: true},
].filter(item =>
("isFromDevTools" in item) == isDevtools &&
(!item.platforms || item.platforms.includes(AppConstants.platform))
).map(item => item.file));
const ignorableWhitelist = new Set([
// chrome://xslt-qa/ isn't referenced, but isn't included in packaged builds,
// so it's fine to just ignore it and ignore if the exceptions are unused.
"chrome://xslt-qa/content/buster/result-view.xul",
"chrome://xslt-qa/content/xslt-qa-overlay.xul",
// The communicator.css file is kept for add-on backward compat, but it is
// referenced by something in xslt-qa, so the exception won't be used when
// running the test on a local non-packaged build.
"chrome://communicator/skin/communicator.css",
// These 2 files are unreferenced only when building without the crash
// reporter (eg. Linux x64 asan builds on treeherder)
"chrome://global/locale/crashes.dtd",
"chrome://global/locale/crashes.properties",
]);
for (let entry of ignorableWhitelist)
whitelist.add(entry);
const gInterestingCategories = new Set([
"agent-style-sheets", "webextension-scripts",
"webextension-schemas", "webextension-scripts-addon",
"webextension-scripts-content", "webextension-scripts-devtools"
]);
var gChromeReg = Cc["@mozilla.org/chrome/chrome-registry;1"]
.getService(Ci.nsIChromeRegistry);
var gChromeMap = new Map();
var gOverrideMap = new Map();
var gReferencesFromCode = new Set();
function getBaseUriForChromeUri(chromeUri) {
let chromeFile = chromeUri + "gobbledygooknonexistentfile.reallynothere";
let uri = Services.io.newURI(chromeFile);
let fileUri = gChromeReg.convertChromeURL(uri);
return fileUri.resolve(".");
}
function parseManifest(manifestUri) {
return fetchFile(manifestUri.spec).then(data => {
for (let line of data.split("\n")) {
let [type, ...argv] = line.split(/\s+/);
if (type == "content" || type == "skin" || type == "locale") {
let chromeUri = `chrome://${argv[0]}/${type}/`;
gChromeMap.set(getBaseUriForChromeUri(chromeUri), chromeUri);
} else if (type == "override" || type == "overlay") {
// Overlays aren't really overrides, but behave the same in
// that the overlay is only referenced if the original xul
// file is referenced somewhere.
let os = "os=" + Services.appinfo.OS;
if (!argv.some(s => s.startsWith("os=") && s != os)) {
gOverrideMap.set(Services.io.newURI(argv[1]).specIgnoringRef,
Services.io.newURI(argv[0]).specIgnoringRef);
}
} else if (type == "category" && gInterestingCategories.has(argv[0])) {
gReferencesFromCode.add(argv[2]);
}
}
});
}
function parseCSSFile(fileUri) {
return fetchFile(fileUri.spec).then(data => {
for (let line of data.split("\n")) {
let urls = line.match(/url\([^()]+\)/g);
if (!urls) {
// @import rules can take a string instead of a url.
let importMatch = line.match(/@import ['"]?([^'"]*)['"]?/);
if (importMatch && importMatch[1]) {
let url = Services.io.newURI(importMatch[1], null, fileUri).spec;
gReferencesFromCode.add(convertToChromeUri(url));
}
continue;
}
for (let url of urls) {
// Remove the url(" prefix and the ") suffix.
url = url.replace(/url\(([^)]*)\)/, "$1")
.replace(/^"(.*)"$/, "$1")
.replace(/^'(.*)'$/, "$1");
if (url.startsWith("data:"))
continue;
try {
url = Services.io.newURI(url, null, fileUri).specIgnoringRef;
gReferencesFromCode.add(convertToChromeUri(url));
} catch (e) {
ok(false, "unexpected error while resolving this URI: " + url);
}
}
}
});
}
function parseCodeFile(fileUri) {
return fetchFile(fileUri.spec).then(data => {
for (let line of data.split("\n")) {
let urls =
line.match(/["']chrome:\/\/[a-zA-Z0-9 -]+\/(content|skin|locale)\/[^"' ]*["']/g);
if (!urls) {
// If there's no absolute chrome URL, look for relative ones in
// src and href attributes.
let match = line.match("(?:src|href)=[\"']([^$&\"']+)");
if (match && match[1]) {
let url = Services.io.newURI(match[1], null, fileUri).spec;
gReferencesFromCode.add(convertToChromeUri(url));
}
if (isDevtools) {
// Handle usage of devtools' LocalizationHelper object
match = line.match('"devtools/client/locales/([^/.]+).properties"');
if (match && match[1]) {
gReferencesFromCode.add("chrome://devtools/locale/" +
match[1] + ".properties");
}
match = line.match('"devtools/shared/locales/([^/.]+).properties"');
if (match && match[1]) {
gReferencesFromCode.add("chrome://devtools-shared/locale/" +
match[1] + ".properties");
}
}
continue;
}
for (let url of urls) {
// Remove quotes.
url = url.slice(1, -1);
// Remove ? or \ trailing characters.
if (url.endsWith("?") || url.endsWith("\\"))
url = url.slice(0, -1);
// Make urls like chrome://browser/skin/ point to an actual file,
// and remove the ref if any.
url = Services.io.newURI(url).specIgnoringRef;
gReferencesFromCode.add(url);
}
}
});
}
function convertToChromeUri(fileUri) {
let baseUri = fileUri;
let path = "";
while (true) {
let slashPos = baseUri.lastIndexOf("/", baseUri.length - 2);
if (slashPos <= 0) {
// File not accessible from chrome protocol,
// TODO: bug 1349005 handle resource:// urls.
return fileUri;
}
path = baseUri.slice(slashPos + 1) + path;
baseUri = baseUri.slice(0, slashPos + 1);
if (gChromeMap.has(baseUri)) {
let chromeBaseUri = gChromeMap.get(baseUri);
return `${chromeBaseUri}${path}`;
}
}
}
function chromeFileExists(aURI) {
let available = 0;
try {
let channel = NetUtil.newChannel({uri: aURI, loadUsingSystemPrincipal: true});
let stream = channel.open();
let sstream = Cc["@mozilla.org/scriptableinputstream;1"]
.createInstance(Ci.nsIScriptableInputStream);
sstream.init(stream);
available = sstream.available();
sstream.close();
} catch (e) {
if (e.result != Components.results.NS_ERROR_FILE_NOT_FOUND) {
dump("Checking " + aURI + ": " + e + "\n");
Cu.reportError(e);
}
}
return available > 0;
}
function findChromeUrlsFromArray(array) {
const prefix = "chrome://";
// Find the 'c' character...
for (let index = 0;
(index = array.indexOf(prefix.charCodeAt(0), index)) != -1;
++index) {
// Then ensure we actually have the whole chrome:// prefix.
let found = true;
for (let i = 1; i < prefix.length; ++i) {
if (array[index + i] != prefix.charCodeAt(i)) {
found = false;
break;
}
}
if (!found)
continue;
// C strings are null terminated, but " also terminates urls
// (nsIndexedToHTML.cpp contains an HTML fragment with several chrome urls)
// Let's also terminate the string on the # character to skip references.
let end = Math.min(array.indexOf(0, index),
array.indexOf('"'.charCodeAt(0), index),
array.indexOf("#".charCodeAt(0), index));
let string = "";
for ( ; index < end; ++index)
string += String.fromCharCode(array[index]);
// Only keep strings that look like real chrome urls.
if (/chrome:\/\/[a-zA-Z09 -]+\/(content|skin|locale)\//.test(string))
gReferencesFromCode.add(string);
}
}
add_task(function* checkAllTheFiles() {
let libxulPath = OS.Constants.Path.libxul;
if (AppConstants.platform != "macosx")
libxulPath = OS.Constants.Path.libDir + "/" + libxulPath;
let libxul = yield OS.File.read(libxulPath);
findChromeUrlsFromArray(libxul);
// Handle NS_LITERAL_STRING.
findChromeUrlsFromArray(new Uint16Array(libxul.buffer));
const kCodeExtensions = [".xul", ".xml", ".xsl", ".js", ".jsm", ".html", ".xhtml"];
let appDir = Services.dirsvc.get("GreD", Ci.nsIFile);
// This asynchronously produces a list of URLs (sadly, mostly sync on our
// test infrastructure because it runs against jarfiles there, and
// our zipreader APIs are all sync)
let uris = yield generateURIsFromDirTree(appDir, [".css", ".manifest", ".json", ".jpg", ".png", ".gif", ".svg", ".dtd", ".properties"].concat(kCodeExtensions));
// Parse and remove all manifests from the list.
// NOTE that this must be done before filtering out devtools paths
// so that all chrome paths can be recorded.
let manifestPromises = [];
uris = uris.filter(uri => {
let path = uri.path;
if (path.endsWith(".manifest")) {
manifestPromises.push(parseManifest(uri));
return false;
}
return true;
});
// Wait for all manifest to be parsed
yield Promise.all(manifestPromises);
// We build a list of promises that get resolved when their respective
// files have loaded and produced no errors.
let allPromises = [];
for (let uri of uris) {
let path = uri.path;
if (path.endsWith(".css"))
allPromises.push(parseCSSFile(uri));
else if (kCodeExtensions.some(ext => path.endsWith(ext)))
allPromises.push(parseCodeFile(uri));
}
// Wait for all the files to have actually loaded:
yield Promise.all(allPromises);
// Keep only chrome:// files, and filter out either the devtools paths or
// the non-devtools paths:
let devtoolsPrefixes = ["chrome://webide/", "chrome://devtools"];
let chromeFiles =
uris.map(uri => convertToChromeUri(uri.spec))
.filter(u => u.startsWith("chrome://"))
.filter(u => isDevtools == devtoolsPrefixes.some(prefix => u.startsWith(prefix)));
let isUnreferenced =
file => !gReferencesFromCode.has(file) &&
!gExceptionPaths.some(e => file.startsWith(e)) &&
(!gOverrideMap.has(file) || isUnreferenced(gOverrideMap.get(file)));
let notWhitelisted = file => {
if (!whitelist.has(file))
return true;
whitelist.delete(file);
return false;
};
let unreferencedFiles =
chromeFiles.filter(isUnreferenced).filter(notWhitelisted).sort();
is(unreferencedFiles.length, 0, "there should be no unreferenced files");
for (let file of unreferencedFiles)
ok(false, "unreferenced chrome file: " + file);
for (let file of whitelist) {
if (ignorableWhitelist.has(file))
info("ignored unused whitelist entry: " + file);
else
ok(false, "unused whitelist entry: " + file);
}
for (let file of gReferencesFromCode) {
if (isDevtools != devtoolsPrefixes.some(prefix => file.startsWith(prefix)))
continue;
if (file.startsWith("chrome://") && !chromeFileExists(file)) {
// Ignore chrome prefixes that have been automatically expanded.
let pathParts =
file.match("chrome://([^/]+)/content/([^/.]+)\.xul") ||
file.match("chrome://([^/]+)/skin/([^/.]+)\.css");
if (!pathParts || pathParts[1] != pathParts[2]) {
// TODO: bug 1349010 - add a whitelist and make this reliable enough
// that we could make the test fail when this catches something new.
info("missing file with code reference: " + file);
}
}
}
});

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

@ -129,30 +129,6 @@ function ignoredError(filepath, key, type) {
return false;
}
function fetchFile(uri) {
return new Promise((resolve, reject) => {
let xhr = new XMLHttpRequest();
xhr.responseType = "text";
xhr.open("GET", uri, true);
xhr.onreadystatechange = function() {
if (this.readyState != this.DONE) {
return;
}
try {
resolve(this.responseText);
} catch (ex) {
ok(false, `Script error reading ${uri}: ${ex}`);
resolve("");
}
};
xhr.onerror = error => {
ok(false, `XHR error reading ${uri}: ${error}`);
resolve("");
};
xhr.send(null);
});
}
function testForError(filepath, key, str, pattern, type, helpText) {
if (str.match(pattern) &&
!ignoredError(filepath, key, type)) {

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

@ -107,30 +107,6 @@ function once(target, name) {
});
}
function fetchFile(uri) {
return new Promise((resolve, reject) => {
let xhr = new XMLHttpRequest();
xhr.responseType = "text";
xhr.open("GET", uri, true);
xhr.onreadystatechange = function() {
if (this.readyState != this.DONE) {
return;
}
try {
resolve(this.responseText);
} catch (ex) {
ok(false, `Script error reading ${uri}: ${ex}`);
resolve("");
}
};
xhr.onerror = error => {
ok(false, `XHR error reading ${uri}: ${error}`);
resolve("");
};
xhr.send(null);
});
}
var gChromeReg = Cc["@mozilla.org/chrome/chrome-registry;1"]
.getService(Ci.nsIChromeRegistry);
var gChromeMap = new Map();

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

@ -125,3 +125,27 @@ function* generateEntriesFromJarFile(jarFile, extension) {
}
zr.close();
}
function fetchFile(uri) {
return new Promise((resolve, reject) => {
let xhr = new XMLHttpRequest();
xhr.responseType = "text";
xhr.open("GET", uri, true);
xhr.onreadystatechange = function() {
if (this.readyState != this.DONE) {
return;
}
try {
resolve(this.responseText);
} catch (ex) {
ok(false, `Script error reading ${uri}: ${ex}`);
resolve("");
}
};
xhr.onerror = error => {
ok(false, `XHR error reading ${uri}: ${error}`);
resolve("");
};
xhr.send(null);
});
}

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

@ -48,6 +48,9 @@ add_task(function* () {
resolve();
}, {once: true});
gURLBar.focus();
if (gURLBar.selectionStart == gURLBar.selectionEnd) {
gURLBar.selectionStart = gURLBar.selectionEnd = gURLBar.textValue.length;
}
EventUtils.synthesizeKey("VK_BACK_SPACE", {});
});
}

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

@ -29,6 +29,8 @@ add_task(function*() {
let promiseLoad = waitForDocLoadAndStopIt(expectedURL);
gURLBar.focus();
if (Object.keys(options).length > 0) {
gURLBar.selectionStart = gURLBar.selectionEnd =
gURLBar.inputField.value.length;
gURLBar.inputField.value = inputValue.slice(0, -1);
EventUtils.synthesizeKey(inputValue.slice(-1), {});
} else {

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

@ -129,6 +129,7 @@ support-files =
[browser_ext_webNavigation_frameId0.js]
[browser_ext_webNavigation_getFrames.js]
[browser_ext_webNavigation_onCreatedNavigationTarget.js]
[browser_ext_webNavigation_onCreatedNavigationTarget_contextmenu.js]
[browser_ext_webNavigation_onCreatedNavigationTarget_window_open.js]
[browser_ext_webNavigation_urlbar_transitions.js]
[browser_ext_windows.js]

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

@ -52,14 +52,6 @@ async function runTestCase({extension, openNavTarget, expectedWebNavProps}) {
is(completedNavMsg.url, url, "Got the expected webNavigation.onCompleted url property");
}
async function clickContextMenuItem({pageElementSelector, contextMenuItemLabel}) {
const contentAreaContextMenu = await openContextMenu(pageElementSelector);
const item = contentAreaContextMenu.getElementsByAttribute("label", contextMenuItemLabel);
is(item.length, 1, `found contextMenu item for "${contextMenuItemLabel}"`);
item[0].click();
await closeContextMenu();
}
add_task(function* test_on_created_navigation_target_from_mouse_click() {
const tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, SOURCE_PAGE);
@ -127,59 +119,6 @@ add_task(function* test_on_created_navigation_target_from_mouse_click() {
yield extension.unload();
});
add_task(function* test_on_created_navigation_target_from_context_menu() {
const tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, SOURCE_PAGE);
const extension = ExtensionTestUtils.loadExtension({
background,
manifest: {
permissions: ["webNavigation"],
},
});
yield extension.startup();
const expectedSourceTab = yield extension.awaitMessage("expectedSourceTab");
info("Open link in a new tab from the context menu");
yield runTestCase({
extension,
async openNavTarget() {
await clickContextMenuItem({
pageElementSelector: "#test-create-new-tab-from-context-menu",
contextMenuItemLabel: "Open Link in New Tab",
});
},
expectedWebNavProps: {
sourceTabId: expectedSourceTab.sourceTabId,
sourceFrameId: 0,
url: `${OPENED_PAGE}#new-tab-from-context-menu`,
},
});
info("Open link in a new window from the context menu");
yield runTestCase({
extension,
async openNavTarget() {
await clickContextMenuItem({
pageElementSelector: "#test-create-new-window-from-context-menu",
contextMenuItemLabel: "Open Link in New Window",
});
},
expectedWebNavProps: {
sourceTabId: expectedSourceTab.sourceTabId,
sourceFrameId: 0,
url: `${OPENED_PAGE}#new-window-from-context-menu`,
},
});
yield BrowserTestUtils.removeTab(tab);
yield extension.unload();
});
add_task(function* test_on_created_navigation_target_from_mouse_click_subframe() {
const tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, SOURCE_PAGE);
@ -256,65 +195,3 @@ add_task(function* test_on_created_navigation_target_from_mouse_click_subframe()
yield extension.unload();
});
add_task(function* test_on_created_navigation_target_from_context_menu_subframe() {
const tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, SOURCE_PAGE);
const extension = ExtensionTestUtils.loadExtension({
background,
manifest: {
permissions: ["webNavigation"],
},
});
yield extension.startup();
const expectedSourceTab = yield extension.awaitMessage("expectedSourceTab");
info("Open a subframe link in a new tab from the context menu");
yield runTestCase({
extension,
async openNavTarget() {
await clickContextMenuItem({
pageElementSelector: function() {
// This code runs as a framescript in the child process and it returns the
// target link in the subframe.
return this.content.frames[0] // eslint-disable-line mozilla/no-cpows-in-tests
.document.querySelector("#test-create-new-tab-from-context-menu-subframe");
},
contextMenuItemLabel: "Open Link in New Tab",
});
},
expectedWebNavProps: {
sourceTabId: expectedSourceTab.sourceTabId,
sourceFrameId: expectedSourceTab.sourceTabFrames[1].frameId,
url: `${OPENED_PAGE}#new-tab-from-context-menu-subframe`,
},
});
info("Open a subframe link in a new window from the context menu");
yield runTestCase({
extension,
async openNavTarget() {
await clickContextMenuItem({
pageElementSelector: function() {
// This code runs as a framescript in the child process and it returns the
// target link in the subframe.
return this.content.frames[0] // eslint-disable-line mozilla/no-cpows-in-tests
.document.querySelector("#test-create-new-window-from-context-menu-subframe");
},
contextMenuItemLabel: "Open Link in New Window",
});
},
expectedWebNavProps: {
sourceTabId: expectedSourceTab.sourceTabId,
sourceFrameId: expectedSourceTab.sourceTabFrames[1].frameId,
url: `${OPENED_PAGE}#new-window-from-context-menu-subframe`,
},
});
yield BrowserTestUtils.removeTab(tab);
yield extension.unload();
});

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

@ -0,0 +1,177 @@
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set sts=2 sw=2 et tw=80: */
"use strict";
const BASE_URL = "http://mochi.test:8888/browser/browser/components/extensions/test/browser";
const SOURCE_PAGE = `${BASE_URL}/webNav_createdTargetSource.html`;
const OPENED_PAGE = `${BASE_URL}/webNav_createdTarget.html`;
async function background() {
const tabs = await browser.tabs.query({active: true, currentWindow: true});
const sourceTabId = tabs[0].id;
const sourceTabFrames = await browser.webNavigation.getAllFrames({tabId: sourceTabId});
browser.webNavigation.onCreatedNavigationTarget.addListener((msg) => {
browser.test.sendMessage("webNavOnCreated", msg);
});
browser.webNavigation.onCompleted.addListener(async (msg) => {
// NOTE: checking the url is currently necessary because of Bug 1252129
// ( Filter out webNavigation events related to new window initialization phase).
if (msg.tabId !== sourceTabId && msg.url !== "about:blank") {
await browser.tabs.remove(msg.tabId);
browser.test.sendMessage("webNavOnCompleted", msg);
}
});
browser.tabs.onCreated.addListener((tab) => {
browser.test.sendMessage("tabsOnCreated", tab.id);
});
browser.test.sendMessage("expectedSourceTab", {
sourceTabId, sourceTabFrames,
});
}
async function runTestCase({extension, openNavTarget, expectedWebNavProps}) {
await openNavTarget();
const webNavMsg = await extension.awaitMessage("webNavOnCreated");
const createdTabId = await extension.awaitMessage("tabsOnCreated");
const completedNavMsg = await extension.awaitMessage("webNavOnCompleted");
let {sourceTabId, sourceFrameId, url} = expectedWebNavProps;
is(webNavMsg.tabId, createdTabId, "Got the expected tabId property");
is(webNavMsg.sourceTabId, sourceTabId, "Got the expected sourceTabId property");
is(webNavMsg.sourceFrameId, sourceFrameId, "Got the expected sourceFrameId property");
is(webNavMsg.url, url, "Got the expected url property");
is(completedNavMsg.tabId, createdTabId, "Got the expected webNavigation.onCompleted tabId property");
is(completedNavMsg.url, url, "Got the expected webNavigation.onCompleted url property");
}
async function clickContextMenuItem({pageElementSelector, contextMenuItemLabel}) {
const contentAreaContextMenu = await openContextMenu(pageElementSelector);
const item = contentAreaContextMenu.getElementsByAttribute("label", contextMenuItemLabel);
is(item.length, 1, `found contextMenu item for "${contextMenuItemLabel}"`);
item[0].click();
await closeContextMenu();
}
add_task(function* test_on_created_navigation_target_from_context_menu() {
const tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, SOURCE_PAGE);
const extension = ExtensionTestUtils.loadExtension({
background,
manifest: {
permissions: ["webNavigation"],
},
});
yield extension.startup();
const expectedSourceTab = yield extension.awaitMessage("expectedSourceTab");
info("Open link in a new tab from the context menu");
yield runTestCase({
extension,
async openNavTarget() {
await clickContextMenuItem({
pageElementSelector: "#test-create-new-tab-from-context-menu",
contextMenuItemLabel: "Open Link in New Tab",
});
},
expectedWebNavProps: {
sourceTabId: expectedSourceTab.sourceTabId,
sourceFrameId: 0,
url: `${OPENED_PAGE}#new-tab-from-context-menu`,
},
});
info("Open link in a new window from the context menu");
yield runTestCase({
extension,
async openNavTarget() {
await clickContextMenuItem({
pageElementSelector: "#test-create-new-window-from-context-menu",
contextMenuItemLabel: "Open Link in New Window",
});
},
expectedWebNavProps: {
sourceTabId: expectedSourceTab.sourceTabId,
sourceFrameId: 0,
url: `${OPENED_PAGE}#new-window-from-context-menu`,
},
});
yield BrowserTestUtils.removeTab(tab);
yield extension.unload();
});
add_task(function* test_on_created_navigation_target_from_context_menu_subframe() {
const tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, SOURCE_PAGE);
const extension = ExtensionTestUtils.loadExtension({
background,
manifest: {
permissions: ["webNavigation"],
},
});
yield extension.startup();
const expectedSourceTab = yield extension.awaitMessage("expectedSourceTab");
info("Open a subframe link in a new tab from the context menu");
yield runTestCase({
extension,
async openNavTarget() {
await clickContextMenuItem({
pageElementSelector: function() {
// This code runs as a framescript in the child process and it returns the
// target link in the subframe.
return this.content.frames[0] // eslint-disable-line mozilla/no-cpows-in-tests
.document.querySelector("#test-create-new-tab-from-context-menu-subframe");
},
contextMenuItemLabel: "Open Link in New Tab",
});
},
expectedWebNavProps: {
sourceTabId: expectedSourceTab.sourceTabId,
sourceFrameId: expectedSourceTab.sourceTabFrames[1].frameId,
url: `${OPENED_PAGE}#new-tab-from-context-menu-subframe`,
},
});
info("Open a subframe link in a new window from the context menu");
yield runTestCase({
extension,
async openNavTarget() {
await clickContextMenuItem({
pageElementSelector: function() {
// This code runs as a framescript in the child process and it returns the
// target link in the subframe.
return this.content.frames[0] // eslint-disable-line mozilla/no-cpows-in-tests
.document.querySelector("#test-create-new-window-from-context-menu-subframe");
},
contextMenuItemLabel: "Open Link in New Window",
});
},
expectedWebNavProps: {
sourceTabId: expectedSourceTab.sourceTabId,
sourceFrameId: expectedSourceTab.sourceTabFrames[1].frameId,
url: `${OPENED_PAGE}#new-window-from-context-menu-subframe`,
},
});
yield BrowserTestUtils.removeTab(tab);
yield extension.unload();
});

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

@ -223,8 +223,7 @@ FeedConverter.prototype = {
try {
let title = feed.title ? feed.title.plainText() : "";
let desc = feed.subtitle ? feed.subtitle.plainText() : "";
let feedReader = safeGetCharPref(getPrefActionForType(feed.type), "bookmarks");
feedService.addToClientReader(result.uri.spec, title, desc, feed.type, feedReader);
feedService.addToClientReader(result.uri.spec, title, desc, feed.type, handler);
return;
} catch (ex) { /* fallback to preview mode */ }
}

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

@ -44,83 +44,11 @@ function makeURI(aURLSpec, aCharset) {
const XML_NS = "http://www.w3.org/XML/1998/namespace";
const HTML_NS = "http://www.w3.org/1999/xhtml";
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
const TYPE_MAYBE_FEED = "application/vnd.mozilla.maybe.feed";
const TYPE_MAYBE_AUDIO_FEED = "application/vnd.mozilla.maybe.audio.feed";
const TYPE_MAYBE_VIDEO_FEED = "application/vnd.mozilla.maybe.video.feed";
const URI_BUNDLE = "chrome://browser/locale/feeds/subscribe.properties";
const PREF_SELECTED_APP = "browser.feeds.handlers.application";
const PREF_SELECTED_WEB = "browser.feeds.handlers.webservice";
const PREF_SELECTED_ACTION = "browser.feeds.handler";
const PREF_SELECTED_READER = "browser.feeds.handler.default";
const PREF_VIDEO_SELECTED_APP = "browser.videoFeeds.handlers.application";
const PREF_VIDEO_SELECTED_WEB = "browser.videoFeeds.handlers.webservice";
const PREF_VIDEO_SELECTED_ACTION = "browser.videoFeeds.handler";
const PREF_VIDEO_SELECTED_READER = "browser.videoFeeds.handler.default";
const PREF_AUDIO_SELECTED_APP = "browser.audioFeeds.handlers.application";
const PREF_AUDIO_SELECTED_WEB = "browser.audioFeeds.handlers.webservice";
const PREF_AUDIO_SELECTED_ACTION = "browser.audioFeeds.handler";
const PREF_AUDIO_SELECTED_READER = "browser.audioFeeds.handler.default";
const PREF_SHOW_FIRST_RUN_UI = "browser.feeds.showFirstRunUI";
const TITLE_ID = "feedTitleText";
const SUBTITLE_ID = "feedSubtitleText";
function getPrefAppForType(t) {
switch (t) {
case Ci.nsIFeed.TYPE_VIDEO:
return PREF_VIDEO_SELECTED_APP;
case Ci.nsIFeed.TYPE_AUDIO:
return PREF_AUDIO_SELECTED_APP;
default:
return PREF_SELECTED_APP;
}
}
function getPrefWebForType(t) {
switch (t) {
case Ci.nsIFeed.TYPE_VIDEO:
return PREF_VIDEO_SELECTED_WEB;
case Ci.nsIFeed.TYPE_AUDIO:
return PREF_AUDIO_SELECTED_WEB;
default:
return PREF_SELECTED_WEB;
}
}
function getPrefActionForType(t) {
switch (t) {
case Ci.nsIFeed.TYPE_VIDEO:
return PREF_VIDEO_SELECTED_ACTION;
case Ci.nsIFeed.TYPE_AUDIO:
return PREF_AUDIO_SELECTED_ACTION;
default:
return PREF_SELECTED_ACTION;
}
}
function getPrefReaderForType(t) {
switch (t) {
case Ci.nsIFeed.TYPE_VIDEO:
return PREF_VIDEO_SELECTED_READER;
case Ci.nsIFeed.TYPE_AUDIO:
return PREF_AUDIO_SELECTED_READER;
default:
return PREF_SELECTED_READER;
}
}
/**
* Converts a number of bytes to the appropriate unit that results in a
* number that needs fewer than 4 digits
@ -153,9 +81,6 @@ function FeedWriter() {
}
FeedWriter.prototype = {
_mimeSvc : Cc["@mozilla.org/mime;1"].
getService(Ci.nsIMIMEService),
_getPropertyAsBag(container, property) {
return container.fields.getProperty(property).
QueryInterface(Ci.nsIPropertyBag2);
@ -226,18 +151,21 @@ FeedWriter.prototype = {
return this._bundle.GetStringFromName(key);
},
_setCheckboxCheckedState(aCheckbox, aValue) {
// see checkbox.xml, xbl bindings are not applied within the sandbox! TODO
let change = (aValue != (aCheckbox.getAttribute("checked") == "true"));
if (aValue)
aCheckbox.setAttribute("checked", "true");
else
aCheckbox.removeAttribute("checked");
_setCheckboxCheckedState(aValue) {
let checkbox = this._document.getElementById("alwaysUse");
if (checkbox) {
// see checkbox.xml, xbl bindings are not applied within the sandbox! TODO
let change = (aValue != (checkbox.getAttribute("checked") == "true"));
if (aValue)
checkbox.setAttribute("checked", "true");
else
checkbox.removeAttribute("checked");
if (change) {
let event = this._document.createEvent("Events");
event.initEvent("CheckboxStateChange", true, true);
aCheckbox.dispatchEvent(event);
if (change) {
let event = this._document.createEvent("Events");
event.initEvent("CheckboxStateChange", true, true);
checkbox.dispatchEvent(event);
}
}
},
@ -290,22 +218,6 @@ FeedWriter.prototype = {
return Ci.nsIFeed.TYPE_FEED;
},
/**
* Maps a feed type to a maybe-feed mimetype.
*/
_getMimeTypeForFeedType() {
switch (this._getFeedType()) {
case Ci.nsIFeed.TYPE_VIDEO:
return TYPE_MAYBE_VIDEO_FEED;
case Ci.nsIFeed.TYPE_AUDIO:
return TYPE_MAYBE_AUDIO_FEED;
default:
return TYPE_MAYBE_FEED;
}
},
/**
* Writes the feed title into the preview document.
* @param container
@ -491,17 +403,11 @@ FeedWriter.prototype = {
if (enc.hasKey("type")) {
type_text = enc.get("type");
try {
let handlerInfoWrapper = this._mimeSvc.getFromTypeAndExtension(enc.get("type"), null);
if (handlerInfoWrapper)
type_text = handlerInfoWrapper.description;
if (type_text && type_text.length > 0)
mozicon = "moz-icon://goat?size=16&contentType=" + enc.get("type");
} catch (ex) { }
if (enc.hasKey("typeDesc"))
type_text = enc.get("typeDesc");
if (type_text && type_text.length > 0)
mozicon = "moz-icon://goat?size=16&contentType=" + enc.get("type");
}
if (enc.hasKey("length") && /^[0-9]+$/.test(enc.get("length"))) {
@ -596,19 +502,7 @@ FeedWriter.prototype = {
this._subscribeCallback = aCallback;
this._mm.sendAsyncMessage("FeedWriter:ChooseClientApp",
{ title: this._getString("chooseApplicationDialogTitle"),
prefName: getPrefAppForType(this._getFeedType()) });
},
_setAlwaysUseCheckedState(feedType) {
let checkbox = this._document.getElementById("alwaysUse");
if (checkbox) {
let alwaysUse = false;
try {
if (Services.prefs.getCharPref(getPrefActionForType(feedType)) != "ask")
alwaysUse = true;
} catch (ex) { }
this._setCheckboxCheckedState(checkbox, alwaysUse);
}
feedType: this._getFeedType() });
},
_setSubscribeUsingLabel() {
@ -671,13 +565,13 @@ FeedWriter.prototype = {
}
break;
case "change":
LOG("Change fired");
if (event.target.selectedOptions[0].id == "chooseApplicationMenuItem") {
this._chooseClientApp((aResult) => {
if (!aResult) {
// Select the (per-prefs) selected handler if no application
// was selected
this._setSelectedHandler(this._getFeedType());
}
this._chooseClientApp(() => {
// Select the (per-prefs) selected handler if no application
// was selected
LOG("Selected handler after callback");
this._setAlwaysUseLabel();
});
} else {
this._setAlwaysUseLabel();
@ -687,28 +581,18 @@ FeedWriter.prototype = {
},
_getWebHandlerElementsForURL(aURL) {
let menu = this._document.getElementById("handlersMenuList");
return menu.querySelectorAll('[webhandlerurl="' + aURL + '"]');
return this._handlersList.querySelectorAll('[webhandlerurl="' + aURL + '"]');
},
_setSelectedHandler(feedType) {
let prefs = Services.prefs;
let handler = prefs.getCharPref(getPrefReaderForType(feedType), "bookmarks");
_setSelectedHandlerResponse(handler, url) {
LOG(`Selecting handler response ${handler} ${url}`);
switch (handler) {
case "web": {
if (this._handlersList) {
let url;
try {
url = prefs.getStringPref(getPrefWebForType(feedType));
} catch (ex) {
LOG("FeedWriter._setSelectedHandler: invalid or no handler in prefs");
return;
}
let handlers =
this._getWebHandlerElementsForURL(url);
if (handlers.length == 0) {
LOG("FeedWriter._setSelectedHandler: selected web handler isn't in the menulist")
LOG(`Selected web handler isn't in the menulist ${url}`);
return;
}
@ -729,10 +613,10 @@ FeedWriter.prototype = {
}
},
_initSubscriptionUI() {
let handlersList = this._document.getElementById("handlersMenuList");
if (!handlersList)
_initSubscriptionUI(setupMessage) {
if (!this._handlersList)
return;
LOG("UI init");
let feedType = this._getFeedType();
@ -763,7 +647,7 @@ FeedWriter.prototype = {
menuItem.style.display = "none";
this._selectedAppMenuItem = menuItem;
handlersList.appendChild(this._selectedAppMenuItem);
this._handlersList.appendChild(this._selectedAppMenuItem);
// Create the menuitem for the default reader, but don't show/populate it until
// we get confirmation of what it is from the parent
@ -774,10 +658,7 @@ FeedWriter.prototype = {
menuItem.style.display = "none";
this._defaultHandlerMenuItem = menuItem;
handlersList.appendChild(this._defaultHandlerMenuItem);
this._mm.sendAsyncMessage("FeedWriter:RequestClientAppName",
{ feedTypePref: getPrefAppForType(feedType) });
this._handlersList.appendChild(this._defaultHandlerMenuItem);
// "Choose Application..." menuitem
menuItem = liveBookmarksMenuItem.cloneNode(false);
@ -785,18 +666,14 @@ FeedWriter.prototype = {
menuItem.setAttribute("id", "chooseApplicationMenuItem");
menuItem.textContent = this._getString("chooseApplicationMenuItem");
handlersList.appendChild(menuItem);
this._handlersList.appendChild(menuItem);
// separator
let chooseAppSep = liveBookmarksMenuItem.nextElementSibling.cloneNode(false);
chooseAppSep.textContent = liveBookmarksMenuItem.nextElementSibling.textContent;
handlersList.appendChild(chooseAppSep);
this._handlersList.appendChild(chooseAppSep);
// List of web handlers
let wccr = Cc["@mozilla.org/embeddor.implemented/web-content-handler-registrar;1"].
getService(Ci.nsIWebContentConverterService);
let handlers = wccr.getContentHandlers(this._getMimeTypeForFeedType(feedType));
for (let handler of handlers) {
for (let handler of setupMessage.handlers) {
if (!handler.uri) {
LOG("Handler with name " + handler.name + " has no URI!? Skipping...");
continue;
@ -807,29 +684,37 @@ FeedWriter.prototype = {
menuItem.textContent = handler.name;
menuItem.setAttribute("handlerType", "web");
menuItem.setAttribute("webhandlerurl", handler.uri);
handlersList.appendChild(menuItem);
this._handlersList.appendChild(menuItem);
}
this._setSelectedHandler(feedType);
this._setSelectedHandlerResponse(setupMessage.reader.handler, setupMessage.reader.url);
if (setupMessage.defaultMenuItem) {
LOG(`Setting default menu item ${setupMessage.defaultMenuItem}`);
this._setApplicationLauncherMenuItem(this._defaultHandlerMenuItem, setupMessage.defaultMenuItem);
}
if (setupMessage.selectedMenuItem) {
LOG(`Setting selected menu item ${setupMessage.selectedMenuItem}`);
this._setApplicationLauncherMenuItem(this._selectedAppMenuItem, setupMessage.selectedMenuItem);
}
// "Subscribe using..."
this._setSubscribeUsingLabel();
// "Always use..." checkbox initial state
this._setAlwaysUseCheckedState(feedType);
this._setCheckboxCheckedState(setupMessage.reader.alwaysUse);
this._setAlwaysUseLabel();
// We update the "Always use.." checkbox label whenever the selected item
// in the list is changed
handlersList.addEventListener("change", this);
this._handlersList.addEventListener("change", this);
// Set up the "Subscribe Now" button
this._document.getElementById("subscribeButton")
.addEventListener("click", this);
// first-run ui
let showFirstRunUI = Services.prefs.getBoolPref(PREF_SHOW_FIRST_RUN_UI, true);
if (showFirstRunUI) {
if (setupMessage.showFirstRunUI) {
let textfeedinfo1, textfeedinfo2;
switch (feedType) {
case Ci.nsIFeed.TYPE_VIDEO:
@ -915,53 +800,74 @@ FeedWriter.prototype = {
LOG("Subscribe Preview: feed uri = " + this._window.location.href);
// Set up the subscription UI
this._initSubscriptionUI();
let prefs = Services.prefs;
prefs.addObserver(PREF_SELECTED_ACTION, this, false);
prefs.addObserver(PREF_SELECTED_READER, this, false);
prefs.addObserver(PREF_SELECTED_WEB, this, false);
prefs.addObserver(PREF_SELECTED_APP, this, false);
prefs.addObserver(PREF_VIDEO_SELECTED_ACTION, this, false);
prefs.addObserver(PREF_VIDEO_SELECTED_READER, this, false);
prefs.addObserver(PREF_VIDEO_SELECTED_WEB, this, false);
prefs.addObserver(PREF_VIDEO_SELECTED_APP, this, false);
prefs.addObserver(PREF_AUDIO_SELECTED_ACTION, this, false);
prefs.addObserver(PREF_AUDIO_SELECTED_READER, this, false);
prefs.addObserver(PREF_AUDIO_SELECTED_WEB, this, false);
prefs.addObserver(PREF_AUDIO_SELECTED_APP, this, false);
this._mm.addMessageListener("FeedWriter:PreferenceUpdated", this);
this._mm.addMessageListener("FeedWriter:SetApplicationLauncherMenuItem", this);
this._mm.addMessageListener("FeedWriter:GetSubscriptionUIResponse", this);
this._mm.addMessageListener("FeedWriter:SetFeedPrefsAndSubscribeResponse", this);
const feedType = this._getFeedType();
this._mm.sendAsyncMessage("FeedWriter:GetSubscriptionUI",
{ feedType });
},
receiveMessage(msg) {
if (!this._window) {
// this._window is null unless this.init was called with a trusted
// window object.
return;
}
LOG(`received message from parent ${msg.name}`);
switch (msg.name) {
case "FeedWriter:SetApplicationLauncherMenuItem":
let menuItem = null;
if (msg.data.type == "DefaultAppMenuItem") {
menuItem = this._defaultHandlerMenuItem;
} else {
// Most likely SelectedAppMenuItem
menuItem = this._selectedAppMenuItem;
case "FeedWriter:PreferenceUpdated":
// This is called when browser-feeds.js spots a pref change
// This will happen when
// - about:preferences#applications changes
// - another feed reader page changes the preference
// - when this page itself changes the select and there isn't a redirect
// bookmarks and launching an external app means the page stays open after subscribe
const feedType = this._getFeedType();
LOG(`Got prefChange! ${JSON.stringify(msg.data)} current type: ${feedType}`);
let feedTypePref = msg.data.default;
if (feedType in msg.data) {
feedTypePref = msg.data[feedType];
}
menuItem.textContent = msg.data.name;
menuItem.style.display = "";
menuItem.selected = true;
LOG(`Got pref ${JSON.stringify(feedTypePref)}`);
this._setCheckboxCheckedState(feedTypePref.alwaysUse);
this._setSelectedHandlerResponse(feedTypePref.handler, feedTypePref.url);
this._setAlwaysUseLabel();
break;
case "FeedWriter:SetFeedPrefsAndSubscribeResponse":
LOG(`FeedWriter:SetFeedPrefsAndSubscribeResponse - Redirecting ${msg.data.redirect}`);
this._window.location.href = msg.data.redirect;
break;
case "FeedWriter:GetSubscriptionUIResponse":
// Set up the subscription UI
this._initSubscriptionUI(msg.data);
break;
case "FeedWriter:SetApplicationLauncherMenuItem":
LOG(`FeedWriter:SetApplicationLauncherMenuItem - picked ${msg.data.name}`);
this._setApplicationLauncherMenuItem(this._selectedAppMenuItem, msg.data.name);
// Potentially a bit racy, but I don't think we can get into a state where this callback is set and
// we're not coming back from ChooseClientApp in browser-feeds.js
if (this._subscribeCallback) {
this._subscribeCallback();
this._subscribeCallback = null;
}
break;
}
},
_setApplicationLauncherMenuItem(menuItem, aName) {
/* unselect all handlers */
[...this._handlersList.children].forEach((option) => {
option.removeAttribute("selected");
});
menuItem.textContent = aName;
menuItem.style.display = "";
menuItem.selected = true;
},
writeContent() {
if (!this._window)
return;
@ -983,24 +889,11 @@ FeedWriter.prototype = {
close() {
this._document.getElementById("subscribeButton")
.removeEventListener("click", this);
this._document.getElementById("handlersMenuList")
this._handlersList
.removeEventListener("change", this);
this._document = null;
this._window = null;
let prefs = Services.prefs;
prefs.removeObserver(PREF_SELECTED_ACTION, this);
prefs.removeObserver(PREF_SELECTED_READER, this);
prefs.removeObserver(PREF_SELECTED_WEB, this);
prefs.removeObserver(PREF_SELECTED_APP, this);
prefs.removeObserver(PREF_VIDEO_SELECTED_ACTION, this);
prefs.removeObserver(PREF_VIDEO_SELECTED_READER, this);
prefs.removeObserver(PREF_VIDEO_SELECTED_WEB, this);
prefs.removeObserver(PREF_VIDEO_SELECTED_APP, this);
prefs.removeObserver(PREF_AUDIO_SELECTED_ACTION, this);
prefs.removeObserver(PREF_AUDIO_SELECTED_READER, this);
prefs.removeObserver(PREF_AUDIO_SELECTED_WEB, this);
prefs.removeObserver(PREF_AUDIO_SELECTED_APP, this);
this._handlersList = null;
this._removeFeedFromCache();
this.__bundle = null;
@ -1020,20 +913,6 @@ FeedWriter.prototype = {
}
},
setFeedCharPref(aPrefName, aPrefValue) {
this._mm.sendAsyncMessage("FeedWriter:SetFeedCharPref",
{ pref: aPrefName,
value: aPrefValue });
},
setFeedComplexString(aPrefName, aPrefValue) {
// This sends the string data across to the parent, which will use it in an nsISupportsString
// for a complex value pref.
this._mm.sendAsyncMessage("FeedWriter:SetFeedComplexString",
{ pref: aPrefName,
value: aPrefValue });
},
subscribe() {
let feedType = this._getFeedType();
@ -1041,26 +920,21 @@ FeedWriter.prototype = {
let defaultHandler = "reader";
let useAsDefault = this._document.getElementById("alwaysUse").getAttribute("checked");
let menuList = this._document.getElementById("handlersMenuList");
let selectedItem = menuList.selectedOptions[0];
let selectedItem = this._handlersList.selectedOptions[0];
let subscribeCallback = () => {
let feedReader = null;
let settings = {
feedType,
useAsDefault,
// Pull the title and subtitle out of the document
feedTitle: this._document.getElementById(TITLE_ID).textContent,
feedSubtitle: this._document.getElementById(SUBTITLE_ID).textContent,
feedLocation: this._window.location.href
};
if (selectedItem.hasAttribute("webhandlerurl")) {
let webURI = selectedItem.getAttribute("webhandlerurl");
this.setFeedCharPref(getPrefReaderForType(feedType), "web");
this.setFeedComplexString(getPrefWebForType(feedType), webURI);
let wccr = Cc["@mozilla.org/embeddor.implemented/web-content-handler-registrar;1"].
getService(Ci.nsIWebContentConverterService);
let handler = wccr.getWebContentHandlerByURI(this._getMimeTypeForFeedType(feedType), webURI);
if (handler) {
if (useAsDefault) {
wccr.setAutoHandler(this._getMimeTypeForFeedType(feedType), handler);
}
this._window.location.href = handler.getHandlerURI(this._window.location.href);
}
feedReader = "web";
settings.uri = selectedItem.getAttribute("webhandlerurl");
} else {
let feedReader = null;
switch (selectedItem.id) {
case "selectedAppMenuItem":
feedReader = "client";
@ -1073,27 +947,20 @@ FeedWriter.prototype = {
feedReader = "bookmarks";
break;
}
this.setFeedCharPref(getPrefReaderForType(feedType), feedReader);
let feedService = Cc["@mozilla.org/browser/feeds/result-service;1"].
getService(Ci.nsIFeedResultService);
// Pull the title and subtitle out of the document
let feedTitle = this._document.getElementById(TITLE_ID).textContent;
let feedSubtitle = this._document.getElementById(SUBTITLE_ID).textContent;
feedService.addToClientReader(this._window.location.href, feedTitle, feedSubtitle, feedType, feedReader);
}
settings.reader = feedReader;
// If "Always use..." is checked, we should set PREF_*SELECTED_ACTION
// to either "reader" (If a web reader or if an application is selected),
// or to "bookmarks" (if the live bookmarks option is selected).
// Otherwise, we should set it to "ask"
if (useAsDefault) {
this.setFeedCharPref(getPrefActionForType(feedType), defaultHandler);
} else {
this.setFeedCharPref(getPrefActionForType(feedType), "ask");
if (!useAsDefault) {
defaultHandler = "ask";
}
settings.action = defaultHandler;
LOG(`FeedWriter:SetFeedPrefsAndSubscribe - ${JSON.stringify(settings)}`);
this._mm.sendAsyncMessage("FeedWriter:SetFeedPrefsAndSubscribe",
settings);
}
// Show the file picker before subscribing if the
@ -1111,37 +978,6 @@ FeedWriter.prototype = {
}
},
// nsIObserver
observe(subject, topic, data) {
if (!this._window) {
// this._window is null unless this.init was called with a trusted
// window object.
return;
}
let feedType = this._getFeedType();
if (topic == "nsPref:changed") {
switch (data) {
case PREF_SELECTED_READER:
case PREF_SELECTED_WEB:
case PREF_SELECTED_APP:
case PREF_VIDEO_SELECTED_READER:
case PREF_VIDEO_SELECTED_WEB:
case PREF_VIDEO_SELECTED_APP:
case PREF_AUDIO_SELECTED_READER:
case PREF_AUDIO_SELECTED_WEB:
case PREF_AUDIO_SELECTED_APP:
this._setSelectedHandler(feedType);
break;
case PREF_SELECTED_ACTION:
case PREF_VIDEO_SELECTED_ACTION:
case PREF_AUDIO_SELECTED_ACTION:
this._setAlwaysUseCheckedState(feedType);
}
}
},
get _mm() {
let mm = this._window.QueryInterface(Ci.nsIInterfaceRequestor).
getInterface(Ci.nsIDocShell).

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

@ -20,7 +20,7 @@
<title>&welcomeback2.tabtitle;</title>
<link rel="stylesheet" href="chrome://global/skin/in-content/info-pages.css" type="text/css" media="all"/>
<link rel="stylesheet" href="chrome://browser/skin/aboutWelcomeBack.css" type="text/css" media="all"/>
<link rel="icon" type="image/png" href="chrome://global/skin/icons/information-16.png"/>
<link rel="icon" type="image/png" href="chrome://browser/skin/info.svg"/>
<script type="application/javascript" src="chrome://browser/content/aboutSessionRestore.js"/>
</head>

7
browser/extensions/e10srollout/bootstrap.js поставляемый
Просмотреть файл

@ -19,7 +19,7 @@ const TEST_THRESHOLD = {
const ADDON_ROLLOUT_POLICY = {
"beta" : "51alladdons", // Any WebExtension or addon except with mpc = false
"release" : "51set1",
"release" : "50allmpc",
"esr" : "esrA", // WebExtensions and Addons with mpc=true
};
@ -73,7 +73,10 @@ function defineCohort() {
Preferences.set(PREF_E10S_ADDON_BLOCKLIST,
// bug 1185672 - Tab Mix Plus
"{dc572301-7619-498c-a57d-39143191b318};");
"{dc572301-7619-498c-a57d-39143191b318};"
// bug 1344345 - Mega
+ "firefox@mega.co.nz"
);
} else {
Preferences.reset(PREF_E10S_ADDON_POLICY);
}

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

@ -10,7 +10,7 @@
<Description about="urn:mozilla:install-manifest">
<em:id>e10srollout@mozilla.org</em:id>
<em:version>1.11</em:version>
<em:version>1.12</em:version>
<em:type>2</em:type>
<em:bootstrap>true</em:bootstrap>
<em:multiprocessCompatible>true</em:multiprocessCompatible>

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

@ -0,0 +1,6 @@
# 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/.
errorReportFalseDeceptiveTitle=This isnt a deceptive site
errorReportFalseDeceptiveMessage=Its not possible to report this error at this time.

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

@ -54,6 +54,7 @@
locale/browser/places/moveBookmarks.dtd (%chrome/browser/places/moveBookmarks.dtd)
locale/browser/safebrowsing/phishing-afterload-warning-message.dtd (%chrome/browser/safebrowsing/phishing-afterload-warning-message.dtd)
locale/browser/safebrowsing/report-phishing.dtd (%chrome/browser/safebrowsing/report-phishing.dtd)
locale/browser/safebrowsing/safebrowsing.properties (%chrome/browser/safebrowsing/safebrowsing.properties)
locale/browser/feeds/subscribe.dtd (%chrome/browser/feeds/subscribe.dtd)
locale/browser/feeds/subscribe.properties (%chrome/browser/feeds/subscribe.properties)
locale/browser/migration/migration.dtd (%chrome/browser/migration/migration.dtd)

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

@ -7,7 +7,7 @@ body {
#message-box {
margin-top: 2em;
background: url('chrome://global/skin/icons/information-24.png') no-repeat left 4px;
background: url(chrome://browser/skin/info.svg) no-repeat left 8px;
padding-inline-start: 30px;
}

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

@ -1,9 +1,9 @@
The certificate authority and server certificates here are generated by $topsrcdir/build/pgo/genpgocert.py.
You can generate a new CA cert by running:
$objdir/_virtualenv/bin/python $topsrcdir/build/pgo/genpgocert.py --gen-ca
./mach python build/pgo/genpgocert.py --gen-ca
You can generate new server certificates by running:
$objdir/_virtualenv/bin/python $topsrcdir/build/pgo/genpgocert.py --gen-server
./mach python build/pgo/genpgocert.py --gen-server
These will place the new files in this directory where you can commit them.
These commands will modify cert8.db and key3.db. The changes to these should be committed.

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

@ -442,6 +442,21 @@ BasePrincipal::GetCsp(nsIContentSecurityPolicy** aCsp)
return NS_OK;
}
NS_IMETHODIMP
BasePrincipal::SetCsp(nsIContentSecurityPolicy* aCsp)
{
// Never destroy an existing CSP on the principal.
// This method should only be called in rare cases.
MOZ_ASSERT(!mCSP, "do not destroy an existing CSP");
if (mCSP) {
return NS_ERROR_ALREADY_INITIALIZED;
}
mCSP = aCsp;
return NS_OK;
}
NS_IMETHODIMP
BasePrincipal::EnsureCSP(nsIDOMDocument* aDocument,
nsIContentSecurityPolicy** aCSP)

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

@ -222,6 +222,7 @@ public:
NS_IMETHOD SubsumesConsideringDomainIgnoringFPD(nsIPrincipal* other, bool* _retval) final;
NS_IMETHOD CheckMayLoad(nsIURI* uri, bool report, bool allowIfInheritsPrincipal) final;
NS_IMETHOD GetCsp(nsIContentSecurityPolicy** aCsp) override;
NS_IMETHOD SetCsp(nsIContentSecurityPolicy* aCsp) override;
NS_IMETHOD EnsureCSP(nsIDOMDocument* aDocument, nsIContentSecurityPolicy** aCSP) override;
NS_IMETHOD GetPreloadCsp(nsIContentSecurityPolicy** aPreloadCSP) override;
NS_IMETHOD EnsurePreloadCSP(nsIDOMDocument* aDocument, nsIContentSecurityPolicy** aCSP) override;

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

@ -151,10 +151,11 @@ interface nsIPrincipal : nsISerializable
/**
* A Content Security Policy associated with this principal.
*
* Use this function to query the associated CSP with this principal.
* Please *only* use this function to *set* a CSP when you know exactly what you are doing.
* Most likely you want to call ensureCSP instead of setCSP.
*/
[noscript] readonly attribute nsIContentSecurityPolicy csp;
[noscript] attribute nsIContentSecurityPolicy csp;
/*
* Use this function to query a CSP associated with this principal.

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

@ -135,7 +135,10 @@ ReadSuffixAndSpec(JSStructuredCloneReader* aReader,
}
nsAutoCString suffix;
suffix.SetLength(suffixLength);
if (!suffix.SetLength(suffixLength, fallible)) {
return false;
}
if (!JS_ReadBytes(aReader, suffix.BeginWriting(), suffixLength)) {
return false;
}
@ -144,7 +147,10 @@ ReadSuffixAndSpec(JSStructuredCloneReader* aReader,
return false;
}
aSpec.SetLength(specLength);
if (!aSpec.SetLength(specLength, fallible)) {
return false;
}
if (!JS_ReadBytes(aReader, aSpec.BeginWriting(), specLength)) {
return false;
}
@ -195,7 +201,7 @@ ReadPrincipalInfo(JSStructuredCloneReader* aReader,
return false;
}
aInfo = ContentPrincipalInfo(attrs, spec);
aInfo = ContentPrincipalInfo(attrs, void_t(), spec);
} else {
MOZ_CRASH("unexpected principal structured clone tag");
}

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

@ -108,6 +108,20 @@ nsNullPrincipal::GetHashValue(uint32_t *aResult)
return NS_OK;
}
NS_IMETHODIMP
nsNullPrincipal::SetCsp(nsIContentSecurityPolicy* aCsp) {
// Never destroy an existing CSP on the principal.
// This method should only be called in rare cases.
MOZ_ASSERT(!mCSP, "do not destroy an existing CSP");
if (mCSP) {
return NS_ERROR_ALREADY_INITIALIZED;
}
mCSP = aCsp;
return NS_OK;
}
NS_IMETHODIMP
nsNullPrincipal::GetURI(nsIURI** aURI)
{

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

@ -45,6 +45,7 @@ public:
NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) override;
NS_IMETHOD GetHashValue(uint32_t* aHashValue) override;
NS_IMETHOD SetCsp(nsIContentSecurityPolicy* aCsp) override;
NS_IMETHOD GetURI(nsIURI** aURI) override;
NS_IMETHOD GetDomain(nsIURI** aDomain) override;
NS_IMETHOD SetDomain(nsIURI* aDomain) override;

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

@ -269,10 +269,68 @@ nsScriptSecurityManager::GetChannelResultPrincipal(nsIChannel* aChannel,
nsIPrincipal** aPrincipal,
bool aIgnoreSandboxing)
{
NS_PRECONDITION(aChannel, "Must have channel!");
// Check whether we have an nsILoadInfo that says what we should do.
nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo();
if (loadInfo && loadInfo->GetForceInheritPrincipalOverruleOwner()) {
NS_PRECONDITION(aChannel, "Must have channel!");
// Check whether we have an nsILoadInfo that says what we should do.
nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo();
if (loadInfo && loadInfo->GetForceInheritPrincipalOverruleOwner()) {
nsCOMPtr<nsIPrincipal> principalToInherit = loadInfo->PrincipalToInherit();
if (!principalToInherit) {
principalToInherit = loadInfo->TriggeringPrincipal();
}
principalToInherit.forget(aPrincipal);
return NS_OK;
}
nsCOMPtr<nsISupports> owner;
aChannel->GetOwner(getter_AddRefs(owner));
if (owner) {
CallQueryInterface(owner, aPrincipal);
if (*aPrincipal) {
return NS_OK;
}
}
if (loadInfo) {
if (!aIgnoreSandboxing && loadInfo->GetLoadingSandboxed()) {
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(loadInfo->GetSandboxedLoadingPrincipal(aPrincipal)));
MOZ_ASSERT(*aPrincipal);
// if the new NullPrincipal (above) loads an iframe[srcdoc], we
// need to inherit an existing CSP to avoid bypasses (bug 1073952).
// We continue inheriting for nested frames with e.g., data: URLs.
if (loadInfo->GetExternalContentPolicyType() == nsIContentPolicy::TYPE_SUBDOCUMENT) {
nsCOMPtr<nsIURI> uri;
aChannel->GetURI(getter_AddRefs(uri));
nsAutoCString URISpec;
uri->GetSpec(URISpec);
bool isData = (NS_SUCCEEDED(uri->SchemeIs("data", &isData)) && isData);
if (URISpec.EqualsLiteral("about:srcdoc") || isData) {
nsCOMPtr<nsIPrincipal> principalToInherit = loadInfo->PrincipalToInherit();
if (!principalToInherit) {
principalToInherit = loadInfo->TriggeringPrincipal();
}
nsCOMPtr<nsIContentSecurityPolicy> originalCsp;
principalToInherit->GetCsp(getter_AddRefs(originalCsp));
// if the principalToInherit had a CSP,
// add it to the newly created NullPrincipal.
if (originalCsp) {
nsresult rv = (*aPrincipal)->SetCsp(originalCsp);
NS_ENSURE_SUCCESS(rv, rv);
}
}
}
return NS_OK;
}
bool forceInherit = loadInfo->GetForceInheritPrincipal();
if (aIgnoreSandboxing && !forceInherit) {
// Check if SEC_FORCE_INHERIT_PRINCIPAL was dropped because of
// sandboxing:
if (loadInfo->GetLoadingSandboxed() &&
loadInfo->GetForceInheritPrincipalDropped()) {
forceInherit = true;
}
}
if (forceInherit) {
nsCOMPtr<nsIPrincipal> principalToInherit = loadInfo->PrincipalToInherit();
if (!principalToInherit) {
principalToInherit = loadInfo->TriggeringPrincipal();
@ -281,67 +339,33 @@ nsScriptSecurityManager::GetChannelResultPrincipal(nsIChannel* aChannel,
return NS_OK;
}
nsCOMPtr<nsISupports> owner;
aChannel->GetOwner(getter_AddRefs(owner));
if (owner) {
CallQueryInterface(owner, aPrincipal);
if (*aPrincipal) {
return NS_OK;
}
nsSecurityFlags securityFlags = loadInfo->GetSecurityMode();
// The data: inheritance flags should only apply to the initial load,
// not to loads that it might have redirected to.
if (loadInfo->RedirectChain().IsEmpty() &&
(securityFlags == nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_INHERITS ||
securityFlags == nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS ||
securityFlags == nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS)) {
nsCOMPtr<nsIURI> uri;
nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIPrincipal> principalToInherit = loadInfo->PrincipalToInherit();
if (!principalToInherit) {
principalToInherit = loadInfo->TriggeringPrincipal();
}
bool inheritForAboutBlank = loadInfo->GetAboutBlankInherits();
if (nsContentUtils::ChannelShouldInheritPrincipal(principalToInherit,
uri,
inheritForAboutBlank,
false)) {
principalToInherit.forget(aPrincipal);
return NS_OK;
}
}
if (loadInfo) {
if (!aIgnoreSandboxing && loadInfo->GetLoadingSandboxed()) {
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(loadInfo->GetSandboxedLoadingPrincipal(aPrincipal)));
MOZ_ASSERT(*aPrincipal);
return NS_OK;
}
bool forceInherit = loadInfo->GetForceInheritPrincipal();
if (aIgnoreSandboxing && !forceInherit) {
// Check if SEC_FORCE_INHERIT_PRINCIPAL was dropped because of
// sandboxing:
if (loadInfo->GetLoadingSandboxed() &&
loadInfo->GetForceInheritPrincipalDropped()) {
forceInherit = true;
}
}
if (forceInherit) {
nsCOMPtr<nsIPrincipal> principalToInherit = loadInfo->PrincipalToInherit();
if (!principalToInherit) {
principalToInherit = loadInfo->TriggeringPrincipal();
}
principalToInherit.forget(aPrincipal);
return NS_OK;
}
nsSecurityFlags securityFlags = loadInfo->GetSecurityMode();
// The data: inheritance flags should only apply to the initial load,
// not to loads that it might have redirected to.
if (loadInfo->RedirectChain().IsEmpty() &&
(securityFlags == nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_INHERITS ||
securityFlags == nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS ||
securityFlags == nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS)) {
nsCOMPtr<nsIURI> uri;
nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIPrincipal> principalToInherit = loadInfo->PrincipalToInherit();
if (!principalToInherit) {
principalToInherit = loadInfo->TriggeringPrincipal();
}
bool inheritForAboutBlank = loadInfo->GetAboutBlankInherits();
if (nsContentUtils::ChannelShouldInheritPrincipal(principalToInherit,
uri,
inheritForAboutBlank,
false)) {
principalToInherit.forget(aPrincipal);
return NS_OK;
}
}
}
return GetChannelURIPrincipal(aChannel, aPrincipal);
}
return GetChannelURIPrincipal(aChannel, aPrincipal);
}
/* The principal of the URI that this channel is loading. This is never

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

@ -57,7 +57,7 @@ nsSystemPrincipal::GetHashValue(uint32_t *result)
return NS_OK;
}
NS_IMETHODIMP
NS_IMETHODIMP
nsSystemPrincipal::GetURI(nsIURI** aURI)
{
*aURI = nullptr;
@ -78,6 +78,15 @@ nsSystemPrincipal::GetCsp(nsIContentSecurityPolicy** aCsp)
return NS_OK;
}
NS_IMETHODIMP
nsSystemPrincipal::SetCsp(nsIContentSecurityPolicy* aCsp)
{
// Never destroy an existing CSP on the principal.
// This method should only be called in rare cases.
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsSystemPrincipal::EnsureCSP(nsIDOMDocument* aDocument,
nsIContentSecurityPolicy** aCSP)

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

@ -37,6 +37,7 @@ public:
NS_IMETHOD GetDomain(nsIURI** aDomain) override;
NS_IMETHOD SetDomain(nsIURI* aDomain) override;
NS_IMETHOD GetCsp(nsIContentSecurityPolicy** aCsp) override;
NS_IMETHOD SetCsp(nsIContentSecurityPolicy* aCsp) override;
NS_IMETHOD EnsureCSP(nsIDOMDocument* aDocument, nsIContentSecurityPolicy** aCSP) override;
NS_IMETHOD GetPreloadCsp(nsIContentSecurityPolicy** aPreloadCSP) override;
NS_IMETHOD EnsurePreloadCSP(nsIDOMDocument* aDocument, nsIContentSecurityPolicy** aCSP) override;

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

@ -34,6 +34,7 @@ ostream
set
stack
string
thread
type_traits
utility
vector

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

@ -5,12 +5,6 @@
const TAB_URL = "data:text/html,<title>foo</title>";
add_task(function* setup() {
yield SpecialPowers.pushPrefEnv({
set: [["dom.ipc.processCount", 1]]
});
});
add_task(function* () {
let { tab, document } = yield openAboutDebugging("tabs");

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

@ -4,12 +4,6 @@
"use strict";
add_task(function* setup() {
yield SpecialPowers.pushPrefEnv({
set: [["dom.ipc.processCount", 1]]
});
});
// Test that the spacebar key press toggles the toggleAll button state
// when a node with no animation is selected.
// This test doesn't need to test if animations actually pause/resume

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

@ -94,5 +94,8 @@ skip-if = os == "mac" && os_version == "10.8" || os == "win" && os_version == "5
[browser_toolbox_window_title_frame_select.js]
[browser_toolbox_zoom.js]
[browser_two_tabs.js]
# We want this test to run for mochitest-dt as well, so we include it here:
# We want these tests to run for mochitest-dt as well, so we include them here:
[../../../../browser/base/content/test/static/browser_parsable_css.js]
skip-if = debug # no point in running on both opt and debug, and will likely intermittently timeout on debug
[../../../../browser/base/content/test/static/browser_all_files_referenced.js]
skip-if = debug # no point in running on both opt and debug, and will likely intermittently timeout on debug

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

@ -30,12 +30,6 @@ let checkToolbox = Task.async(function* (tab, location) {
ok(!!gDevTools.getToolbox(target), `Toolbox exists ${location}`);
});
add_task(function* setup() {
yield SpecialPowers.pushPrefEnv({
set: [["dom.ipc.processCount", 1]]
});
});
add_task(function* () {
let tab = yield addTab(TEST_URL);

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

@ -51,6 +51,7 @@
.notificationbox .messageImage {
display: inline-block;
background-size: 16px;
width: 16px;
height: 16px;
margin: 6px;
@ -59,7 +60,7 @@
/* Default icons for notifications */
.notificationbox .messageImage[data-type="info"] {
background-image: url("chrome://global/skin/icons/information-16.png");
background-image: url("chrome://global/skin/icons/info.svg");
}
.notificationbox .messageImage[data-type="warning"] {

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

@ -181,7 +181,6 @@ skip-if = (os == 'linux' && bits == 32 && debug) # bug 1328915, disable linux32
[browser_console_native_getters.js]
[browser_console_navigation_marker.js]
[browser_console_netlogging.js]
skip-if = true # Bug 1298364
[browser_console_nsiconsolemessage.js]
[browser_console_optimized_out_vars.js]
[browser_console_private_browsing.js]
@ -338,6 +337,7 @@ skip-if = e10s # Bug 1042253 - webconsole e10s tests (Linux debug timeout)
[browser_webconsole_message_node_id.js]
[browser_webconsole_multiline_input.js]
[browser_webconsole_netlogging.js]
skip-if = true # Bug 1298364
[browser_webconsole_netlogging_basic.js]
[browser_webconsole_netlogging_panel.js]
[browser_webconsole_netlogging_reset_filter.js]

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

@ -13,12 +13,6 @@ const TEST_DOC = "https://example.com/browser/devtools/client/webconsole/" +
"test/test_bug1092055_shouldwarn.html";
const SAMPLE_MSG = "specified a header that could not be parsed successfully.";
add_task(function* setup() {
yield SpecialPowers.pushPrefEnv({
set: [["dom.ipc.processCount", 1]]
});
});
add_task(function* () {
let { browser } = yield loadTab(TEST_URI);

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

@ -9,10 +9,6 @@ const TEST_URI = "data:text/html;charset=utf-8,Web Console test for splitting";
function test() {
waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [["dom.ipc.processCount", 1]]}, runTest);
}
function runTest() {
// Test is slow on Linux EC2 instances - Bug 962931
requestLongerTimeout(2);

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

@ -125,11 +125,16 @@ var LayoutActor = ActorClassWithSpec(layoutSpec, {
* @return {Array} An array of GridActor objects.
*/
getAllGrids: function (rootNode, traverseFrames) {
let grids = [];
if (!rootNode) {
return grids;
}
if (!traverseFrames) {
return this.getGrids(rootNode.rawNode);
}
let grids = [];
for (let {document} of this.tabActor.windows) {
grids = [...grids, ...this.getGrids(document.documentElement)];
}

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

@ -4,12 +4,6 @@
"use strict";
add_task(function* setup() {
yield SpecialPowers.pushPrefEnv({
set: [["dom.ipc.processCount", 1]]
});
});
// Check that the duration, iterationCount and delay are retrieved correctly for
// multiple animations.

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

@ -2865,6 +2865,7 @@ exports.CSS_PROPERTIES = {
"column-rule-color",
"column-rule-style",
"column-rule-width",
"column-span",
"column-width",
"contain",
"content",
@ -9346,6 +9347,10 @@ exports.PREFERENCES = [
"color-adjust",
"layout.css.color-adjust.enabled"
],
[
"column-span",
"layout.css.column-span.enabled"
],
[
"contain",
"layout.css.contain.enabled"

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

@ -36,6 +36,8 @@ using namespace mozilla;
using namespace mozilla::dom;
using namespace mozilla::hal;
static mozilla::LazyLogModule gAudioChannelLog("AudioChannel");
namespace {
// If true, any new AudioChannelAgent will be muted when created.
@ -226,13 +228,9 @@ AudioChannelService::Get()
return service.forget();
}
/* static */ PRLogModuleInfo*
/* static */ LogModule*
AudioChannelService::GetAudioChannelLog()
{
static PRLogModuleInfo *gAudioChannelLog;
if (!gAudioChannelLog) {
gAudioChannelLog = PR_NewLogModule("AudioChannel");
}
return gAudioChannelLog;
}

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

@ -16,6 +16,7 @@
#include "AudioChannelAgent.h"
#include "nsAttrValue.h"
#include "mozilla/dom/AudioChannelBinding.h"
#include "mozilla/Logging.h"
#include <functional>
@ -102,7 +103,7 @@ public:
static bool IsAudioChannelMutedByDefault();
static PRLogModuleInfo* GetAudioChannelLog();
static LogModule* GetAudioChannelLog();
static bool IsEnableAudioCompeting();

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

@ -4406,7 +4406,8 @@ nsDocument::LoadAdditionalStyleSheet(additionalSheetType aType,
return NS_ERROR_INVALID_ARG;
// Loading the sheet sync.
RefPtr<css::Loader> loader = new css::Loader(GetStyleBackendType());
RefPtr<css::Loader> loader =
new css::Loader(GetStyleBackendType(), GetDocGroup());
css::SheetParsingMode parsingMode;
switch (aType) {
@ -10564,14 +10565,12 @@ public:
NS_DECL_CYCLE_COLLECTION_CLASS(UnblockParsingPromiseHandler)
explicit UnblockParsingPromiseHandler(nsIDocument* aDocument, Promise* aPromise)
: mDocument(aDocument)
, mPromise(aPromise)
: mPromise(aPromise)
{
nsCOMPtr<nsIParser> parser = mDocument->CreatorParserOrNull();
nsCOMPtr<nsIParser> parser = aDocument->CreatorParserOrNull();
if (parser) {
parser->BlockParser();
} else {
mDocument = nullptr;
mParser = do_GetWeakReference(parser);
}
}
@ -10599,21 +10598,19 @@ protected:
private:
void MaybeUnblockParser() {
if (mDocument) {
nsCOMPtr<nsIParser> parser = mDocument->CreatorParserOrNull();
if (parser) {
parser->UnblockParser();
parser->ContinueInterruptedParsingAsync();
}
mDocument = nullptr;
nsCOMPtr<nsIParser> parser = do_QueryReferent(mParser);
if (parser) {
parser->UnblockParser();
parser->ContinueInterruptedParsingAsync();
mParser = nullptr;
}
}
RefPtr<nsIDocument> mDocument;
nsWeakPtr mParser;
RefPtr<Promise> mPromise;
};
NS_IMPL_CYCLE_COLLECTION(UnblockParsingPromiseHandler, mDocument, mPromise)
NS_IMPL_CYCLE_COLLECTION(UnblockParsingPromiseHandler, mPromise)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(UnblockParsingPromiseHandler)
NS_INTERFACE_MAP_ENTRY(nsISupports)

6
dom/cache/DBSchema.cpp поставляемый
Просмотреть файл

@ -1975,15 +1975,15 @@ ReadResponse(mozIStorageConnection* aConn, EntryId aEntryId,
aSavedResponseOut->mValue.principalInfo() = void_t();
if (!serializedInfo.IsEmpty()) {
nsAutoCString originNoSuffix;
nsAutoCString specNoSuffix;
OriginAttributes attrs;
if (!attrs.PopulateFromOrigin(serializedInfo, originNoSuffix)) {
if (!attrs.PopulateFromOrigin(serializedInfo, specNoSuffix)) {
NS_WARNING("Something went wrong parsing a serialized principal!");
return NS_ERROR_FAILURE;
}
aSavedResponseOut->mValue.principalInfo() =
mozilla::ipc::ContentPrincipalInfo(attrs, originNoSuffix);
mozilla::ipc::ContentPrincipalInfo(attrs, void_t(), specNoSuffix);
}
rv = state->GetBlobAsUTF8String(6, aSavedResponseOut->mValue.channelInfo().securityInfo());

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

@ -12,7 +12,7 @@
namespace mozilla {
#define NS_EVENT_STATE_HIGHEST_SERVO_BIT 12
#define NS_EVENT_STATE_HIGHEST_SERVO_BIT 19
/**
* EventStates is the class used to represent the event states of nsIContent
@ -223,6 +223,21 @@ private:
#define NS_EVENT_STATE_INVALID NS_DEFINE_EVENT_STATE_MACRO(11)
// UI friendly version of :valid pseudo-class.
#define NS_EVENT_STATE_MOZ_UI_VALID NS_DEFINE_EVENT_STATE_MACRO(12)
// Content could not be rendered (image/object/etc).
#define NS_EVENT_STATE_BROKEN NS_DEFINE_EVENT_STATE_MACRO(13)
// Content disabled by the user (images turned off, say).
#define NS_EVENT_STATE_USERDISABLED NS_DEFINE_EVENT_STATE_MACRO(14)
// Content suppressed by the user (ad blocking, etc).
#define NS_EVENT_STATE_SUPPRESSED NS_DEFINE_EVENT_STATE_MACRO(15)
// Content is still loading such that there is nothing to show the
// user (eg an image which hasn't started coming in yet).
#define NS_EVENT_STATE_LOADING NS_DEFINE_EVENT_STATE_MACRO(16)
// Handler for the content has been blocked.
#define NS_EVENT_STATE_HANDLER_BLOCKED NS_DEFINE_EVENT_STATE_MACRO(17)
// Handler for the content has been disabled.
#define NS_EVENT_STATE_HANDLER_DISABLED NS_DEFINE_EVENT_STATE_MACRO(18)
// Handler for the content has crashed
#define NS_EVENT_STATE_HANDLER_CRASHED NS_DEFINE_EVENT_STATE_MACRO(19)
/*
* Bits below here do not have Servo-related ordering constraints.
@ -232,42 +247,27 @@ private:
*/
// Drag is hovering over content.
#define NS_EVENT_STATE_DRAGOVER NS_DEFINE_EVENT_STATE_MACRO(13)
#define NS_EVENT_STATE_DRAGOVER NS_DEFINE_EVENT_STATE_MACRO(20)
// Content is required.
#define NS_EVENT_STATE_REQUIRED NS_DEFINE_EVENT_STATE_MACRO(14)
#define NS_EVENT_STATE_REQUIRED NS_DEFINE_EVENT_STATE_MACRO(21)
// Content is optional (and can be required).
#define NS_EVENT_STATE_OPTIONAL NS_DEFINE_EVENT_STATE_MACRO(15)
#define NS_EVENT_STATE_OPTIONAL NS_DEFINE_EVENT_STATE_MACRO(22)
// Link has been visited.
#define NS_EVENT_STATE_VISITED NS_DEFINE_EVENT_STATE_MACRO(16)
#define NS_EVENT_STATE_VISITED NS_DEFINE_EVENT_STATE_MACRO(23)
// Link hasn't been visited.
#define NS_EVENT_STATE_UNVISITED NS_DEFINE_EVENT_STATE_MACRO(17)
#define NS_EVENT_STATE_UNVISITED NS_DEFINE_EVENT_STATE_MACRO(24)
// Content value is in-range (and can be out-of-range).
#define NS_EVENT_STATE_INRANGE NS_DEFINE_EVENT_STATE_MACRO(18)
#define NS_EVENT_STATE_INRANGE NS_DEFINE_EVENT_STATE_MACRO(25)
// Content value is out-of-range.
#define NS_EVENT_STATE_OUTOFRANGE NS_DEFINE_EVENT_STATE_MACRO(19)
#define NS_EVENT_STATE_OUTOFRANGE NS_DEFINE_EVENT_STATE_MACRO(26)
// These two are temporary (see bug 302188)
// Content is read-only.
#define NS_EVENT_STATE_MOZ_READONLY NS_DEFINE_EVENT_STATE_MACRO(20)
#define NS_EVENT_STATE_MOZ_READONLY NS_DEFINE_EVENT_STATE_MACRO(27)
// Content is editable.
#define NS_EVENT_STATE_MOZ_READWRITE NS_DEFINE_EVENT_STATE_MACRO(21)
#define NS_EVENT_STATE_MOZ_READWRITE NS_DEFINE_EVENT_STATE_MACRO(28)
// Content is the default one (meaning depends of the context).
#define NS_EVENT_STATE_DEFAULT NS_DEFINE_EVENT_STATE_MACRO(22)
// Content could not be rendered (image/object/etc).
#define NS_EVENT_STATE_BROKEN NS_DEFINE_EVENT_STATE_MACRO(23)
// Content disabled by the user (images turned off, say).
#define NS_EVENT_STATE_USERDISABLED NS_DEFINE_EVENT_STATE_MACRO(24)
// Content suppressed by the user (ad blocking, etc).
#define NS_EVENT_STATE_SUPPRESSED NS_DEFINE_EVENT_STATE_MACRO(25)
// Content is still loading such that there is nothing to show the
// user (eg an image which hasn't started coming in yet).
#define NS_EVENT_STATE_LOADING NS_DEFINE_EVENT_STATE_MACRO(26)
#define NS_EVENT_STATE_INCREMENT_SCRIPT_LEVEL NS_DEFINE_EVENT_STATE_MACRO(27)
// Handler for the content has been blocked.
#define NS_EVENT_STATE_HANDLER_BLOCKED NS_DEFINE_EVENT_STATE_MACRO(28)
// Handler for the content has been disabled.
#define NS_EVENT_STATE_HANDLER_DISABLED NS_DEFINE_EVENT_STATE_MACRO(29)
// Handler for the content has crashed
#define NS_EVENT_STATE_HANDLER_CRASHED NS_DEFINE_EVENT_STATE_MACRO(30)
#define NS_EVENT_STATE_DEFAULT NS_DEFINE_EVENT_STATE_MACRO(29)
#define NS_EVENT_STATE_INCREMENT_SCRIPT_LEVEL NS_DEFINE_EVENT_STATE_MACRO(30)
// Content has focus and should show a ring.
#define NS_EVENT_STATE_FOCUSRING NS_DEFINE_EVENT_STATE_MACRO(31)
// Content is a submit control and the form isn't valid.

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

@ -6,6 +6,16 @@ support-files =
pointerevent_styles.css
pointerevent_support.js
[test_bug1285128.html]
[test_bug1293174_implicit_pointer_capture_for_touch_1.html]
support-files = bug1293174_implicit_pointer_capture_for_touch_1.html
[test_bug1293174_implicit_pointer_capture_for_touch_2.html]
support-files = bug1293174_implicit_pointer_capture_for_touch_2.html
[test_bug1303704.html]
[test_bug1315862.html]
[test_bug1323158.html]
[test_empty_file.html]
disabled = disabled # Bug 1150091 - Issue with support-files
[test_pointerevent_attributes_hoverable_pointers-manual.html]
support-files =
pointerevent_attributes_hoverable_pointers-manual.html
@ -118,14 +128,5 @@ support-files =
pointerevent_touch-action-pan-left-css_touch-manual.html
pointerevent_touch-action-pan-right-css_touch-manual.html
pointerevent_touch-action-pan-up-css_touch-manual.html
[test_bug1285128.html]
[test_bug1293174_implicit_pointer_capture_for_touch_1.html]
support-files = bug1293174_implicit_pointer_capture_for_touch_1.html
[test_bug1293174_implicit_pointer_capture_for_touch_2.html]
support-files = bug1293174_implicit_pointer_capture_for_touch_2.html
[test_bug1303704.html]
[test_bug1323158.html]
[test_trigger_fullscreen_by_pointer_events.html]
[test_trigger_popup_by_pointer_events.html]
[test_empty_file.html]
disabled = disabled # Bug 1150091 - Issue with support-files
[test_bug1315862.html]

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

@ -0,0 +1,53 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Test for triggering Fullscreen by pointer events</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<script src="/tests/SimpleTest/EventUtils.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<div id="target" style="width: 50px; height: 50px; background: green"></div>
<script>
SimpleTest.waitForExplicitFinish();
var target = document.getElementById("target");
target.addEventListener("pointerdown", () => {
target.requestFullscreen();
target.addEventListener("pointerdown", () => {
document.exitFullscreen();
}, {once: true});
}, {once: true});
document.addEventListener("fullscreenchange", () => {
if (document.fullscreenElement) {
ok(document.fullscreenElement, target, "fullscreenElement should be the div element");
// synthesize mouse events to generate pointer events and leave full screen.
synthesizeMouseAtCenter(target, { type: "mousedown" });
synthesizeMouseAtCenter(target, { type: "mouseup" });
} else {
SimpleTest.finish();
}
});
function startTest() {
// synthesize mouse events to generate pointer events and enter full screen.
synthesizeMouseAtCenter(target, { type: "mousedown" });
synthesizeMouseAtCenter(target, { type: "mouseup" });
}
SimpleTest.waitForFocus(() => {
SpecialPowers.pushPrefEnv({
"set": [
["full-screen-api.unprefix.enabled", true],
["full-screen-api.allow-trusted-requests-only", false],
["dom.w3c_pointer_events.enabled", true]
]
}, startTest);
});
</script>
</body>
</html>

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

@ -993,7 +993,8 @@ RemoteInputStream::BlockAndWaitForStream()
nsTArray<FileDescriptor> fds;
OptionalFileDescriptorSetToFDs(optionalFDs, fds);
nsCOMPtr<nsIInputStream> stream = DeserializeInputStream(params, fds);
nsCOMPtr<nsIInputStream> stream =
InputStreamHelper::DeserializeInputStream(params, fds);
MOZ_ASSERT(stream);
SetStream(stream);
@ -4450,7 +4451,7 @@ BlobParent::RecvPBlobStreamConstructor(PBlobStreamParent* aActor,
if (mBlobImpl->IsMemoryFile()) {
InputStreamParams params;
nsTArray<FileDescriptor> fds;
SerializeInputStream(stream, params, fds);
InputStreamHelper::SerializeInputStream(stream, params, fds);
MOZ_ASSERT(params.type() != InputStreamParams::T__None);
MOZ_ASSERT(fds.IsEmpty());
@ -4788,7 +4789,8 @@ InputStreamChild::Recv__delete__(const InputStreamParams& aParams,
const_cast<OptionalFileDescriptorSet&>(aOptionalSet),
fds);
nsCOMPtr<nsIInputStream> stream = DeserializeInputStream(aParams, fds);
nsCOMPtr<nsIInputStream> stream =
InputStreamHelper::DeserializeInputStream(aParams, fds);
MOZ_ASSERT(stream);
mRemoteStream->SetStream(stream);

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

@ -18796,10 +18796,12 @@ Maintenance::DirectoryWork()
MOZ_ASSERT(origin.IsEmpty());
int64_t dummyTimeStamp;
bool dummyPersisted;
nsCString dummySuffix;
if (NS_WARN_IF(NS_FAILED(
quotaManager->GetDirectoryMetadata2(originDir,
&dummyTimeStamp,
&dummyPersisted,
dummySuffix,
group,
origin)))) {

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

@ -4009,7 +4009,8 @@ MediaStreamGraph::ApplyAudioContextOperation(MediaStream* aDestinationStream,
}
void RunDuringShutdown() override
{
MOZ_ASSERT(false, "We should be reviving the graph?");
MOZ_ASSERT(mAudioContextOperation == AudioContextOperation::Close,
"We should be reviving the graph?");
}
private:

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

@ -107,7 +107,7 @@ class OriginKeyStore : public nsISupports
private:
void
PrincipalInfoToString(const ipc::PrincipalInfo& aPrincipalInfo,
nsAutoCString aString)
nsACString& aString)
{
switch (aPrincipalInfo.type()) {
case ipc::PrincipalInfo::TSystemPrincipalInfo:
@ -124,11 +124,11 @@ class OriginKeyStore : public nsISupports
case ipc::PrincipalInfo::TContentPrincipalInfo: {
const ipc::ContentPrincipalInfo& info =
aPrincipalInfo.get_ContentPrincipalInfo();
aString.Assign(info.spec());
aString.Assign(info.originNoSuffix());
nsAutoCString suffix;
info.attrs().CreateSuffix(suffix);
suffix.Append(suffix);
aString.Append(suffix);
return;
}

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

@ -1096,7 +1096,7 @@ tags = webvtt
[test_unseekable.html]
skip-if = toolkit == 'android' # android(bug 1232305)
[test_video_to_canvas.html]
skip-if = android_version == '15' || android_version == '17' || (android_version == '19' && debug) || android_version == '22' # bug 1320418, android(bug 1232305)
skip-if = toolkit == 'android' # android(bug 1232305), bugs 1320418,1347953,1347954,1348140,1348386
[test_video_in_audio_element.html]
skip-if = android_version == '15' || android_version == '17' # bug 1320417, 1326326, android(bug 1232323, bug 1232305)
[test_videoDocumentTitle.html]

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

@ -117,8 +117,7 @@ runTest(async () => {
"Same origin deviceId for " + device.label + " must match");
}
for (let device of differentOriginDevices) {
// TODO: s/todo/ok/ once bug 1340163 is fixed.
todo(!devices.find(d => d.deviceId == device.deviceId),
ok(!devices.find(d => d.deviceId == device.deviceId),
"Different origin deviceId for " + device.label + " must be different");
}

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

@ -404,7 +404,7 @@ Cu.import('resource://gre/modules/Services.jsm');
// Otherwise just ignore the end tag.
continue;
}
var ts = collectTimeStamp(t.substr(1, t.length - 2));
var ts = collectTimeStamp(t.substr(1, t.length - 1));
var node;
if (ts) {
// Timestamps are lead nodes as well.

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

@ -272,6 +272,7 @@ QuotaRequestChild::Recv__delete__(const RequestResponse& aResponse)
case RequestResponse::TClearDataResponse:
case RequestResponse::TClearAllResponse:
case RequestResponse::TResetAllResponse:
case RequestResponse::TPersistResponse:
HandleResponse();
break;
@ -279,6 +280,10 @@ QuotaRequestChild::Recv__delete__(const RequestResponse& aResponse)
HandleResponse(aResponse.get_InitOriginResponse().created());
break;
case RequestResponse::TPersistedResponse:
HandleResponse(aResponse.get_PersistedResponse().persisted());
break;
default:
MOZ_CRASH("Unknown response type!");
}

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

@ -1255,6 +1255,63 @@ private:
GetResponse(RequestResponse& aResponse) override;
};
class PersistRequestBase
: public QuotaRequestBase
{
const PrincipalInfo mPrincipalInfo;
protected:
nsCString mSuffix;
nsCString mGroup;
public:
bool
Init(Quota* aQuota) override;
protected:
explicit PersistRequestBase(const PrincipalInfo& aPrincipalInfo);
private:
nsresult
DoInitOnMainThread() override;
};
class PersistedOp final
: public PersistRequestBase
{
bool mPersisted;
public:
explicit PersistedOp(const RequestParams& aParams);
private:
~PersistedOp()
{ }
nsresult
DoDirectoryWork(QuotaManager* aQuotaManager) override;
void
GetResponse(RequestResponse& aResponse) override;
};
class PersistOp final
: public PersistRequestBase
{
public:
explicit PersistOp(const RequestParams& aParams);
private:
~PersistOp()
{ }
nsresult
DoDirectoryWork(QuotaManager* aQuotaManager) override;
void
GetResponse(RequestResponse& aResponse) override;
};
/*******************************************************************************
* Helper Functions
******************************************************************************/
@ -1852,6 +1909,52 @@ EnsureDirectory(nsIFile* aDirectory, bool* aCreated)
return NS_OK;
}
nsresult
EnsureOriginDirectory(nsIFile* aDirectory, bool* aCreated)
{
AssertIsOnIOThread();
nsresult rv;
#ifndef RELEASE_OR_BETA
bool exists;
rv = aDirectory->Exists(&exists);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (!exists) {
nsString leafName;
nsresult rv = aDirectory->GetLeafName(leafName);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (!leafName.EqualsLiteral(kChromeOrigin)) {
nsCString spec;
OriginAttributes attrs;
OriginParser::ResultType result =
OriginParser::ParseOrigin(NS_ConvertUTF16toUTF8(leafName),
spec,
&attrs);
if (NS_WARN_IF(result != OriginParser::ValidOrigin)) {
QM_WARNING("Preventing creation of a new origin directory which is not "
"supported by our origin parser or is obsolete!");
return NS_ERROR_FAILURE;
}
}
}
#endif
rv = EnsureDirectory(aDirectory, aCreated);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
return NS_OK;
}
enum FileFlag {
kTruncateFileFlag,
kUpdateFileFlag,
@ -2077,6 +2180,7 @@ CreateDirectoryMetadata(nsIFile* aDirectory, int64_t aTimestamp,
nsresult
CreateDirectoryMetadata2(nsIFile* aDirectory,
int64_t aTimestamp,
bool aPersisted,
const nsACString& aSuffix,
const nsACString& aGroup,
const nsACString& aOrigin)
@ -2108,8 +2212,7 @@ CreateDirectoryMetadata2(nsIFile* aDirectory,
return rv;
}
// Reserved for navigator.persist()
rv = stream->WriteBoolean(false);
rv = stream->WriteBoolean(aPersisted);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
@ -2168,6 +2271,43 @@ CreateDirectoryMetadata2(nsIFile* aDirectory,
return NS_OK;
}
nsresult
CreateDirectoryMetadataFiles(nsIFile* aDirectory,
bool aPersisted,
const nsACString& aSuffix,
const nsACString& aGroup,
const nsACString& aOrigin,
int64_t* aTimestamp)
{
AssertIsOnIOThread();
int64_t timestamp = PR_Now();
nsresult rv = CreateDirectoryMetadata(aDirectory,
timestamp,
aSuffix,
aGroup,
aOrigin);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = CreateDirectoryMetadata2(aDirectory,
timestamp,
aPersisted,
aSuffix,
aGroup,
aOrigin);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (aTimestamp) {
*aTimestamp = timestamp;
}
return NS_OK;
}
nsresult
GetBinaryInputStream(nsIFile* aDirectory,
const nsAString& aFilename,
@ -3512,6 +3652,8 @@ QuotaManager::UpdateOriginAccessTime(PersistenceType aPersistenceType,
void
QuotaManager::RemoveQuota()
{
AssertIsOnIOThread();
MutexAutoLock lock(mQuotaMutex);
for (auto iter = mGroupInfoPairs.Iter(); !iter.Done(); iter.Next()) {
@ -3637,6 +3779,40 @@ QuotaManager::GetQuotaObject(PersistenceType aPersistenceType,
return GetQuotaObject(aPersistenceType, aGroup, aOrigin, file);
}
Nullable<bool>
QuotaManager::OriginPersisted(const nsACString& aGroup,
const nsACString& aOrigin)
{
AssertIsOnIOThread();
MutexAutoLock lock(mQuotaMutex);
RefPtr<OriginInfo> originInfo = LockedGetOriginInfo(PERSISTENCE_TYPE_DEFAULT,
aGroup,
aOrigin);
if (originInfo) {
return Nullable<bool>(originInfo->LockedPersisted());
}
return Nullable<bool>();
}
void
QuotaManager::PersistOrigin(const nsACString& aGroup,
const nsACString& aOrigin)
{
AssertIsOnIOThread();
MutexAutoLock lock(mQuotaMutex);
RefPtr<OriginInfo> originInfo = LockedGetOriginInfo(PERSISTENCE_TYPE_DEFAULT,
aGroup,
aOrigin);
if (originInfo && !originInfo->LockedPersisted()) {
originInfo->LockedPersist();
}
}
void
QuotaManager::AbortOperationsForProcess(ContentParentId aContentParentId)
{
@ -3691,6 +3867,7 @@ QuotaManager::RestoreDirectoryMetadata2(nsIFile* aDirectory, bool aPersistent)
nsresult
QuotaManager::GetDirectoryMetadata2(nsIFile* aDirectory,
int64_t* aTimestamp,
bool* aPersisted,
nsACString& aSuffix,
nsACString& aGroup,
nsACString& aOrigin)
@ -3698,6 +3875,7 @@ QuotaManager::GetDirectoryMetadata2(nsIFile* aDirectory,
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(aDirectory);
MOZ_ASSERT(aTimestamp);
MOZ_ASSERT(aPersisted);
MOZ_ASSERT(mStorageInitialized);
nsCOMPtr<nsIBinaryInputStream> binaryStream;
@ -3750,6 +3928,7 @@ QuotaManager::GetDirectoryMetadata2(nsIFile* aDirectory,
}
*aTimestamp = timestamp;
*aPersisted = persisted;
aSuffix = suffix;
aGroup = group;
aOrigin = origin;
@ -3760,12 +3939,14 @@ nsresult
QuotaManager::GetDirectoryMetadata2WithRestore(nsIFile* aDirectory,
bool aPersistent,
int64_t* aTimestamp,
bool* aPersisted,
nsACString& aSuffix,
nsACString& aGroup,
nsACString& aOrigin)
{
nsresult rv = GetDirectoryMetadata2(aDirectory,
aTimestamp,
aPersisted,
aSuffix,
aGroup,
aOrigin);
@ -3777,6 +3958,7 @@ QuotaManager::GetDirectoryMetadata2WithRestore(nsIFile* aDirectory,
rv = GetDirectoryMetadata2(aDirectory,
aTimestamp,
aPersisted,
aSuffix,
aGroup,
aOrigin);
@ -3789,11 +3971,13 @@ QuotaManager::GetDirectoryMetadata2WithRestore(nsIFile* aDirectory,
}
nsresult
QuotaManager::GetDirectoryMetadata2(nsIFile* aDirectory, int64_t* aTimestamp)
QuotaManager::GetDirectoryMetadata2(nsIFile* aDirectory,
int64_t* aTimestamp,
bool* aPersisted)
{
AssertIsOnIOThread();
MOZ_ASSERT(aDirectory);
MOZ_ASSERT(aTimestamp);
MOZ_ASSERT(aTimestamp || aPersisted);
MOZ_ASSERT(mStorageInitialized);
nsCOMPtr<nsIBinaryInputStream> binaryStream;
@ -3810,23 +3994,37 @@ QuotaManager::GetDirectoryMetadata2(nsIFile* aDirectory, int64_t* aTimestamp)
return rv;
}
*aTimestamp = timestamp;
bool persisted;
if (aPersisted) {
rv = binaryStream->ReadBoolean(&persisted);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}
if (aTimestamp) {
*aTimestamp = timestamp;
}
if (aPersisted) {
*aPersisted = persisted;
}
return NS_OK;
}
nsresult
QuotaManager::GetDirectoryMetadata2WithRestore(nsIFile* aDirectory,
bool aPersistent,
int64_t* aTimestamp)
int64_t* aTimestamp,
bool* aPersisted)
{
nsresult rv = GetDirectoryMetadata2(aDirectory, aTimestamp);
nsresult rv = GetDirectoryMetadata2(aDirectory, aTimestamp, aPersisted);
if (NS_WARN_IF(NS_FAILED(rv))) {
rv = RestoreDirectoryMetadata2(aDirectory, aPersistent);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = GetDirectoryMetadata2(aDirectory, aTimestamp);
rv = GetDirectoryMetadata2(aDirectory, aTimestamp, aPersisted);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
@ -3899,12 +4097,14 @@ QuotaManager::InitializeRepository(PersistenceType aPersistenceType)
}
int64_t timestamp;
bool persisted;
nsCString suffix;
nsCString group;
nsCString origin;
rv = GetDirectoryMetadata2WithRestore(childDirectory,
/* aPersistent */ false,
&timestamp,
&persisted,
suffix,
group,
origin);
@ -3912,8 +4112,8 @@ QuotaManager::InitializeRepository(PersistenceType aPersistenceType)
return rv;
}
rv = InitializeOrigin(aPersistenceType, group, origin, timestamp,
/* aPersisted */ false, childDirectory);
rv = InitializeOrigin(aPersistenceType, group, origin, timestamp, persisted,
childDirectory);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
@ -4820,66 +5020,29 @@ QuotaManager::EnsureOriginIsInitializedInternal(
CheckTemporaryStorageLimits();
}
int64_t timestamp;
#ifndef RELEASE_OR_BETA
bool exists;
rv = directory->Exists(&exists);
bool created;
rv = EnsureOriginDirectory(directory, &created);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (!exists) {
nsString leafName;
nsresult rv = directory->GetLeafName(leafName);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (!leafName.EqualsLiteral(kChromeOrigin)) {
nsCString spec;
OriginAttributes attrs;
OriginParser::ResultType result =
OriginParser::ParseOrigin(NS_ConvertUTF16toUTF8(leafName),
spec,
&attrs);
if (NS_WARN_IF(result != OriginParser::ValidOrigin)) {
QM_WARNING("Preventing creation of a new origin directory which is not "
"supported by our origin parser or is obsolete!");
return NS_ERROR_FAILURE;
}
}
}
#endif
bool created;
rv = EnsureDirectory(directory, &created);
NS_ENSURE_SUCCESS(rv, rv);
int64_t timestamp;
if (aPersistenceType == PERSISTENCE_TYPE_PERSISTENT) {
if (created) {
timestamp = PR_Now();
rv = CreateDirectoryMetadata(directory,
timestamp,
aSuffix,
aGroup,
aOrigin);
rv = CreateDirectoryMetadataFiles(directory,
/* aPersisted */ true,
aSuffix,
aGroup,
aOrigin,
&timestamp);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = CreateDirectoryMetadata2(directory,
timestamp,
aSuffix,
aGroup,
aOrigin);
NS_ENSURE_SUCCESS(rv, rv);
} else {
rv = GetDirectoryMetadata2WithRestore(directory,
/* aPersistent */ true,
&timestamp);
&timestamp,
/* aPersisted */ nullptr);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
@ -4893,24 +5056,16 @@ QuotaManager::EnsureOriginIsInitializedInternal(
mInitializedOrigins.AppendElement(aOrigin);
} else if (created) {
timestamp = PR_Now();
rv = CreateDirectoryMetadata(directory,
timestamp,
aSuffix,
aGroup,
aOrigin);
rv = CreateDirectoryMetadataFiles(directory,
/* aPersisted */ false,
aSuffix,
aGroup,
aOrigin,
&timestamp);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = CreateDirectoryMetadata2(directory,
timestamp,
aSuffix,
aGroup,
aOrigin);
NS_ENSURE_SUCCESS(rv, rv);
rv = InitializeOrigin(aPersistenceType, aGroup, aOrigin, timestamp,
/* aPersisted */ false, directory);
NS_ENSURE_SUCCESS(rv, rv);
@ -5228,6 +5383,25 @@ QuotaManager::LockedRemoveQuotaForOrigin(PersistenceType aPersistenceType,
}
}
already_AddRefed<OriginInfo>
QuotaManager::LockedGetOriginInfo(PersistenceType aPersistenceType,
const nsACString& aGroup,
const nsACString& aOrigin)
{
mQuotaMutex.AssertCurrentThreadOwns();
MOZ_ASSERT(aPersistenceType != PERSISTENCE_TYPE_PERSISTENT);
GroupInfoPair* pair;
if (mGroupInfoPairs.Get(aGroup, &pair)) {
RefPtr<GroupInfo> groupInfo = pair->LockedGetGroupInfo(aPersistenceType);
if (groupInfo) {
return groupInfo->LockedGetOriginInfo(aOrigin);
}
}
return nullptr;
}
void
QuotaManager::CheckTemporaryStorageLimits()
{
@ -6135,6 +6309,14 @@ Quota::AllocPQuotaRequestParent(const RequestParams& aParams)
actor = new ResetOrClearOp(/* aClear */ false);
break;
case RequestParams::TPersistedParams:
actor = new PersistedOp(aParams);
break;
case RequestParams::TPersistParams:
actor = new PersistOp(aParams);
break;
default:
MOZ_CRASH("Should never get here!");
}
@ -6817,9 +6999,11 @@ ClearRequestBase::DeleteFiles(QuotaManager* aQuotaManager,
nsCString suffix;
nsCString group;
nsCString origin;
bool persisted;
rv = aQuotaManager->GetDirectoryMetadata2WithRestore(file,
persistent,
&timestamp,
&persisted,
suffix,
group,
origin);
@ -6981,6 +7165,235 @@ ClearDataOp::GetResponse(RequestResponse& aResponse)
aResponse = ClearDataResponse();
}
PersistRequestBase::PersistRequestBase(const PrincipalInfo& aPrincipalInfo)
: QuotaRequestBase(/* aExclusive */ false)
, mPrincipalInfo(aPrincipalInfo)
{
AssertIsOnOwningThread();
}
bool
PersistRequestBase::Init(Quota* aQuota)
{
AssertIsOnOwningThread();
MOZ_ASSERT(aQuota);
if (NS_WARN_IF(!QuotaRequestBase::Init(aQuota))) {
return false;
}
mPersistenceType.SetValue(PERSISTENCE_TYPE_DEFAULT);
mNeedsMainThreadInit = true;
return true;
}
nsresult
PersistRequestBase::DoInitOnMainThread()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(GetState() == State_Initializing);
MOZ_ASSERT(mNeedsMainThreadInit);
nsresult rv;
nsCOMPtr<nsIPrincipal> principal =
PrincipalInfoToPrincipal(mPrincipalInfo, &rv);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
// Figure out which origin we're dealing with.
nsCString origin;
rv = QuotaManager::GetInfoFromPrincipal(principal, &mSuffix, &mGroup,
&origin);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
mOriginScope.SetFromOrigin(origin);
return NS_OK;
}
PersistedOp::PersistedOp(const RequestParams& aParams)
: PersistRequestBase(aParams.get_PersistedParams().principalInfo())
, mPersisted(false)
{
MOZ_ASSERT(aParams.type() == RequestParams::TPersistedParams);
}
nsresult
PersistedOp::DoDirectoryWork(QuotaManager* aQuotaManager)
{
AssertIsOnIOThread();
MOZ_ASSERT(!mPersistenceType.IsNull());
MOZ_ASSERT(mPersistenceType.Value() == PERSISTENCE_TYPE_DEFAULT);
MOZ_ASSERT(mOriginScope.IsOrigin());
PROFILER_LABEL("Quota", "PersistedOp::DoDirectoryWork",
js::ProfileEntry::Category::OTHER);
Nullable<bool> persisted =
aQuotaManager->OriginPersisted(mGroup, mOriginScope.GetOrigin());
if (!persisted.IsNull()) {
mPersisted = persisted.Value();
return NS_OK;
}
// If we get here, it means the origin hasn't been initialized yet.
// Try to get the persisted flag from directory metadata on disk.
nsCOMPtr<nsIFile> directory;
nsresult rv = aQuotaManager->GetDirectoryForOrigin(mPersistenceType.Value(),
mOriginScope.GetOrigin(),
getter_AddRefs(directory));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
bool exists;
rv = directory->Exists(&exists);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (exists) {
// Get the persisted flag.
bool persisted;
rv =
aQuotaManager->GetDirectoryMetadata2WithRestore(directory,
/* aPersistent */ false,
/* aTimestamp */ nullptr,
&persisted);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
mPersisted = persisted;
} else {
// The directory has not been created yet.
mPersisted = false;
}
return NS_OK;
}
void
PersistedOp::GetResponse(RequestResponse& aResponse)
{
AssertIsOnOwningThread();
PersistedResponse persistedResponse;
persistedResponse.persisted() = mPersisted;
aResponse = persistedResponse;
}
PersistOp::PersistOp(const RequestParams& aParams)
: PersistRequestBase(aParams.get_PersistParams().principalInfo())
{
MOZ_ASSERT(aParams.type() == RequestParams::TPersistParams);
}
nsresult
PersistOp::DoDirectoryWork(QuotaManager* aQuotaManager)
{
AssertIsOnIOThread();
MOZ_ASSERT(!mPersistenceType.IsNull());
MOZ_ASSERT(mPersistenceType.Value() == PERSISTENCE_TYPE_DEFAULT);
MOZ_ASSERT(mOriginScope.IsOrigin());
PROFILER_LABEL("Quota", "PersistOp::DoDirectoryWork",
js::ProfileEntry::Category::OTHER);
// Update directory metadata on disk first.
nsCOMPtr<nsIFile> directory;
nsresult rv = aQuotaManager->GetDirectoryForOrigin(mPersistenceType.Value(),
mOriginScope.GetOrigin(),
getter_AddRefs(directory));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
bool created;
rv = EnsureOriginDirectory(directory, &created);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (created) {
rv = CreateDirectoryMetadataFiles(directory,
/* aPersisted */ true,
mSuffix,
mGroup,
mOriginScope.GetOrigin(),
/* aTimestamp */ nullptr);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
} else {
// Get the persisted flag (restore the metadata file if necessary).
bool persisted;
rv =
aQuotaManager->GetDirectoryMetadata2WithRestore(directory,
/* aPersistent */ false,
/* aTimestamp */ nullptr,
&persisted);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (!persisted) {
nsCOMPtr<nsIFile> file;
nsresult rv = directory->Clone(getter_AddRefs(file));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = file->Append(NS_LITERAL_STRING(METADATA_V2_FILE_NAME));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
nsCOMPtr<nsIBinaryOutputStream> stream;
rv = GetBinaryOutputStream(file, kUpdateFileFlag, getter_AddRefs(stream));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
MOZ_ASSERT(stream);
// Update origin access time while we are here.
rv = stream->Write64(PR_Now());
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
// Set the persisted flag to true.
rv = stream->WriteBoolean(true);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}
}
// Directory metadata has been successfully created/updated, try to update
// OriginInfo too (it's ok if OriginInfo doesn't exist yet).
aQuotaManager->PersistOrigin(mGroup, mOriginScope.GetOrigin());
return NS_OK;
}
void
PersistOp::GetResponse(RequestResponse& aResponse)
{
AssertIsOnOwningThread();
aResponse = PersistResponse();
}
nsresult
StorageDirectoryHelper::GetDirectoryMetadata(nsIFile* aDirectory,
int64_t& aTimestamp,
@ -8125,6 +8538,7 @@ UpgradeStorageFrom0_0To1_0Helper::ProcessOriginDirectory(
rv = CreateDirectoryMetadata2(aOriginProps.mDirectory,
aOriginProps.mTimestamp,
/* aPersisted */ false,
aOriginProps.mSuffix,
aOriginProps.mGroup,
aOriginProps.mOrigin);
@ -8407,6 +8821,7 @@ UpgradeStorageFrom1_0To2_0Helper::MaybeStripObsoleteOriginAttributes(
rv = CreateDirectoryMetadata2(aOriginProps.mDirectory,
aOriginProps.mTimestamp,
/* aPersisted */ false,
aOriginProps.mSuffix,
aOriginProps.mGroup,
aOriginProps.mOrigin);
@ -8478,6 +8893,7 @@ UpgradeStorageFrom1_0To2_0Helper::ProcessOriginDirectory(
if (aOriginProps.mNeedsRestore2) {
rv = CreateDirectoryMetadata2(aOriginProps.mDirectory,
aOriginProps.mTimestamp,
/* aPersisted */ false,
aOriginProps.mSuffix,
aOriginProps.mGroup,
aOriginProps.mOrigin);
@ -8520,8 +8936,10 @@ RestoreDirectoryMetadata2Helper::ProcessOriginDirectory(
{
AssertIsOnIOThread();
// We don't have any approach to restore aPersisted, so reset it to false.
nsresult rv = CreateDirectoryMetadata2(aOriginProps.mDirectory,
aOriginProps.mTimestamp,
/* aPersisted */ false,
aOriginProps.mSuffix,
aOriginProps.mGroup,
aOriginProps.mOrigin);

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

@ -59,6 +59,16 @@ struct ResetAllParams
{
};
struct PersistedParams
{
PrincipalInfo principalInfo;
};
struct PersistParams
{
PrincipalInfo principalInfo;
};
union RequestParams
{
InitParams;
@ -67,6 +77,8 @@ union RequestParams
ClearDataParams;
ClearAllParams;
ResetAllParams;
PersistedParams;
PersistParams;
};
protocol PQuota

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

@ -33,6 +33,15 @@ struct ResetAllResponse
{
};
struct PersistedResponse
{
bool persisted;
};
struct PersistResponse
{
};
union RequestResponse
{
nsresult;
@ -42,6 +51,8 @@ union RequestResponse
ClearDataResponse;
ClearAllResponse;
ResetAllResponse;
PersistedResponse;
PersistResponse;
};
protocol PQuotaRequest

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

@ -185,6 +185,14 @@ public:
const nsACString& aOrigin,
const nsAString& aPath);
Nullable<bool>
OriginPersisted(const nsACString& aGroup,
const nsACString& aOrigin);
void
PersistOrigin(const nsACString& aGroup,
const nsACString& aOrigin);
// Called when a process is being shot down. Aborts any running operations
// for the given process.
void
@ -201,6 +209,7 @@ public:
nsresult
GetDirectoryMetadata2(nsIFile* aDirectory,
int64_t* aTimestamp,
bool* aPersisted,
nsACString& aSuffix,
nsACString& aGroup,
nsACString& aOrigin);
@ -209,17 +218,21 @@ public:
GetDirectoryMetadata2WithRestore(nsIFile* aDirectory,
bool aPersistent,
int64_t* aTimestamp,
bool* aPersisted,
nsACString& aSuffix,
nsACString& aGroup,
nsACString& aOrigin);
nsresult
GetDirectoryMetadata2(nsIFile* aDirectory, int64_t* aTimestamp);
GetDirectoryMetadata2(nsIFile* aDirectory,
int64_t* aTimestamp,
bool* aPersisted);
nsresult
GetDirectoryMetadata2WithRestore(nsIFile* aDirectory,
bool aPersistent,
int64_t* aTimestamp);
int64_t* aTimestamp,
bool* aPersisted);
// This is the main entry point into the QuotaManager API.
// Any storage API implementation (quota client) that participates in
@ -438,6 +451,11 @@ private:
const nsACString& aGroup,
const nsACString& aOrigin);
already_AddRefed<OriginInfo>
LockedGetOriginInfo(PersistenceType aPersistenceType,
const nsACString& aGroup,
const nsACString& aOrigin);
nsresult
MaybeUpgradeIndexedDBDirectory();

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

@ -60,6 +60,25 @@ TestingPrefChangedCallback(const char* aPrefName,
gTestingMode = Preferences::GetBool(aPrefName);
}
nsresult
CheckedPrincipalToPrincipalInfo(nsIPrincipal* aPrincipal,
PrincipalInfo& aPrincipalInfo)
{
MOZ_ASSERT(aPrincipal);
nsresult rv = PrincipalToPrincipalInfo(aPrincipal, &aPrincipalInfo);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (aPrincipalInfo.type() != PrincipalInfo::TContentPrincipalInfo &&
aPrincipalInfo.type() != PrincipalInfo::TSystemPrincipalInfo) {
return NS_ERROR_UNEXPECTED;
}
return NS_OK;
}
class AbortOperationsRunnable final
: public Runnable
{
@ -540,18 +559,12 @@ QuotaManagerService::InitStoragesForPrincipal(
InitOriginParams params;
PrincipalInfo& principalInfo = params.principalInfo();
nsresult rv = PrincipalToPrincipalInfo(aPrincipal, &principalInfo);
nsresult rv = CheckedPrincipalToPrincipalInfo(aPrincipal,
params.principalInfo());
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (principalInfo.type() != PrincipalInfo::TContentPrincipalInfo &&
principalInfo.type() != PrincipalInfo::TSystemPrincipalInfo) {
return NS_ERROR_UNEXPECTED;
}
Nullable<PersistenceType> persistenceType;
rv = NullablePersistenceTypeFromText(aPersistenceType, &persistenceType);
if (NS_WARN_IF(NS_FAILED(rv)) || persistenceType.IsNull()) {
@ -585,17 +598,12 @@ QuotaManagerService::GetUsageForPrincipal(nsIPrincipal* aPrincipal,
UsageParams params;
PrincipalInfo& principalInfo = params.principalInfo();
nsresult rv = PrincipalToPrincipalInfo(aPrincipal, &principalInfo);
nsresult rv = CheckedPrincipalToPrincipalInfo(aPrincipal,
params.principalInfo());
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (principalInfo.type() != PrincipalInfo::TContentPrincipalInfo &&
principalInfo.type() != PrincipalInfo::TSystemPrincipalInfo) {
return NS_ERROR_UNEXPECTED;
}
params.getGroupUsage() = aGetGroupUsage;
nsAutoPtr<PendingRequestInfo> info(new UsageRequestInfo(request, params));
@ -655,18 +663,12 @@ QuotaManagerService::ClearStoragesForPrincipal(nsIPrincipal* aPrincipal,
ClearOriginParams params;
PrincipalInfo& principalInfo = params.principalInfo();
nsresult rv = PrincipalToPrincipalInfo(aPrincipal, &principalInfo);
nsresult rv = CheckedPrincipalToPrincipalInfo(aPrincipal,
params.principalInfo());
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (principalInfo.type() != PrincipalInfo::TContentPrincipalInfo &&
principalInfo.type() != PrincipalInfo::TSystemPrincipalInfo) {
return NS_ERROR_UNEXPECTED;
}
Nullable<PersistenceType> persistenceType;
rv = NullablePersistenceTypeFromText(aPersistenceType, &persistenceType);
if (NS_WARN_IF(NS_FAILED(rv))) {
@ -717,6 +719,64 @@ QuotaManagerService::Reset(nsIQuotaRequest** _retval)
return NS_OK;
}
NS_IMETHODIMP
QuotaManagerService::Persisted(nsIPrincipal* aPrincipal,
nsIQuotaRequest** _retval)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aPrincipal);
MOZ_ASSERT(_retval);
RefPtr<Request> request = new Request(aPrincipal);
PersistedParams params;
nsresult rv = CheckedPrincipalToPrincipalInfo(aPrincipal,
params.principalInfo());
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
nsAutoPtr<PendingRequestInfo> info(new RequestInfo(request, params));
rv = InitiateRequest(info);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
request.forget(_retval);
return NS_OK;
}
NS_IMETHODIMP
QuotaManagerService::Persist(nsIPrincipal* aPrincipal,
nsIQuotaRequest** _retval)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aPrincipal);
MOZ_ASSERT(_retval);
RefPtr<Request> request = new Request(aPrincipal);
PersistParams params;
nsresult rv = CheckedPrincipalToPrincipalInfo(aPrincipal,
params.principalInfo());
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
nsAutoPtr<PendingRequestInfo> info(new RequestInfo(request, params));
rv = InitiateRequest(info);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
request.forget(_retval);
return NS_OK;
}
NS_IMETHODIMP
QuotaManagerService::Observe(nsISupports* aSubject,
const char* aTopic,

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

@ -100,4 +100,22 @@ interface nsIQuotaManagerService : nsISupports
*/
[must_use] nsIQuotaRequest
reset();
/**
* Check if given origin is persisted.
*
* @param aPrincipal
* A principal for the origin which we want to check.
*/
[must_use] nsIQuotaRequest
persisted(in nsIPrincipal aPrincipal);
/**
* Persist given origin.
*
* @param aPrincipal
* A principal for the origin which we want to persist.
*/
[must_use] nsIQuotaRequest
persist(in nsIPrincipal aPrincipal);
};

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

@ -6,6 +6,7 @@
const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
const NS_OK = Cr.NS_OK;
const NS_ERROR_FAILURE = Cr.NS_ERROR_FAILURE;
const NS_ERROR_UNEXPECTED = Cr.NS_ERROR_UNEXPECTED;
function is(a, b, msg)
@ -146,6 +147,20 @@ function reset(callback)
return request;
}
function persist(principal, callback) {
let request = SpecialPowers._getQuotaManager().persist(principal);
request.callback = callback;
return request;
}
function persisted(principal, callback) {
let request = SpecialPowers._getQuotaManager().persisted(principal);
request.callback = callback;
return request;
}
function installPackage(packageName)
{
let directoryService = Cc["@mozilla.org/file/directory_service;1"]
@ -237,6 +252,15 @@ function compareBuffers(buffer1, buffer2)
return true;
}
function getPersistedFromMetadata(readBuffer)
{
const persistedPosition = 8; // Persisted state is stored in the 9th byte
let view =
readBuffer instanceof Uint8Array ? readBuffer : new Uint8Array(readBuffer);
return !!view[persistedPosition];
}
function grabUsageAndContinueHandler(request)
{
testGenerator.next(request.usage);

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

@ -0,0 +1,150 @@
/**
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
var testGenerator = testSteps();
function* testSteps()
{
const origins = [
{
url: "http://default.test.persist",
path: "storage/default/http+++default.test.persist",
persistence: "default"
},
{
url: "ftp://ftp.invalid.origin",
path: "storage/default/ftp+++ftp.invalid.origin",
persistence: "default"
},
];
const metadataFileName = ".metadata-v2";
let principal = getPrincipal(origins[0].url);
info("Persisting an uninitialized origin");
// Origin directory doesn't exist yet, so only check the result for
// persisted().
let request = persisted(principal, continueToNextStepSync);
yield undefined;
ok(request.resultCode === NS_OK, "Persisted() succeeded");
ok(!request.result, "The origin is not persisted");
info("Verifying persist() does update the metadata");
request = persist(principal, continueToNextStepSync);
yield undefined;
ok(request.resultCode === NS_OK, "Persist() succeeded");
let originDir = getRelativeFile(origins[0].path);
let exists = originDir.exists();
ok(exists, "Origin directory does exist");
info("Reading out contents of metadata file");
let metadataFile = originDir.clone();
metadataFile.append(metadataFileName);
File.createFromNsIFile(metadataFile).then(grabArgAndContinueHandler);
let file = yield undefined;
let fileReader = new FileReader();
fileReader.onload = continueToNextStepSync;
fileReader.readAsArrayBuffer(file);
yield undefined;
let originPersisted = getPersistedFromMetadata(fileReader.result);
ok(originPersisted, "The origin is persisted");
info("Verifying persisted()");
request = persisted(principal, continueToNextStepSync);
yield undefined;
ok(request.resultCode === NS_OK, "Persisted() succeeded");
ok(request.result === originPersisted, "Persisted() concurs with metadata");
info("Clearing the origin");
// Clear the origin since we'll test the same directory again under different
// circumstances.
clearOrigin(principal, origins[0].persistence, continueToNextStepSync);
yield undefined;
info("Persisting an already initialized origin");
initOrigin(principal, origins[0].persistence, continueToNextStepSync);
yield undefined;
info("Reading out contents of metadata file");
fileReader = new FileReader();
fileReader.onload = continueToNextStepSync;
fileReader.readAsArrayBuffer(file);
yield undefined;
originPersisted = getPersistedFromMetadata(fileReader.result);
ok(!originPersisted, "The origin isn't persisted after clearing");
info("Verifying persisted()");
request = persisted(principal, continueToNextStepSync);
yield undefined;
ok(request.resultCode === NS_OK, "Persisted() succeeded");
ok(request.result === originPersisted, "Persisted() concurs with metadata");
info("Verifying persist() does update the metadata");
request = persist(principal, continueToNextStepSync);
yield undefined;
ok(request.resultCode === NS_OK, "Persist() succeeded");
info("Reading out contents of metadata file");
fileReader = new FileReader();
fileReader.onload = continueToNextStepSync;
fileReader.readAsArrayBuffer(file);
yield undefined;
originPersisted = getPersistedFromMetadata(fileReader.result);
ok(originPersisted, "The origin is persisted");
info("Verifying persisted()");
request = persisted(principal, continueToNextStepSync);
yield undefined;
ok(request.resultCode === NS_OK, "Persisted() succeeded");
ok(request.result === originPersisted, "Persisted() concurs with metadata");
info("Persisting an invalid origin");
let invalidPrincipal = getPrincipal(origins[1].url);
request = persist(invalidPrincipal, continueToNextStepSync);
yield undefined;
ok(request.resultCode === NS_ERROR_FAILURE,
"Persist() failed because of the invalid origin");
originDir = getRelativeFile(origins[1].path);
exists = originDir.exists();
ok(!exists, "Directory for invalid origin doesn't exist");
request = persisted(invalidPrincipal, continueToNextStepSync);
yield undefined;
ok(request.resultCode === NS_OK, "Persisted() succeeded");
ok(!request.result,
"The origin isn't persisted since the operation failed");
finishTest();
}

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

@ -22,6 +22,7 @@ support-files =
[test_morgueCleanup.js]
[test_obsoleteOriginAttributesUpgrade.js]
[test_originAttributesUpgrade.js]
[test_persist.js]
[test_removeAppsUpgrade.js]
[test_storagePersistentUpgrade.js]
[test_tempMetadataCleanup.js]

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

@ -0,0 +1,11 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Bug 1073952 - CSP should restrict scripts in srcdoc iframe even if sandboxed</title>
</head>
<body>
<iframe srcdoc="<img src=x onerror='parent.postMessage({result: `unexpected-csp-violation`}, `*`);'>"
sandbox="allow-scripts"></iframe>
</body>
</html>

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

@ -0,0 +1 @@
content-security-policy: default-src *;

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

@ -0,0 +1,79 @@
// Custom *.sjs file specifically for the needs of
// https://bugzilla.mozilla.org/show_bug.cgi?id=1073952
"use strict";
Components.utils.importGlobalProperties(["URLSearchParams"]);
const SCRIPT = `
<script>
parent.parent.postMessage({result: &quot;allowed&quot;}, &quot;*&quot;);
</script>`;
const SIMPLE_IFRAME_SRCDOC = `
<!DOCTYPE html>
<html>
<head><meta charset="utf-8"></head>
<body>
<iframe sandbox="allow-scripts" srcdoc="` + SCRIPT + `"></iframe>
</body>
</html>`;
const INNER_SRCDOC_IFRAME = `
<iframe sandbox='allow-scripts' srcdoc='<script>
parent.parent.parent.postMessage({result: &quot;allowed&quot;}, &quot;*&quot;);
</script>'>
</iframe>`;
const NESTED_IFRAME_SRCDOC = `
<!DOCTYPE html>
<html>
<head><meta charset="utf-8"></head>
<body>
<iframe sandbox="allow-scripts" srcdoc="` + INNER_SRCDOC_IFRAME + `"></iframe>
</body>
</html>`;
const INNER_DATAURI_IFRAME = `
<iframe sandbox='allow-scripts' src='data:text/html,<script>
parent.parent.parent.postMessage({result: &quot;allowed&quot;}, &quot;*&quot;);
</script>'>
</iframe>`;
const NESTED_IFRAME_SRCDOC_DATAURI = `
<!DOCTYPE html>
<html>
<head><meta charset="utf-8"></head>
<body>
<iframe sandbox="allow-scripts" srcdoc="` + INNER_DATAURI_IFRAME + `"></iframe>
</body>
</html>`;
function handleRequest(request, response) {
const query = new URLSearchParams(request.queryString);
response.setHeader("Cache-Control", "no-cache", false);
if (typeof query.get("csp") === "string") {
response.setHeader("Content-Security-Policy", query.get("csp"), false);
}
response.setHeader("Content-Type", "text/html", false);
if (query.get("action") === "simple_iframe_srcdoc") {
response.write(SIMPLE_IFRAME_SRCDOC);
return;
}
if (query.get("action") === "nested_iframe_srcdoc") {
response.write(NESTED_IFRAME_SRCDOC);
return;
}
if (query.get("action") === "nested_iframe_srcdoc_datauri") {
response.write(NESTED_IFRAME_SRCDOC_DATAURI);
return;
}
// we should never get here, but just in case
// return something unexpected
response.write("do'h");
}

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

@ -205,6 +205,9 @@ support-files =
file_upgrade_insecure_navigation.sjs
file_punycode_host_src.sjs
file_punycode_host_src.js
file_iframe_srcdoc.sjs
file_iframe_sandbox_srcdoc.html
file_iframe_sandbox_srcdoc.html^headers^
[test_base-uri.html]
[test_blob_data_schemes.html]
@ -293,3 +296,5 @@ tags = mcb
[test_strict_dynamic_default_src.html]
[test_upgrade_insecure_navigation.html]
[test_punycode_host_src.html]
[test_iframe_sandbox_srcdoc.html]
[test_iframe_srcdoc.html]

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

@ -0,0 +1,62 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Bug 1073952 - CSP should restrict scripts in srcdoc iframe even if sandboxed</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<p id="display">Bug 1073952</p>
<iframe style="width:200px;height:200px;" id='cspframe'></iframe>
<script class="testbody" type="text/javascript">
// This is used to watch the blocked data bounce off CSP and allowed data
// get sent out to the wire.
function examiner() {
SpecialPowers.addObserver(this, "csp-on-violate-policy", false);
}
examiner.prototype = {
observe: function(subject, topic, data) {
if(topic === "csp-on-violate-policy") {
var violationString = SpecialPowers.getPrivilegedProps(SpecialPowers.
do_QueryInterface(subject, "nsISupportsCString"), "data");
// the violation subject for inline script violations is unfortunately vague,
// all we can do is match the string.
if (!violationString.includes("Inline Script")) {
return
}
ok(true, "CSP inherited into sandboxed srcdoc iframe, script blocked.");
window.testFinished();
}
},
// must eventually call this to remove the listener,
// or mochitests might get borked.
remove: function() {
SpecialPowers.removeObserver(this, "csp-on-violate-policy");
}
}
window.examiner = new examiner();
function testFinished() {
window.examiner.remove();
SimpleTest.finish();
}
addEventListener("message", function(e) {
ok(false, "We should not execute JS in srcdoc iframe.");
window.testFinished();
})
SimpleTest.waitForExplicitFinish();
// save this for last so that our listeners are registered.
// ... this loads the testbed of good and bad requests.
document.getElementById('cspframe').src = 'file_iframe_sandbox_srcdoc.html';
</script>
</body>
</html>

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

@ -0,0 +1,140 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Bug 1073952 - Test CSP enforcement within iframe srcdoc</title>
<!-- Including SimpleTest.js so we can use waitForExplicitFinish !-->
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<iframe style="width:100%;" id="testframe"></iframe>
<script class="testbody" type="text/javascript">
/*
* Description of the test:
* (1) We serve a site which makes use of script-allowed sandboxed iframe srcdoc
* and make sure that CSP applies to the nested browsing context
* within the iframe.
* [PAGE WITH CSP [IFRAME SANDBOX SRCDOC [SCRIPT]]]
*
* (2) We serve a site which nests script within an script-allowed sandboxed
* iframe srcdoc within another script-allowed sandboxed iframe srcdoc and
* make sure that CSP applies to the nested browsing context
* within the iframe*s*.
* [PAGE WITH CSP [IFRAME SANDBOX SRCDOC [IFRAME SANDBOX SRCDOC [SCRIPT]]]]
*
* Please note that the test relies on the "csp-on-violate-policy" observer.
* Whenever the script within the iframe is blocked observers are notified.
* In turn, this renders the 'result' within tests[] unused. In case the script
* would execute however, the postMessageHandler would bubble up 'allowed' and
* the test would fail.
*/
SimpleTest.waitForExplicitFinish();
var tests = [
// [PAGE *WITHOUT* CSP [IFRAME SRCDOC [SCRIPT]]]
{ csp: "",
result: "allowed",
query: "simple_iframe_srcdoc",
desc: "No CSP should run script within script-allowed sandboxed iframe srcdoc"
},
{ csp: "script-src https://test1.com",
result: "blocked",
query: "simple_iframe_srcdoc",
desc: "CSP should block script within script-allowed sandboxediframe srcdoc"
},
// [PAGE *WITHOUT* CSP [IFRAME SRCDOC [IFRAME SRCDOC [SCRIPT]]]]
{ csp: "",
result: "allowed",
query: "nested_iframe_srcdoc",
desc: "No CSP should run script within script-allowed sandboxed iframe srcdoc nested within another script-allowed sandboxed iframe srcdoc"
},
// [PAGE WITH CSP [IFRAME SRCDOC ]]
{ csp: "script-src https://test2.com",
result: "blocked",
query: "nested_iframe_srcdoc",
desc: "CSP should block script within script-allowed sandboxed iframe srcdoc nested within another script-allowed sandboxed iframe srcdoc"
},
{ csp: "",
result: "allowed",
query: "nested_iframe_srcdoc_datauri",
desc: "No CSP, should run script within script-allowed sandboxed iframe src with data URL nested within another script-allowed sandboxed iframe srcdoc"
},
{ csp: "script-src https://test3.com",
result: "blocked",
query: "nested_iframe_srcdoc_datauri",
desc: "CSP should block script within script-allowed sandboxed iframe src with data URL nested within another script-allowed sandboxed iframe srcdoc"
},
];
// initializing to -1 so we start at index 0 when we start the test
var counter = -1;
function finishTest() {
window.removeEventListener("message", receiveMessage, false);
window.examiner.remove();
SimpleTest.finish();
}
window.addEventListener("message", receiveMessage, false);
function receiveMessage(event) {
var result = event.data.result;
testComplete(result, tests[counter].result, tests[counter].desc);
}
function examiner() {
SpecialPowers.addObserver(this, "csp-on-violate-policy", false);
}
examiner.prototype = {
observe: function(subject, topic, data) {
if (topic === "csp-on-violate-policy") {
var violationString = SpecialPowers.getPrivilegedProps(SpecialPowers.
do_QueryInterface(subject, "nsISupportsCString"), "data");
// the violation subject for inline script violations is unfortunately vague,
// all we can do is match the string.
if (!violationString.includes("Inline Script")) {
return
}
testComplete("blocked", tests[counter].result, tests[counter].desc);
}
},
remove: function() {
SpecialPowers.removeObserver(this, "csp-on-violate-policy");
}
}
function testComplete(result, expected, desc) {
is(result, expected, desc);
// ignore cases when we get csp violations and postMessage from the same frame.
var frameURL = new URL(document.getElementById("testframe").src);
var params = new URLSearchParams(frameURL.search);
var counterInFrame = params.get("counter");
if (counterInFrame == counter) {
loadNextTest();
}
}
function loadNextTest() {
counter++;
if (counter == tests.length) {
finishTest();
return;
}
var src = "file_iframe_srcdoc.sjs";
src += "?csp=" + escape(tests[counter].csp);
src += "&action=" + escape(tests[counter].query);
src += "&counter=" + counter;
document.getElementById("testframe").src = src;
}
// start running the tests
window.examiner = new examiner();
loadNextTest();
</script>
</body>
</html>

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

@ -385,6 +385,8 @@ nsSMILAnimationController::DoSample(bool aSkipUnchangedContainers)
// Create the compositor table
nsAutoPtr<nsSMILCompositorTable>
currentCompositorTable(new nsSMILCompositorTable(0));
nsTArray<RefPtr<SVGAnimationElement>>
animElems(mAnimationElementTable.Count());
for (auto iter = mAnimationElementTable.Iter(); !iter.Done(); iter.Next()) {
SVGAnimationElement* animElem = iter.Get()->GetKey();
@ -392,6 +394,7 @@ nsSMILAnimationController::DoSample(bool aSkipUnchangedContainers)
AddAnimationToCompositorTable(animElem,
currentCompositorTable,
isStyleFlushNeeded);
animElems.AppendElement(animElem);
}
activeContainers.Clear();

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

@ -658,7 +658,7 @@ RespondWithHandler::ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValu
nsCOMPtr<nsIOutputStream> responseBody;
rv = mInterceptedChannel->GetResponseBody(getter_AddRefs(responseBody));
if (NS_WARN_IF(NS_FAILED(rv))) {
if (NS_WARN_IF(NS_FAILED(rv)) || !responseBody) {
return;
}

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

@ -1580,7 +1580,8 @@ private:
nsresult rv2 =
DispatchExtendableEventOnWorkerScope(aCx, aWorkerPrivate->GlobalScope(),
event, nullptr);
if (NS_WARN_IF(NS_FAILED(rv2)) || !event->WaitToRespond()) {
if ((NS_WARN_IF(NS_FAILED(rv2)) && rv2 != NS_ERROR_XPC_JS_THREW_EXCEPTION) ||
!event->WaitToRespond()) {
nsCOMPtr<nsIRunnable> runnable;
MOZ_ASSERT(!aWorkerPrivate->UsesSystemPrincipal(),
"We don't support system-principal serviceworkers");

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

@ -354,7 +354,7 @@ ServiceWorkerRegistrar::ReadData()
GET_LINE(entry->scope());
entry->principal() =
mozilla::ipc::ContentPrincipalInfo(attrs, entry->scope());
mozilla::ipc::ContentPrincipalInfo(attrs, void_t(), entry->scope());
GET_LINE(entry->currentWorkerURL());
@ -395,7 +395,7 @@ ServiceWorkerRegistrar::ReadData()
GET_LINE(entry->scope());
entry->principal() =
mozilla::ipc::ContentPrincipalInfo(attrs, entry->scope());
mozilla::ipc::ContentPrincipalInfo(attrs, void_t(), entry->scope());
GET_LINE(entry->currentWorkerURL());
@ -428,7 +428,7 @@ ServiceWorkerRegistrar::ReadData()
GET_LINE(entry->scope());
entry->principal() =
mozilla::ipc::ContentPrincipalInfo(attrs, entry->scope());
mozilla::ipc::ContentPrincipalInfo(attrs, void_t(), entry->scope());
GET_LINE(entry->currentWorkerURL());
@ -458,7 +458,7 @@ ServiceWorkerRegistrar::ReadData()
GET_LINE(entry->scope());
entry->principal() =
mozilla::ipc::ContentPrincipalInfo(attrs, entry->scope());
mozilla::ipc::ContentPrincipalInfo(attrs, void_t(), entry->scope());
GET_LINE(entry->currentWorkerURL());
@ -488,7 +488,7 @@ ServiceWorkerRegistrar::ReadData()
GET_LINE(entry->scope());
entry->principal() =
mozilla::ipc::ContentPrincipalInfo(attrs, entry->scope());
mozilla::ipc::ContentPrincipalInfo(attrs, void_t(), entry->scope());
// scriptSpec is no more used in latest version.
GET_LINE(unused);

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

@ -243,7 +243,8 @@ TEST(ServiceWorkerRegistrar, TestWriteData)
nsAutoCString spec;
spec.AppendPrintf("spec write %d", i);
reg.principal() =
mozilla::ipc::ContentPrincipalInfo(mozilla::OriginAttributes(i, i % 2), spec);
mozilla::ipc::ContentPrincipalInfo(mozilla::OriginAttributes(i, i % 2),
mozilla::void_t(), spec);
swr->TestRegisterServiceWorker(reg);
}
@ -597,7 +598,8 @@ TEST(ServiceWorkerRegistrar, TestDedupeWrite)
nsAutoCString spec;
spec.AppendPrintf("spec write dedupe/%d", i);
reg.principal() =
mozilla::ipc::ContentPrincipalInfo(mozilla::OriginAttributes(0, false), spec);
mozilla::ipc::ContentPrincipalInfo(mozilla::OriginAttributes(0, false),
mozilla::void_t(), spec);
swr->TestRegisterServiceWorker(reg);
}

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

@ -416,8 +416,10 @@ public:
~AutoStyleNewChildren()
{
nsIPresShell* presShell = mElement->OwnerDoc()->GetShell();
ServoStyleSet* servoSet = presShell ? presShell->StyleSet()->GetAsServo() : nullptr;
if (servoSet) {
if (!presShell || !presShell->DidInitialize()) {
return;
}
if (ServoStyleSet* servoSet = presShell->StyleSet()->GetAsServo()) {
// In general the element is always styled by the time we're applying XBL
// bindings, because we need to style the element to know what the binding
// URI is. However, programmatic consumers of the XBL service (like the

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

@ -2338,7 +2338,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
else
{
yy_size_t num_to_read =
int num_to_read =
YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
while ( num_to_read <= 0 )

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

@ -1273,6 +1273,9 @@ nsEventStatus AsyncPanZoomController::OnTouchEnd(const MultiTouchInput& aEvent)
flingVelocity.Length().value, gfxPrefs::APZFlingMinVelocityThreshold());
if (flingVelocity.Length() < gfxPrefs::APZFlingMinVelocityThreshold()) {
// Relieve overscroll now if needed, since we will not transition to a fling
// animation and then an overscroll animation, and relieve it then.
GetCurrentTouchBlock()->GetOverscrollHandoffChain()->SnapBackOverscrolledApzc(this);
return nsEventStatus_eConsumeNoDefault;
}

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

@ -314,6 +314,23 @@ TEST_F(APZCBasicTester, OverScroll_Bug1152051b) {
SampleAnimationUntilRecoveredFromOverscroll(expectedScrollOffset);
}
// Tests that the page doesn't get stuck in an
// overscroll animation after a low-velocity pan.
TEST_F(APZCBasicTester, OverScrollAfterLowVelocityPan_Bug1343775) {
SCOPED_GFX_PREF(APZOverscrollEnabled, bool, true);
// Pan into overscroll with a velocity less than the
// apz.fling_min_velocity_threshold preference.
Pan(apzc, 10, 30);
EXPECT_TRUE(apzc->IsOverscrolled());
apzc->AdvanceAnimationsUntilEnd();
// Check that we recovered from overscroll.
EXPECT_FALSE(apzc->IsOverscrolled());
}
TEST_F(APZCBasicTester, OverScrollAbort) {
SCOPED_GFX_PREF(APZOverscrollEnabled, bool, true);

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

@ -0,0 +1,77 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width; initial-scale=1.0">
<title>Dragging the scrollbar on a page with a fixed-positioned element just past the right edge of the content</title>
<script type="application/javascript" src="apz_test_native_event_utils.js"></script>
<script type="application/javascript" src="apz_test_utils.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
<style>
body {
height: 2000px;
}
#fixed {
width: 240px;
height: 100%;
position: fixed;
top: 0px;
right: -240px;
z-index: 1000;
overflow-y: scroll;
}
#fixed-content {
height: 2000px;
}
</style>
<script type="text/javascript">
var root;
var scrollPos;
var haveScrolled = false;
var generatedAll = false;
// Be careful not to call subtestDone() until we've scrolled AND generated
// all of the events.
function maybeDone() {
if (haveScrolled && generatedAll) {
subtestDone();
}
}
function scrolled(e) {
// Test that we have scrolled
ok(root.scrollTop > scrollPos, "document scrolled after dragging scrollbar");
haveScrolled = true;
maybeDone();
}
function* test(testDriver) {
root = document.scrollingElement;
scrollPos = root.scrollTop;
document.addEventListener('scroll', scrolled);
var scrollbarX = (window.innerWidth + root.clientWidth) / 2;
// Move the mouse to the scrollbar
yield synthesizeNativeMouseEvent(root, scrollbarX, 100, nativeMouseMoveEventMsg(), testDriver);
// mouse down
yield synthesizeNativeMouseEvent(root, scrollbarX, 100, nativeMouseDownEventMsg(), testDriver);
// drag vertically
yield synthesizeNativeMouseEvent(root, scrollbarX, 150, nativeMouseMoveEventMsg(), testDriver);
// and release
yield synthesizeNativeMouseEvent(root, scrollbarX, 150, nativeMouseUpEventMsg(), testDriver);
generatedAll = true;
maybeDone();
}
waitUntilApzStable()
.then(runContinuation(test));
</script>
</head>
<body>
<div id="fixed">
<p id="fixed-content"></p>
</div>
</body>
</html>

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

@ -10,6 +10,7 @@
helper_bug1280013.html
helper_bug1285070.html
helper_bug1299195.html
helper_bug1346632.html
helper_click.html
helper_div_pan.html
helper_drag_click.html

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

@ -17,7 +17,9 @@ var subtests = [
// Sanity test for click but with some mouse movement between the down and up
{'file': 'helper_drag_click.html'},
// Test for dragging on a fake-scrollbar element that scrolls the page
{'file': 'helper_drag_scroll.html'}
{'file': 'helper_drag_scroll.html'},
// Test for dragging the scrollbar with a fixed-pos element overlaying it
{'file': 'helper_bug1346632.html'}
];
if (isApzEnabled()) {

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

@ -628,8 +628,15 @@ PrepareForSetTargetAPZCNotification(nsIWidget* aWidget,
ScrollableLayerGuid guid(aGuid.mLayersId, 0, FrameMetrics::NULL_SCROLL_ID);
nsPoint point =
nsLayoutUtils::GetEventCoordinatesRelativeTo(aWidget, aRefPoint, aRootFrame);
uint32_t flags = 0;
#ifdef MOZ_WIDGET_ANDROID
// On Android, we need IGNORE_ROOT_SCROLL_FRAME for correct hit testing
// when zoomed out. On desktop, don't use it because it interferes with
// hit testing for some purposes such as scrollbar dragging.
flags = nsLayoutUtils::IGNORE_ROOT_SCROLL_FRAME;
#endif
nsIFrame* target =
nsLayoutUtils::GetFrameForPoint(aRootFrame, point, nsLayoutUtils::IGNORE_ROOT_SCROLL_FRAME);
nsLayoutUtils::GetFrameForPoint(aRootFrame, point, flags);
nsIScrollableFrame* scrollAncestor = target
? nsLayoutUtils::GetAsyncScrollableAncestorFrame(target)
: aRootFrame->PresContext()->PresShell()->GetRootScrollFrameAsScrollable();

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

@ -74,6 +74,7 @@ APZThreadUtils::IsControllerThread()
}
NS_IMPL_ISUPPORTS(GenericTimerCallbackBase, nsITimerCallback)
NS_IMPL_ISUPPORTS(GenericNamedTimerCallbackBase, nsITimerCallback, nsINamed)
} // namespace layers
} // namespace mozilla

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

@ -7,6 +7,7 @@
#define mozilla_layers_APZThreadUtils_h
#include "base/message_loop.h"
#include "nsINamed.h"
#include "nsITimer.h"
namespace mozilla {
@ -98,6 +99,68 @@ GenericTimerCallback<Function>* NewTimerCallback(const Function& aFunction)
return new GenericTimerCallback<Function>(aFunction);
}
// A base class for GenericNamedTimerCallback<Function>.
// This is necessary because NS_IMPL_ISUPPORTS doesn't work for a class
// template.
class GenericNamedTimerCallbackBase : public nsITimerCallback,
public nsINamed
{
public:
NS_DECL_THREADSAFE_ISUPPORTS
protected:
virtual ~GenericNamedTimerCallbackBase() {}
};
// An nsITimerCallback implementation with nsINamed that can be used with any
// function object that's callable with no arguments.
template <typename Function>
class GenericNamedTimerCallback final : public GenericNamedTimerCallbackBase
{
public:
explicit GenericNamedTimerCallback(const Function& aFunction,
const char* aName)
: mFunction(aFunction)
, mName(aName)
{
}
NS_IMETHOD Notify(nsITimer*) override
{
mFunction();
return NS_OK;
}
NS_IMETHOD GetName(nsACString& aName) override
{
aName = mName;
return NS_OK;
}
NS_IMETHOD SetName(const char * aName) override
{
mName.Assign(aName);
return NS_OK;
}
private:
Function mFunction;
nsCString mName;
};
// Convenience function for constructing a GenericNamedTimerCallback.
// Returns a raw pointer, suitable for passing directly as an argument to
// nsITimer::InitWithCallback(). The intention is to enable the following
// terse inline usage:
// timer->InitWithCallback(NewNamedTimerCallback([](){ ... }, name), delay);
template <typename Function>
GenericNamedTimerCallback<Function>*
NewNamedTimerCallback(const Function& aFunction,
const char* aName)
{
return new GenericNamedTimerCallback<Function>(aFunction, aName);
}
} // namespace layers
} // namespace mozilla

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

@ -98,6 +98,7 @@ static pfn_ovr_GetFloatArray ovr_GetFloatArray = nullptr;
static pfn_ovr_SetFloatArray ovr_SetFloatArray = nullptr;
static pfn_ovr_GetString ovr_GetString = nullptr;
static pfn_ovr_SetString ovr_SetString = nullptr;
static pfn_ovr_GetBoundaryDimensions ovr_GetBoundaryDimensions = nullptr;
#ifdef XP_WIN
static pfn_ovr_CreateTextureSwapChainDX ovr_CreateTextureSwapChainDX = nullptr;
@ -286,6 +287,7 @@ InitializeOculusCAPI()
REQUIRE_FUNCTION(ovr_SetFloatArray);
REQUIRE_FUNCTION(ovr_GetString);
REQUIRE_FUNCTION(ovr_SetString);
REQUIRE_FUNCTION(ovr_GetBoundaryDimensions);
#ifdef XP_WIN
@ -356,6 +358,7 @@ VRDisplayOculus::VRDisplayOculus(ovrSession aSession)
, mVertexBuffer(nullptr)
, mInputLayout(nullptr)
, mIsPresenting(false)
, mEyeHeight(OVR_DEFAULT_EYE_HEIGHT)
{
MOZ_COUNT_CTOR_INHERITED(VRDisplayOculus, VRDisplayHost);
@ -373,6 +376,7 @@ VRDisplayOculus::VRDisplayOculus(ovrSession aSession)
if (mDesc.AvailableTrackingCaps & ovrTrackingCap_Position) {
mDisplayInfo.mCapabilityFlags |= VRDisplayCapabilityFlags::Cap_Position;
mDisplayInfo.mCapabilityFlags |= VRDisplayCapabilityFlags::Cap_LinearAcceleration;
mDisplayInfo.mCapabilityFlags |= VRDisplayCapabilityFlags::Cap_StageParameters;
}
mDisplayInfo.mCapabilityFlags |= VRDisplayCapabilityFlags::Cap_External;
mDisplayInfo.mCapabilityFlags |= VRDisplayCapabilityFlags::Cap_MountDetection;
@ -401,6 +405,8 @@ VRDisplayOculus::VRDisplayOculus(ovrSession aSession)
// take the max of both for eye resolution
mDisplayInfo.mEyeResolution.width = std::max(texSize[VRDisplayInfo::Eye_Left].w, texSize[VRDisplayInfo::Eye_Right].w);
mDisplayInfo.mEyeResolution.height = std::max(texSize[VRDisplayInfo::Eye_Left].h, texSize[VRDisplayInfo::Eye_Right].h);
UpdateStageParameters();
}
VRDisplayOculus::~VRDisplayOculus() {
@ -418,10 +424,49 @@ VRDisplayOculus::Destroy()
}
}
void
VRDisplayOculus::UpdateStageParameters()
{
ovrVector3f playArea;
ovrResult res = ovr_GetBoundaryDimensions(mSession, ovrBoundary_PlayArea, &playArea);
if (res == ovrSuccess) {
mDisplayInfo.mStageSize.width = playArea.x;
mDisplayInfo.mStageSize.height = playArea.z;
} else {
// If we fail, fall back to reasonable defaults.
// 1m x 1m space
mDisplayInfo.mStageSize.width = 1.0f;
mDisplayInfo.mStageSize.height = 1.0f;
}
mEyeHeight = ovr_GetFloat(mSession, OVR_KEY_EYE_HEIGHT, OVR_DEFAULT_EYE_HEIGHT);
mDisplayInfo.mSittingToStandingTransform._11 = 1.0f;
mDisplayInfo.mSittingToStandingTransform._12 = 0.0f;
mDisplayInfo.mSittingToStandingTransform._13 = 0.0f;
mDisplayInfo.mSittingToStandingTransform._14 = 0.0f;
mDisplayInfo.mSittingToStandingTransform._21 = 0.0f;
mDisplayInfo.mSittingToStandingTransform._22 = 1.0f;
mDisplayInfo.mSittingToStandingTransform._23 = 0.0f;
mDisplayInfo.mSittingToStandingTransform._24 = 0.0f;
mDisplayInfo.mSittingToStandingTransform._31 = 0.0f;
mDisplayInfo.mSittingToStandingTransform._32 = 0.0f;
mDisplayInfo.mSittingToStandingTransform._33 = 1.0f;
mDisplayInfo.mSittingToStandingTransform._34 = 0.0f;
mDisplayInfo.mSittingToStandingTransform._41 = 0.0f;
mDisplayInfo.mSittingToStandingTransform._42 = mEyeHeight;
mDisplayInfo.mSittingToStandingTransform._43 = 0.0f;
mDisplayInfo.mSittingToStandingTransform._44 = 1.0f;
}
void
VRDisplayOculus::ZeroSensor()
{
ovr_RecenterTrackingOrigin(mSession);
UpdateStageParameters();
}
VRHMDSensorState
@ -440,6 +485,7 @@ VRDisplayOculus::GetSensorState()
result = GetSensorState(frameDelta);
result.inputFrameID = mInputFrameID;
mLastSensorState[result.inputFrameID % kMaxLatencyFrames] = result;
result.position[1] -= mEyeHeight;
return result;
}
@ -988,6 +1034,11 @@ VRSystemManagerOculus::GetHMDs(nsTArray<RefPtr<VRDisplayHost>>& aHMDResult)
ovrResult orv = ovr_Create(&session, &luid);
if (orv == ovrSuccess) {
mSession = session;
orv = ovr_SetTrackingOriginType(session, ovrTrackingOrigin_FloorLevel);
if (orv != ovrSuccess) {
NS_WARNING("ovr_SetTrackingOriginType failed.\n");
}
mHMDInfo = new VRDisplayOculus(session);
}
}
@ -1099,6 +1150,9 @@ VRSystemManagerOculus::HandleInput()
poseState.linearAcceleration[0] = pose.LinearAcceleration.x;
poseState.linearAcceleration[1] = pose.LinearAcceleration.y;
poseState.linearAcceleration[2] = pose.LinearAcceleration.z;
float eyeHeight = ovr_GetFloat(mSession, OVR_KEY_EYE_HEIGHT, OVR_DEFAULT_EYE_HEIGHT);
poseState.position[1] -= eyeHeight;
}
HandlePoseTracking(i, poseState, controller);
}

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

@ -48,6 +48,7 @@ protected:
const VRHMDSensorState& aSensorState,
const gfx::Rect& aLeftEyeRect,
const gfx::Rect& aRightEyeRect) override;
void UpdateStageParameters();
public:
explicit VRDisplayOculus(ovrSession aSession);
@ -82,7 +83,8 @@ protected:
RefPtr<ID3D11InputLayout> mInputLayout;
bool mIsPresenting;
float mEyeHeight;
bool UpdateConstantBuffers();
struct Vertex

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

@ -45,10 +45,6 @@ parent:
// asynchronously to children via UpdateDisplayInfo.
async RefreshDisplays();
// GetDisplays synchronously returns the VR displays that have already been
// enumerated by RefreshDisplays() but does not enumerate new ones.
sync GetDisplays() returns(VRDisplayInfo[] aDisplayInfo);
// Reset the sensor of the display identified by aDisplayID so that the current
// sensor state is the "Zero" position.
async ResetSensor(uint32_t aDisplayID);

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