merge mozilla-inbound to mozilla-central a=merge

This commit is contained in:
Carsten "Tomcat" Book 2016-06-06 11:55:56 +02:00
Родитель 11e77b01e4 08ef5cffc4
Коммит 4aea0165dc
448 изменённых файлов: 9799 добавлений и 4052 удалений

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

@ -425,14 +425,14 @@ private:
enum Interfaces
{
HYPERTEXT = 1,
HYPERLINK = 2,
IMAGE = 4,
VALUE = 8,
TABLE = 16,
TABLECELL = 32,
DOCUMENT = 64,
SELECTION = 128,
ACTION = 256,
HYPERLINK = 1 << 1,
IMAGE = 1 << 2,
VALUE = 1 << 3,
TABLE = 1 << 4,
TABLECELL = 1 << 5,
DOCUMENT = 1 << 6,
SELECTION = 1 << 7,
ACTION = 1 << 8,
};
}

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

@ -30,14 +30,12 @@
#include "nsStringGlue.h"
#ifdef XP_WIN
// we want a wmain entry point
#ifdef MOZ_ASAN
// ASAN requires firefox.exe to be built with -MD, and it's OK if we don't
// support Windows XP SP2 in ASAN builds.
#define XRE_DONT_SUPPORT_XPSP2
#endif
#define XRE_WANT_ENVIRON
#include "nsWindowsWMain.cpp"
#if defined(_MSC_VER) && (_MSC_VER < 1900)
#define snprintf _snprintf
#endif
@ -53,6 +51,12 @@
#include "mozilla/Telemetry.h"
#include "mozilla/WindowsDllBlocklist.h"
#if !defined(MOZ_WIDGET_COCOA) && !defined(MOZ_WIDGET_ANDROID) \
&& !(defined(XP_LINUX) && defined(MOZ_SANDBOX))
#define MOZ_BROWSER_CAN_BE_CONTENTPROC
#include "../../ipc/contentproc/plugin-container.cpp"
#endif
using namespace mozilla;
#ifdef XP_MACOSX
@ -128,6 +132,10 @@ XRE_StartupTimelineRecordType XRE_StartupTimelineRecord;
XRE_mainType XRE_main;
XRE_StopLateWriteChecksType XRE_StopLateWriteChecks;
XRE_XPCShellMainType XRE_XPCShellMain;
XRE_GetProcessTypeType XRE_GetProcessType;
XRE_SetProcessTypeType XRE_SetProcessType;
XRE_InitChildProcessType XRE_InitChildProcess;
XRE_EnableSameExecutableForContentProcType XRE_EnableSameExecutableForContentProc;
static const nsDynamicFunctionLoad kXULFuncs[] = {
{ "XRE_GetFileFromPath", (NSFuncPtr*) &XRE_GetFileFromPath },
@ -138,6 +146,10 @@ static const nsDynamicFunctionLoad kXULFuncs[] = {
{ "XRE_main", (NSFuncPtr*) &XRE_main },
{ "XRE_StopLateWriteChecks", (NSFuncPtr*) &XRE_StopLateWriteChecks },
{ "XRE_XPCShellMain", (NSFuncPtr*) &XRE_XPCShellMain },
{ "XRE_GetProcessType", (NSFuncPtr*) &XRE_GetProcessType },
{ "XRE_SetProcessType", (NSFuncPtr*) &XRE_SetProcessType },
{ "XRE_InitChildProcess", (NSFuncPtr*) &XRE_InitChildProcess },
{ "XRE_EnableSameExecutableForContentProc", (NSFuncPtr*) &XRE_EnableSameExecutableForContentProc },
{ nullptr, nullptr }
};
@ -296,25 +308,54 @@ sizeof(XPCOM_DLL) - 1))
// This will set this thread as the main thread.
NS_LogInit();
// chop XPCOM_DLL off exePath
*lastSlash = '\0';
if (xreDirectory) {
// chop XPCOM_DLL off exePath
*lastSlash = '\0';
#ifdef XP_MACOSX
lastSlash = strrchr(exePath, XPCOM_FILE_PATH_SEPARATOR[0]);
strcpy(lastSlash + 1, kOSXResourcesFolder);
lastSlash = strrchr(exePath, XPCOM_FILE_PATH_SEPARATOR[0]);
strcpy(lastSlash + 1, kOSXResourcesFolder);
#endif
#ifdef XP_WIN
rv = NS_NewLocalFile(NS_ConvertUTF8toUTF16(exePath), false,
xreDirectory);
rv = NS_NewLocalFile(NS_ConvertUTF8toUTF16(exePath), false,
xreDirectory);
#else
rv = NS_NewNativeLocalFile(nsDependentCString(exePath), false,
xreDirectory);
rv = NS_NewNativeLocalFile(nsDependentCString(exePath), false,
xreDirectory);
#endif
}
return rv;
}
int main(int argc, char* argv[], char* envp[])
{
#ifdef MOZ_BROWSER_CAN_BE_CONTENTPROC
// We are launching as a content process, delegate to the appropriate
// main
if (argc > 1 && IsArg(argv[1], "contentproc")) {
#if defined(XP_WIN) && defined(MOZ_SANDBOX)
// We need to initialize the sandbox TargetServices before InitXPCOMGlue
// because we might need the sandbox broker to give access to some files.
if (!sandboxing::GetInitializedTargetServices()) {
Output("Failed to initialize the sandbox target services.");
return 255;
}
#endif
nsresult rv = InitXPCOMGlue(argv[0], nullptr);
if (NS_FAILED(rv)) {
return 255;
}
int result = content_process_main(argc, argv);
// InitXPCOMGlue calls NS_LogInit, so we need to balance it here.
NS_LogTerm();
return result;
}
#endif
mozilla::TimeStamp start = mozilla::TimeStamp::Now();
#ifdef XP_MACOSX
@ -379,6 +420,10 @@ int main(int argc, char* argv[], char* envp[])
#endif
}
#ifdef MOZ_BROWSER_CAN_BE_CONTENTPROC
XRE_EnableSameExecutableForContentProc();
#endif
int result = do_main(argc, argv, envp, xreDirectory);
NS_LogTerm();

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

@ -1401,10 +1401,8 @@ pref("dom.push.enabled", true);
pref("toolkit.pageThumbs.minWidth", 280);
pref("toolkit.pageThumbs.minHeight", 190);
#ifdef NIGHTLY_BUILD
// Enable speech synthesis, only Nightly for now
// Enable speech synthesis
pref("media.webspeech.synth.enabled", true);
#endif
pref("browser.esedbreader.loglevel", "Error");

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

@ -576,15 +576,20 @@ Sanitizer.prototype = {
// Clear all push notification subscriptions
try {
let push = Cc["@mozilla.org/push/Service;1"]
.getService(Ci.nsIPushService);
push.clearForDomain("*", status => {
if (!Components.isSuccessCode(status)) {
dump("Error clearing Web Push data: " + status + "\n");
}
yield new Promise((resolve, reject) => {
let push = Cc["@mozilla.org/push/Service;1"]
.getService(Ci.nsIPushService);
push.clearForDomain("*", status => {
if (Components.isSuccessCode(status)) {
resolve();
} else {
reject(new Error("Error clearing push subscriptions: " +
status));
}
});
});
} catch (e) {
dump("Web Push may not be available.\n");
} catch (ex) {
seenException = ex;
}
TelemetryStopwatch.finish("FX_SANITIZE_SITESETTINGS", refObj);

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

@ -2891,11 +2891,17 @@
let tabs = this.visibleTabs;
// count backwards for aIndex < 0
if (aIndex < 0)
if (aIndex < 0) {
aIndex += tabs.length;
// clamp at index 0 if still negative.
if (aIndex < 0)
aIndex = 0;
} else if (aIndex >= tabs.length) {
// clamp at right-most tab if out of range.
aIndex = tabs.length - 1;
}
if (aIndex >= 0 && aIndex < tabs.length)
this.selectedTab = tabs[aIndex];
this.selectedTab = tabs[aIndex];
if (aEvent) {
aEvent.preventDefault();

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

@ -1,22 +1,81 @@
"use strict";
function test() {
for (let i = 0; i < 9; i++)
gBrowser.addTab();
const isLinux = navigator.platform.indexOf("Linux") == 0;
var isLinux = navigator.platform.indexOf("Linux") == 0;
for (let i = 9; i >= 1; i--) {
// Make sure the keystroke goes to chrome.
document.activeElement.blur();
EventUtils.synthesizeKey(i.toString(), { altKey: isLinux, accelKey: !isLinux });
is(gBrowser.tabContainer.selectedIndex, (i == 9 ? gBrowser.tabs.length : i) - 1,
(isLinux ? "Alt" : "Accel") + "+" + i + " selects expected tab");
function assertTab(expectedTab) {
is(gBrowser.tabContainer.selectedIndex, expectedTab,
`tab index ${expectedTab} should be selected`);
}
gBrowser.selectTabAtIndex(-3);
is(gBrowser.tabContainer.selectedIndex, gBrowser.tabs.length - 3,
"gBrowser.selectTabAtIndex(-3) selects expected tab");
function sendAccelKey(key) {
// Make sure the keystroke goes to chrome.
document.activeElement.blur();
EventUtils.synthesizeKey(key.toString(), { altKey: isLinux, accelKey: !isLinux });
}
for (let i = 0; i < 9; i++)
function createTabs(count) {
for (let n = 0; n < count; n++)
gBrowser.addTab();
}
function testKey(key, expectedTab) {
sendAccelKey(key);
assertTab(expectedTab);
}
function testIndex(index, expectedTab) {
gBrowser.selectTabAtIndex(index);
assertTab(expectedTab);
}
// Create fewer tabs than our 9 number keys.
is(gBrowser.tabs.length, 1, "should have 1 tab");
createTabs(4);
is(gBrowser.tabs.length, 5, "should have 5 tabs");
// Test keyboard shortcuts. Order tests so that no two test cases have the
// same expected tab in a row. This ensures that tab selection actually
// changed the selected tab.
testKey(8, 4);
testKey(1, 0);
testKey(2, 1);
testKey(4, 3);
testKey(9, 4);
// Test index selection.
testIndex(0, 0);
testIndex(4, 4);
testIndex(-5, 0);
testIndex(5, 4);
testIndex(-4, 1);
testIndex(1, 1);
testIndex(-1, 4);
testIndex(9, 4);
// Create more tabs than our 9 number keys.
createTabs(10);
is(gBrowser.tabs.length, 15, "should have 15 tabs");
// Test keyboard shortcuts.
testKey(2, 1);
testKey(1, 0);
testKey(4, 3);
testKey(8, 7);
testKey(9, 14);
// Test index selection.
testIndex(-15, 0);
testIndex(14, 14);
testIndex(-14, 1);
testIndex(15, 14);
testIndex(-1, 14);
testIndex(0, 0);
testIndex(1, 1);
testIndex(9, 9);
// Clean up tabs.
for (let n = 15; n > 1; n--)
gBrowser.removeTab(gBrowser.selectedTab, {skipPermitUnload: true});
is(gBrowser.tabs.length, 1, "should have 1 tab");
}

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

@ -2,6 +2,8 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
add_task(function* () {
// There should be one tab when we start the test
let [origTab] = gBrowser.visibleTabs;
@ -33,16 +35,18 @@ add_task(function* () {
is(visible[1], testTab, "next is the test tab");
is(gBrowser.tabs.length, 3, "3 tabs should still be open");
gBrowser.selectTabAtIndex(0);
is(gBrowser.selectedTab, pinned, "first tab is pinned");
gBrowser.selectTabAtIndex(1);
is(gBrowser.selectedTab, testTab, "second tab is the test tab");
gBrowser.selectTabAtIndex(0);
is(gBrowser.selectedTab, pinned, "first tab is pinned");
gBrowser.selectTabAtIndex(2);
is(gBrowser.selectedTab, testTab, "no third tab, so no change");
gBrowser.selectTabAtIndex(0);
is(gBrowser.selectedTab, pinned, "switch back to the pinned");
gBrowser.selectTabAtIndex(2);
is(gBrowser.selectedTab, pinned, "no third tab, so no change");
is(gBrowser.selectedTab, testTab, "no third tab, so select last tab");
gBrowser.selectTabAtIndex(-2);
is(gBrowser.selectedTab, pinned, "pinned tab is second from left (when orig tab is hidden)");
gBrowser.selectTabAtIndex(-1);
is(gBrowser.selectedTab, testTab, "last tab is the test tab");
@ -91,4 +95,3 @@ add_task(function* () {
is(gBrowser.selectedTab, origTab, "got the orig tab");
is(origTab.hidden, false, "and it's not hidden -- visible!");
});

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

@ -422,12 +422,13 @@ function createUserContextMenu(event, addCommandAttribute = true) {
menuitem.setAttribute("usercontextid", identity.userContextId);
menuitem.setAttribute("label", bundle.getString(identity.label));
menuitem.setAttribute("accesskey", bundle.getString(identity.accessKey));
menuitem.classList.add("menuitem-iconic");
if (addCommandAttribute) {
menuitem.setAttribute("command", "Browser:NewUserContextTab");
}
menuitem.style.listStyleImage = "url(" + identity.icon + ")";
menuitem.setAttribute("image", identity.icon);
docfrag.appendChild(menuitem);
});

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

@ -33,6 +33,11 @@ const NOTIFY_TAB_RESTORED = "sessionstore-debug-tab-restored"; // WARNING: debug
// the browser.sessionstore.max_concurrent_tabs pref.
const MAX_CONCURRENT_TAB_RESTORES = 3;
// Amount (in CSS px) by which we allow window edges to be off-screen
// when restoring a window, before we override the saved position to
// pull the window back within the available screen area.
const SCREEN_EDGE_SLOP = 8;
// global notifications observed
const OBSERVING = [
"browser-window-before-show", "domwindowclosed",
@ -2165,7 +2170,7 @@ var SessionStoreInternal = {
// create a new tab
let tabbrowser = aWindow.gBrowser;
let tab = tabbrowser.selectedTab = tabbrowser.addTab();
let tab = tabbrowser.selectedTab = tabbrowser.addTab(null, state);
// restore tab content
this.restoreTab(tab, state);
@ -2923,12 +2928,26 @@ var SessionStoreInternal = {
let numVisibleTabs = 0;
for (var t = 0; t < newTabCount; t++) {
tabs.push(t < openTabCount ?
tabbrowser.tabs[t] :
tabbrowser.addTab("about:blank", {
skipAnimation: true,
forceNotRemote: true,
}));
// When trying to restore into existing tab, we also take the userContextId
// into account if present.
let userContextId = winData.tabs[t].userContextId;
let reuseExisting = t < openTabCount &&
(tabbrowser.tabs[t].getAttribute("usercontextid") == (userContextId || ""));
let tab = reuseExisting ? tabbrowser.tabs[t] :
tabbrowser.addTab("about:blank",
{skipAnimation: true,
forceNotRemote: true,
userContextId});
// If we inserted a new tab because the userContextId didn't match with the
// open tab, even though `t < openTabCount`, we need to remove that open tab
// and put the newly added tab in its place.
if (!reuseExisting && t < openTabCount) {
tabbrowser.removeTab(tabbrowser.tabs[t]);
tabbrowser.moveTabTo(tab, t);
}
tabs.push(tab);
if (winData.tabs[t].pinned)
tabbrowser.pinTab(tabs[t]);
@ -3471,26 +3490,40 @@ var SessionStoreInternal = {
// convert screen's device pixel dimensions to CSS px dimensions
screen.GetAvailRect(screenLeft, screenTop, screenWidth, screenHeight);
let cssToDevScale = screen.defaultCSSScaleFactor;
let screenWidthCss = screenWidth.value / cssToDevScale;
let screenHeightCss = screenHeight.value / cssToDevScale;
// constrain the dimensions to the actual space available
if (aWidth > screenWidthCss) {
aWidth = screenWidthCss;
}
if (aHeight > screenHeightCss) {
aHeight = screenHeightCss;
}
// and then pull the window within the screen's bounds
if (aLeft < screenLeftCss) {
let screenRightCss = screenLeftCss + screenWidth.value / cssToDevScale;
let screenBottomCss = screenTopCss + screenHeight.value / cssToDevScale;
// Pull the window within the screen's bounds (allowing a little slop
// for windows that may be deliberately placed with their border off-screen
// as when Win10 "snaps" a window to the left/right edge -- bug 1276516).
// First, ensure the left edge is large enough...
if (aLeft < screenLeftCss - SCREEN_EDGE_SLOP) {
aLeft = screenLeftCss;
} else if (aLeft + aWidth > screenLeftCss + screenWidthCss) {
aLeft = screenLeftCss + screenWidthCss - aWidth;
}
if (aTop < screenTopCss) {
// Then check the resulting right edge, and reduce it if necessary.
let right = aLeft + aWidth;
if (right > screenRightCss + SCREEN_EDGE_SLOP) {
right = screenRightCss;
// See if we can move the left edge leftwards to maintain width.
if (aLeft > screenLeftCss) {
aLeft = Math.max(right - aWidth, screenLeftCss);
}
}
// Finally, update aWidth to account for the adjusted left and right edges.
aWidth = right - aLeft;
// And do the same in the vertical dimension.
if (aTop < screenTopCss - SCREEN_EDGE_SLOP) {
aTop = screenTopCss;
} else if (aTop + aHeight > screenTopCss + screenHeightCss) {
aTop = screenTopCss + screenHeightCss - aHeight;
}
let bottom = aTop + aHeight;
if (bottom > screenBottomCss + SCREEN_EDGE_SLOP) {
bottom = screenBottomCss;
if (aTop > screenTopCss) {
aTop = Math.max(bottom - aHeight, screenTopCss);
}
}
aHeight = bottom - aTop;
}
// only modify those aspects which aren't correct yet

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

@ -2,9 +2,11 @@
* 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/. */
requestLongerTimeout(3);
add_task(function* () {
for (let i = 0; i < 3; ++i) {
let tab = gBrowser.addTab("http://example.com/", {userContextId: i});
let tab = gBrowser.addTab("http://example.com/", { userContextId: i });
let browser = tab.linkedBrowser;
yield promiseBrowserLoaded(browser);
@ -26,7 +28,7 @@ add_task(function* () {
});
add_task(function* () {
let tab = gBrowser.addTab("http://example.com/", {userContextId: 1});
let tab = gBrowser.addTab("http://example.com/", { userContextId: 1 });
let browser = tab.linkedBrowser;
yield promiseBrowserLoaded(browser);
@ -37,7 +39,7 @@ add_task(function* () {
let browser2 = tab2.linkedBrowser;
yield promiseTabRestored(tab2)
yield ContentTask.spawn(browser2, { expectedId: 1}, function* (args) {
yield ContentTask.spawn(browser2, { expectedId: 1 }, function* (args) {
Assert.equal(docShell.getOriginAttributes().userContextId,
args.expectedId,
"The docShell has the correct userContextId");
@ -47,3 +49,138 @@ add_task(function* () {
yield promiseRemoveTab(tab2);
});
add_task(function* () {
let tab = gBrowser.addTab("http://example.com/", { userContextId: 1 });
let browser = tab.linkedBrowser;
yield promiseBrowserLoaded(browser);
gBrowser.removeTab(tab);
let tab2 = ss.undoCloseTab(window, 0);
Assert.equal(tab2.getAttribute("usercontextid"), 1);
yield promiseTabRestored(tab2);
yield ContentTask.spawn(tab2.linkedBrowser, { expectedId: 1 }, function* (args) {
Assert.equal(docShell.getOriginAttributes().userContextId,
args.expectedId,
"The docShell has the correct userContextId");
});
yield promiseRemoveTab(tab2);
});
add_task(function* () {
let win = window.openDialog(location, "_blank", "chrome,all,dialog=no");
yield promiseWindowLoaded(win);
// Create 4 tabs with different userContextId.
for (let userContextId = 1; userContextId < 5; userContextId++) {
let tab = win.gBrowser.addTab("http://example.com/", {userContextId});
yield promiseBrowserLoaded(tab.linkedBrowser);
yield TabStateFlusher.flush(tab.linkedBrowser);
}
// Move the default tab of window to the end.
// We want the 1st tab to have non-default userContextId, so later when we
// restore into win2 we can test restore into an existing tab with different
// userContextId.
win.gBrowser.moveTabTo(win.gBrowser.tabs[0], win.gBrowser.tabs.length - 1);
let winState = JSON.parse(ss.getWindowState(win));
for (let i = 0; i < 4; i++) {
Assert.equal(winState.windows[0].tabs[i].userContextId, i + 1,
"1st Window: tabs[" + i + "].userContextId should exist.");
}
let win2 = window.openDialog(location, "_blank", "chrome,all,dialog=no");
yield promiseWindowLoaded(win2);
// Create tabs with different userContextId, but this time we create them with
// fewer tabs and with different order with win.
for (let userContextId = 3; userContextId > 0; userContextId--) {
let tab = win2.gBrowser.addTab("http://example.com/", {userContextId});
yield promiseBrowserLoaded(tab.linkedBrowser);
yield TabStateFlusher.flush(tab.linkedBrowser);
}
ss.setWindowState(win2, JSON.stringify(winState), true);
for (let i = 0; i < 4; i++) {
let browser = win2.gBrowser.tabs[i].linkedBrowser;
yield ContentTask.spawn(browser, { expectedId: i + 1 }, function* (args) {
Assert.equal(docShell.getOriginAttributes().userContextId,
args.expectedId,
"The docShell has the correct userContextId");
Assert.equal(content.document.nodePrincipal.originAttributes.userContextId,
args.expectedId,
"The document has the correct userContextId");
});
}
// Test the last tab, which doesn't have userContextId.
let browser = win2.gBrowser.tabs[4].linkedBrowser;
yield ContentTask.spawn(browser, { expectedId: 0 }, function* (args) {
Assert.equal(docShell.getOriginAttributes().userContextId,
args.expectedId,
"The docShell has the correct userContextId");
Assert.equal(content.document.nodePrincipal.originAttributes.userContextId,
args.expectedId,
"The document has the correct userContextId");
});
yield BrowserTestUtils.closeWindow(win);
yield BrowserTestUtils.closeWindow(win2);
});
add_task(function* () {
let win = window.openDialog(location, "_blank", "chrome,all,dialog=no");
yield promiseWindowLoaded(win);
let tab = win.gBrowser.addTab("http://example.com/", { userContextId: 1 });
yield promiseBrowserLoaded(tab.linkedBrowser);
yield TabStateFlusher.flush(tab.linkedBrowser);
// win should have 1 default tab, and 1 container tab.
Assert.equal(win.gBrowser.tabs.length, 2, "win should have 2 tabs");
let winState = JSON.parse(ss.getWindowState(win));
for (let i = 0; i < 2; i++) {
Assert.equal(winState.windows[0].tabs[i].userContextId, i,
"1st Window: tabs[" + i + "].userContextId should be " + i);
}
let win2 = window.openDialog(location, "_blank", "chrome,all,dialog=no");
yield promiseWindowLoaded(win2);
let tab2 = win2.gBrowser.addTab("http://example.com/", { userContextId : 1 });
yield promiseBrowserLoaded(tab2.linkedBrowser);
yield TabStateFlusher.flush(tab2.linkedBrowser);
// Move the first normal tab to end, so the first tab of win2 will be a
// container tab.
win2.gBrowser.moveTabTo(win2.gBrowser.tabs[0], win2.gBrowser.tabs.length - 1);
yield TabStateFlusher.flush(win2.gBrowser.tabs[0].linkedBrowser);
ss.setWindowState(win2, JSON.stringify(winState), true);
for (let i = 0; i < 2; i++) {
let browser = win2.gBrowser.tabs[i].linkedBrowser;
yield ContentTask.spawn(browser, { expectedId: i }, function* (args) {
Assert.equal(docShell.getOriginAttributes().userContextId,
args.expectedId,
"The docShell has the correct userContextId");
Assert.equal(content.document.nodePrincipal.originAttributes.userContextId,
args.expectedId,
"The document has the correct userContextId");
});
}
yield BrowserTestUtils.closeWindow(win);
yield BrowserTestUtils.closeWindow(win2);
});

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

@ -160,12 +160,10 @@ function makeContentReadable(obj, window) {
return Cu.cloneInto(obj, window);
}
function createNewChannel(uri, node, principal) {
function createNewChannel(uri) {
return NetUtil.newChannel({
uri: uri,
loadingNode: node,
loadingPrincipal: principal,
contentPolicyType: Ci.nsIContentPolicy.TYPE_OTHER,
loadUsingSystemPrincipal: true
});
}
@ -266,7 +264,7 @@ ChromeActions.prototype = {
getService(Ci.nsIExternalHelperAppService);
var docIsPrivate = this.isInPrivateBrowsing();
var netChannel = createNewChannel(blobUri, this.domWindow.document, null);
var netChannel = createNewChannel(blobUri);
if ('nsIPrivateBrowsingChannel' in Ci &&
netChannel instanceof Ci.nsIPrivateBrowsingChannel) {
netChannel.setPrivate(docIsPrivate);
@ -293,6 +291,7 @@ ChromeActions.prototype = {
}
} catch (e) {}
channel.setURI(originalUri);
channel.loadInfo = netChannel.loadInfo;
channel.contentStream = aInputStream;
if ('nsIPrivateBrowsingChannel' in Ci &&
channel instanceof Ci.nsIPrivateBrowsingChannel) {
@ -328,7 +327,7 @@ ChromeActions.prototype = {
}
};
channel.asyncOpen(listener, null);
channel.asyncOpen2(listener);
});
},
getLocale: function() {
@ -973,8 +972,7 @@ PdfStreamConverter.prototype = {
.createInstance(Ci.nsIBinaryInputStream);
// Create a new channel that is viewer loaded as a resource.
var systemPrincipal = Services.scriptSecurityManager.getSystemPrincipal();
var channel = createNewChannel(PDF_VIEWER_WEB_PAGE, null, systemPrincipal);
var channel = createNewChannel(PDF_VIEWER_WEB_PAGE);
var listener = this.listener;
var dataListener = this.dataListener;
@ -984,10 +982,11 @@ PdfStreamConverter.prototype = {
// trigger an assertion.
var proxy = {
onStartRequest: function(request, context) {
listener.onStartRequest(aRequest, context);
listener.onStartRequest(aRequest, aContext);
},
onDataAvailable: function(request, context, inputStream, offset, count) {
listener.onDataAvailable(aRequest, context, inputStream, offset, count);
listener.onDataAvailable(aRequest, aContext, inputStream,
offset, count);
},
onStopRequest: function(request, context, statusCode) {
// We get the DOM window here instead of before the request since it
@ -1010,7 +1009,7 @@ PdfStreamConverter.prototype = {
var findEventManager = new FindEventManager(domWindow);
findEventManager.bind();
}
listener.onStopRequest(aRequest, context, statusCode);
listener.onStopRequest(aRequest, aContext, statusCode);
if (domWindow.frameElement) {
var isObjectEmbed = domWindow.frameElement.tagName !== 'IFRAME' ||
@ -1036,7 +1035,7 @@ PdfStreamConverter.prototype = {
var resourcePrincipal;
resourcePrincipal = ssm.createCodebasePrincipal(uri, attrs);
aRequest.owner = resourcePrincipal;
channel.asyncOpen(proxy, aContext);
channel.asyncOpen2(proxy);
},
// nsIRequestObserver::onStopRequest

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

@ -53,8 +53,6 @@ PluginContent.prototype = {
global.addMessageListener("BrowserPlugins:NPAPIPluginProcessCrashed", this);
global.addMessageListener("BrowserPlugins:CrashReportSubmitted", this);
global.addMessageListener("BrowserPlugins:Test:ClearCrashData", this);
Services.obs.addObserver(this, "Plugin::HiddenPluginTouched", false);
},
uninit: function() {
@ -77,8 +75,6 @@ PluginContent.prototype = {
global.removeMessageListener("BrowserPlugins:Test:ClearCrashData", this);
delete this.global;
delete this.content;
Services.obs.removeObserver(this, "Plugin::HiddenPluginTouched");
},
receiveMessage: function (msg) {
@ -120,15 +116,6 @@ PluginContent.prototype = {
}
},
observe: function observe(aSubject, aTopic, aData) {
let pluginTag = aSubject;
if (aTopic == "Plugin::HiddenPluginTouched") {
this._showClickToPlayNotification(pluginTag, false);
} else {
Cu.reportError("unknown topic observed: " + aTopic);
}
},
onPageShow: function (event) {
// Ignore events that aren't from the main document.
if (!this.content || event.target != this.content.document) {
@ -207,45 +194,6 @@ PluginContent.prototype = {
};
},
_getPluginInfoForTag: function (pluginTag, tagMimetype, fallbackType) {
let pluginHost = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
let pluginName = gNavigatorBundle.GetStringFromName("pluginInfo.unknownPlugin");
let permissionString = null;
let blocklistState = null;
if (pluginTag) {
pluginName = BrowserUtils.makeNicePluginName(pluginTag.name);
permissionString = pluginHost.getPermissionStringForTag(pluginTag);
blocklistState = pluginTag.blocklistState;
// Convert this from nsIPluginTag so it can be serialized.
let properties = ["name", "description", "filename", "version", "enabledState", "niceName"];
let pluginTagCopy = {};
for (let prop of properties) {
pluginTagCopy[prop] = pluginTag[prop];
}
pluginTag = pluginTagCopy;
// Make state-softblocked == state-notblocked for our purposes,
// they have the same UI. STATE_OUTDATED should not exist for plugin
// items, but let's alias it anyway, just in case.
if (blocklistState == Ci.nsIBlocklistService.STATE_SOFTBLOCKED ||
blocklistState == Ci.nsIBlocklistService.STATE_OUTDATED) {
blocklistState = Ci.nsIBlocklistService.STATE_NOT_BLOCKED;
}
}
return { mimetype: tagMimetype,
pluginName: pluginName,
pluginTag: pluginTag,
permissionString: permissionString,
fallbackType: fallbackType,
blocklistState: blocklistState,
};
},
/**
* Update the visibility of the plugin overlay.
*/

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

@ -1960,3 +1960,7 @@ notification.pluginVulnerable > .notification-inner > .messageCloseButton:not(:h
padding: 0;
overflow: hidden;
}
.menuitem-iconic[command="Browser:NewUserContextTab"] > .menu-iconic-left > .menu-iconic-icon {
visibility: visible;
}

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

@ -186,6 +186,42 @@ public:
return true;
}
bool Overlaps(const OriginAttributesPattern& aOther) const
{
if (mAppId.WasPassed() && aOther.mAppId.WasPassed() &&
mAppId.Value() != aOther.mAppId.Value()) {
return false;
}
if (mInIsolatedMozBrowser.WasPassed() &&
aOther.mInIsolatedMozBrowser.WasPassed() &&
mInIsolatedMozBrowser.Value() != aOther.mInIsolatedMozBrowser.Value()) {
return false;
}
if (mAddonId.WasPassed() && aOther.mAddonId.WasPassed() &&
mAddonId.Value() != aOther.mAddonId.Value()) {
return false;
}
if (mUserContextId.WasPassed() && aOther.mUserContextId.WasPassed() &&
mUserContextId.Value() != aOther.mUserContextId.Value()) {
return false;
}
if (mSignedPkg.WasPassed() && aOther.mSignedPkg.WasPassed() &&
mSignedPkg.Value() != aOther.mSignedPkg.Value()) {
return false;
}
if (mPrivateBrowsingId.WasPassed() && aOther.mPrivateBrowsingId.WasPassed() &&
mPrivateBrowsingId.Value() != aOther.mPrivateBrowsingId.Value()) {
return false;
}
return true;
}
};
/*

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

@ -169,8 +169,7 @@ devtools.jar:
skin/images/filetypes/dir-open.svg (themes/images/filetypes/dir-open.svg)
skin/images/filetypes/globe.svg (themes/images/filetypes/globe.svg)
skin/images/filetypes/store.svg (themes/images/filetypes/store.svg)
skin/images/commandline-icon.png (themes/images/commandline-icon.png)
skin/images/commandline-icon@2x.png (themes/images/commandline-icon@2x.png)
skin/images/commandline-icon.svg (themes/images/commandline-icon.svg)
skin/images/alerticon-warning.png (themes/images/alerticon-warning.png)
skin/images/alerticon-warning@2x.png (themes/images/alerticon-warning@2x.png)
skin/rules.css (themes/rules.css)

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

@ -17,6 +17,8 @@
--gcli-border-color: #dde1e4; /* --theme-splitter-color */
--selection-background: #4c9ed9; /* --theme-selection-background */
--selection-color: #f5f7fa; /* --theme-selection-color */
--command-line-image: url(chrome://devtools/skin/images/commandline-icon.svg#light-theme); /* --theme-command-line-image */
--command-line-image-focus: url(chrome://devtools/skin/images/commandline-icon.svg#light-theme-focus); /* --theme-command-line-image-focus */
}
:root[devtoolstheme="dark"] #developer-toolbar {
@ -27,6 +29,8 @@
--gcli-border-color: #454d5d; /* --theme-splitter-color */
--selection-background: #5675b9; /* --theme-selection-background */
--selection-color: #f5f7fa; /* --theme-selection-color */
--command-line-image: url(chrome://devtools/skin/images/commandline-icon.svg#dark-theme); /* --theme-command-line-image */
--command-line-image-focus: url(chrome://devtools/skin/images/commandline-icon.svg#dark-theme-focus); /* --theme-command-line-image-focus */
}
#developer-toolbar {
@ -160,19 +164,11 @@ html|*#gcli-output-frame {
width: 16px;
height: 16px;
margin: 0 2px;
background-image: url("chrome://devtools/skin/images/commandline-icon.png");
background-position: 0 center;
background-size: 32px 16px;
background-image: var(--command-line-image);
}
.gclitoolbar-input-node[focused="true"]::before {
background-position: -16px center;
}
@media (min-resolution: 1.1dppx) {
.gclitoolbar-input-node::before {
background-image: url("chrome://devtools/skin/images/commandline-icon@2x.png");
}
background-image: var(--command-line-image-focus);
}
.gclitoolbar-input-node > .textbox-input-box > html|*.textbox-input::-moz-selection {

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

@ -350,21 +350,12 @@
}
.dbg-expression-arrow {
background-image: url(images/commandline-icon.png);
background-position: -16px 0;
background-repeat: no-repeat;
background-size: 32px 16px;
background-image: var(--theme-command-line-image-focus);
width: 16px;
height: 16px;
margin: 2px;
}
@media (min-resolution: 1.1dppx) {
.dbg-expression-arrow {
background-image: url(images/commandline-icon@2x.png);
}
}
.dbg-expression-input {
color: inherit;
}

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 254 B

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

@ -0,0 +1,42 @@
<!-- 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/. -->
<svg width="16px" height="16px" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<defs>
<style>
g {
display: none;
}
#light-theme:target,
#light-theme-focus:target ~ #light-theme,
#dark-theme:target,
#dark-theme-focus:target ~ #dark-theme {
display: inline;
}
#light-theme-focus:target ~ #light-theme {
fill: #4A90E2;
}
#dark-theme-focus:target ~ #dark-theme {
fill: #00FF7F;
}
/* Unfocused states */
#light-theme,
#dark-theme {
fill: rgba(128, 128, 128, .5);
}
</style>
</defs>
<g id="light-theme-focus"/>
<g id="light-theme">
<path d="M7.29 13.907l7-5a.5.5 0 0 0 .033-.789l-6.5-5.5a.5.5 0 1 0-.646.764l6.5 5.5.032-.789-7 5a.5.5 0 1 0 .582.814z"/>
<path d="M2.29 13.907l7-5a.5.5 0 0 0 .033-.789l-6.5-5.5a.5.5 0 1 0-.646.764l6.5 5.5.032-.789-7 5a.5.5 0 1 0 .582.814z"/>
</g>
<g id="dark-theme-focus"/>
<g id="dark-theme">
<path d="M7.29 13.907l7-5a.5.5 0 0 0 .033-.789l-6.5-5.5a.5.5 0 1 0-.646.764l6.5 5.5.032-.789-7 5a.5.5 0 1 0 .582.814z"/>
<path d="M2.29 13.907l7-5a.5.5 0 0 0 .033-.789l-6.5-5.5a.5.5 0 1 0-.646.764l6.5 5.5.032-.789-7 5a.5.5 0 1 0 .582.814z"/>
</g>
</svg>

После

Ширина:  |  Высота:  |  Размер: 1.4 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 586 B

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

@ -3,6 +3,14 @@
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="14" height="14">
<defs>
<style>
path {
opacity: 0.5;
}
path:target {
opacity: 1;
}
</style>
<linearGradient id="b">
<stop offset="0" stop-color="#234ccd"/>
<stop offset="1" stop-color="#5d7de3"/>
@ -14,5 +22,5 @@
<linearGradient x1="2.002" y1="12.252" x2="-.099" y2="6.755" id="d" xlink:href="#a" gradientUnits="userSpaceOnUse" gradientTransform="translate(5.841 1034.646)"/>
<linearGradient x1="3.309" y1="11.177" x2="1.468" y2="6.456" id="c" xlink:href="#b" gradientUnits="userSpaceOnUse" gradientTransform="translate(5.841 1034.646)"/>
</defs>
<path d="M6.841 1040.052l-.437.406 2.469 3.688-2.47 3.687.438.407 3.438-4.094z" fill="url(#c)" stroke="url(#d)" stroke-width=".4" stroke-linecap="round" stroke-linejoin="round" transform="translate(-1.341 -1037.146)"/>
<path id="focus" d="M6.841 1040.052l-.437.406 2.469 3.688-2.47 3.687.438.407 3.438-4.094z" fill="url(#c)" stroke="url(#d)" stroke-width=".4" stroke-linecap="round" stroke-linejoin="round" transform="translate(-1.341 -1037.146)"/>
</svg>

До

Ширина:  |  Высота:  |  Размер: 1.2 KiB

После

Ширина:  |  Высота:  |  Размер: 1.3 KiB

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

@ -68,6 +68,10 @@
--theme-tooltip-border: #d9e1e8;
--theme-tooltip-background: rgba(255, 255, 255, .9);
--theme-tooltip-shadow: rgba(155, 155, 155, 0.26);
/* Command line */
--theme-command-line-image: url(chrome://devtools/skin/images/commandline-icon.svg#light-theme);
--theme-command-line-image-focus: url(chrome://devtools/skin/images/commandline-icon.svg#light-theme-focus);
}
:root.theme-dark {
@ -124,6 +128,10 @@
--theme-tooltip-border: #434850;
--theme-tooltip-background: rgba(19, 28, 38, .9);
--theme-tooltip-shadow: rgba(25, 25, 25, 0.76);
/* Command line */
--theme-command-line-image: url(chrome://devtools/skin/images/commandline-icon.svg#dark-theme);
--theme-command-line-image-focus: url(chrome://devtools/skin/images/commandline-icon.svg#dark-theme-focus);
}
:root.theme-firebug {
@ -178,6 +186,10 @@
--theme-header-background: #F0F0F0 linear-gradient(to top,
rgba(0, 0, 0, 0.1),
transparent) repeat-x;
/* Command line */
--theme-command-line-image: url(chrome://devtools/skin/images/firebug/commandline-icon.svg);
--theme-command-line-image-focus: url(chrome://devtools/skin/images/firebug/commandline-icon.svg#focus);
}
:root {
@ -188,6 +200,4 @@
* should improve keyboard navigation usability. */
--theme-focus-outline: 1px dotted var(--theme-focus-outline-color);
--theme-focus-box-shadow-textbox: 0 0 0 1px var(--theme-textbox-box-shadow);
--theme-focus-box-shadow-inset-bottom: 0 -2px 1px var(--theme-textbox-box-shadow) inset,
0px -2px var(--theme-highlight-blue) inset;
}

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

@ -3,21 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* Webconsole specific theme variables */
.theme-dark {
--command-line-image: -moz-image-rect(url("chrome://devtools/skin/images/commandline-icon.png"), 0, 32, 16, 16);
--command-line-image-2x: -moz-image-rect(url('chrome://devtools/skin/images/commandline-icon@2x.png'), 0, 64, 32, 32);
}
.theme-light {
--command-line-image: -moz-image-rect(url("chrome://devtools/skin/images/commandline-icon.png"), 0, 32, 16, 16);
--command-line-image-2x: -moz-image-rect(url('chrome://devtools/skin/images/commandline-icon@2x.png'), 0, 64, 32, 32);
}
.theme-firebug {
--command-line-image: url(chrome://devtools/skin/images/firebug/commandline-icon.svg);
--command-line-image-2x: url(chrome://devtools/skin/images/firebug/commandline-icon.svg);
--error-color: #FF0000;
--error-background-color: #FFEBEB;
--warning-background-color: #FFFFC8;
@ -414,9 +400,7 @@ a {
}
.jsterm-input-node[focused="true"] {
outline: var(--theme-focus-outline);
outline-offset: -1px;
transition: none;
background-image: var(--theme-command-line-image-focus);
box-shadow: none;
}
@ -428,19 +412,13 @@ a {
/* Always allow scrolling on input - it auto expands in js by setting height,
but don't want it to get bigger than the window. 24px = toolbar height. */
max-height: calc(90vh - 24px);
background-image: var(--command-line-image);
background-image: var(--theme-command-line-image);
background-repeat: no-repeat;
background-size: 16px 16px;
background-position: 4px 50%;
color: var(--theme-content-color1);
}
@media (min-resolution: 1.1dppx) {
.jsterm-input-node {
background-image: var(--command-line-image-2x);
}
}
:-moz-any(.jsterm-input-node,
.jsterm-complete-node) > .textbox-input-box > .textbox-textarea {
overflow-x: hidden;

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

@ -141,6 +141,7 @@ support-files =
test_bug1092055_shouldwarn.js^headers^
test_bug1092055_shouldwarn.js
test_bug1092055_shouldwarn.html
test_bug_1247459_violation.html
!/devtools/client/framework/test/shared-head.js
!/devtools/client/netmonitor/test/sjs_cors-test-server.sjs
!/image/test/mochitest/blue.png
@ -295,6 +296,8 @@ skip-if = os != "mac"
skip-if = e10s # Bug 1042253 - webconsole e10s tests (Linux debug intermittent)
[browser_webconsole_bug_1010953_cspro.js]
skip-if = e10s && (os == 'win' || os == 'mac') # Bug 1243967
[browser_webconsole_bug_1247459_violation.js]
skip-if = e10s && (os == 'win') # Bug 1264955
[browser_webconsole_certificate_messages.js]
skip-if = e10s # Bug 1042253 - webconsole tests disabled with e10s
[browser_webconsole_show_subresource_security_errors.js]

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

@ -0,0 +1,40 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
// Tests that the Web Console CSP messages for two META policies
// are correctly displayed.
"use strict";
const TEST_URI = "data:text/html;charset=utf8,Web Console CSP violation test";
const TEST_VIOLATION = "https://example.com/browser/devtools/client/" +
"webconsole/test/test_bug_1247459_violation.html";
const CSP_VIOLATION_MSG = "Content Security Policy: The page\u2019s settings " +
"blocked the loading of a resource at " +
"http://some.example.com/test.png (\u201cimg-src " +
"https://example.com\u201d).";
add_task(function* () {
let { browser } = yield loadTab(TEST_URI);
let hud = yield openConsole();
hud.jsterm.clearOutput();
let loaded = loadBrowser(browser);
BrowserTestUtils.loadURI(browser, TEST_VIOLATION);
yield loaded;
yield waitForMessages({
webconsole: hud,
messages: [
{
name: "CSP policy URI warning displayed successfully",
text: CSP_VIOLATION_MSG,
repeats: 2
}
]
});
});

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

@ -13,7 +13,7 @@ const TEST_VIOLATION = "https://example.com/browser/devtools/client/" +
const CSP_VIOLATION_MSG = "Content Security Policy: The page\u2019s settings " +
"blocked the loading of a resource at " +
"http://some.example.com/test.png (\u201cdefault-src " +
"https://example.com\u201d).";
"https://example.com\u201d).";
add_task(function* () {
let { browser } = yield loadTab(TEST_URI);

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

@ -0,0 +1,15 @@
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Security-Policy" content="img-src https://example.com"></meta>
<meta http-equiv="Content-Security-Policy" content="img-src https://example.com"></meta>
<meta charset="UTF-8">
<title>Test for Bug 1247459 - policy violations for header and META are displayed separately</title>
<!-- Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ -->
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1247459">Mozilla Bug 1247459</a>
<img src="http://some.example.com/test.png">
</body>
</html>

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

@ -9,15 +9,51 @@
"use strict";
const baseURL = "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/";
const ErrorDocs = {
JSMSG_READ_ONLY: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Read-only",
JSMSG_BAD_ARRAY_LENGTH: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Invalid_array_length",
JSMSG_NEGATIVE_REPETITION_COUNT: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Negative_repetition_count",
JSMSG_RESULTING_STRING_TOO_LARGE: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Resulting_string_too_large",
JSMSG_BAD_RADIX: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Bad_radix",
JSMSG_PRECISION_RANGE: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Precision_range",
JSMSG_BAD_FORMAL: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Malformed_formal_parameter",
JSMSG_STMT_AFTER_RETURN: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Stmt_after_return",
JSMSG_READ_ONLY: "Read-only",
JSMSG_BAD_ARRAY_LENGTH: "Invalid_array_length",
JSMSG_NEGATIVE_REPETITION_COUNT: "Negative_repetition_count",
JSMSG_RESULTING_STRING_TOO_LARGE: "Resulting_string_too_large",
JSMSG_BAD_RADIX: "Bad_radix",
JSMSG_PRECISION_RANGE: "Precision_range",
JSMSG_BAD_FORMAL: "Malformed_formal_parameter",
JSMSG_STMT_AFTER_RETURN: "Stmt_after_return",
JSMSG_NOT_A_CODEPOINT: "Not_a_codepoint",
JSMSG_BAD_SORT_ARG: "Array_sort_argument",
JSMSG_UNEXPECTED_TYPE: "Unexpected_type",
JSMSG_NOT_DEFINED: "Not_defined",
JSMSG_NOT_FUNCTION: "Not_a_function",
JSMSG_EQUAL_AS_ASSIGN: "Equal_as_assign",
JSMSG_UNDEFINED_PROP: "Undefined_prop",
JSMSG_DEPRECATED_PRAGMA: "Deprecated_source_map_pragma",
JSMSG_DEPRECATED_USAGE: "Deprecated_caller_or_arguments_usage",
JSMSG_CANT_DELETE: "Cant_delete",
JSMSG_VAR_HIDES_ARG: "Var_hides_argument",
JSMSG_JSON_BAD_PARSE: "JSON_bad_parse",
JSMSG_UNDECLARED_VAR: "Undeclared_var",
JSMSG_UNEXPECTED_TOKEN: "Unexpected_token",
JSMSG_BAD_OCTAL: "Bad_octal",
JSMSG_PROPERTY_ACCESS_DENIED: "Property_access_denied",
JSMSG_NO_PROPERTIES: "No_properties",
JSMSG_ALREADY_HAS_PRAGMA: "Already_has_pragma",
JSMSG_BAD_RETURN_OR_YIELD: "Bad_return_or_yield",
JSMSG_SEMI_BEFORE_STMNT: "Missing_semicolon_before_statement",
JSMSG_OVER_RECURSED: "Too_much_recursion",
JSMSG_BRACKET_AFTER_LIST: "Missing_bracket_after_list",
JSMSG_PAREN_AFTER_ARGS: "Missing_parenthesis_after_argument_list",
JSMSG_MORE_ARGS_NEEDED: "More_arguments_needed",
JSMSG_BAD_LEFTSIDE_OF_ASS: "Invalid_assignment_left-hand_side",
JSMSG_UNTERMINATED_STRING: "Unterminated_string_literal",
JSMSG_NOT_CONSTRUCTOR: "Not_a_constructor",
JSMSG_CURLY_AFTER_LIST: "Missing_curly_after_property_list",
};
exports.GetURL = (errorName) => ErrorDocs[errorName];
exports.GetURL = (errorName) => {
let doc = ErrorDocs[errorName];
if (doc) {
return baseURL + doc;
}
return undefined;
}

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

@ -325,7 +325,7 @@ WebConsoleActor.prototype =
// We are very explicitly examining the "console" property of
// the non-Xrayed object here.
let console = aWindow.wrappedJSObject.console;
isNative = console instanceof aWindow.Console;
isNative = new XPCNativeWrapper(console).IS_NATIVE_CONSOLE
}
catch (ex) { }
return isNative;

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

@ -589,6 +589,7 @@ private:
// State initialized during eInitial:
quota::PersistenceType mPersistence;
nsCString mSuffix;
nsCString mGroup;
nsCString mOrigin;
RefPtr<DirectoryLock> mDirectoryLock;
@ -685,8 +686,8 @@ ParentRunnable::InitOnMainThread()
return rv;
}
rv = QuotaManager::GetInfoFromPrincipal(principal, &mGroup, &mOrigin,
&mIsApp);
rv = QuotaManager::GetInfoFromPrincipal(principal, &mSuffix, &mGroup,
&mOrigin, &mIsApp);
NS_ENSURE_SUCCESS(rv, rv);
InitPersistenceType();
@ -727,8 +728,8 @@ ParentRunnable::ReadMetadata()
MOZ_ASSERT(qm, "We are on the QuotaManager's IO thread");
nsresult rv =
qm->EnsureOriginIsInitialized(mPersistence, mGroup, mOrigin, mIsApp,
getter_AddRefs(mDirectory));
qm->EnsureOriginIsInitialized(mPersistence, mSuffix, mGroup, mOrigin,
mIsApp, getter_AddRefs(mDirectory));
if (NS_WARN_IF(NS_FAILED(rv))) {
mResult = JS::AsmJSCache_StorageInitFailure;
return rv;

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

@ -24,6 +24,7 @@
#include "ScriptSettings.h"
#include "WorkerPrivate.h"
#include "WorkerRunnable.h"
#include "WorkerScope.h"
#include "xpcprivate.h"
#include "nsContentUtils.h"
#include "nsDocShell.h"
@ -832,7 +833,7 @@ private:
}
}
mConsole->ProfileMethod(aCx, mAction, arguments);
mConsole->ProfileMethodInternal(aCx, mAction, arguments);
}
virtual void
@ -857,7 +858,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Console)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindow)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mConsoleEventNotifier)
tmp->Shutdown();
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Console)
@ -875,14 +875,12 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(Console)
tmp->mCallDataStoragePending[i]->Trace(aCallbacks, aClosure);
}
NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(Console)
NS_IMPL_CYCLE_COLLECTING_RELEASE(Console)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Console)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRY(nsIObserver)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIObserver)
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
@ -1027,17 +1025,11 @@ Console::ClearStorage()
mCallDataStorage.Clear();
}
JSObject*
Console::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
{
return ConsoleBinding::Wrap(aCx, this, aGivenProto);
}
#define METHOD(name, string) \
void \
Console::name(JSContext* aCx, const Sequence<JS::Value>& aData) \
{ \
Method(aCx, Method##name, NS_LITERAL_STRING(string), aData); \
#define METHOD(name, string) \
/* static */ void \
Console::name(const GlobalObject& aGlobal, const Sequence<JS::Value>& aData) \
{ \
Method(aGlobal, Method##name, NS_LITERAL_STRING(string), aData); \
}
METHOD(Log, "log")
@ -1049,13 +1041,11 @@ METHOD(Debug, "debug")
METHOD(Table, "table")
METHOD(Clear, "clear")
void
Console::Trace(JSContext* aCx)
/* static */ void
Console::Trace(const GlobalObject& aGlobal)
{
AssertIsOnOwningThread();
const Sequence<JS::Value> data;
Method(aCx, MethodTrace, NS_LITERAL_STRING("trace"), data);
Method(aGlobal, MethodTrace, NS_LITERAL_STRING("trace"), data);
}
// Displays an interactive listing of all the properties of an object.
@ -1066,79 +1056,87 @@ METHOD(Group, "group")
METHOD(GroupCollapsed, "groupCollapsed")
METHOD(GroupEnd, "groupEnd")
void
Console::Time(JSContext* aCx, const JS::Handle<JS::Value> aTime)
/* static */ void
Console::Time(const GlobalObject& aGlobal, const JS::Handle<JS::Value> aTime)
{
AssertIsOnOwningThread();
JSContext* cx = aGlobal.Context();
Sequence<JS::Value> data;
SequenceRooter<JS::Value> rooter(aCx, &data);
SequenceRooter<JS::Value> rooter(cx, &data);
if (!aTime.isUndefined() && !data.AppendElement(aTime, fallible)) {
return;
}
Method(aCx, MethodTime, NS_LITERAL_STRING("time"), data);
Method(aGlobal, MethodTime, NS_LITERAL_STRING("time"), data);
}
void
Console::TimeEnd(JSContext* aCx, const JS::Handle<JS::Value> aTime)
/* static */ void
Console::TimeEnd(const GlobalObject& aGlobal, const JS::Handle<JS::Value> aTime)
{
AssertIsOnOwningThread();
JSContext* cx = aGlobal.Context();
Sequence<JS::Value> data;
SequenceRooter<JS::Value> rooter(aCx, &data);
SequenceRooter<JS::Value> rooter(cx, &data);
if (!aTime.isUndefined() && !data.AppendElement(aTime, fallible)) {
return;
}
Method(aCx, MethodTimeEnd, NS_LITERAL_STRING("timeEnd"), data);
Method(aGlobal, MethodTimeEnd, NS_LITERAL_STRING("timeEnd"), data);
}
void
Console::TimeStamp(JSContext* aCx, const JS::Handle<JS::Value> aData)
/* static */ void
Console::TimeStamp(const GlobalObject& aGlobal,
const JS::Handle<JS::Value> aData)
{
AssertIsOnOwningThread();
JSContext* cx = aGlobal.Context();
Sequence<JS::Value> data;
SequenceRooter<JS::Value> rooter(aCx, &data);
SequenceRooter<JS::Value> rooter(cx, &data);
if (aData.isString() && !data.AppendElement(aData, fallible)) {
return;
}
Method(aCx, MethodTimeStamp, NS_LITERAL_STRING("timeStamp"), data);
Method(aGlobal, MethodTimeStamp, NS_LITERAL_STRING("timeStamp"), data);
}
void
Console::Profile(JSContext* aCx, const Sequence<JS::Value>& aData)
/* static */ void
Console::Profile(const GlobalObject& aGlobal, const Sequence<JS::Value>& aData)
{
AssertIsOnOwningThread();
ProfileMethod(aCx, NS_LITERAL_STRING("profile"), aData);
ProfileMethod(aGlobal, NS_LITERAL_STRING("profile"), aData);
}
void
Console::ProfileEnd(JSContext* aCx, const Sequence<JS::Value>& aData)
/* static */ void
Console::ProfileEnd(const GlobalObject& aGlobal,
const Sequence<JS::Value>& aData)
{
AssertIsOnOwningThread();
ProfileMethod(aCx, NS_LITERAL_STRING("profileEnd"), aData);
ProfileMethod(aGlobal, NS_LITERAL_STRING("profileEnd"), aData);
}
void
Console::ProfileMethod(JSContext* aCx, const nsAString& aAction,
/* static */ void
Console::ProfileMethod(const GlobalObject& aGlobal, const nsAString& aAction,
const Sequence<JS::Value>& aData)
{
if (IsShuttingDown()) {
RefPtr<Console> console = GetConsole(aGlobal);
if (!console) {
return;
}
JSContext* cx = aGlobal.Context();
console->ProfileMethodInternal(cx, aAction, aData);
}
void
Console::ProfileMethodInternal(JSContext* aCx, const nsAString& aAction,
const Sequence<JS::Value>& aData)
{
if (!NS_IsMainThread()) {
// Here we are in a worker thread.
RefPtr<ConsoleProfileRunnable> runnable =
new ConsoleProfileRunnable(this, aAction, aData);
JS::Rooted<JSObject*> global(aCx, JS::CurrentGlobalOrNull(aCx));
runnable->Dispatch(aCx);
return;
}
@ -1184,28 +1182,25 @@ Console::ProfileMethod(JSContext* aCx, const nsAString& aAction,
}
}
void
Console::Assert(JSContext* aCx, bool aCondition,
/* static */ void
Console::Assert(const GlobalObject& aGlobal, bool aCondition,
const Sequence<JS::Value>& aData)
{
AssertIsOnOwningThread();
if (!aCondition) {
Method(aCx, MethodAssert, NS_LITERAL_STRING("assert"), aData);
Method(aGlobal, MethodAssert, NS_LITERAL_STRING("assert"), aData);
}
}
METHOD(Count, "count")
void
Console::NoopMethod()
/* static */ void
Console::NoopMethod(const GlobalObject& aGlobal)
{
AssertIsOnOwningThread();
// Nothing to do.
}
static
namespace {
nsresult
StackFrameToStackEntry(JSContext* aCx, nsIStackFrame* aStackFrame,
ConsoleStackEntry& aStackEntry)
@ -1241,7 +1236,6 @@ StackFrameToStackEntry(JSContext* aCx, nsIStackFrame* aStackFrame,
return NS_OK;
}
static
nsresult
ReifyStack(JSContext* aCx, nsIStackFrame* aStack,
nsTArray<ConsoleStackEntry>& aRefiedStack)
@ -1267,17 +1261,30 @@ ReifyStack(JSContext* aCx, nsIStackFrame* aStack,
return NS_OK;
}
} // anonymous namespace
// Queue a call to a console method. See the CALL_DELAY constant.
void
Console::Method(JSContext* aCx, MethodName aMethodName,
/* static */ void
Console::Method(const GlobalObject& aGlobal, MethodName aMethodName,
const nsAString& aMethodString,
const Sequence<JS::Value>& aData)
{
AssertIsOnOwningThread();
if (IsShuttingDown()) {
RefPtr<Console> console = GetConsole(aGlobal);
if (!console) {
return;
}
console->MethodInternal(aGlobal.Context(), aMethodName, aMethodString,
aData);
}
void
Console::MethodInternal(JSContext* aCx, MethodName aMethodName,
const nsAString& aMethodString,
const Sequence<JS::Value>& aData)
{
AssertIsOnOwningThread();
RefPtr<ConsoleCallData> callData(new ConsoleCallData());
ClearException ce(aCx);
@ -2416,5 +2423,71 @@ Console::IsShuttingDown() const
return mStatus == eShuttingDown;
}
/* static */ already_AddRefed<Console>
Console::GetConsole(const GlobalObject& aGlobal)
{
RefPtr<Console> console;
if (NS_IsMainThread()) {
nsCOMPtr<nsPIDOMWindowInner> innerWindow =
do_QueryInterface(aGlobal.GetAsSupports());
if (NS_WARN_IF(!innerWindow)) {
return nullptr;
}
nsGlobalWindow* window = nsGlobalWindow::Cast(innerWindow);
ErrorResult rv;
console = window->GetConsole(rv);
if (NS_WARN_IF(rv.Failed())) {
rv.SuppressException();
return nullptr;
}
} else {
JSContext* cx = aGlobal.Context();
WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(cx);
MOZ_ASSERT(workerPrivate);
nsCOMPtr<nsIGlobalObject> global =
do_QueryInterface(aGlobal.GetAsSupports());
if (NS_WARN_IF(!global)) {
return nullptr;
}
WorkerGlobalScope* scope = workerPrivate->GlobalScope();
MOZ_ASSERT(scope);
// Normal worker scope.
ErrorResult rv;
if (scope == global) {
console = scope->GetConsole(rv);
}
// Debugger worker scope
else {
WorkerDebuggerGlobalScope* debuggerScope =
workerPrivate->DebuggerGlobalScope();
MOZ_ASSERT(debuggerScope);
MOZ_ASSERT(debuggerScope == global, "Which kind of global do we have?");
console = debuggerScope->GetConsole(rv);
}
if (NS_WARN_IF(rv.Failed())) {
rv.SuppressException();
return nullptr;
}
}
MOZ_ASSERT(console);
console->AssertIsOnOwningThread();
if (console->IsShuttingDown()) {
return nullptr;
}
return console.forget();
}
} // namespace dom
} // namespace mozilla

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

@ -15,7 +15,6 @@
#include "nsHashKeys.h"
#include "nsIObserver.h"
#include "nsWeakReference.h"
#include "nsWrapperCache.h"
#include "nsDOMNavigationTiming.h"
#include "nsPIDOMWindow.h"
@ -33,7 +32,6 @@ class ConsoleProfileRunnable;
struct ConsoleStackEntry;
class Console final : public nsIObserver
, public nsWrapperCache
, public nsSupportsWeakReference
{
public:
@ -50,74 +48,72 @@ public:
return mWindow;
}
virtual JSObject*
WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
static void
Log(const GlobalObject& aGlobal, const Sequence<JS::Value>& aData);
void
Log(JSContext* aCx, const Sequence<JS::Value>& aData);
static void
Info(const GlobalObject& aGlobal, const Sequence<JS::Value>& aData);
void
Info(JSContext* aCx, const Sequence<JS::Value>& aData);
static void
Warn(const GlobalObject& aGlobal, const Sequence<JS::Value>& aData);
void
Warn(JSContext* aCx, const Sequence<JS::Value>& aData);
static void
Error(const GlobalObject& aGlobal, const Sequence<JS::Value>& aData);
void
Error(JSContext* aCx, const Sequence<JS::Value>& aData);
static void
Exception(const GlobalObject& aGlobal, const Sequence<JS::Value>& aData);
void
Exception(JSContext* aCx, const Sequence<JS::Value>& aData);
static void
Debug(const GlobalObject& aGlobal, const Sequence<JS::Value>& aData);
void
Debug(JSContext* aCx, const Sequence<JS::Value>& aData);
static void
Table(const GlobalObject& aGlobal, const Sequence<JS::Value>& aData);
void
Table(JSContext* aCx, const Sequence<JS::Value>& aData);
static void
Trace(const GlobalObject& aGlobal);
void
Trace(JSContext* aCx);
static void
Dir(const GlobalObject& aGlobal, const Sequence<JS::Value>& aData);
void
Dir(JSContext* aCx, const Sequence<JS::Value>& aData);
static void
Dirxml(const GlobalObject& aGlobal, const Sequence<JS::Value>& aData);
void
Dirxml(JSContext* aCx, const Sequence<JS::Value>& aData);
static void
Group(const GlobalObject& aGlobal, const Sequence<JS::Value>& aData);
void
Group(JSContext* aCx, const Sequence<JS::Value>& aData);
static void
GroupCollapsed(const GlobalObject& aGlobal, const Sequence<JS::Value>& aData);
void
GroupCollapsed(JSContext* aCx, const Sequence<JS::Value>& aData);
static void
GroupEnd(const GlobalObject& aGlobal, const Sequence<JS::Value>& aData);
void
GroupEnd(JSContext* aCx, const Sequence<JS::Value>& aData);
static void
Time(const GlobalObject& aGlobal, const JS::Handle<JS::Value> aTime);
void
Time(JSContext* aCx, const JS::Handle<JS::Value> aTime);
static void
TimeEnd(const GlobalObject& aGlobal, const JS::Handle<JS::Value> aTime);
void
TimeEnd(JSContext* aCx, const JS::Handle<JS::Value> aTime);
static void
TimeStamp(const GlobalObject& aGlobal, const JS::Handle<JS::Value> aData);
void
TimeStamp(JSContext* aCx, const JS::Handle<JS::Value> aData);
static void
Profile(const GlobalObject& aGlobal, const Sequence<JS::Value>& aData);
void
Profile(JSContext* aCx, const Sequence<JS::Value>& aData);
static void
ProfileEnd(const GlobalObject& aGlobal, const Sequence<JS::Value>& aData);
void
ProfileEnd(JSContext* aCx, const Sequence<JS::Value>& aData);
static void
Assert(const GlobalObject& aGlobal, bool aCondition,
const Sequence<JS::Value>& aData);
void
Assert(JSContext* aCx, bool aCondition, const Sequence<JS::Value>& aData);
static void
Count(const GlobalObject& aGlobal, const Sequence<JS::Value>& aData);
void
Count(JSContext* aCx, const Sequence<JS::Value>& aData);
static void
Clear(const GlobalObject& aGlobal, const Sequence<JS::Value>& aData);
void
Clear(JSContext* aCx, const Sequence<JS::Value>& aData);
void
NoopMethod();
static void
NoopMethod(const GlobalObject& aGlobal);
void
ClearStorage();
@ -162,9 +158,24 @@ private:
MethodClear
};
static already_AddRefed<Console>
GetConsole(const GlobalObject& aGlobal);
static void
ProfileMethod(const GlobalObject& aGlobal, const nsAString& aAction,
const Sequence<JS::Value>& aData);
void
Method(JSContext* aCx, MethodName aName, const nsAString& aString,
const Sequence<JS::Value>& aData);
ProfileMethodInternal(JSContext* aCx, const nsAString& aAction,
const Sequence<JS::Value>& aData);
static void
Method(const GlobalObject& aGlobal, MethodName aName,
const nsAString& aString, const Sequence<JS::Value>& aData);
void
MethodInternal(JSContext* aCx, MethodName aName,
const nsAString& aString, const Sequence<JS::Value>& aData);
// This method must receive aCx and aArguments in the same JSCompartment.
void
@ -305,10 +316,6 @@ private:
ArgumentsToValueList(const Sequence<JS::Value>& aData,
Sequence<JS::Value>& aSequence) const;
void
ProfileMethod(JSContext* aCx, const nsAString& aAction,
const Sequence<JS::Value>& aData);
// This method follows the same pattern as StartTimer: its runs on the owning
// thread and populate aCountLabel, used by CreateCounterValue. Returns
// MAX_PAGE_COUNTERS in case of error, otherwise the incremented counter

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

@ -200,6 +200,7 @@ Navigator::Init()
Navigator::Navigator(nsPIDOMWindowInner* aWindow)
: mWindow(aWindow)
, mBatteryTelemetryReported(false)
{
MOZ_ASSERT(aWindow->IsInnerWindow(), "Navigator must get an inner window!");
}
@ -303,6 +304,7 @@ Navigator::Invalidate()
}
mBatteryPromise = nullptr;
mBatteryTelemetryReported = false;
#ifdef MOZ_B2G_FM
if (mFMRadio) {
@ -1589,6 +1591,10 @@ Navigator::GetBattery(ErrorResult& aRv)
}
mBatteryPromise = batteryPromise;
// We just initialized mBatteryPromise, so we know this is the first time
// this page has accessed navigator.getBattery(). 1 = navigator.getBattery()
Telemetry::Accumulate(Telemetry::BATTERY_STATUS_COUNT, 1);
if (!mBatteryManager) {
mBatteryManager = new battery::BatteryManager(mWindow);
mBatteryManager->Init();

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

@ -403,6 +403,8 @@ private:
nsTArray<RefPtr<Promise> > mVRGetDevicesPromises;
nsTArray<uint32_t> mRequestedVibrationPattern;
bool mBatteryTelemetryReported;
};
} // namespace dom

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

@ -422,11 +422,13 @@ TextInputProcessor::AppendClauseToPendingComposition(uint32_t aLength,
{
MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome());
RefPtr<TextEventDispatcher> kungfuDeathGrip(mDispatcher);
TextRangeType textRangeType;
switch (aAttribute) {
case ATTR_RAW_CLAUSE:
case ATTR_SELECTED_RAW_CLAUSE:
case ATTR_CONVERTED_CLAUSE:
case ATTR_SELECTED_CLAUSE:
textRangeType = ToTextRangeType(aAttribute);
break;
default:
return NS_ERROR_INVALID_ARG;
@ -435,7 +437,7 @@ TextInputProcessor::AppendClauseToPendingComposition(uint32_t aLength,
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
return mDispatcher->AppendClauseToPendingComposition(aLength, aAttribute);
return mDispatcher->AppendClauseToPendingComposition(aLength, textRangeType);
}
NS_IMETHODIMP

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

@ -2911,7 +2911,8 @@ nsDOMWindowUtils::GetFileReferences(const nsAString& aDatabaseName, int64_t aId,
nsCString origin;
nsresult rv =
quota::QuotaManager::GetInfoFromWindow(window, nullptr, &origin, nullptr);
quota::QuotaManager::GetInfoFromWindow(window, nullptr, nullptr, &origin,
nullptr);
NS_ENSURE_SUCCESS(rv, rv);
IDBOpenDBOptions options;

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

@ -19,8 +19,6 @@
#include "nsIWeakReference.h"
#include "mozilla/Services.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsIPermissionManager.h"
#include "nsIDocument.h"
using namespace mozilla;
using namespace mozilla::dom;
@ -68,8 +66,7 @@ NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(nsPluginArray,
mWindow,
mPlugins,
mCTPPlugins)
mPlugins)
static void
GetPluginMimeTypes(const nsTArray<RefPtr<nsPluginElement> >& aPlugins,
@ -149,7 +146,6 @@ nsPluginArray::Refresh(bool aReloadDocuments)
}
mPlugins.Clear();
mCTPPlugins.Clear();
nsCOMPtr<nsIDOMNavigator> navigator = mWindow->GetNavigator();
@ -225,13 +221,6 @@ nsPluginArray::NamedGetter(const nsAString& aName, bool &aFound)
nsPluginElement* plugin = FindPlugin(mPlugins, aName);
aFound = (plugin != nullptr);
if (!aFound) {
nsPluginElement* hiddenPlugin = FindPlugin(mCTPPlugins, aName);
if (hiddenPlugin) {
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
obs->NotifyObservers(hiddenPlugin->PluginTag(), "Plugin::HiddenPluginTouched", nsString(aName).get());
}
}
return plugin;
}
@ -293,7 +282,7 @@ operator<(const RefPtr<nsPluginElement>& lhs,
void
nsPluginArray::EnsurePlugins()
{
if (!mPlugins.IsEmpty() || !mCTPPlugins.IsEmpty()) {
if (!mPlugins.IsEmpty()) {
// We already have an array of plugin elements.
return;
}
@ -310,31 +299,7 @@ nsPluginArray::EnsurePlugins()
// need to wrap each of these with a nsPluginElement, which is
// scriptable.
for (uint32_t i = 0; i < pluginTags.Length(); ++i) {
nsCOMPtr<nsPluginTag> pluginTag = do_QueryInterface(pluginTags[i]);
if (!pluginTag) {
mPlugins.AppendElement(new nsPluginElement(mWindow, pluginTags[i]));
} else if (pluginTag->IsActive()) {
uint32_t permission = nsIPermissionManager::ALLOW_ACTION;
if (pluginTag->IsClicktoplay()) {
nsCString name;
pluginTag->GetName(name);
if (NS_LITERAL_CSTRING("Shockwave Flash").Equals(name)) {
RefPtr<nsPluginHost> pluginHost = nsPluginHost::GetInst();
nsCString permString;
nsresult rv = pluginHost->GetPermissionStringForTag(pluginTag, 0, permString);
if (rv == NS_OK) {
nsIPrincipal* principal = mWindow->GetExtantDoc()->NodePrincipal();
nsCOMPtr<nsIPermissionManager> permMgr = services::GetPermissionManager();
permMgr->TestPermissionFromPrincipal(principal, permString.get(), &permission);
}
}
}
if (permission == nsIPermissionManager::ALLOW_ACTION) {
mPlugins.AppendElement(new nsPluginElement(mWindow, pluginTags[i]));
} else {
mCTPPlugins.AppendElement(new nsPluginElement(mWindow, pluginTags[i]));
}
}
mPlugins.AppendElement(new nsPluginElement(mWindow, pluginTags[i]));
}
// Alphabetize the enumeration order of non-hidden plugins to reduce

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

@ -60,10 +60,6 @@ private:
nsCOMPtr<nsPIDOMWindowInner> mWindow;
nsTArray<RefPtr<nsPluginElement> > mPlugins;
/* A separate list of click-to-play plugins that we don't tell content
* about but keep track of so we can still prompt the user to click to play.
*/
nsTArray<RefPtr<nsPluginElement> > mCTPPlugins;
};
class nsPluginElement final : public nsISupports,

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

@ -866,8 +866,6 @@ ResolveRequestedModules(nsModuleLoadRequest* aRequest, nsCOMArray<nsIURI> &aUrls
return NS_ERROR_FAILURE;
}
nsCOMArray<nsIURI> uris(length);
MOZ_ASSERT(uris.Length() == 0);
JS::Rooted<JS::Value> arrayValue(cx, JS::ObjectValue(*specifiers));
JS::ForOfIterator iter(cx);
if (!iter.init(arrayValue)) {

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

@ -916,4 +916,6 @@ support-files = test_XHR_timeout.js
[test_XHRDocURI.html]
[test_XHRResponseURL.html]
[test_XHRSendData.html]
[test_console_binding.html]
[test_unknown_url_origin.html]
[test_console_proto.html]

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

@ -0,0 +1,42 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Test Console binding</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<script type="application/javascript">
function consoleListener() {
SpecialPowers.addObserver(this, "console-api-log-event", false);
}
var order = 0;
consoleListener.prototype = {
observe: function(aSubject, aTopic, aData) {
if (aTopic == "console-api-log-event") {
var obj = aSubject.wrappedJSObject;
if (order+1 == parseInt(obj.arguments[0])) {
ok(true, "Message received: " + obj.arguments[0]);
order++;
}
if (order == 3) {
SpecialPowers.removeObserver(this, "console-api-log-event");
SimpleTest.finish();
return;
}
}
}
}
var cl = new consoleListener();
SimpleTest.waitForExplicitFinish();
[1,2,3].forEach(console.log);
</script>
</body>
</html>

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

@ -0,0 +1,17 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Test for console.__proto__</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<script type="application/javascript">
isnot(Object.getPrototypeOf(console), Object.prototype, "Foo");
is(Object.getPrototypeOf(Object.getPrototypeOf(console)), Object.prototype, "Boo");
</script>
</body>
</html>

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

@ -309,8 +309,8 @@ DOMInterfaces = {
'headerFile': 'mozilla/dom/workers/bindings/ServiceWorkerClients.h',
},
'Console': {
'implicitJSContext': [ 'trace', 'time', 'timeEnd', 'timeStamp' ],
'console': {
'nativeType': 'mozilla::dom::Console',
},
'ConvolverNode': {

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

@ -100,30 +100,26 @@ CallbackObject::CallSetup::CallSetup(CallbackObject* aCallback,
// global to get a context. Everything here is simple getters that cannot
// GC, so just paper over the necessary dataflow inversion.
JS::AutoSuppressGCAnalysis nogc;
if (mIsMainThread) {
// Now get the global for this callback. Note that for the case of
// JS-implemented WebIDL we never have a window here.
nsGlobalWindow* win =
aIsJSImplementedWebIDL ? nullptr : xpc::WindowGlobalOrNull(realCallback);
if (win) {
MOZ_ASSERT(win->IsInnerWindow());
// We don't want to run script in windows that have been navigated away
// from.
if (!win->AsInner()->HasActiveDocument()) {
aRv.ThrowDOMException(NS_ERROR_DOM_NOT_SUPPORTED_ERR,
NS_LITERAL_CSTRING("Refusing to execute function from window "
"whose document is no longer active."));
return;
}
globalObject = win;
} else {
// No DOM Window. Store the global.
JSObject* glob = js::GetGlobalForObjectCrossCompartment(realCallback);
globalObject = xpc::NativeGlobal(glob);
MOZ_ASSERT(globalObject);
// Now get the global for this callback. Note that for the case of
// JS-implemented WebIDL we never have a window here.
nsGlobalWindow* win = mIsMainThread && !aIsJSImplementedWebIDL
? xpc::WindowGlobalOrNull(realCallback)
: nullptr;
if (win) {
MOZ_ASSERT(win->IsInnerWindow());
// We don't want to run script in windows that have been navigated away
// from.
if (!win->AsInner()->HasActiveDocument()) {
aRv.ThrowDOMException(NS_ERROR_DOM_NOT_SUPPORTED_ERR,
NS_LITERAL_CSTRING("Refusing to execute function from window "
"whose document is no longer active."));
return;
}
globalObject = win;
} else {
JSObject *global = js::GetGlobalForObjectCrossCompartment(realCallback);
// No DOM Window. Store the global.
JSObject* global = js::GetGlobalForObjectCrossCompartment(realCallback);
globalObject = xpc::NativeGlobal(global);
MOZ_ASSERT(globalObject);
}

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

@ -2286,6 +2286,10 @@ class MethodDefiner(PropertyDefiner):
"returnsPromise": m.returnsPromise(),
"hasIteratorAlias": "@@iterator" in m.aliases
}
if m.isStatic():
method["nativeName"] = CppKeywords.checkMethodName(IDLToCIdentifier(m.identifier.name))
if isChromeOnly(m):
self.chrome.append(method)
else:
@ -6061,7 +6065,7 @@ def convertConstIDLValueToJSVal(value):
if tag in [IDLType.Tags.int64, IDLType.Tags.uint64]:
return "JS::CanonicalizedDoubleValue(%s)" % numericValue(tag, value.value)
if tag == IDLType.Tags.bool:
return "JSVAL_TRUE" if value.value else "JSVAL_FALSE"
return "JS::BooleanValue(true)" if value.value else "JS::BooleanValue(false)"
if tag in [IDLType.Tags.float, IDLType.Tags.double]:
return "JS::CanonicalizedDoubleValue(%s)" % (value.value)
raise TypeError("Const value of unhandled type: %s" % value.type)
@ -8613,7 +8617,7 @@ class CGStaticMethod(CGAbstractStaticBindingMethod):
"""
def __init__(self, descriptor, method):
self.method = method
name = IDLToCIdentifier(method.identifier.name)
name = CppKeywords.checkMethodName(IDLToCIdentifier(method.identifier.name))
CGAbstractStaticBindingMethod.__init__(self, descriptor, name)
def generate_code(self):

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

@ -795,6 +795,7 @@ public:
static void StaticMethodWithContext(const GlobalObject&, JS::Value);
static bool StaticAttribute(const GlobalObject&);
static void SetStaticAttribute(const GlobalObject&, bool);
static void Assert(const GlobalObject&, bool);
// Deprecated static methods and attributes
static int8_t StaticDeprecatedAttribute(const GlobalObject&);

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

@ -783,6 +783,9 @@ interface TestInterface {
static void staticMethod(boolean arg);
static void staticMethodWithContext(any arg);
// Testing static method with a reserved C++ keyword as the name
static void assert(boolean arg);
// Deprecated static methods and attributes
[Deprecated="GetAttributeNode"]
static attribute byte staticDeprecatedAttribute;

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

@ -26,3 +26,4 @@ skip-if = buildapp != 'mulet'
[test_bfcache.html]
[test_invalidState.html]
[test_ordering.html]
[test_dataCloning.html]

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

@ -0,0 +1,27 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for BroadcastChannel.postMessage invalid State</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<div id="content"></div>
<script type="application/javascript">
let c = new BroadcastChannel("foo");
try {
c.postMessage(Symbol());
ok(false, "This should throw!");
} catch(e) {
ok(true, "This should throw!");
is(e.name, "DataCloneError", "Correct DataCloneError exception thrown");
}
</script>
</body>
</html>

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

@ -377,6 +377,7 @@ Context::QuotaInitRunnable::Run()
RefPtr<ManagerId> managerId = mManager->GetManagerId();
nsCOMPtr<nsIPrincipal> principal = managerId->Principal();
nsresult rv = QuotaManager::GetInfoFromPrincipal(principal,
&mQuotaInfo.mSuffix,
&mQuotaInfo.mGroup,
&mQuotaInfo.mOrigin,
&mQuotaInfo.mIsApp);
@ -435,6 +436,7 @@ Context::QuotaInitRunnable::Run()
QuotaManager* qm = QuotaManager::Get();
MOZ_ASSERT(qm);
nsresult rv = qm->EnsureOriginIsInitialized(PERSISTENCE_TYPE_DEFAULT,
mQuotaInfo.mSuffix,
mQuotaInfo.mGroup,
mQuotaInfo.mOrigin,
mQuotaInfo.mIsApp,

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

@ -28,7 +28,8 @@ ManagerId::Create(nsIPrincipal* aPrincipal, ManagerId** aManagerIdOut)
// order to interpret calls from QM correctly.
nsCString quotaOrigin;
nsresult rv = QuotaManager::GetInfoFromPrincipal(aPrincipal,
nullptr, //group
nullptr, // suffix
nullptr, // group
&quotaOrigin,
nullptr); // is app
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }

1
dom/cache/Types.h поставляемый
Просмотреть файл

@ -31,6 +31,7 @@ struct QuotaInfo
{
QuotaInfo() : mIsApp(false) { }
nsCOMPtr<nsIFile> mDir;
nsCString mSuffix;
nsCString mGroup;
nsCString mOrigin;
bool mIsApp;

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

@ -275,15 +275,16 @@ public:
mode = ExtendMode::REPEAT;
}
Filter filter;
SamplingFilter samplingFilter;
if (state.imageSmoothingEnabled) {
filter = Filter::GOOD;
samplingFilter = SamplingFilter::GOOD;
} else {
filter = Filter::POINT;
samplingFilter = SamplingFilter::POINT;
}
mPattern.InitSurfacePattern(state.patternStyles[aStyle]->mSurface, mode,
state.patternStyles[aStyle]->mTransform, filter);
state.patternStyles[aStyle]->mTransform,
samplingFilter);
}
return *mPattern.GetPattern();
@ -4711,12 +4712,12 @@ CanvasRenderingContext2D::DrawImage(const CanvasImageSource& aImage,
return;
}
Filter filter;
SamplingFilter samplingFilter;
if (CurrentState().imageSmoothingEnabled)
filter = gfx::Filter::LINEAR;
samplingFilter = gfx::SamplingFilter::LINEAR;
else
filter = gfx::Filter::POINT;
samplingFilter = gfx::SamplingFilter::POINT;
gfx::Rect bounds;
@ -4739,7 +4740,7 @@ CanvasRenderingContext2D::DrawImage(const CanvasImageSource& aImage,
DrawSurface(srcSurf,
gfx::Rect(aDx, aDy, aDw, aDh),
sourceRect,
DrawSurfaceOptions(filter),
DrawSurfaceOptions(samplingFilter),
DrawOptions(CurrentState().globalAlpha, UsedOperation()));
} else {
DrawDirectlyToCanvas(drawInfo, &bounds,
@ -4806,7 +4807,7 @@ CanvasRenderingContext2D::DrawDirectlyToCanvas(
auto result = aImage.mImgContainer->
Draw(context, scaledImageSize,
ImageRegion::Create(gfxRect(aSrc.x, aSrc.y, aSrc.width, aSrc.height)),
aImage.mWhichFrame, Filter::GOOD, Some(svgContext), modifiedFlags);
aImage.mWhichFrame, SamplingFilter::GOOD, Some(svgContext), modifiedFlags);
if (result != DrawResult::SUCCESS) {
NS_WARNING("imgIContainer::Draw failed");
@ -5041,7 +5042,7 @@ CanvasRenderingContext2D::DrawWindow(nsGlobalWindow& aWindow, double aX,
gfx::Rect destRect(0, 0, aW, aH);
gfx::Rect sourceRect(0, 0, sw, sh);
mTarget->DrawSurface(source, destRect, sourceRect,
DrawSurfaceOptions(gfx::Filter::POINT),
DrawSurfaceOptions(gfx::SamplingFilter::POINT),
DrawOptions(GlobalAlpha(), UsedOperation(),
AntialiasMode::NONE));
mTarget->Flush();

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

@ -67,6 +67,7 @@
#include "WebGLQuery.h"
#include "WebGLSampler.h"
#include "WebGLShader.h"
#include "WebGLTimerQuery.h"
#include "WebGLTransformFeedback.h"
#include "WebGLVertexArray.h"
#include "WebGLVertexAttribData.h"
@ -213,6 +214,15 @@ WebGLContext::~WebGLContext()
mContextLossHandler = nullptr;
}
template<typename T>
static void
ClearLinkedList(LinkedList<T>& list)
{
while (!list.isEmpty()) {
list.getLast()->DeleteOnce();
}
}
void
WebGLContext::DestroyResourcesAndContext()
{
@ -247,26 +257,21 @@ WebGLContext::DestroyResourcesAndContext()
mBoundTransformFeedbackBuffers.Clear();
mBoundUniformBuffers.Clear();
while (!mTextures.isEmpty())
mTextures.getLast()->DeleteOnce();
while (!mVertexArrays.isEmpty())
mVertexArrays.getLast()->DeleteOnce();
while (!mBuffers.isEmpty())
mBuffers.getLast()->DeleteOnce();
while (!mRenderbuffers.isEmpty())
mRenderbuffers.getLast()->DeleteOnce();
while (!mFramebuffers.isEmpty())
mFramebuffers.getLast()->DeleteOnce();
while (!mShaders.isEmpty())
mShaders.getLast()->DeleteOnce();
while (!mPrograms.isEmpty())
mPrograms.getLast()->DeleteOnce();
while (!mQueries.isEmpty())
mQueries.getLast()->DeleteOnce();
while (!mSamplers.isEmpty())
mSamplers.getLast()->DeleteOnce();
while (!mTransformFeedbacks.isEmpty())
mTransformFeedbacks.getLast()->DeleteOnce();
//////
ClearLinkedList(mBuffers);
ClearLinkedList(mFramebuffers);
ClearLinkedList(mPrograms);
ClearLinkedList(mQueries);
ClearLinkedList(mRenderbuffers);
ClearLinkedList(mSamplers);
ClearLinkedList(mShaders);
ClearLinkedList(mTextures);
ClearLinkedList(mTimerQueries);
ClearLinkedList(mTransformFeedbacks);
ClearLinkedList(mVertexArrays);
//////
mFakeBlack_2D_0000 = nullptr;
mFakeBlack_2D_0001 = nullptr;

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

@ -101,6 +101,7 @@ class WebGLSampler;
class WebGLShader;
class WebGLShaderPrecisionFormat;
class WebGLTexture;
class WebGLTimerQuery;
class WebGLTransformFeedback;
class WebGLUniformLocation;
class WebGLVertexArray;
@ -1394,18 +1395,17 @@ protected:
WebGLRefPtr<WebGLTransformFeedback> mBoundTransformFeedback;
WebGLRefPtr<WebGLVertexArray> mBoundVertexArray;
LinkedList<WebGLTexture> mTextures;
LinkedList<WebGLBuffer> mBuffers;
LinkedList<WebGLFramebuffer> mFramebuffers;
LinkedList<WebGLProgram> mPrograms;
LinkedList<WebGLQuery> mQueries;
LinkedList<WebGLShader> mShaders;
LinkedList<WebGLRenderbuffer> mRenderbuffers;
LinkedList<WebGLFramebuffer> mFramebuffers;
LinkedList<WebGLVertexArray> mVertexArrays;
// TODO(djg): Does this need a rethink? Should it be WebGL2Context?
LinkedList<WebGLSampler> mSamplers;
LinkedList<WebGLShader> mShaders;
LinkedList<WebGLTexture> mTextures;
LinkedList<WebGLTimerQuery> mTimerQueries;
LinkedList<WebGLTransformFeedback> mTransformFeedbacks;
LinkedList<WebGLVertexArray> mVertexArrays;
WebGLRefPtr<WebGLTransformFeedback> mDefaultTransformFeedback;
WebGLRefPtr<WebGLVertexArray> mDefaultVertexArray;

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

@ -26,6 +26,7 @@ WebGLTimerQuery::WebGLTimerQuery(WebGLContext* webgl, GLuint name)
, mTarget(LOCAL_GL_NONE)
, mCanBeAvailable(false)
{
mContext->mTimerQueries.insertBack(this);
}
WebGLTimerQuery::~WebGLTimerQuery()
@ -45,8 +46,12 @@ WebGLTimerQuery::Create(WebGLContext* webgl)
void
WebGLTimerQuery::Delete()
{
mContext->MakeContextCurrent();
mContext->gl->fDeleteQueries(1, &mGLName);
gl::GLContext* gl = mContext->GL();
gl->MakeCurrent();
gl->fDeleteQueries(1, &mGLName);
LinkedListElement<WebGLTimerQuery>::removeFrom(mContext->mTimerQueries);
}
WebGLContext*

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

@ -16,6 +16,7 @@ namespace mozilla {
class WebGLTimerQuery final
: public nsWrapperCache
, public WebGLRefCountedObject<WebGLTimerQuery>
, public LinkedListElement<WebGLTimerQuery>
, public WebGLContextBoundObject
{
public:

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

@ -151,7 +151,7 @@ static_assert(JS_STRUCTURED_CLONE_VERSION == 6,
"Need to update the major schema version.");
// Major schema version. Bump for almost everything.
const uint32_t kMajorSchemaVersion = 22;
const uint32_t kMajorSchemaVersion = 23;
// Minor schema version. Should almost always be 0 (maybe bump on release
// branches if we have to).
@ -1055,6 +1055,13 @@ CreateTables(mozIStorageConnection* aConnection)
js::ProfileEntry::Category::STORAGE);
// Table `database`
// There are two reasons for having the origin column.
// First, we can ensure that we don't have collisions in the origin hash we
// use for the path because when we open the db we can make sure that the
// origins exactly match. Second, chrome code crawling through the idb
// directory can figure out the origin of every db without having to
// reverse-engineer our hash scheme.
nsresult rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"CREATE TABLE database"
"( name TEXT PRIMARY KEY"
@ -4053,6 +4060,45 @@ UpgradeSchemaFrom21_0To22_0(mozIStorageConnection* aConnection)
return NS_OK;
}
nsresult
UpgradeSchemaFrom22_0To23_0(mozIStorageConnection* aConnection,
const nsACString& aOrigin)
{
AssertIsOnIOThread();
MOZ_ASSERT(aConnection);
MOZ_ASSERT(!aOrigin.IsEmpty());
PROFILER_LABEL("IndexedDB",
"UpgradeSchemaFrom22_0To23_0",
js::ProfileEntry::Category::STORAGE);
nsCOMPtr<mozIStorageStatement> stmt;
nsresult rv = aConnection->CreateStatement(NS_LITERAL_CSTRING(
"UPDATE database "
"SET origin = :origin;"
), getter_AddRefs(stmt));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = stmt->BindUTF8StringByName(NS_LITERAL_CSTRING("origin"), aOrigin);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = stmt->Execute();
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = aConnection->SetSchemaVersion(MakeSchemaVersion(23, 0));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
return NS_OK;
}
nsresult
GetDatabaseFileURL(nsIFile* aDatabaseFile,
PersistenceType aPersistenceType,
@ -4545,7 +4591,7 @@ CreateStorageConnection(nsIFile* aDBFile,
}
} else {
// This logic needs to change next time we change the schema!
static_assert(kSQLiteSchemaVersion == int32_t((22 << 4) + 0),
static_assert(kSQLiteSchemaVersion == int32_t((23 << 4) + 0),
"Upgrade function needed due to schema version increase.");
while (schemaVersion != kSQLiteSchemaVersion) {
@ -4587,6 +4633,8 @@ CreateStorageConnection(nsIFile* aDBFile,
rv = UpgradeSchemaFrom20_0To21_0(connection);
} else if (schemaVersion == MakeSchemaVersion(21, 0)) {
rv = UpgradeSchemaFrom21_0To22_0(connection);
} else if (schemaVersion == MakeSchemaVersion(22, 0)) {
rv = UpgradeSchemaFrom22_0To23_0(connection, aOrigin);
} else {
IDB_WARNING("Unable to open IndexedDB database, no upgrade path is "
"available!");
@ -7191,6 +7239,7 @@ protected:
nsTArray<MaybeBlockedDatabaseInfo> mMaybeBlockedDatabases;
const CommonFactoryRequestParams mCommonParams;
nsCString mSuffix;
nsCString mGroup;
nsCString mOrigin;
nsCString mDatabaseId;
@ -17634,6 +17683,10 @@ Maintenance::DirectoryWork()
QuotaManager* quotaManager = QuotaManager::Get();
MOZ_ASSERT(quotaManager);
if (NS_WARN_IF(NS_FAILED(quotaManager->EnsureStorageIsInitialized()))) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIFile> storageDir = GetFileForPath(quotaManager->GetStoragePath());
MOZ_ASSERT(storageDir);
@ -17799,13 +17852,15 @@ Maintenance::DirectoryWork()
MOZ_ASSERT(origin.IsEmpty());
int64_t dummyTimeStamp;
nsCString dummySuffix;
bool dummyIsApp;
if (NS_WARN_IF(NS_FAILED(
QuotaManager::GetDirectoryMetadata(originDir,
&dummyTimeStamp,
group,
origin,
&dummyIsApp)))) {
quotaManager->GetDirectoryMetadata2(originDir,
&dummyTimeStamp,
dummySuffix,
group,
origin,
&dummyIsApp)))) {
// Not much we can do here...
continue;
}
@ -20154,7 +20209,7 @@ FactoryOp::CheckPermission(ContentParent* aContentParent,
}
if (State::Initial == mState) {
QuotaManager::GetInfoForChrome(&mGroup, &mOrigin, &mIsApp);
QuotaManager::GetInfoForChrome(&mSuffix, &mGroup, &mOrigin, &mIsApp);
MOZ_ASSERT(!QuotaManager::IsFirstPromptRequired(persistenceType, mOrigin,
mIsApp));
@ -20176,10 +20231,15 @@ FactoryOp::CheckPermission(ContentParent* aContentParent,
return rv;
}
nsCString suffix;
nsCString group;
nsCString origin;
bool isApp;
rv = QuotaManager::GetInfoFromPrincipal(principal, &group, &origin, &isApp);
rv = QuotaManager::GetInfoFromPrincipal(principal,
&suffix,
&group,
&origin,
&isApp);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
@ -20221,6 +20281,7 @@ FactoryOp::CheckPermission(ContentParent* aContentParent,
if (permission != PermissionRequestBase::kPermissionDenied &&
State::Initial == mState) {
mSuffix = suffix;
mGroup = group;
mOrigin = origin;
mIsApp = isApp;
@ -20695,6 +20756,7 @@ OpenDatabaseOp::DoDatabaseWork()
nsresult rv =
quotaManager->EnsureOriginIsInitialized(persistenceType,
mSuffix,
mGroup,
mOrigin,
mIsApp,
@ -20859,7 +20921,7 @@ OpenDatabaseOp::LoadDatabaseInformation(mozIStorageConnection* aConnection)
// Load version information.
nsCOMPtr<mozIStorageStatement> stmt;
nsresult rv = aConnection->CreateStatement(NS_LITERAL_CSTRING(
"SELECT name, version "
"SELECT name, origin, version "
"FROM database"
), getter_AddRefs(stmt));
if (NS_WARN_IF(NS_FAILED(rv))) {
@ -20886,8 +20948,18 @@ OpenDatabaseOp::LoadDatabaseInformation(mozIStorageConnection* aConnection)
return NS_ERROR_FILE_CORRUPTED;
}
nsCString origin;
rv = stmt->GetUTF8String(1, origin);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (mOrigin != origin) {
NS_WARNING("Origins don't match!");
}
int64_t version;
rv = stmt->GetInt64(1, &version);
rv = stmt->GetInt64(2, &version);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}

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

@ -1071,7 +1071,7 @@ IDBDatabase::GetQuotaInfo(nsACString& aOrigin,
MOZ_CRASH("Is this needed?!");
case PrincipalInfo::TSystemPrincipalInfo:
QuotaManager::GetInfoForChrome(nullptr, &aOrigin, nullptr);
QuotaManager::GetInfoForChrome(nullptr, nullptr, &aOrigin, nullptr);
return NS_OK;
case PrincipalInfo::TContentPrincipalInfo: {
@ -1083,6 +1083,7 @@ IDBDatabase::GetQuotaInfo(nsACString& aOrigin,
}
rv = QuotaManager::GetInfoFromPrincipal(principal,
nullptr,
nullptr,
&aOrigin,
nullptr);

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

@ -381,14 +381,14 @@ skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
[test_webapp_clearBrowserData_inproc_inproc.html]
# The clearBrowserData tests are only supposed to run in the main process.
# They currently time out on android.
skip-if = buildapp != 'mulet'
skip-if = buildapp == 'b2g' || e10s || toolkit == 'android'
[test_webapp_clearBrowserData_inproc_oop.html]
# The clearBrowserData tests are only supposed to run in the main process.
# They currently time out on android.
skip-if = buildapp != 'mulet'
skip-if = buildapp == 'b2g' || e10s || toolkit == 'android'
[test_webapp_clearBrowserData_oop_inproc.html]
# The clearBrowserData tests are only supposed to run in the main process.
# They currently time out on android.
skip-if = buildapp != 'mulet'
skip-if = buildapp == 'b2g' || e10s || toolkit == 'android'
[test_serviceworker.html]
skip-if = buildapp == 'b2g'

Двоичный файл не отображается.

Двоичные данные
dom/indexedDB/test/unit/idbSubdirUpgrade1_profile.zip Normal file

Двоичный файл не отображается.

Двоичные данные
dom/indexedDB/test/unit/idbSubdirUpgrade2_profile.zip Normal file

Двоичный файл не отображается.

Двоичные данные
dom/indexedDB/test/unit/metadata2Restore_profile.zip Normal file

Двоичный файл не отображается.

Двоичные данные
dom/indexedDB/test/unit/oldDirectories_profile.zip Normal file

Двоичный файл не отображается.

Двоичные данные
dom/indexedDB/test/unit/schema23upgrade_profile.zip Normal file

Двоичный файл не отображается.

Двоичные данные
dom/indexedDB/test/unit/storagePersistentUpgrade_profile.zip Normal file

Двоичный файл не отображается.

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

@ -75,6 +75,30 @@ function testSteps()
// This one lives in storage/default/file++++++index.html
{ url: "file://///index.html", dbName: "dbS", dbVersion: 1 },
// This one lives in storage/permanent/resource+++fx-share-addon-at-mozilla-dot-org-fx-share-addon-data
{ url: "resource://fx-share-addon-at-mozilla-dot-org-fx-share-addon-data",
dbName: "dbU", dbOptions: { version: 1, storage: "persistent" } },
// This one lives in storage/temporary/http+++localhost+81
// The .metadata file was intentionally removed for this origin directory
// to test restoring during upgrade.
{ url: "http://localhost:81", dbName: "dbV",
dbOptions: { version: 1, storage: "temporary" } },
// This one lives in storage/temporary/http+++localhost+82
// The .metadata file was intentionally truncated for this origin directory
// to test restoring during upgrade.
{ url: "http://localhost:82", dbName: "dbW",
dbOptions: { version: 1, storage: "temporary" } },
// This one lives in storage/temporary/1007+f+app+++system.gaiamobile.org
{ appId: 1007, inIsolatedMozBrowser: false, url: "app://system.gaiamobile.org",
dbName: "dbX", dbOptions: { version: 1, storage: "temporary" } },
// This one lives in storage/temporary/1007+t+https+++developer.cdn.mozilla.net
{ appId: 1007, inIsolatedMozBrowser: true, url: "https://developer.cdn.mozilla.net",
dbName: "dbY", dbOptions: { version: 1, storage: "temporary" } },
// This one lives in storage/temporary/http+++localhost
{ url: "http://localhost", dbName: "dbZ",
dbOptions: { version: 1, storage: "temporary" } }

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

@ -0,0 +1,72 @@
/**
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
var testGenerator = testSteps();
function testSteps()
{
const openParams = [
// This one lives in storage/default/http+++www.mozilla.org
{ url: "http://www.mozilla.org", dbName: "dbB", dbVersion: 1 },
// This one lives in storage/default/1007+f+app+++system.gaiamobile.org
{ appId: 1007, inIsolatedMozBrowser: false, url: "app://system.gaiamobile.org",
dbName: "dbM", dbVersion: 1 },
// This one lives in storage/default/1007+t+https+++developer.cdn.mozilla.net
{ appId: 1007, inIsolatedMozBrowser: true, url: "https://developer.cdn.mozilla.net",
dbName: "dbN", dbVersion: 1 },
];
let ios = SpecialPowers.Cc["@mozilla.org/network/io-service;1"]
.getService(SpecialPowers.Ci.nsIIOService);
let ssm = SpecialPowers.Cc["@mozilla.org/scriptsecuritymanager;1"]
.getService(SpecialPowers.Ci.nsIScriptSecurityManager);
function openDatabase(params) {
let uri = ios.newURI(params.url, null, null);
let principal =
ssm.createCodebasePrincipal(uri,
{appId: params.appId || ssm.NO_APPID,
inIsolatedMozBrowser: params.inIsolatedMozBrowser});
let request = indexedDB.openForPrincipal(principal, params.dbName,
params.dbVersion);
return request;
}
for (let i = 1; i <= 2; i++) {
clearAllDatabases(continueToNextStepSync);
yield undefined;
installPackagedProfile("idbSubdirUpgrade" + i + "_profile");
for (let params of openParams) {
let request = openDatabase(params);
request.onerror = errorHandler;
request.onupgradeneeded = unexpectedSuccessHandler;
request.onsuccess = grabEventAndContinueHandler;
let event = yield undefined;
is(event.type, "success", "Correct event type");
}
resetAllDatabases(continueToNextStepSync);
yield undefined;
for (let params of openParams) {
let request = openDatabase(params);
request.onerror = errorHandler;
request.onupgradeneeded = unexpectedSuccessHandler;
request.onsuccess = grabEventAndContinueHandler;
let event = yield undefined;
is(event.type, "success", "Correct event type");
}
}
finishTest();
yield undefined;
}

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

@ -0,0 +1,268 @@
/**
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
var testGenerator = testSteps();
function testSteps()
{
const openParams = [
// This one lives in storage/permanent/chrome
// The .metadata-v2 file was intentionally removed for this origin directory
// to test restoring.
{ dbName: "dbA",
dbOptions: { version: 1, storage: "persistent" } },
// This one lives in storage/temporary/http+++localhost
// The .metadata-v2 file was intentionally removed for this origin directory
// to test restoring.
{ url: "http://localhost", dbName: "dbB",
dbOptions: { version: 1, storage: "temporary" } },
// This one lives in storage/default/http+++localhost+81^userContextId=1
// The .metadata-v2 file was intentionally removed for this origin directory
// to test restoring.
{ attrs: { userContextId: 1 }, url: "http://localhost:81", dbName: "dbC",
dbOptions: { version: 1, storage: "default" } },
// This one lives in storage/default/http+++localhost+82^userContextId=1
// The .metadata-v2 file was intentionally truncated for this origin directory
// to test restoring.
{ attrs: { userContextId: 1 }, url: "http://localhost:82", dbName: "dbD",
dbOptions: { version: 1, storage: "default" } },
// This one lives in storage/default/http+++localhost+83^userContextId=1
// The .metadata-v2 file was intentionally modified to contain only
// 4 bytes of the 64 bit timestamp
// for this origin directory to test restoring.
{ attrs: { userContextId: 1 }, url: "http://localhost:83", dbName: "dbE",
dbOptions: { version: 1, storage: "default" } },
// This one lives in storage/default/http+++localhost+84^userContextId=1
// The .metadata-v2 file was intentionally modified to contain only
// the 64 bit timestamp
// for this origin directory to test restoring.
{ attrs: { userContextId: 1 }, url: "http://localhost:84", dbName: "dbF",
dbOptions: { version: 1, storage: "default" } },
// This one lives in storage/default/http+++localhost+85^userContextId=1
// The .metadata-v2 file was intentionally modified to contain only
// the 64 bit timestamp and
// the 8 bit persisted flag
// for this origin directory to test restoring.
{ attrs: { userContextId: 1 }, url: "http://localhost:85", dbName: "dbG",
dbOptions: { version: 1, storage: "default" } },
// This one lives in storage/default/http+++localhost+86^userContextId=1
// The .metadata-v2 file was intentionally modified to contain only
// the 64 bit timestamp,
// the 8 bit persisted flag and
// 2 bytes of the 32 bit reserved data 1
// for this origin directory to test restoring.
{ attrs: { userContextId: 1 }, url: "http://localhost:86", dbName: "dbH",
dbOptions: { version: 1, storage: "default" } },
// This one lives in storage/default/http+++localhost+87^userContextId=1
// The .metadata-v2 file was intentionally modified to contain only
// the 64 bit timestamp,
// the 8 bit persisted flag and
// the 32 bit reserved data 1
// for this origin directory to test restoring.
{ attrs: { userContextId: 1 }, url: "http://localhost:87", dbName: "dbI",
dbOptions: { version: 1, storage: "default" } },
// This one lives in storage/default/http+++localhost+88^userContextId=1
// The .metadata-v2 file was intentionally modified to contain only
// the 64 bit timestamp,
// the 8 bit persisted flag,
// the 32 bit reserved data 1 and
// 2 bytes of the 32 bit reserved data 2
// for this origin directory to test restoring.
{ attrs: { userContextId: 1 }, url: "http://localhost:88", dbName: "dbJ",
dbOptions: { version: 1, storage: "default" } },
// This one lives in storage/default/http+++localhost+89^userContextId=1
// The .metadata-v2 file was intentionally modified to contain only
// the 64 bit timestamp,
// the 8 bit persisted flag,
// the 32 bit reserved data 1 and
// the 32 bit reserved data 2
// for this origin directory to test restoring.
{ attrs: { userContextId: 1 }, url: "http://localhost:89", dbName: "dbK",
dbOptions: { version: 1, storage: "default" } },
// This one lives in storage/default/http+++localhost+90^userContextId=1
// The .metadata-v2 file was intentionally modified to contain only
// the 64 bit timestamp,
// the 8 bit persisted flag,
// the 32 bit reserved data 1,
// the 32 bit reserved data 2 and
// 2 bytes of the 32 bit suffix length
// for this origin directory to test restoring.
{ attrs: { userContextId: 1 }, url: "http://localhost:90", dbName: "dbL",
dbOptions: { version: 1, storage: "default" } },
// This one lives in storage/default/http+++localhost+91^userContextId=1
// The .metadata-v2 file was intentionally modified to contain only
// the 64 bit timestamp,
// the 8 bit persisted flag,
// the 32 bit reserved data 1,
// the 32 bit reserved data 2,
// the 32 bit suffix length and
// first 5 chars of the suffix
// for this origin directory to test restoring.
{ attrs: { userContextId: 1 }, url: "http://localhost:91", dbName: "dbM",
dbOptions: { version: 1, storage: "default" } },
// This one lives in storage/default/http+++localhost+92^userContextId=1
// The .metadata-v2 file was intentionally modified to contain only
// the 64 bit timestamp,
// the 8 bit persisted flag,
// the 32 bit reserved data 1,
// the 32 bit reserved data 2,
// the 32 bit suffix length and
// the suffix
// for this origin directory to test restoring.
{ attrs: { userContextId: 1 }, url: "http://localhost:92", dbName: "dbN",
dbOptions: { version: 1, storage: "default" } },
// This one lives in storage/default/http+++localhost+93^userContextId=1
// The .metadata-v2 file was intentionally modified to contain only
// the 64 bit timestamp,
// the 8 bit persisted flag,
// the 32 bit reserved data 1,
// the 32 bit reserved data 2,
// the 32 bit suffix length,
// the suffix and
// 2 bytes of the 32 bit group length
// for this origin directory to test restoring.
{ attrs: { userContextId: 1 }, url: "http://localhost:93", dbName: "dbO",
dbOptions: { version: 1, storage: "default" } },
// This one lives in storage/default/http+++localhost+94^userContextId=1
// The .metadata-v2 file was intentionally modified to contain only
// the 64 bit timestamp,
// the 8 bit persisted flag,
// the 32 bit reserved data 1,
// the 32 bit reserved data 2,
// the 32 bit suffix length,
// the suffix,
// the 32 bit group length and
// first 5 chars of the group
// for this origin directory to test restoring.
{ attrs: { userContextId: 1 }, url: "http://localhost:94", dbName: "dbP",
dbOptions: { version: 1, storage: "default" } },
// This one lives in storage/default/http+++localhost+95^userContextId=1
// The .metadata-v2 file was intentionally modified to contain only
// the 64 bit timestamp,
// the 8 bit persisted flag,
// the 32 bit reserved data 1,
// the 32 bit reserved data 2,
// the 32 bit suffix length,
// the suffix,
// the 32 bit group length and
// the group
// for this origin directory to test restoring.
{ attrs: { userContextId: 1 }, url: "http://localhost:95", dbName: "dbQ",
dbOptions: { version: 1, storage: "default" } },
// This one lives in storage/default/http+++localhost+96^userContextId=1
// The .metadata-v2 file was intentionally modified to contain only
// the 64 bit timestamp,
// the 8 bit persisted flag,
// the 32 bit reserved data 1,
// the 32 bit reserved data 2,
// the 32 bit suffix length,
// the suffix,
// the 32 bit group length,
// the group and
// 2 bytes of the 32 bit origin length
// for this origin directory to test restoring.
{ attrs: { userContextId: 1 }, url: "http://localhost:96", dbName: "dbR",
dbOptions: { version: 1, storage: "default" } },
// This one lives in storage/default/http+++localhost+97^userContextId=1
// The .metadata-v2 file was intentionally modified to contain only
// the 64 bit timestamp,
// the 8 bit persisted flag,
// the 32 bit reserved data 1,
// the 32 bit reserved data 2,
// the 32 bit suffix length,
// the suffix,
// the 32 bit group length,
// the group,
// the 32 bit origin length and
// first 12 char of the origin
// for this origin directory to test restoring.
{ attrs: { userContextId: 1 }, url: "http://localhost:97", dbName: "dbS",
dbOptions: { version: 1, storage: "default" } },
// This one lives in storage/default/http+++localhost+98^userContextId=1
// The .metadata-v2 file was intentionally modified to contain only
// the 64 bit timestamp,
// the 8 bit persisted flag,
// the 32 bit reserved data 1,
// the 32 bit reserved data 2,
// the 32 bit suffix length,
// the suffix,
// the 32 bit group length,
// the group,
// the 32 bit origin length and
// the origin
// for this origin directory to test restoring.
{ attrs: { userContextId: 1 }, url: "http://localhost:98", dbName: "dbT",
dbOptions: { version: 1, storage: "default" } }
];
let ios = SpecialPowers.Cc["@mozilla.org/network/io-service;1"]
.getService(SpecialPowers.Ci.nsIIOService);
let ssm = SpecialPowers.Cc["@mozilla.org/scriptsecuritymanager;1"]
.getService(SpecialPowers.Ci.nsIScriptSecurityManager);
function openDatabase(params) {
let request;
if ("url" in params) {
let uri = ios.newURI(params.url, null, null);
let principal = ssm.createCodebasePrincipal(uri, params.attrs || {});
request = indexedDB.openForPrincipal(principal, params.dbName,
params.dbOptions);
} else {
request = indexedDB.open(params.dbName, params.dbOptions);
}
return request;
}
clearAllDatabases(continueToNextStepSync);
yield undefined;
installPackagedProfile("metadata2Restore_profile");
for (let params of openParams) {
let request = openDatabase(params);
request.onerror = errorHandler;
request.onupgradeneeded = unexpectedSuccessHandler;
request.onsuccess = grabEventAndContinueHandler;
let event = yield undefined;
is(event.type, "success", "Correct event type");
}
resetAllDatabases(continueToNextStepSync);
yield undefined;
for (let params of openParams) {
let request = openDatabase(params);
request.onerror = errorHandler;
request.onupgradeneeded = unexpectedSuccessHandler;
request.onsuccess = grabEventAndContinueHandler;
let event = yield undefined;
is(event.type, "success", "Correct event type");
}
finishTest();
yield undefined;
}

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

@ -0,0 +1,72 @@
/**
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
var testGenerator = testSteps();
function testSteps()
{
// This lives in storage/default/http+++www.mozilla.org
const url = "http://www.mozilla.org";
const dbName = "dbC";
const dbVersion = 1;
let ios = SpecialPowers.Cc["@mozilla.org/network/io-service;1"]
.getService(SpecialPowers.Ci.nsIIOService);
let ssm = SpecialPowers.Cc["@mozilla.org/scriptsecuritymanager;1"]
.getService(SpecialPowers.Ci.nsIScriptSecurityManager);
function openDatabase() {
let uri = ios.newURI(url, null, null);
let principal = ssm.createCodebasePrincipal(uri, {});
let request = indexedDB.openForPrincipal(principal, dbName, dbVersion);
return request;
}
clearAllDatabases(continueToNextStepSync);
yield undefined;
installPackagedProfile("oldDirectories_profile");
let request = openDatabase();
request.onerror = errorHandler;
request.onupgradeneeded = unexpectedSuccessHandler;
request.onsuccess = grabEventAndContinueHandler;
let event = yield undefined;
is(event.type, "success", "Correct event type");
resetAllDatabases(continueToNextStepSync);
yield undefined;
request = openDatabase();
request.onerror = errorHandler;
request.onupgradeneeded = unexpectedSuccessHandler;
request.onsuccess = grabEventAndContinueHandler;
event = yield undefined;
is(event.type, "success", "Correct event type");
let directoryService = Cc["@mozilla.org/file/directory_service;1"]
.getService(Ci.nsIProperties);
let profileDir = directoryService.get("ProfD", Ci.nsIFile);
let dir = profileDir.clone();
dir.append("indexedDB");
let exists = dir.exists();
ok(!exists, "indexedDB doesn't exist");
dir = profileDir.clone();
dir.append("storage");
dir.append("persistent");
exists = dir.exists();
ok(!exists, "storage/persistent doesn't exist");
finishTest();
yield undefined;
}

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

@ -0,0 +1,70 @@
/**
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
var testGenerator = testSteps();
function testSteps()
{
const openParams = [
// This one lives in storage/default/http+++www.mozilla.org
{ url: "http://www.mozilla.org", dbName: "dbB", dbVersion: 1 },
// This one lives in storage/default/1007+f+app+++system.gaiamobile.org
{ appId: 1007, inIsolatedMozBrowser: false, url: "app://system.gaiamobile.org",
dbName: "dbM", dbVersion: 1 },
// This one lives in storage/default/1007+t+https+++developer.cdn.mozilla.net
{ appId: 1007, inIsolatedMozBrowser: true, url: "https://developer.cdn.mozilla.net",
dbName: "dbN", dbVersion: 1 },
];
let ios = SpecialPowers.Cc["@mozilla.org/network/io-service;1"]
.getService(SpecialPowers.Ci.nsIIOService);
let ssm = SpecialPowers.Cc["@mozilla.org/scriptsecuritymanager;1"]
.getService(SpecialPowers.Ci.nsIScriptSecurityManager);
function openDatabase(params) {
let uri = ios.newURI(params.url, null, null);
let principal =
ssm.createCodebasePrincipal(uri,
{appId: params.appId || ssm.NO_APPID,
inIsolatedMozBrowser: params.inIsolatedMozBrowser});
let request = indexedDB.openForPrincipal(principal, params.dbName,
params.dbVersion);
return request;
}
clearAllDatabases(continueToNextStepSync);
yield undefined;
installPackagedProfile("schema23upgrade_profile");
for (let params of openParams) {
let request = openDatabase(params);
request.onerror = errorHandler;
request.onupgradeneeded = unexpectedSuccessHandler;
request.onsuccess = grabEventAndContinueHandler;
let event = yield undefined;
is(event.type, "success", "Correct event type");
}
resetAllDatabases(continueToNextStepSync);
yield undefined;
for (let params of openParams) {
let request = openDatabase(params);
request.onerror = errorHandler;
request.onupgradeneeded = unexpectedSuccessHandler;
request.onsuccess = grabEventAndContinueHandler;
let event = yield undefined;
is(event.type, "success", "Correct event type");
}
finishTest();
yield undefined;
}

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

@ -0,0 +1,70 @@
/**
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
var testGenerator = testSteps();
function testSteps()
{
const openParams = [
// This one lives in storage/default/http+++www.mozilla.org
{ url: "http://www.mozilla.org", dbName: "dbB", dbVersion: 1 },
// This one lives in storage/default/1007+f+app+++system.gaiamobile.org
{ appId: 1007, inIsolatedMozBrowser: false, url: "app://system.gaiamobile.org",
dbName: "dbM", dbVersion: 1 },
// This one lives in storage/default/1007+t+https+++developer.cdn.mozilla.net
{ appId: 1007, inIsolatedMozBrowser: true, url: "https://developer.cdn.mozilla.net",
dbName: "dbN", dbVersion: 1 },
];
let ios = SpecialPowers.Cc["@mozilla.org/network/io-service;1"]
.getService(SpecialPowers.Ci.nsIIOService);
let ssm = SpecialPowers.Cc["@mozilla.org/scriptsecuritymanager;1"]
.getService(SpecialPowers.Ci.nsIScriptSecurityManager);
function openDatabase(params) {
let uri = ios.newURI(params.url, null, null);
let principal =
ssm.createCodebasePrincipal(uri,
{appId: params.appId || ssm.NO_APPID,
inIsolatedMozBrowser: params.inIsolatedMozBrowser});
let request = indexedDB.openForPrincipal(principal, params.dbName,
params.dbVersion);
return request;
}
clearAllDatabases(continueToNextStepSync);
yield undefined;
installPackagedProfile("storagePersistentUpgrade_profile");
for (let params of openParams) {
let request = openDatabase(params);
request.onerror = errorHandler;
request.onupgradeneeded = unexpectedSuccessHandler;
request.onsuccess = grabEventAndContinueHandler;
let event = yield undefined;
is(event.type, "success", "Correct event type");
}
resetAllDatabases(continueToNextStepSync);
yield undefined;
for (let params of openParams) {
let request = openDatabase(params);
request.onerror = errorHandler;
request.onupgradeneeded = unexpectedSuccessHandler;
request.onsuccess = grabEventAndContinueHandler;
let event = yield undefined;
is(event.type, "success", "Correct event type");
}
finishTest();
yield undefined;
}

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

@ -10,15 +10,21 @@ skip-if = toolkit == 'gonk'
support-files =
bug1056939_profile.zip
defaultStorageUpgrade_profile.zip
idbSubdirUpgrade1_profile.zip
idbSubdirUpgrade2_profile.zip
mutableFileUpgrade_profile.zip
oldDirectories_profile.zip
GlobalObjectsChild.js
GlobalObjectsComponent.js
GlobalObjectsComponent.manifest
GlobalObjectsModule.jsm
GlobalObjectsSandbox.js
metadata2Restore_profile.zip
metadataRestore_profile.zip
schema18upgrade_profile.zip
schema21upgrade_profile.zip
schema23upgrade_profile.zip
storagePersistentUpgrade_profile.zip
xpcshell-shared.ini
[include:xpcshell-shared.ini]
@ -27,6 +33,7 @@ support-files =
[test_bug1056939.js]
[test_cleanup_transaction.js]
[test_defaultStorageUpgrade.js]
[test_idbSubdirUpgrade.js]
[test_globalObjects_ipc.js]
skip-if = toolkit == 'android'
[test_idle_maintenance.js]
@ -34,12 +41,16 @@ skip-if = toolkit == 'android'
# disabled for the moment.
skip-if = true
[test_lowDiskSpace.js]
[test_metadata2Restore.js]
[test_metadataRestore.js]
[test_mutableFileUpgrade.js]
[test_oldDirectories.js]
[test_quotaExceeded_recovery.js]
[test_readwriteflush_disabled.js]
[test_schema18upgrade.js]
[test_schema21upgrade.js]
[test_schema23upgrade.js]
[test_storagePersistentUpgrade.js]
[test_temporary_storage.js]
# bug 951017: intermittent failure on Android x86 emulator
skip-if = os == "android" && processor == "x86"

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

@ -90,17 +90,13 @@
info("blocking browserFrame");
event.preventDefault();
let request = navigator.mozApps.getSelf();
request.onsuccess = function() {
let app = request.result;
ok(app, "got app");
let appId = SpecialPowers.wrap(document).nodePrincipal.appId;
info("clearing browser data");
app.clearBrowserData();
info("clearing browser data");
SpecialPowers.clearAppPrivateData(appId, true);
info("unblocking browserFrame");
event.detail.unblock();
}
info("unblocking browserFrame");
event.detail.unblock();
break;
case "done":
continueToNextStepSync();

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

@ -663,9 +663,10 @@ void AudioClock::UpdateFrameHistory(uint32_t aServiced, uint32_t aUnderrun)
mFrameHistory->Append(aServiced, aUnderrun, mOutRate);
}
int64_t AudioClock::GetPositionInFrames(int64_t frames) const
int64_t AudioClock::GetPositionInFrames(int64_t aFrames) const
{
return (GetPosition(frames) * mInRate) / USECS_PER_S;
CheckedInt64 v = UsecsToFrames(GetPosition(aFrames), mInRate);
return v.isValid() ? v.value() : -1;
}
int64_t AudioClock::GetPosition(int64_t frames) const

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

@ -46,11 +46,11 @@ public:
void UpdateFrameHistory(uint32_t aServiced, uint32_t aUnderrun);
/**
* @param frames The playback position in frames of the audio engine.
* @param aFrames The playback position in frames of the audio engine.
* @return The playback position in frames of the stream,
* adjusted by playback rate changes and underrun frames.
*/
int64_t GetPositionInFrames(int64_t frames) const;
int64_t GetPositionInFrames(int64_t aFrames) const;
/**
* @param frames The playback position in frames of the audio engine.

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

@ -626,6 +626,9 @@ AudioCallbackDriver::Init()
mGraphImpl->mOutputWanted ? &output : nullptr, latency,
DataCallback_s, StateCallback_s, this) == CUBEB_OK) {
mAudioStream.own(stream);
DebugOnly<int> rv = cubeb_stream_set_volume(mAudioStream, CubebUtils::GetVolumeScale());
NS_WARN_IF_FALSE(rv == CUBEB_OK,
"Could not set the audio stream volume in GraphDriver.cpp");
} else {
#ifdef MOZ_WEBRTC
StaticMutexAutoUnlock unlock(AudioInputCubeb::Mutex());

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

@ -129,6 +129,7 @@ public:
uint64_t aWindowID,
const PrincipalHandle& aPrincipalHandle)
: mMediaThread(aThread)
, mMainThreadCheck(nullptr)
, mWindowID(aWindowID)
, mPrincipalHandle(aPrincipalHandle)
, mStopped(false)
@ -149,6 +150,7 @@ public:
VideoDevice* aVideoDevice)
{
MOZ_ASSERT(NS_IsMainThread());
mMainThreadCheck = PR_GetCurrentThread();
mStream = aStream;
mAudioDevice = aAudioDevice;
mVideoDevice = aVideoDevice;
@ -274,14 +276,33 @@ public:
NotifyEvent(MediaStreamGraph* aGraph,
MediaStreamListener::MediaStreamGraphEvent aEvent) override
{
nsresult rv;
nsCOMPtr<nsIThread> thread;
switch (aEvent) {
case EVENT_FINISHED:
NS_DispatchToMainThread(
NewRunnableMethod(this, &GetUserMediaCallbackMediaStreamListener::NotifyFinished));
rv = NS_GetMainThread(getter_AddRefs(thread));
if (NS_WARN_IF(NS_FAILED(rv))) {
NS_ASSERTION(false, "Mainthread not available; running on current thread");
// Ensure this really *was* MainThread (NS_GetCurrentThread won't work)
MOZ_RELEASE_ASSERT(mMainThreadCheck == PR_GetCurrentThread());
NotifyFinished();
return;
}
thread->Dispatch(NewRunnableMethod(this, &GetUserMediaCallbackMediaStreamListener::NotifyFinished),
NS_DISPATCH_NORMAL);
break;
case EVENT_REMOVED:
NS_DispatchToMainThread(
NewRunnableMethod(this, &GetUserMediaCallbackMediaStreamListener::NotifyRemoved));
rv = NS_GetMainThread(getter_AddRefs(thread));
if (NS_WARN_IF(NS_FAILED(rv))) {
NS_ASSERTION(false, "Mainthread not available; running on current thread");
// Ensure this really *was* MainThread (NS_GetCurrentThread won't work)
MOZ_RELEASE_ASSERT(mMainThreadCheck == PR_GetCurrentThread());
NotifyRemoved();
return;
}
thread->Dispatch(NewRunnableMethod(this, &GetUserMediaCallbackMediaStreamListener::NotifyRemoved),
NS_DISPATCH_NORMAL);
break;
case EVENT_HAS_DIRECT_LISTENERS:
NotifyDirectListeners(aGraph, true);
@ -308,6 +329,9 @@ public:
private:
// Set at construction
base::Thread* mMediaThread;
// never ever indirect off this; just for assertions
PRThread* mMainThreadCheck;
uint64_t mWindowID;
const PrincipalHandle mPrincipalHandle;

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

@ -30,6 +30,7 @@ class PeerConnectionMedia;
class PeerIdentity;
class ProcessedMediaStream;
class RemoteSourceStreamInfo;
class SourceStreamInfo;
namespace dom {
@ -228,6 +229,7 @@ class MediaStreamTrack : public DOMEventTargetHelper,
// PeerConnection and friends need to know our owning DOMStream and track id.
friend class mozilla::PeerConnectionImpl;
friend class mozilla::PeerConnectionMedia;
friend class mozilla::SourceStreamInfo;
friend class mozilla::RemoteSourceStreamInfo;
class PrincipalHandleListener;

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

@ -39,7 +39,7 @@ TextTrackCue::SetDefaultCueSettings()
mSnapToLines = true;
mLineIsAutoKeyword = true;
mAlign = AlignSetting::Middle;
mLineAlign = AlignSetting::Start;
mLineAlign = LineAlignSetting::Start;
mVertical = DirectionSetting::_empty;
mActive = false;
}

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

@ -172,19 +172,15 @@ public:
}
}
AlignSetting LineAlign() const
LineAlignSetting LineAlign() const
{
return mLineAlign;
}
void SetLineAlign(AlignSetting& aLineAlign, ErrorResult& aRv)
void SetLineAlign(LineAlignSetting& aLineAlign, ErrorResult& aRv)
{
if (mLineAlign == aLineAlign)
if (mLineAlign == aLineAlign) {
return;
if (aLineAlign == AlignSetting::Left ||
aLineAlign == AlignSetting::Right) {
return aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
}
mReset = true;
@ -364,7 +360,7 @@ private:
bool mLineIsAutoKeyword;
long mLineLong;
AlignSetting mAlign;
AlignSetting mLineAlign;
LineAlignSetting mLineAlign;
// Holds the computed DOM elements that represent the parsed cue text.
// http://www.whatwg.org/specs/web-apps/current-work/#text-track-cue-display-state

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

@ -212,21 +212,34 @@ navigator.requestMediaKeySystemAccess('com.adobe.primetime',
"""
reset_widevine_gmp_script = """
navigator.requestMediaKeySystemAccess('com.widevine.alpha',
[{initDataTypes: ['cenc']}]).then(
function(access) {
marionetteScriptFinished('success');
},
function(ex) {
marionetteScriptFinished(ex);
}
);
"""
class EMESetupMixin(object):
"""
An object that needs to use the Adobe GMP system must inherit from this
class, and then call check_eme_system() to insure that everything is
setup correctly.
An object that needs to use the Adobe or Widevine GMP system must inherit
from this class, and then call check_eme_system() to insure that everything
is setup correctly.
"""
version_needs_reset = True
def check_eme_system(self):
"""
Download the most current version of the Adobe GMP Plugin. Verify
that all MSE and EME prefs are set correctly. Raises if things
are not OK.
Download the most current version of the Adobe and Widevine GMP
Plugins. Verify that all MSE and EME prefs are set correctly. Raises
if things are not OK.
"""
self.set_eme_prefs()
self.reset_GMP_version()
@ -244,13 +257,21 @@ class EMESetupMixin(object):
with self.marionette.using_context('chrome'):
if self.prefs.get_pref('media.gmp-eme-adobe.version'):
self.prefs.reset_pref('media.gmp-eme-adobe.version')
if self.prefs.get_pref('media.gmp-widevinecdm.version'):
self.prefs.reset_pref('media.gmp-widevinecdm.version')
with self.marionette.using_context('content'):
result = self.marionette.execute_async_script(
adobe_result = self.marionette.execute_async_script(
reset_adobe_gmp_script,
script_timeout=60000)
if not result == 'success':
widevine_result = self.marionette.execute_async_script(
reset_widevine_gmp_script,
script_timeout=60000)
if not adobe_result == 'success':
raise VideoException(
'ERROR: Resetting Adobe GMP failed % s' % result)
if not widevine_result == 'success':
raise VideoException(
'ERROR: Resetting Widevine GMP failed % s' % result)
EMESetupMixin.version_needs_reset = False
@ -287,20 +308,50 @@ class EMESetupMixin(object):
return pref_value >= minimum_value
def chceck_and_log_version_string_pref(self, pref_name, minimum_value='0'):
"""
Compare a pref made up of integers separated by stops .s, with a
version string of the same format. The number of integers in each string
does not need to match. The comparison is done by converting each to an
integer array and comparing those. Both version strings must be made
up of only integers, or this method will raise an unhandled exception
of type ValueError when the conversion to int fails.
"""
with self.marionette.using_context('chrome'):
pref_value = self.prefs.get_pref(pref_name)
if pref_value is None:
self.logger.info('Pref %s has no value.' % pref_name)
return False
else:
self.logger.info('Pref %s = %s' % (pref_name, pref_value))
match = re.search('^\d(.\d+)*$', pref_value)
if not match:
self.logger.info('Pref %s is not a version string' % pref_name)
return False
pref_ints = [int(n) for n in pref_value.split('.')]
minumum_ints = [int(n) for n in minimum_value.split('.')]
return pref_ints >= minumum_ints
def check_eme_prefs(self):
with self.marionette.using_context('chrome'):
prefs_ok = self.check_and_log_boolean_pref(
'media.mediasource.enabled', True)
prefs_ok = self.check_and_log_boolean_pref(
'media.eme.enabled', True) and prefs_ok
prefs_ok = self.check_and_log_boolean_pref(
'media.mediasource.mp4.enabled', True) and prefs_ok
prefs_ok = self.check_and_log_boolean_pref(
'media.gmp-eme-adobe.enabled', True) and prefs_ok
prefs_ok = self.check_and_log_integer_pref(
'media.gmp-eme-adobe.version', 1) and prefs_ok
return prefs_ok
return all([
self.check_and_log_boolean_pref(
'media.mediasource.enabled', True),
self.check_and_log_boolean_pref(
'media.eme.enabled', True),
self.check_and_log_boolean_pref(
'media.mediasource.mp4.enabled', True),
self.check_and_log_boolean_pref(
'media.gmp-eme-adobe.enabled', True),
self.check_and_log_integer_pref(
'media.gmp-eme-adobe.version', 1),
self.check_and_log_boolean_pref(
'media.gmp-widevinecdm.enabled', True),
self.chceck_and_log_version_string_pref(
'media.gmp-widevinecdm.version', '1.0.0.0')
])

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

@ -128,33 +128,13 @@ SpecialPowers.pushPrefEnv({"set": [["media.webvtt.regions.enabled", true]]},
}
checkEnumValue("align", "middle", [ "start", "left", "middle", "right", "end" ]);
checkEnumValue("lineAlign", "start", [ "start", "center", "end" ]);
checkEnumValue("vertical", "", [ "", "lr", "rl" ]);
// Check that cue line align works properly
is(cue.lineAlign, "start", "Cue's default line alignment should be start.");
exceptionHappened = false;
try {
cue.lineAlign = "left";
} catch(e) {
exceptionHappened = true;
is(e.name, "SyntaxError", "Should have thrown SyntaxError.");
}
ok(exceptionHappened, "Exception should have happened.");
exceptionHappened = false;
try {
cue.lineAlign = "right";
} catch(e) {
exceptionHappened = true;
is(e.name, "SyntaxError", "Should have thrown SyntaxError.");
}
ok(exceptionHappened, "Exception should have happened.");
cue.lineAlign = "middle";
is(cue.lineAlign, "middle", "Cue's line align should be middle.");
cue.lineAlign = "center";
is(cue.lineAlign, "center", "Cue's line align should be center.");
cue.lineAlign = "START";
is(cue.lineAlign, "middle", "Cue's line align should be middle.");
is(cue.lineAlign, "center", "Cue's line align should be center.");
cue.lineAlign = "end";
is(cue.lineAlign, "end", "Cue's line align should be end.");

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

@ -204,7 +204,7 @@ this.EXPORTED_SYMBOLS = ["WebVTT"];
settings.percent(k, vals0) ? settings.set("snapToLines", false) : null;
settings.alt(k, vals0, ["auto"]);
if (vals.length === 2) {
settings.alt("lineAlign", vals[1], ["start", "middle", "end"]);
settings.alt("lineAlign", vals[1], ["start", "center", "end"]);
}
break;
case "position":
@ -1076,7 +1076,7 @@ this.EXPORTED_SYMBOLS = ["WebVTT"];
var calculatedPercentage = (boxPosition.lineHeight / containerBox.height) * 100;
switch (cue.lineAlign) {
case "middle":
case "center":
linePos -= (calculatedPercentage / 2);
break;
case "end":

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

@ -99,18 +99,6 @@ interface nsIPluginHost : nsISupports
ACString getPermissionStringForType(in AUTF8String mimeType,
[optional] in uint32_t excludeFlags);
/**
* Get the "permission string" for the plugin. This is a string that can be
* passed to the permission manager to see whether the plugin is allowed to
* run, for example. This will typically be based on the plugin's "nice name"
* and its blocklist state.
*
* @tag The tage we're interested in
* @excludeFlags Set of the EXCLUDE_* flags above, defaulting to EXCLUDE_NONE.
*/
ACString getPermissionStringForTag(in nsIPluginTag tag,
[optional] in uint32_t excludeFlags);
/**
* Get the nsIPluginTag for this MIME type. This method works with both
* enabled and disabled/blocklisted plugins, but an enabled plugin will

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

@ -1110,19 +1110,11 @@ nsPluginHost::GetPermissionStringForType(const nsACString &aMimeType,
nsresult rv = GetPluginTagForType(aMimeType, aExcludeFlags,
getter_AddRefs(tag));
NS_ENSURE_SUCCESS(rv, rv);
return GetPermissionStringForTag(tag, aExcludeFlags, aPermissionString);
}
NS_IMETHODIMP
nsPluginHost::GetPermissionStringForTag(nsIPluginTag* aTag,
uint32_t aExcludeFlags,
nsACString &aPermissionString)
{
NS_ENSURE_TRUE(aTag, NS_ERROR_FAILURE);
NS_ENSURE_TRUE(tag, NS_ERROR_FAILURE);
aPermissionString.Truncate();
uint32_t blocklistState;
nsresult rv = aTag->GetBlocklistState(&blocklistState);
rv = tag->GetBlocklistState(&blocklistState);
NS_ENSURE_SUCCESS(rv, rv);
if (blocklistState == nsIBlocklistService::STATE_VULNERABLE_UPDATE_AVAILABLE ||
@ -1134,7 +1126,7 @@ nsPluginHost::GetPermissionStringForTag(nsIPluginTag* aTag,
}
nsCString niceName;
rv = aTag->GetNiceName(niceName);
rv = tag->GetNiceName(niceName);
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(!niceName.IsEmpty(), NS_ERROR_FAILURE);

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

@ -886,16 +886,16 @@ nsPluginInstanceOwner::GetCompositionString(uint32_t aType,
for (TextRange& range : *ranges) {
uint8_t type = ATTR_INPUT;
switch(range.mRangeType) {
case NS_TEXTRANGE_RAWINPUT:
case TextRangeType::eRawClause:
type = ATTR_INPUT;
break;
case NS_TEXTRANGE_SELECTEDRAWTEXT:
case TextRangeType::eSelectedRawClause:
type = ATTR_TARGET_NOTCONVERTED;
break;
case NS_TEXTRANGE_CONVERTEDTEXT:
case TextRangeType::eConvertedClause:
type = ATTR_CONVERTED;
break;
case NS_TEXTRANGE_SELECTEDCONVERTEDTEXT:
case TextRangeType::eSelectedClause:
type = ATTR_TARGET_CONVERTED;
break;
default:

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

@ -323,7 +323,7 @@ nsPluginTag::~nsPluginTag()
NS_ASSERTION(!mNext, "Risk of exhausting the stack space, bug 486349");
}
NS_IMPL_ISUPPORTS(nsPluginTag, nsPluginTag, nsIInternalPluginTag, nsIPluginTag)
NS_IMPL_ISUPPORTS(nsPluginTag, nsIPluginTag, nsIInternalPluginTag)
void nsPluginTag::InitMime(const char* const* aMimeTypes,
const char* const* aMimeDescriptions,

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

@ -31,9 +31,6 @@ struct FakePluginTagInit;
{ 0xe8fdd227, 0x27da, 0x46ee, \
{ 0xbe, 0xf3, 0x1a, 0xef, 0x5a, 0x8f, 0xc5, 0xb4 } }
#define NS_PLUGINTAG_IID \
{ 0xcce2e8b9, 0x9702, 0x4d4b, \
{ 0xbe, 0xa4, 0x7c, 0x1e, 0x13, 0x1f, 0xaf, 0x78 } }
class nsIInternalPluginTag : public nsIPluginTag
{
public:
@ -94,8 +91,6 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsIInternalPluginTag, NS_IINTERNALPLUGINTAG_IID)
class nsPluginTag final : public nsIInternalPluginTag
{
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_PLUGINTAG_IID)
NS_DECL_ISUPPORTS
NS_DECL_NSIPLUGINTAG
@ -198,7 +193,6 @@ private:
static uint32_t sNextId;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsPluginTag, NS_PLUGINTAG_IID)
// A class representing "fake" plugin tags; that is plugin tags not
// corresponding to actual NPAPI plugins. In practice these are all

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

@ -0,0 +1,46 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "DCPresentationChannelDescription.h"
namespace mozilla {
namespace dom {
NS_IMPL_ISUPPORTS(DCPresentationChannelDescription,
nsIPresentationChannelDescription)
NS_IMETHODIMP
DCPresentationChannelDescription::GetType(uint8_t* aRetVal)
{
if (NS_WARN_IF(!aRetVal)) {
return NS_ERROR_INVALID_POINTER;
}
*aRetVal = nsIPresentationChannelDescription::TYPE_DATACHANNEL;
return NS_OK;
}
NS_IMETHODIMP
DCPresentationChannelDescription::GetTcpAddress(nsIArray** aRetVal)
{
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
DCPresentationChannelDescription::GetTcpPort(uint16_t* aRetVal)
{
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
DCPresentationChannelDescription::GetDataChannelSDP(nsAString& aDataChannelSDP)
{
aDataChannelSDP = mSDP;
return NS_OK;
}
} // namespace dom
} // namespace mozilla

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

@ -0,0 +1,37 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_DCPresentationChannelDescription_h
#define mozilla_dom_DCPresentationChannelDescription_h
#include "nsIPresentationControlChannel.h"
#include "nsString.h"
namespace mozilla {
namespace dom {
// PresentationChannelDescription for Data Channel
class DCPresentationChannelDescription final : public nsIPresentationChannelDescription
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIPRESENTATIONCHANNELDESCRIPTION
explicit DCPresentationChannelDescription(const nsAString& aSDP)
: mSDP(aSDP)
{
}
private:
virtual ~DCPresentationChannelDescription() = default;
nsString mSDP;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_DCPresentationChannelDescription_h

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

@ -49,11 +49,10 @@ PresentationTransportBuilder.prototype = {
classID: PRESENTATIONTRANSPORTBUILDER_CID,
contractID: PRESENTATIONTRANSPORTBUILDER_CONTRACTID,
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationDataChannelSessionTransportBuilder,
Ci.nsIPresentationControlChannelListener,
Ci.nsITimerCallback]),
buildDataChannelTransport: function(aRole, aWindow, aControlChannel, aListener) {
if (!aRole || !aWindow || !aControlChannel || !aListener) {
buildDataChannelTransport: function(aRole, aWindow, aListener) {
if (!aRole || !aWindow || !aListener) {
log("buildDataChannelTransport with illegal parameters");
throw Cr.NS_ERROR_ILLEGAL_VALUE;
}
@ -66,23 +65,21 @@ PresentationTransportBuilder.prototype = {
log("buildDataChannelTransport with role " + aRole);
this._role = aRole;
this._window = aWindow;
this._controlChannel = aControlChannel.QueryInterface(Ci.nsIPresentationControlChannel);
this._controlChannel.listener = this;
this._listener = aListener.QueryInterface(Ci.nsIPresentationSessionTransportBuilderListener);
// TODO bug 1227053 set iceServers from |nsIPresentationDevice|
this._peerConnection = new this._window.RTCPeerConnection();
// |this._controlChannel == null| will throw since the control channel is
// |this._listener == null| will throw since the control channel is
// abnormally closed.
this._peerConnection.onicecandidate = aEvent => aEvent.candidate &&
this._controlChannel.sendIceCandidate(JSON.stringify(aEvent.candidate));
this._listener.sendIceCandidate(JSON.stringify(aEvent.candidate));
this._peerConnection.onnegotiationneeded = () => {
log("onnegotiationneeded with role " + this._role);
this._peerConnection.createOffer()
.then(aOffer => this._peerConnection.setLocalDescription(aOffer))
.then(() => this._controlChannel
.then(() => this._listener
.sendOffer(new PresentationDataChannelDescription(this._peerConnection.localDescription)))
.catch(e => this._reportError(e));
}
@ -169,11 +166,6 @@ PresentationTransportBuilder.prototype = {
this._role = null;
this._window = null;
if (this._controlChannel) {
this._controlChannel.close(aReason);
this._controlChannel = null;
}
this._listener = null;
this._sessionTransport = null;
@ -202,7 +194,7 @@ PresentationTransportBuilder.prototype = {
.then(aAnswer => this._peerConnection.setLocalDescription(aAnswer))
.then(() => {
this._isControlChannelNeeded = false;
this._controlChannel
this._listener
.sendAnswer(new PresentationDataChannelDescription(this._peerConnection.localDescription))
}).catch(e => this._reportError(e));
},
@ -229,10 +221,6 @@ PresentationTransportBuilder.prototype = {
this._peerConnection.addIceCandidate(candidate).catch(e => this._reportError(e));
},
notifyOpened: function() {
log("notifyOpened, should be opened beforehand");
},
notifyClosed: function(aReason) {
log("notifyClosed reason: " + aReason);
@ -241,7 +229,6 @@ PresentationTransportBuilder.prototype = {
} else if (this._isControlChannelNeeded) {
this._cleanup(Cr.NS_ERROR_FAILURE);
}
this._controlChannel = null;
},
};

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

@ -453,7 +453,7 @@ PresentationService::StartSession(const nsAString& aUrl,
NS_ConvertUTF16toUTF8 utf8DeviceId(aDeviceId);
bool hasMore;
while(NS_SUCCEEDED(enumerator->HasMoreElements(&hasMore)) && hasMore){
while (NS_SUCCEEDED(enumerator->HasMoreElements(&hasMore)) && hasMore) {
nsCOMPtr<nsISupports> isupports;
rv = enumerator->GetNext(getter_AddRefs(isupports));
@ -618,6 +618,25 @@ PresentationService::UnregisterSessionListener(const nsAString& aSessionId,
return NS_OK;
}
nsresult
PresentationService::RegisterTransportBuilder(const nsAString& aSessionId,
uint8_t aRole,
nsIPresentationSessionTransportBuilder* aBuilder)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aBuilder);
MOZ_ASSERT(aRole == nsIPresentationService::ROLE_CONTROLLER ||
aRole == nsIPresentationService::ROLE_RECEIVER);
RefPtr<PresentationSessionInfo> info = GetSessionInfo(aSessionId, aRole);
if (NS_WARN_IF(!info)) {
return NS_ERROR_NOT_AVAILABLE;
}
info->SetBuilder(aBuilder);
return NS_OK;
}
NS_IMETHODIMP
PresentationService::RegisterRespondingListener(
uint64_t aWindowId,
@ -683,6 +702,23 @@ PresentationService::NotifyReceiverReady(const nsAString& aSessionId,
return static_cast<PresentationPresentingInfo*>(info.get())->NotifyResponderReady();
}
nsresult
PresentationService::NotifyTransportClosed(const nsAString& aSessionId,
uint8_t aRole,
nsresult aReason) {
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!aSessionId.IsEmpty());
MOZ_ASSERT(aRole == nsIPresentationService::ROLE_CONTROLLER ||
aRole == nsIPresentationService::ROLE_RECEIVER);
RefPtr<PresentationSessionInfo> info = GetSessionInfo(aSessionId, aRole);
if (NS_WARN_IF(!info)) {
return NS_ERROR_NOT_AVAILABLE;
}
return info->NotifyTransportClosed(aReason);
}
NS_IMETHODIMP
PresentationService::UntrackSessionInfo(const nsAString& aSessionId,
uint8_t aRole)

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

@ -15,6 +15,7 @@
class nsIPresentationSessionRequest;
class nsIURI;
class nsIPresentationSessionTransportBuilder;
namespace mozilla {
namespace dom {
@ -54,6 +55,10 @@ public:
const uint8_t aRole,
base::ProcessId aProcessId);
nsresult RegisterTransportBuilder(const nsAString& aSessionId,
uint8_t aRole,
nsIPresentationSessionTransportBuilder* aBuilder);
private:
friend class PresentationDeviceRequest;

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

@ -7,6 +7,7 @@
#ifndef mozilla_dom_PresentationServiceBase_h
#define mozilla_dom_PresentationServiceBase_h
#include "nsClassHashtable.h"
#include "nsRefPtrHashtable.h"
#include "nsTArray.h"

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

@ -237,7 +237,7 @@ PresentationSessionInfo::Shutdown(nsresult aReason)
mIsResponderReady = false;
mBuilder = nullptr;
SetBuilder(nullptr);
}
nsresult
@ -350,6 +350,11 @@ PresentationSessionInfo::NotifyTransportReady()
mIsTransportReady = true;
// Established RTCDataChannel implies responder is ready.
if (mTransportType == nsIPresentationChannelDescription::TYPE_DATACHANNEL) {
mIsResponderReady = true;
}
// At sender side, session might not be ready at this point (waiting for
// receiver's answer). Yet at receiver side, session must be ready at this
// point since the data transport channel is created after the receiver page
@ -413,6 +418,13 @@ PresentationSessionInfo::NotifyData(const nsACString& aData)
NS_IMETHODIMP
PresentationSessionInfo::OnSessionTransport(nsIPresentationSessionTransport* transport)
{
SetBuilder(nullptr);
// The session transport is managed by content process
if (!transport) {
return NS_OK;
}
mTransport = transport;
nsresult rv = mTransport->SetCallback(this);
@ -430,9 +442,34 @@ PresentationSessionInfo::OnSessionTransport(nsIPresentationSessionTransport* tra
NS_IMETHODIMP
PresentationSessionInfo::OnError(nsresult reason)
{
SetBuilder(nullptr);
return ReplyError(reason);
}
NS_IMETHODIMP
PresentationSessionInfo::SendOffer(nsIPresentationChannelDescription* aOffer)
{
return mControlChannel->SendOffer(aOffer);
}
NS_IMETHODIMP
PresentationSessionInfo::SendAnswer(nsIPresentationChannelDescription* aAnswer)
{
return mControlChannel->SendAnswer(aAnswer);
}
NS_IMETHODIMP
PresentationSessionInfo::SendIceCandidate(const nsAString& candidate)
{
return mControlChannel->SendIceCandidate(candidate);
}
NS_IMETHODIMP
PresentationSessionInfo::Close(nsresult reason)
{
return mControlChannel->Close(reason);
}
/**
* Implementation of PresentationControllingInfo
*
@ -577,13 +614,6 @@ PresentationControllingInfo::GetAddress()
return NS_OK;
}
NS_IMETHODIMP
PresentationControllingInfo::OnIceCandidate(const nsAString& aCandidate)
{
MOZ_ASSERT(false, "Should not receive ICE candidates.");
return NS_ERROR_FAILURE;
}
nsresult
PresentationControllingInfo::OnGetAddress(const nsACString& aAddress)
{
@ -602,6 +632,23 @@ PresentationControllingInfo::OnGetAddress(const nsACString& aAddress)
}
// nsIPresentationControlChannelListener
NS_IMETHODIMP
PresentationControllingInfo::OnIceCandidate(const nsAString& aCandidate)
{
if (mTransportType != nsIPresentationChannelDescription::TYPE_DATACHANNEL) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIPresentationDataChannelSessionTransportBuilder>
builder = do_QueryInterface(mBuilder);
if (NS_WARN_IF(!builder)) {
return NS_ERROR_FAILURE;
}
return builder->OnIceCandidate(aCandidate);
}
NS_IMETHODIMP
PresentationControllingInfo::OnOffer(nsIPresentationChannelDescription* aDescription)
{
@ -612,6 +659,17 @@ PresentationControllingInfo::OnOffer(nsIPresentationChannelDescription* aDescrip
NS_IMETHODIMP
PresentationControllingInfo::OnAnswer(nsIPresentationChannelDescription* aDescription)
{
if (mTransportType == nsIPresentationChannelDescription::TYPE_DATACHANNEL) {
nsCOMPtr<nsIPresentationDataChannelSessionTransportBuilder>
builder = do_QueryInterface(mBuilder);
if (NS_WARN_IF(!builder)) {
return NS_ERROR_FAILURE;
}
return builder->OnAnswer(aDescription);
}
mIsResponderReady = true;
// Close the control channel since it's no longer needed.
@ -639,21 +697,48 @@ PresentationControllingInfo::NotifyOpened()
return GetAddress();
}
nsCOMPtr<nsIPresentationDataChannelSessionTransportBuilder> builder =
do_CreateInstance("@mozilla.org/presentation/datachanneltransportbuilder;1");
if (NS_WARN_IF(!builder)) {
return NS_ERROR_NOT_AVAILABLE;
nsPIDOMWindowInner* window = nullptr;
/**
* Generally transport is maintained by the chrome process. However, data
* channel should be live with the DOM , which implies RTCDataChannel in an OOP
* page should be establish in the content process.
*
* In OOP data channel transport case, |mBuilder| is hooked when the content
* process is ready to build a data channel transport, trigger by:
* 1. PresentationIPCService::StartSession (sender)
* 2. PresentationIPCService::NotifyReceiverReady (receiver).
*
* In this case, |mBuilder| would be an object of |PresentationBuilderParent|
* and set previously. Therefore, |BuildDataChannelTransport| triggers an IPC
* call to make content process establish a RTCDataChannel transport.
*/
// in-process case
if (!mBuilder) {
nsCOMPtr<nsIPresentationDataChannelSessionTransportBuilder> builder =
do_CreateInstance("@mozilla.org/presentation/datachanneltransportbuilder;1");
if (NS_WARN_IF(!builder)) {
return NS_ERROR_NOT_AVAILABLE;
}
SetBuilder(builder);
// OOP window would be set from content process
window = GetWindow();
}
mBuilder = builder;
// OOP case
mTransportType = nsIPresentationChannelDescription::TYPE_DATACHANNEL;
return builder->BuildDataChannelTransport(nsIPresentationService::ROLE_CONTROLLER,
GetWindow(),
mControlChannel,
nsCOMPtr<nsIPresentationDataChannelSessionTransportBuilder>
dataChannelBuilder(do_QueryInterface(mBuilder));
if (NS_WARN_IF(!dataChannelBuilder)) {
return NS_ERROR_NOT_AVAILABLE;
}
nsresult rv = dataChannelBuilder->
BuildDataChannelTransport(nsIPresentationService::ROLE_CONTROLLER,
window,
this);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
return NS_OK;
}
NS_IMETHODIMP
@ -661,6 +746,14 @@ PresentationControllingInfo::NotifyClosed(nsresult aReason)
{
MOZ_ASSERT(NS_IsMainThread());
if (mTransportType == nsIPresentationChannelDescription::TYPE_DATACHANNEL) {
nsCOMPtr<nsIPresentationDataChannelSessionTransportBuilder>
builder = do_QueryInterface(mBuilder);
if (builder) {
NS_WARN_IF(NS_FAILED(builder->NotifyClosed(aReason)));
}
}
// Unset control channel here so it won't try to re-close it in potential
// subsequent |Shutdown| calls.
SetControlChannel(nullptr);
@ -784,6 +877,7 @@ PresentationPresentingInfo::Shutdown(nsresult aReason)
mDevice = nullptr;
mLoadingCallback = nullptr;
mRequesterDescription = nullptr;
mPendingCandidates.Clear();
mPromise = nullptr;
}
@ -797,6 +891,11 @@ PresentationPresentingInfo::OnSessionTransport(nsIPresentationSessionTransport*
return rv;
}
// The session transport is managed by content process
if (!transport) {
return NS_OK;
}
// send answer for TCP session transport
if (mTransportType == nsIPresentationChannelDescription::TYPE_TCP) {
// Prepare and send the answer.
@ -823,10 +922,26 @@ PresentationPresentingInfo::OnSessionTransport(nsIPresentationSessionTransport*
return NS_OK;
}
// Delegate the pending offer and ICE candidates to builder.
NS_IMETHODIMP
PresentationPresentingInfo::OnError(nsresult reason)
PresentationPresentingInfo::FlushPendingEvents(nsIPresentationDataChannelSessionTransportBuilder* builder)
{
return PresentationSessionInfo::OnError(reason);
if (NS_WARN_IF(!builder)) {
return NS_ERROR_FAILURE;
}
mHasFlushPendingEvents = true;
if (mRequesterDescription) {
builder->OnOffer(mRequesterDescription);
}
mRequesterDescription = nullptr;
for (size_t i = 0; i < mPendingCandidates.Length(); ++i) {
builder->OnIceCandidate(mPendingCandidates[i]);
}
mPendingCandidates.Clear();
return NS_OK;
}
nsresult
@ -849,7 +964,7 @@ PresentationPresentingInfo::InitTransportAndSendAnswer()
return NS_ERROR_NOT_AVAILABLE;
}
mBuilder = builder;
SetBuilder(builder);
mTransportType = nsIPresentationChannelDescription::TYPE_TCP;
return builder->BuildTCPReceiverTransport(mRequesterDescription, this);
}
@ -858,31 +973,57 @@ PresentationPresentingInfo::InitTransportAndSendAnswer()
if (!Preferences::GetBool("dom.presentation.session_transport.data_channel.enable")) {
return NS_ERROR_NOT_IMPLEMENTED;
}
nsCOMPtr<nsIPresentationDataChannelSessionTransportBuilder> builder =
do_CreateInstance("@mozilla.org/presentation/datachanneltransportbuilder;1");
nsPIDOMWindowInner* window = nullptr;
if (NS_WARN_IF(!builder)) {
/**
* Generally transport is maintained by the chrome process. However, data
* channel should be live with the DOM , which implies RTCDataChannel in an OOP
* page should be establish in the content process.
*
* In OOP data channel transport case, |mBuilder| is hooked when the content
* process is ready to build a data channel transport, trigger by:
* 1. PresentationIPCService::StartSession (sender)
* 2. PresentationIPCService::NotifyReceiverReady (receiver).
*
* In this case, |mBuilder| would be an object of |PresentationBuilderParent|
* and set previously. Therefore, |BuildDataChannelTransport| triggers an IPC
* call to make content process establish a RTCDataChannel transport.
*/
// in-process case
if (!mBuilder) {
nsCOMPtr<nsIPresentationDataChannelSessionTransportBuilder> builder =
do_CreateInstance("@mozilla.org/presentation/datachanneltransportbuilder;1");
if (NS_WARN_IF(!builder)) {
return NS_ERROR_NOT_AVAILABLE;
}
SetBuilder(builder);
// OOP window would be set from content process
window = GetWindow();
}
mTransportType = nsIPresentationChannelDescription::TYPE_DATACHANNEL;
nsCOMPtr<nsIPresentationDataChannelSessionTransportBuilder>
dataChannelBuilder(do_QueryInterface(mBuilder));
if (NS_WARN_IF(!dataChannelBuilder)) {
return NS_ERROR_NOT_AVAILABLE;
}
mBuilder = builder;
mTransportType = nsIPresentationChannelDescription::TYPE_DATACHANNEL;
rv = builder->BuildDataChannelTransport(nsIPresentationService::ROLE_RECEIVER,
GetWindow(),
mControlChannel,
this);
rv = dataChannelBuilder->
BuildDataChannelTransport(nsIPresentationService::ROLE_RECEIVER,
window,
this);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
// delegate |onOffer| to builder
nsCOMPtr<nsIPresentationControlChannelListener> listener(do_QueryInterface(builder));
if (NS_WARN_IF(!listener)) {
return NS_ERROR_NOT_AVAILABLE;
rv = this->FlushPendingEvents(dataChannelBuilder);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
return listener->OnOffer(mRequesterDescription);
return NS_OK;
}
MOZ_ASSERT(false, "Unknown nsIPresentationChannelDescription type!");
@ -943,6 +1084,10 @@ PresentationPresentingInfo::NotifyResponderReady()
NS_IMETHODIMP
PresentationPresentingInfo::OnOffer(nsIPresentationChannelDescription* aDescription)
{
if (NS_WARN_IF(mHasFlushPendingEvents)) {
return ReplyError(NS_ERROR_DOM_OPERATION_ERR);
}
if (NS_WARN_IF(!aDescription)) {
return ReplyError(NS_ERROR_DOM_OPERATION_ERR);
}
@ -971,8 +1116,19 @@ PresentationPresentingInfo::OnAnswer(nsIPresentationChannelDescription* aDescrip
NS_IMETHODIMP
PresentationPresentingInfo::OnIceCandidate(const nsAString& aCandidate)
{
MOZ_ASSERT(false, "Should not receive ICE candidates.");
return NS_ERROR_FAILURE;
if (!mBuilder && !mHasFlushPendingEvents) {
mPendingCandidates.AppendElement(nsString(aCandidate));
return NS_OK;
}
if (NS_WARN_IF(!mBuilder && mHasFlushPendingEvents)) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIPresentationDataChannelSessionTransportBuilder>
builder = do_QueryInterface(mBuilder);
return builder->OnIceCandidate(aCandidate);
}
NS_IMETHODIMP
@ -987,6 +1143,14 @@ PresentationPresentingInfo::NotifyClosed(nsresult aReason)
{
MOZ_ASSERT(NS_IsMainThread());
if (mTransportType == nsIPresentationChannelDescription::TYPE_DATACHANNEL) {
nsCOMPtr<nsIPresentationDataChannelSessionTransportBuilder>
builder = do_QueryInterface(mBuilder);
if (builder) {
NS_WARN_IF(NS_FAILED(builder->NotifyClosed(aReason)));
}
}
// Unset control channel here so it won't try to re-close it in potential
// subsequent |Shutdown| calls.
SetControlChannel(nullptr);

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

@ -77,6 +77,11 @@ public:
mDevice = aDevice;
}
void SetBuilder(nsIPresentationSessionTransportBuilder* aBuilder)
{
mBuilder = aBuilder;
}
already_AddRefed<nsIPresentationDevice> GetDevice() const
{
nsCOMPtr<nsIPresentationDevice> device = mDevice;
@ -114,7 +119,10 @@ protected:
nsresult ReplySuccess();
virtual bool IsSessionReady() = 0;
bool IsSessionReady()
{
return mIsResponderReady && mIsTransportReady;
}
virtual nsresult UntrackFromService();
@ -186,18 +194,6 @@ private:
nsresult OnGetAddress(const nsACString& aAddress);
nsCOMPtr<nsIServerSocket> mServerSocket;
protected:
bool IsSessionReady() override
{
if (mTransportType == nsIPresentationChannelDescription::TYPE_TCP) {
return mIsResponderReady && mIsTransportReady;
} else if (mTransportType == nsIPresentationChannelDescription::TYPE_DATACHANNEL) {
// Established RTCDataChannel implies responder is ready.
return mIsTransportReady;
}
return false;
}
};
// Session info with presenting browsing context (receiver side) behaviors.
@ -208,7 +204,6 @@ class PresentationPresentingInfo final : public PresentationSessionInfo
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIPRESENTATIONCONTROLCHANNELLISTENER
NS_DECL_NSIPRESENTATIONSESSIONTRANSPORTBUILDERLISTENER
NS_DECL_NSITIMERCALLBACK
PresentationPresentingInfo(const nsAString& aUrl,
@ -226,6 +221,8 @@ public:
nsresult NotifyResponderReady();
NS_IMETHODIMP OnSessionTransport(nsIPresentationSessionTransport* transport) override;
void ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override;
void RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override;
@ -250,20 +247,19 @@ private:
nsresult UntrackFromService() override;
NS_IMETHODIMP
FlushPendingEvents(nsIPresentationDataChannelSessionTransportBuilder* builder);
bool mHasFlushPendingEvents = false;
RefPtr<PresentationResponderLoadingCallback> mLoadingCallback;
nsCOMPtr<nsITimer> mTimer;
nsCOMPtr<nsIPresentationChannelDescription> mRequesterDescription;
nsTArray<nsString> mPendingCandidates;
RefPtr<Promise> mPromise;
// The content parent communicating with the content process which the OOP
// receiver page belongs to.
nsCOMPtr<nsIContentParent> mContentParent;
protected:
bool IsSessionReady() override
{
return mIsResponderReady && mIsTransportReady;
}
};
} // namespace dom

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

@ -68,12 +68,13 @@ NS_IMPL_CYCLE_COLLECTING_RELEASE(PresentationTCPSessionTransport)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PresentationTCPSessionTransport)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIPresentationSessionTransport)
NS_INTERFACE_MAP_ENTRY(nsIPresentationSessionTransport)
NS_INTERFACE_MAP_ENTRY(nsITransportEventSink)
NS_INTERFACE_MAP_ENTRY(nsIPresentationTCPSessionTransportBuilder)
NS_INTERFACE_MAP_ENTRY(nsIInputStreamCallback)
NS_INTERFACE_MAP_ENTRY(nsIStreamListener)
NS_INTERFACE_MAP_ENTRY(nsIPresentationSessionTransport)
NS_INTERFACE_MAP_ENTRY(nsIPresentationSessionTransportBuilder)
NS_INTERFACE_MAP_ENTRY(nsIPresentationTCPSessionTransportBuilder)
NS_INTERFACE_MAP_ENTRY(nsIRequestObserver)
NS_INTERFACE_MAP_ENTRY(nsIStreamListener)
NS_INTERFACE_MAP_ENTRY(nsITransportEventSink)
NS_INTERFACE_MAP_END
PresentationTCPSessionTransport::PresentationTCPSessionTransport()

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

@ -54,7 +54,8 @@ interface nsIPresentationControlChannelListener: nsISupports
void onIceCandidate(in DOMString candidate);
/*
* The callback for notifying channel opened.
* The callback for notifying channel opened. This should be async called
* after nsIPresentationDevice::establishControlChannel.
*/
void notifyOpened();

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