This commit is contained in:
Kyle Huey 2012-08-14 11:14:40 -07:00
Родитель 9c834443ea a88ffe5c80
Коммит c95d073d8c
317 изменённых файлов: 5530 добавлений и 2574 удалений

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

@ -1125,6 +1125,8 @@ pref("browser.panorama.animate_zoom", true);
// Defines the url to be used for new tabs.
pref("browser.newtab.url", "about:newtab");
// Activates preloading of the new tab url.
pref("browser.newtab.preload", false);
// Toggles the content of 'about:newtab'. Shows the grid when enabled.
pref("browser.newtabpage.enabled", true);

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

@ -597,10 +597,7 @@ var FullScreen = {
fullscreenctls.setAttribute("flex", "1");
navbar.appendChild(fullscreenctls);
}
var controls = document.getElementsByAttribute("fullscreencontrol", "true");
for (var i = 0; i < controls.length; ++i)
controls[i].hidden = aShow;
fullscreenctls.hidden = aShow;
}
};
XPCOMUtils.defineLazyGetter(FullScreen, "useLionFullScreen", function() {

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

@ -151,6 +151,12 @@ XPCOMUtils.defineLazyGetter(this, "SafeBrowsing", function() {
});
#endif
XPCOMUtils.defineLazyGetter(this, "gBrowserNewTabPreloader", function () {
let tmp = {};
Cu.import("resource://gre/modules/BrowserNewTabPreloader.jsm", tmp);
return new tmp.BrowserNewTabPreloader();
});
let gInitialPages = [
"about:blank",
"about:newtab",
@ -214,7 +220,7 @@ XPCOMUtils.defineLazyGetter(this, "PageMenu", function() {
*/
function pageShowEventHandlers(event) {
// Filter out events that are not about the document load we are interested in
if (event.originalTarget == content.document) {
if (event.target == content.document) {
charsetLoadListener(event);
XULBrowserWindow.asyncUpdateUI();
@ -1401,6 +1407,12 @@ var gBrowserInit = {
gSyncUI.init();
#endif
// Don't preload new tab pages when the toolbar is hidden
// (i.e. when the current window is a popup window).
if (window.toolbar.visible) {
gBrowserNewTabPreloader.init(window);
}
gBrowserThumbnails.init();
TabView.init();
@ -1557,6 +1569,10 @@ var gBrowserInit = {
Services.obs.removeObserver(gPluginHandler.pluginCrashed, "plugin-crashed");
if (!__lookupGetter__("gBrowserNewTabPreloader")) {
gBrowserNewTabPreloader.uninit();
}
try {
gBrowser.removeProgressListener(window.XULBrowserWindow);
gBrowser.removeTabsProgressListener(window.TabsProgressListener);
@ -2515,6 +2531,9 @@ let BrowserOnClick = {
else if (/^about:blocked/.test(ownerDoc.documentURI)) {
this.onAboutBlocked(originalTarget, ownerDoc);
}
else if (/^about:neterror/.test(ownerDoc.documentURI)) {
this.onAboutNetError(originalTarget, ownerDoc);
}
else if (/^about:home$/i.test(ownerDoc.documentURI)) {
this.onAboutHome(originalTarget, ownerDoc);
}
@ -2681,6 +2700,13 @@ let BrowserOnClick = {
notification.persistence = -1;
},
onAboutNetError: function BrowserOnClick_onAboutNetError(aTargetElm, aOwnerDoc) {
let elmId = aTargetElm.getAttribute("id");
if (elmId != "errorTryAgain" || !/e=netOffline/.test(aOwnerDoc.documentURI))
return;
Services.io.offline = false;
},
onAboutHome: function BrowserOnClick_onAboutHome(aTargetElm, aOwnerDoc) {
let elmId = aTargetElm.getAttribute("id");
@ -4476,11 +4502,11 @@ var TabsProgressListener = {
if (aStateFlags & Ci.nsIWebProgressListener.STATE_STOP &&
Components.isSuccessCode(aStatus) &&
/^about:/.test(aWebProgress.DOMWindow.document.documentURI)) {
aBrowser.addEventListener("click", BrowserOnClick, false);
aBrowser.addEventListener("click", BrowserOnClick, true);
aBrowser.addEventListener("pagehide", function onPageHide(event) {
if (event.target.defaultView.frameElement)
return;
aBrowser.removeEventListener("click", BrowserOnClick, false);
aBrowser.removeEventListener("click", BrowserOnClick, true);
aBrowser.removeEventListener("pagehide", onPageHide, true);
}, true);

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

@ -788,7 +788,7 @@
</toolbarbutton>
</toolbaritem>
<hbox id="window-controls" hidden="true" fullscreencontrol="true" pack="end">
<hbox id="window-controls" hidden="true" pack="end">
<toolbarbutton id="minimize-button"
tooltiptext="&fullScreenMinimize.tooltip;"
oncommand="window.minimize();"/>

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

@ -1383,6 +1383,12 @@
// activeness in the tab switcher.
b.docShellIsActive = false;
// If we just created a new tab that loads the default
// newtab url, swap in a preloaded page if possible.
if (aURI == BROWSER_NEW_TAB_URL) {
gBrowserNewTabPreloader.newTab(t);
}
// Check if we're opening a tab related to the current tab and
// move it to after the current tab.
// aReferrerURI is null or undefined if the tab is opened from
@ -1616,6 +1622,11 @@
evt.initUIEvent("TabClose", true, false, window, aTabWillBeMoved ? 1 : 0);
aTab.dispatchEvent(evt);
// Prevent this tab from showing further dialogs, since we're closing it
var windowUtils = browser.contentWindow.QueryInterface(Ci.nsIInterfaceRequestor).
getInterface(Ci.nsIDOMWindowUtils);
windowUtils.preventFurtherDialogs();
// Remove the tab's filter and progress listener.
const filter = this.mTabFilters[aTab._tPos];
#ifdef MOZ_E10S_COMPAT
@ -1813,6 +1824,33 @@
</body>
</method>
<method name="swapNewTabWithBrowser">
<parameter name="aNewTab"/>
<parameter name="aBrowser"/>
<body>
<![CDATA[
// The browser must be standalone.
if (aBrowser.getTabBrowser())
throw Cr.NS_ERROR_INVALID_ARG;
// The tab is definitely not loading.
aNewTab.removeAttribute("busy");
if (aNewTab == this.selectedTab) {
this.mIsBusy = false;
}
this._swapBrowserDocShells(aNewTab, aBrowser);
// Update the new tab's title.
this.setTabTitle(aNewTab);
if (aNewTab == this.selectedTab) {
this.updateCurrentBrowser(true);
}
]]>
</body>
</method>
<method name="swapBrowsersAndCloseOther">
<parameter name="aOurTab"/>
<parameter name="aOtherTab"/>
@ -1827,29 +1865,10 @@
if (!remoteBrowser._beginRemoveTab(aOtherTab, true, true))
return;
// Unhook our progress listener
var ourIndex = aOurTab._tPos;
const filter = this.mTabFilters[ourIndex];
var tabListener = this.mTabListeners[ourIndex];
var ourBrowser = this.getBrowserForTab(aOurTab);
ourBrowser.webProgress.removeProgressListener(filter);
filter.removeProgressListener(tabListener);
var tabListenerBlank = tabListener.mBlank;
var otherBrowser = aOtherTab.linkedBrowser;
// Restore current registered open URI.
if (ourBrowser.registeredOpenURI) {
this._placesAutocomplete.unregisterOpenPage(ourBrowser.registeredOpenURI);
delete ourBrowser.registeredOpenURI;
}
if (otherBrowser.registeredOpenURI) {
ourBrowser.registeredOpenURI = otherBrowser.registeredOpenURI;
delete otherBrowser.registeredOpenURI;
}
// Workarounds for bug 458697
// Icon might have been set on DOMLinkAdded, don't override that.
let ourBrowser = this.getBrowserForTab(aOurTab);
let otherBrowser = aOtherTab.linkedBrowser;
if (!ourBrowser.mIconURL && otherBrowser.mIconURL)
this.setIcon(aOurTab, otherBrowser.mIconURL);
var isBusy = aOtherTab.hasAttribute("busy");
@ -1860,22 +1879,11 @@
this.mIsBusy = true;
}
// Swap the docshells
ourBrowser.swapDocShells(otherBrowser);
this._swapBrowserDocShells(aOurTab, otherBrowser);
// Finish tearing down the tab that's going away.
remoteBrowser._endRemoveTab(aOtherTab);
// Restore the progress listener
tabListener = this.mTabProgressListener(aOurTab, ourBrowser,
tabListenerBlank);
this.mTabListeners[ourIndex] = tabListener;
filter.addProgressListener(tabListener,
Components.interfaces.nsIWebProgress.NOTIFY_ALL);
ourBrowser.webProgress.addProgressListener(filter,
Components.interfaces.nsIWebProgress.NOTIFY_ALL);
if (isBusy)
this.setTabTitleLoading(aOurTab);
else
@ -1889,6 +1897,43 @@
</body>
</method>
<method name="_swapBrowserDocShells">
<parameter name="aOurTab"/>
<parameter name="aOtherBrowser"/>
<body>
<![CDATA[
// Unhook our progress listener
let index = aOurTab._tPos;
const filter = this.mTabFilters[index];
let tabListener = this.mTabListeners[index];
let ourBrowser = this.getBrowserForTab(aOurTab);
ourBrowser.webProgress.removeProgressListener(filter);
filter.removeProgressListener(tabListener);
// Restore current registered open URI.
if (ourBrowser.registeredOpenURI) {
this._placesAutocomplete.unregisterOpenPage(ourBrowser.registeredOpenURI);
delete ourBrowser.registeredOpenURI;
}
if (aOtherBrowser.registeredOpenURI) {
ourBrowser.registeredOpenURI = aOtherBrowser.registeredOpenURI;
delete aOtherBrowser.registeredOpenURI;
}
// Swap the docshells
ourBrowser.swapDocShells(aOtherBrowser);
// Restore the progress listener
this.mTabListeners[index] = tabListener =
this.mTabProgressListener(aOurTab, ourBrowser, false);
const notifyAll = Ci.nsIWebProgress.NOTIFY_ALL;
filter.addProgressListener(tabListener, notifyAll);
ourBrowser.webProgress.addProgressListener(filter, notifyAll);
]]>
</body>
</method>
<method name="reloadAllTabs">
<body>
<![CDATA[

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

@ -199,6 +199,7 @@ _BROWSER_FILES = \
browser_tabfocus.js \
browser_tabs_isActive.js \
browser_tabs_owner.js \
browser_unloaddialogs.js \
browser_urlbarAutoFillTrimURLs.js \
browser_urlbarCopying.js \
browser_urlbarEnter.js \

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

@ -21,6 +21,11 @@ function test() {
}
function whenBrowserLoaded(aBrowser, aCallback) {
if (aBrowser.contentDocument.readyState == "complete") {
executeSoon(aCallback);
return;
}
aBrowser.addEventListener("load", function onLoad() {
aBrowser.removeEventListener("load", onLoad, true);
executeSoon(aCallback);

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

@ -67,8 +67,13 @@ function togglePrivateBrowsing(aCallback) {
function openNewTab(aCallback) {
// Open a new tab
BrowserOpenTab();
let browser = gBrowser.selectedBrowser;
if (browser.contentDocument.readyState == "complete") {
executeSoon(aCallback);
return;
}
browser.addEventListener("load", function onLoad() {
browser.removeEventListener("load", onLoad, true);
executeSoon(aCallback);

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

@ -84,8 +84,13 @@ function togglePrivateBrowsing(aCallback) {
function openNewTab(aCallback) {
// Open a new tab
BrowserOpenTab();
let browser = gBrowser.selectedBrowser;
if (browser.contentDocument.readyState == "complete") {
executeSoon(aCallback);
return;
}
browser.addEventListener("load", function onLoad() {
browser.removeEventListener("load", onLoad, true);
executeSoon(aCallback);

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

@ -0,0 +1,134 @@
function notify(event)
{
if (event.target.location == "about:blank")
return;
var eventname = event.type;
if (eventname == "pagehide")
details.pagehides++;
else if (eventname == "beforeunload")
details.beforeunloads++;
else if (eventname == "unload")
details.unloads++;
}
var details;
var gUseFrame = false;
const windowMediator = Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator);
const TEST_BASE_URL = "data:text/html,<script>" +
"function note(event) { try { alert(event.type); } catch(ex) { return; } throw 'alert appeared'; }" +
"</script>" +
"<body onpagehide='note(event)' onbeforeunload='alert(event.type);' onunload='note(event)'>";
const TEST_URL = TEST_BASE_URL + "Test</body>";
const TEST_FRAME_URL = TEST_BASE_URL + "Frames</body>";
function test()
{
waitForExplicitFinish();
windowMediator.addListener(promptListener);
runTest();
}
function runTest()
{
details = {
testNumber : 0,
beforeunloads : 0,
pagehides : 0,
unloads : 0,
prompts : 0
};
var tab = gBrowser.addTab(TEST_URL);
gBrowser.selectedTab = tab;
tab.linkedBrowser.addEventListener("pageshow", shown, true);
tab.linkedBrowser.addEventListener("pagehide", notify, true);
tab.linkedBrowser.addEventListener("beforeunload", notify, true);
tab.linkedBrowser.addEventListener("unload", notify, true);
}
function shown(event)
{
if (details.testNumber == 0) {
var browser;
var iframe;
if (gUseFrame) {
iframe = event.target.createElement("iframe");
iframe.src = TEST_FRAME_URL;
event.target.documentElement.appendChild(iframe);
browser = iframe.contentWindow;
}
else {
browser = gBrowser.selectedTab.linkedBrowser;
details.testNumber = 1; // Move onto to the next step immediately
}
}
if (details.testNumber == 1) {
// Test going to another page
executeSoon(function () {
const urlToLoad = "data:text/html,<body>Another Page</body>";
if (gUseFrame) {
event.target.location = urlToLoad;
}
else {
gBrowser.selectedBrowser.loadURI(urlToLoad);
}
});
}
else if (details.testNumber == 2) {
is(details.pagehides, 1, "pagehides after next page")
is(details.beforeunloads, 1, "beforeunloads after next page")
is(details.unloads, 1, "unloads after next page")
is(details.prompts, 1, "prompts after next page")
executeSoon(function () gUseFrame ? gBrowser.goBack() : event.target.defaultView.back());
}
else if (details.testNumber == 3) {
is(details.pagehides, 2, "pagehides after back")
is(details.beforeunloads, 2, "beforeunloads after back")
// No cache, so frame is unloaded
is(details.unloads, gUseFrame ? 2 : 1, "unloads after back")
is(details.prompts, 1, "prompts after back")
// Test closing the tab
gBrowser.selectedBrowser.removeEventListener("pageshow", shown, true);
gBrowser.removeTab(gBrowser.selectedTab);
// When the frame is present, there is are two beforeunload and prompts,
// one for the frame and the other for the parent.
is(details.pagehides, 3, "pagehides after close")
is(details.beforeunloads, gUseFrame ? 4 : 3, "beforeunloads after close")
is(details.unloads, gUseFrame ? 3 : 2, "unloads after close")
is(details.prompts, gUseFrame ? 3 : 2, "prompts after close")
// Now run the test again using a child frame.
if (gUseFrame) {
windowMediator.removeListener(promptListener);
finish();
}
else {
gUseFrame = true;
runTest();
}
return;
}
details.testNumber++;
}
var promptListener = {
onWindowTitleChange: function () {},
onOpenWindow: function (win) {
details.prompts++;
let domWin = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindow);
executeSoon(function () { domWin.close() });
},
onCloseWindow: function () {},
};

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

@ -203,10 +203,7 @@ function addNewTabPageTab() {
let tab = gBrowser.selectedTab = gBrowser.addTab("about:newtab");
let browser = tab.linkedBrowser;
// Wait for the new tab page to be loaded.
browser.addEventListener("load", function onLoad() {
browser.removeEventListener("load", onLoad, true);
function whenNewTabLoaded() {
if (NewTabUtils.allPages.enabled) {
// Continue when the link cache has been populated.
NewTabUtils.links.populateCache(function () {
@ -215,6 +212,18 @@ function addNewTabPageTab() {
} else {
TestRunner.next();
}
}
// The new tab page might have been preloaded in the background.
if (browser.contentDocument.readyState == "complete") {
whenNewTabLoaded();
return;
}
// Wait for the new tab page to be loaded.
browser.addEventListener("load", function onLoad() {
browser.removeEventListener("load", onLoad, true);
whenNewTabLoaded();
}, true);
}

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

@ -3,184 +3,105 @@
function test() {
waitForExplicitFinish();
requestLongerTimeout(2);
newWindowWithTabView(onTabViewWindowLoaded);
}
function moveTabOutOfGroup(aTab, aGroup, aCW, aCallback) {
let tabPos = aTab.getBounds().center();
let groupPos = aGroup.getBounds();
let groupPosX = (groupPos.left + groupPos.right) / 2;
let groupPosY = groupPos.bottom + 200;
let offsetX = Math.round(groupPosX - tabPos.x);
let offsetY = Math.round(groupPosY - tabPos.y);
function onTabViewWindowLoaded(win) {
ok(win.TabView.isVisible(), "Tab View is visible");
simulateDragDrop(aTab, offsetX, offsetY, aCW);
}
let contentWindow = win.document.getElementById("tab-view").contentWindow;
let [originalTab] = win.gBrowser.visibleTabs;
function moveTabInGroup(aTab, aIndexTo, aGroup, aCW) {
let tabTo = aGroup.getChild(aIndexTo);
let tabPos = aTab.getBounds().center();
let tabToPos = tabTo.getBounds().center();
let offsetX = Math.round(tabToPos.x - tabPos.x);
let offsetY = Math.round(tabToPos.y - tabPos.y);
let currentGroup = contentWindow.GroupItems.getActiveGroupItem();
simulateDragDrop(aTab, offsetX, offsetY, aCW);
}
// Create a group and make it active
let box = new contentWindow.Rect(100, 100, 400, 430);
let group = new contentWindow.GroupItem([], { bounds: box });
ok(group.isEmpty(), "This group is empty");
contentWindow.UI.setActive(group);
// Create a bunch of tabs in the group
let tabs = [];
tabs.push(win.gBrowser.loadOneTab("about:blank#0", {inBackground: true}));
tabs.push(win.gBrowser.loadOneTab("about:blank#1", {inBackground: true}));
tabs.push(win.gBrowser.loadOneTab("about:blank#2", {inBackground: true}));
tabs.push(win.gBrowser.loadOneTab("about:blank#3", {inBackground: true}));
tabs.push(win.gBrowser.loadOneTab("about:blank#4", {inBackground: true}));
tabs.push(win.gBrowser.loadOneTab("about:blank#5", {inBackground: true}));
tabs.push(win.gBrowser.loadOneTab("about:blank#6", {inBackground: true}));
function getTabNumbers(aGroup) {
return aGroup.getChildren().map(function (child) {
let url = child.tab.linkedBrowser.currentURI.spec;
return url.replace("about:blank#", "");
}).join(",");
}
ok(!group.shouldStack(group._children.length), "Group should not stack.");
is(group._columns, 3, "There should be three columns.");
// STAGE 1: move the last tab to the third position
let currentTarget = tabs[6]._tabViewTabItem;
let currentPos = currentTarget.getBounds().center();
let targetPos = tabs[2]._tabViewTabItem.getBounds().center();
let vector = new contentWindow.Point(targetPos.x - currentPos.x,
targetPos.y - currentPos.y);
checkDropIndexAndDropSpace(currentTarget, group, vector.x, vector.y, contentWindow,
function(index, dropSpaceActiveValues) {
// Now: 0, 1, 6, 2, 3, 4, 5
is(index, 2, "Tab 6 is now in the third position");
is(dropSpaceActiveValues[0], true, "dropSpace was always showing");
function moveTabs(aGroup, aCW) {
// Test 1: Move the last tab to the third position.
let tab = aGroup.getChild(6);
moveTabInGroup(tab, 2, aGroup, aCW);
is(getTabNumbers(aGroup), "0,1,6,2,3,4,5", "Validate tab positions in test 1.");
// STAGE 2: move the second tab to the end of the list
let currentTarget = tabs[1]._tabViewTabItem;
let currentPos = currentTarget.getBounds().center();
// pick a point in that empty bottom part of the group
let groupBounds = group.getBounds();
let bottomPos = new contentWindow.Point(
(groupBounds.left + groupBounds.right) / 2,
groupBounds.bottom - 15);
let vector = new contentWindow.Point(bottomPos.x - currentPos.x,
bottomPos.y - currentPos.y);
checkDropIndexAndDropSpace(currentTarget, group, vector.x, vector.y, contentWindow,
function(index, dropSpaceActiveValues) {
// Now: 0, 6, 2, 3, 4, 5, 1
is(index, 6, "Tab 1 is now at the end of the group");
is(dropSpaceActiveValues[0], true, "dropSpace was always showing");
// STAGE 3: move the fifth tab outside the group
// Note: there should be room below the active group...
let currentTarget = tabs[4]._tabViewTabItem;
let currentPos = currentTarget.getBounds().center();
// Pick a point below the group.
let belowPos = new contentWindow.Point(
(groupBounds.left + groupBounds.right) / 2,
groupBounds.bottom + 300);
let vector = new contentWindow.Point(belowPos.x - currentPos.x,
belowPos.y - currentPos.y);
checkDropIndexAndDropSpace(currentTarget, group, vector.x, vector.y, contentWindow,
function(index, dropSpaceActiveValues) {
// Now: 0, 6, 2, 3, 5, 1
is(index, -1, "Tab 5 is no longer in the group");
contentWindow.Utils.log('dropSpaceActiveValues',dropSpaceActiveValues);
is(dropSpaceActiveValues[0], true, "The group began by showing a dropSpace");
is(dropSpaceActiveValues[dropSpaceActiveValues.length - 1], false, "In the end, the group was not showing a dropSpace");
// We wrap this in a setTimeout with 1000ms delay in order to wait for the
// tab to resize, as it does after we drop it in stage 3 outside of the group.
setTimeout(function() {
// STAGE 4: move the fifth tab back into the group, on the second row.
let currentTarget = tabs[4]._tabViewTabItem;
let currentPos = currentTarget.getBounds().center();
let targetPos = tabs[5]._tabViewTabItem.getBounds().center();
// contentWindow.Utils.log(targetPos, currentPos);
vector = new contentWindow.Point(targetPos.x - currentPos.x,
targetPos.y - currentPos.y);
// Call with time = 4000
checkDropIndexAndDropSpace(currentTarget, group, vector.x, vector.y, contentWindow,
function(index, dropSpaceActiveValues) {
// Test 2: Move the second tab to the end of the list.
tab = aGroup.getChild(1);
moveTabInGroup(tab, 6, aGroup, aCW);
is(getTabNumbers(aGroup), "0,6,2,3,4,5,1", "Validate tab positions in test 2.");
is(group._columns, 3, "There should be three columns.");
// Test 3: Move the fifth tab outside the group.
tab = aGroup.getChild(4);
moveTabOutOfGroup(tab, aGroup, aCW);
is(getTabNumbers(aGroup), "0,6,2,3,5,1", "Validate tab positions in test 3.");
is(aCW.GroupItems.groupItems.length, 3, "Validate group count in test 3.");
// Now: 0, 6, 2, 3, 4, 5, 1
is(index, 4, "Tab 5 is back and again the fifth tab.");
contentWindow.Utils.log('dropSpaceActiveValues',dropSpaceActiveValues);
is(dropSpaceActiveValues[0], false, "The group began by not showing a dropSpace");
is(dropSpaceActiveValues[dropSpaceActiveValues.length - 1], true, "In the end, the group was showing a dropSpace");
// Close the window and we're done!
win.close();
finish();
}, 10000, false);
}, 2000);
});
// Test 4: Move the fifth tab back into the group, on the second row.
waitForTransition(tab, function() {
moveTabInGroup(tab, 4, aGroup, aCW);
is(getTabNumbers(aGroup), "0,6,2,3,4,5,1", "Validate tab positions in test 4.");
is(aCW.GroupItems.groupItems.length, 2, "Validate group count in test 4.");
closeGroupItem(aGroup, function() { hideTabView(finish) });
});
}
});
function createGroup(win) {
registerCleanupFunction(function() win.close());
let cw = win.TabView.getContentWindow();
let group = createGroupItemWithTabs(win, 400, 430, 100, [
"about:blank#0", "about:blank#1", "about:blank#2", "about:blank#3",
"about:blank#4", "about:blank#5", "about:blank#6"
]);
let groupSize = group.getChildren().length;
is(cw.GroupItems.groupItems.length, 2, "Validate group count in tab view.");
ok(!group.shouldStack(groupSize), "Check that group should not stack.");
is(group._columns, 3, "Check the there should be three columns.");
moveTabs(group, cw);
}
newWindowWithTabView(createGroup);
}
function simulateSlowDragDrop(srcElement, offsetX, offsetY, contentWindow, time) {
// enter drag mode
let dataTransfer;
let bounds = srcElement.getBoundingClientRect();
function simulateDragDrop(aTab, aOffsetX, aOffsetY, aCW) {
let target = aTab.container;
let rect = target.getBoundingClientRect();
let startX = (rect.right - rect.left) / 2;
let startY = (rect.bottom - rect.top) / 2;
let steps = 2;
let incrementX = aOffsetX / steps;
let incrementY = aOffsetY / steps;
EventUtils.synthesizeMouse(
srcElement, 2, 2, { type: "mousedown" }, contentWindow);
let event = contentWindow.document.createEvent("DragEvents");
event.initDragEvent(
"dragenter", true, true, contentWindow, 0, 0, 0, 0, 0,
false, false, false, false, 1, null, dataTransfer);
srcElement.dispatchEvent(event);
let steps = 20;
// drag over
let moveIncremental = function moveIncremental(i, steps) {
// calculate how much to move
let offsetXDiff = Math.round(i * offsetX / steps) - Math.round((i - 1) * offsetX / steps);
let offsetYDiff = Math.round(i * offsetY / steps) - Math.round((i - 1) * offsetY / steps);
// contentWindow.Utils.log('step', offsetXDiff, offsetYDiff);
// simulate mousemove
target, startX, startY, { type: "mousedown" }, aCW);
for (let i = 1; i <= steps; i++) {
EventUtils.synthesizeMouse(
srcElement, offsetXDiff + 2, offsetYDiff + 2,
{ type: "mousemove" }, contentWindow);
// simulate dragover
let event = contentWindow.document.createEvent("DragEvents");
event.initDragEvent(
"dragover", true, true, contentWindow, 0, 0, 0, 0, 0,
false, false, false, false, 0, null, dataTransfer);
srcElement.dispatchEvent(event);
let bounds = srcElement.getBoundingClientRect();
// contentWindow.Utils.log(i, 'center', bounds.left + bounds.width / 2, bounds.top + bounds.height / 2);
target, incrementX + startX, incrementY + startY,
{ type: "mousemove" }, aCW);
};
for (let i = 1; i <= steps; i++)
setTimeout(moveIncremental, i / (steps + 1) * time, i, steps);
// drop
let finalDrop = function finalDrop() {
EventUtils.synthesizeMouseAtCenter(srcElement, { type: "mouseup" }, contentWindow);
event = contentWindow.document.createEvent("DragEvents");
event.initDragEvent(
"drop", true, true, contentWindow, 0, 0, 0, 0, 0,
false, false, false, false, 0, null, dataTransfer);
srcElement.dispatchEvent(event);
contentWindow.iQ(srcElement).css({border: 'green 1px solid'});
}
setTimeout(finalDrop, time);
EventUtils.synthesizeMouseAtCenter(target, { type: "mouseup" }, aCW);
}
function checkDropIndexAndDropSpace(item, group, offsetX, offsetY, contentWindow, callback, time) {
contentWindow.UI.setActive(item);
let dropSpaceActiveValues = [];
let recordDropSpaceValue = function() {
dropSpaceActiveValues.push(group._dropSpaceActive);
};
let onDrop = function() {
item.container.removeEventListener('dragover', recordDropSpaceValue, false);
item.container.removeEventListener('drop', onDrop, false);
let index = group._children.indexOf(item);
callback(index, dropSpaceActiveValues);
};
item.container.addEventListener('dragover', recordDropSpaceValue, false);
item.container.addEventListener('drop', onDrop, false);
simulateSlowDragDrop(item.container, offsetX, offsetY, contentWindow, time || 1000);
function waitForTransition(aTab, aCallback) {
let groupContainer = aTab.parent.container;
groupContainer.addEventListener("transitionend", function onTransitionEnd(aEvent) {
if (aEvent.target == groupContainer) {
groupContainer.removeEventListener("transitionend", onTransitionEnd);
executeSoon(aCallback);
}
});
}

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

@ -62,9 +62,6 @@ function testLeavePage() {
let dialogsAccepted = 0;
whenDialogOpened(function onDialogOpened(dialog) {
if (++dialogsAccepted < 3)
whenDialogOpened(onDialogOpened);
// Leave page
dialog.acceptDialog();
});

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

@ -953,7 +953,7 @@ function JSPropertyProvider(aScope, aInputValue)
return null;
}
let matches = Object.keys(getMatchedProps(obj, matchProp));
let matches = Object.keys(getMatchedProps(obj, {matchProp:matchProp}));
return {
matchProp: matchProp,
@ -962,51 +962,60 @@ function JSPropertyProvider(aScope, aInputValue)
}
/**
* Get all accessible properties on this object.
* Get all accessible properties on this JS value.
* Filter those properties by name.
* Take only a certain number of those.
*
* @param object obj
* Object whose properties we want to collect.
* @param mixed aObj
* JS value whose properties we want to collect.
*
* @param string matchProp
* Filter for properties that match this one.
* Defaults to the empty string (which always matches).
* @param object aOptions
* Options that the algorithm takes.
* - matchProp (string): Filter for properties that match this one.
* Defaults to the empty string (which always matches).
*
* @return object
* Object whose keys are all accessible properties on the object.
*/
function getMatchedProps(aObj, aMatchProp = "")
function getMatchedProps(aObj, aOptions = {matchProp: ""})
{
// Argument defaults.
aOptions.matchProp = aOptions.matchProp || "";
if (aObj == null) { return {}; }
try {
Object.getPrototypeOf(aObj);
} catch(e) {
aObj = aObj.constructor.prototype;
}
let c = MAX_COMPLETIONS;
let names = {}; // Using an Object to avoid duplicates.
let ownNames = Object.getOwnPropertyNames(aObj);
for (let i = 0; i < ownNames.length; i++) {
if (ownNames[i].indexOf(aMatchProp) == 0) {
if (names[ownNames[i]] != true) {
c--;
if (c < 0) {
return names;
}
// We need to go up the prototype chain.
let ownNames = null;
while (aObj !== null) {
ownNames = Object.getOwnPropertyNames(aObj);
for (let i = 0; i < ownNames.length; i++) {
// Filtering happens here.
// If we already have it in, no need to append it.
if (ownNames[i].indexOf(aOptions.matchProp) != 0 ||
names[ownNames[i]] == true) {
continue;
}
c--;
if (c < 0) {
return names;
}
// If it is an array index, we can't take it.
// This uses a trick: converting a string to a number yields NaN if
// the operation failed, and NaN is not equal to itself.
if (+ownNames[i] != +ownNames[i]) {
names[ownNames[i]] = true;
}
}
aObj = Object.getPrototypeOf(aObj);
}
// We need to recursively go up the prototype chain.
aObj = Object.getPrototypeOf(aObj);
if (aObj !== null) {
let parentScope = getMatchedProps(aObj, aMatchProp);
for (let name in parentScope) {
if (names[name] != true) {
c--;
if (c < 0) {
return names;
}
names[name] = true;
}
}
}
return names;
}

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

@ -195,7 +195,7 @@ function testReturnKey()
ok(!completeNode.value, "completeNode is empty");
executeSoon(finishTest);
dontShowArrayNumbers();
}, false);
EventUtils.synthesizeKey("VK_RETURN", {});
@ -207,3 +207,30 @@ function testReturnKey()
EventUtils.synthesizeKey(".", {});
});
}
function dontShowArrayNumbers()
{
content.wrappedJSObject.foobarBug585991 = ["Sherlock Holmes"];
let jsterm = HUD.jsterm;
let popup = jsterm.autocompletePopup;
let completeNode = jsterm.completeNode;
popup._panel.addEventListener("popupshown", function onShown() {
popup._panel.removeEventListener("popupshown", onShown, false);
let sameItems = popup.getItems().map(function(e) {return e.label;});
ok(!sameItems.some(function(prop, index) { prop === "0"; }),
"Completing on an array doesn't show numbers.");
popup._panel.addEventListener("popuphidden", consoleOpened, false);
EventUtils.synthesizeKey("VK_TAB", {});
executeSoon(finishTest);
}, false);
jsterm.setInputValue("window.foobarBug585991");
EventUtils.synthesizeKey(".", {});
}

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

@ -98,6 +98,13 @@ function testCompletion(hud) {
is(jsterm.completeNode.value, " \n e", "multi-line completion");
// Test non-object autocompletion.
input.value = "Object.name.sl";
jsterm.complete(jsterm.COMPLETE_HINT_ONLY, testNext);
yield;
is(jsterm.completeNode.value, " ice", "non-object completion");
testDriver = jsterm = input = null;
executeSoon(finishTest);
yield;

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

@ -6,7 +6,7 @@
<!ENTITY % webConsoleDTD SYSTEM "chrome://browser/locale/devtools/webConsole.dtd">
%webConsoleDTD;
]>
<?xml-stylesheet href="chrome://browser/skin/" type="text/css"?>
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<?xml-stylesheet href="chrome://browser/skin/devtools/webconsole.css"
type="text/css"?>
<?xul-overlay href="chrome://global/content/editMenuOverlay.xul"?>

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

@ -0,0 +1,160 @@
/* 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/. */
"use strict";
let EXPORTED_SYMBOLS = ["BrowserNewTabPreloader"];
const Cu = Components.utils;
Cu.import("resource://gre/modules/Services.jsm");
const PREF_NEWTAB_URL = "browser.newtab.url";
const PREF_NEWTAB_PRELOAD = "browser.newtab.preload";
function BrowserNewTabPreloader() {
}
BrowserNewTabPreloader.prototype = {
_url: null,
_window: null,
_browser: null,
_enabled: null,
init: function Preloader_init(aWindow) {
if (this._window) {
return;
}
this._window = aWindow;
this._enabled = Preferences.enabled;
this._url = Preferences.url;
Preferences.addObserver(this);
if (this._enabled) {
this._createBrowser();
}
},
uninit: function Preloader_uninit() {
if (!this._window) {
return;
}
if (this._browser) {
this._browser.parentNode.removeChild(this._browser);
this._browser = null;
}
this._window = null;
Preferences.removeObserver(this);
},
newTab: function Preloader_newTab(aTab) {
if (!this._window || !this._enabled) {
return;
}
let tabbrowser = this._window.gBrowser;
if (tabbrowser && this._isPreloaded()) {
tabbrowser.swapNewTabWithBrowser(aTab, this._browser);
}
},
observe: function Preloader_observe(aEnabled, aURL) {
if (this._url != aURL) {
this._url = aURL;
if (this._enabled && aEnabled) {
// We're still enabled but the newtab URL has changed.
this._browser.setAttribute("src", aURL);
return;
}
}
if (this._enabled && !aEnabled) {
// We got disabled. Remove the browser.
this._browser.parentNode.removeChild(this._browser);
this._browser = null;
this._enabled = false;
} else if (!this._enabled && aEnabled) {
// We got enabled. Create a browser and start preloading.
this._createBrowser();
this._enabled = true;
}
},
_createBrowser: function Preloader_createBrowser() {
let document = this._window.document;
this._browser = document.createElement("browser");
this._browser.setAttribute("type", "content");
this._browser.setAttribute("src", this._url);
this._browser.collapsed = true;
let panel = document.getElementById("browser-panel");
panel.appendChild(this._browser);
},
_isPreloaded: function Preloader_isPreloaded() {
return this._browser &&
this._browser.contentDocument &&
this._browser.contentDocument.readyState == "complete" &&
this._browser.currentURI.spec == this._url;
}
};
let Preferences = {
_observers: [],
get _branch() {
delete this._branch;
return this._branch = Services.prefs.getBranch("browser.newtab.");
},
get enabled() {
if (!this._branch.getBoolPref("preload")) {
return false;
}
if (this._branch.prefHasUserValue("url")) {
return false;
}
let url = this.url;
return url && url != "about:blank";
},
get url() {
return this._branch.getCharPref("url");
},
addObserver: function Preferences_addObserver(aObserver) {
let index = this._observers.indexOf(aObserver);
if (index == -1) {
if (this._observers.length == 0) {
this._branch.addObserver("", this, false);
}
this._observers.push(aObserver);
}
},
removeObserver: function Preferences_removeObserver(aObserver) {
let index = this._observers.indexOf(aObserver);
if (index > -1) {
if (this._observers.length == 1) {
this._branch.removeObserver("", this);
}
this._observers.splice(index, 1);
}
},
observe: function Preferences_observe(aSubject, aTopic, aData) {
let url = this.url;
let enabled = this.enabled;
for (let obs of this._observers) {
obs.observe(enabled, url);
}
}
};

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

@ -14,6 +14,7 @@ include $(topsrcdir)/config/config.mk
TEST_DIRS += test
EXTRA_JS_MODULES = \
BrowserNewTabPreloader.jsm \
openLocationLastURL.jsm \
NetworkPrioritizer.jsm \
NewTabUtils.jsm \

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

@ -2564,11 +2564,6 @@ stack[anonid=browserStack][responsivemode] {
box-shadow: 0 -1px 0 0 ThreeDShadow inset, 0 0 0 10px -moz-Dialog inset;
}
.web-console-panel {
-moz-appearance: none;
background-color: white;
}
/* Developer Toolbar */

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

@ -3331,11 +3331,6 @@ stack[anonid=browserStack][responsivemode] {
-moz-linear-gradient(top, #fcfcfc, #dfdfdf);
}
.web-console-panel {
-moz-appearance: none;
background-color: white;
}
/* Developer Toolbar */
.developer-toolbar-button {

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

@ -3245,11 +3245,6 @@ stack[anonid=browserStack][responsivemode] {
border-top: none;
}
.web-console-panel {
-moz-appearance: none;
background-color: white;
}
/* Developer Toolbar */
.developer-toolbar-button {

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

@ -18,6 +18,7 @@ import java.io.PrintWriter;
import java.nio.IntBuffer;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.lang.Class;
import java.lang.reflect.InvocationTargetException;
@ -422,6 +423,20 @@ public class FennecNativeDriver implements Driver {
return retVal;
}
public static void logAllStackTraces(LogLevel level) {
StringBuffer sb = new StringBuffer();
sb.append("Dumping ALL the threads!\n");
Map<Thread, StackTraceElement[]> allStacks = Thread.getAllStackTraces();
for (Thread t : allStacks.keySet()) {
sb.append(t.toString()).append('\n');
for (StackTraceElement ste : allStacks.get(t)) {
sb.append(ste.toString()).append('\n');
}
sb.append('\n');
}
log(level, sb.toString());
}
/**
* Set the filename used for logging. If the file already exists, delete it
* as a safe-guard against accidentally appending to an old log file.

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

@ -69,6 +69,7 @@ public class FennecNativeElement implements Element {
if (syncQueue.poll(MAX_WAIT_MS, TimeUnit.MILLISECONDS) == null) {
FennecNativeDriver.log(FennecNativeDriver.LogLevel.ERROR,
"click: time-out waiting for UI thread");
FennecNativeDriver.logAllStackTraces(FennecNativeDriver.LogLevel.ERROR);
}
} catch (InterruptedException e) {
FennecNativeDriver.log(FennecNativeDriver.LogLevel.ERROR, e);
@ -121,6 +122,7 @@ public class FennecNativeElement implements Element {
if (syncQueue.poll(MAX_WAIT_MS, TimeUnit.MILLISECONDS) == null) {
FennecNativeDriver.log(FennecNativeDriver.LogLevel.ERROR,
"getText: time-out waiting for UI thread");
FennecNativeDriver.logAllStackTraces(FennecNativeDriver.LogLevel.ERROR);
}
} catch (InterruptedException e) {
FennecNativeDriver.log(FennecNativeDriver.LogLevel.ERROR, e);
@ -157,6 +159,7 @@ public class FennecNativeElement implements Element {
if (syncQueue.poll(MAX_WAIT_MS, TimeUnit.MILLISECONDS) == null) {
FennecNativeDriver.log(FennecNativeDriver.LogLevel.ERROR,
"isDisplayed: time-out waiting for UI thread");
FennecNativeDriver.logAllStackTraces(FennecNativeDriver.LogLevel.ERROR);
}
} catch (InterruptedException e) {
FennecNativeDriver.log(FennecNativeDriver.LogLevel.ERROR, e);

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

@ -240,6 +240,18 @@ interface nsIPrincipal : nsISerializable
*/
readonly attribute unsigned short appStatus;
%{C++
PRUint16 GetAppStatus()
{
PRUint16 appStatus;
nsresult rv = GetAppStatus(&appStatus);
if (NS_FAILED(rv)) {
return APP_STATUS_NOT_INSTALLED;
}
return appStatus;
}
%}
/**
* Returns the app id the principal is in, or returns
* nsIScriptSecurityManager::NO_APP_ID if this principal isn't part of an

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

@ -87,20 +87,12 @@ endif
CONFIG_TOOLS = $(MOZ_BUILD_ROOT)/config
AUTOCONF_TOOLS = $(topsrcdir)/build/autoconf
ifeq ($(OS_ARCH),QNX)
ifeq ($(OS_TARGET),NTO)
LD := qcc -Vgcc_ntox86 -nostdlib
else
LD := $(CC)
endif
endif
#
# Strip off the excessively long version numbers on these platforms,
# but save the version to allow multiple versions of the same base
# platform to be built in the same tree.
#
ifneq (,$(filter FreeBSD HP-UX Linux NetBSD OpenBSD OSF1 SunOS,$(OS_ARCH)))
ifneq (,$(filter FreeBSD HP-UX Linux NetBSD OpenBSD SunOS,$(OS_ARCH)))
OS_RELEASE := $(basename $(OS_RELEASE))
# Allow the user to ignore the OS_VERSION, which is usually irrelevant.

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

@ -500,17 +500,6 @@ endif # HAS_EXTRAEXPORTS
endif # IS_COMPONENT
endif # AIX
#
# OSF1: add -B symbolic flag for components
#
ifeq ($(OS_ARCH),OSF1)
ifdef IS_COMPONENT
ifeq ($(GNU_CC)$(GNU_CXX),)
EXTRA_DSO_LDOPTS += -B symbolic
endif
endif
endif
#
# Linux: add -Bsymbolic flag for components
#

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

@ -9125,7 +9125,7 @@ nsDocument::RequestFullScreen(Element* aElement,
// trusted and so are automatically approved.
if (!mIsApprovedForFullscreen) {
mIsApprovedForFullscreen =
GetWindow()->IsInAppOrigin() ||
NodePrincipal()->GetAppStatus() >= nsIPrincipal::APP_STATUS_INSTALLED ||
nsContentUtils::IsSitePermAllow(NodePrincipal(), "fullscreen");
}

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

@ -288,6 +288,7 @@ NS_INTERFACE_MAP_END
nsFrameLoader::nsFrameLoader(Element* aOwner, bool aNetworkCreated)
: mOwnerContent(aOwner)
, mDetachedSubdocViews(nullptr)
, mDepthTooGreat(false)
, mIsTopLevelContent(false)
, mDestroyCalled(false)
@ -2374,12 +2375,21 @@ nsFrameLoader::SetRemoteBrowser(nsITabParent* aTabParent)
MOZ_ASSERT(!mCurrentRemoteFrame);
mRemoteBrowser = static_cast<TabParent*>(aTabParent);
EnsureMessageManager();
nsCOMPtr<nsIObserverService> os = services::GetObserverService();
if (OwnerIsBrowserFrame() && os) {
mRemoteBrowserInitialized = true;
os->NotifyObservers(NS_ISUPPORTS_CAST(nsIFrameLoader*, this),
"remote-browser-frame-shown", NULL);
}
ShowRemoteFrame(nsIntSize(0, 0));
}
void
nsFrameLoader::SetDetachedSubdocView(nsIView* aDetachedViews,
nsIDocument* aContainerDoc)
{
mDetachedSubdocViews = aDetachedViews;
mContainerDocWhileDetached = aContainerDoc;
}
nsIView*
nsFrameLoader::GetDetachedSubdocView(nsIDocument** aContainerDoc) const
{
NS_IF_ADDREF(*aContainerDoc = mContainerDocWhileDetached);
return mDetachedSubdocViews;
}

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

@ -268,6 +268,25 @@ public:
*/
void SetRemoteBrowser(nsITabParent* aTabParent);
/**
* Stashes a detached view on the frame loader. We do this when we're
* destroying the nsSubDocumentFrame. If the nsSubdocumentFrame is
* being reframed we'll restore the detached view when it's recreated,
* otherwise we'll discard the old presentation and set the detached
* subdoc view to null. aContainerDoc is the document containing the
* the subdoc frame. This enables us to detect when the containing
* document has changed during reframe, so we can discard the presentation
* in that case.
*/
void SetDetachedSubdocView(nsIView* aDetachedView,
nsIDocument* aContainerDoc);
/**
* Retrieves the detached view and the document containing the view,
* as set by SetDetachedSubdocView().
*/
nsIView* GetDetachedSubdocView(nsIDocument** aContainerDoc) const;
private:
void SetOwnerContent(mozilla::dom::Element* aContent);
@ -326,6 +345,16 @@ public:
nsRefPtr<nsFrameMessageManager> mMessageManager;
nsCOMPtr<nsIInProcessContentFrameMessageManager> mChildMessageManager;
private:
// Stores the root view of the subdocument while the subdocument is being
// reframed. Used to restore the presentation after reframing.
nsIView* mDetachedSubdocViews;
// Stores the containing document of the frame corresponding to this
// frame loader. This is reference is kept valid while the subframe's
// presentation is detached and stored in mDetachedSubdocViews. This
// enables us to detect whether the frame has moved documents during
// a reframe, so that we know not to restore the presentation.
nsCOMPtr<nsIDocument> mContainerDocWhileDetached;
bool mDepthTooGreat : 1;
bool mIsTopLevelContent : 1;
bool mDestroyCalled : 1;

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

@ -607,10 +607,7 @@ PRInt32
nsGenericElement::GetScrollTop()
{
nsIScrollableFrame* sf = GetScrollFrame();
return sf ?
nsPresContext::AppUnitsToIntCSSPixels(sf->GetScrollPosition().y) :
0;
return sf ? sf->GetScrollPositionCSSPixels().y : 0;
}
NS_IMETHODIMP
@ -626,9 +623,7 @@ nsGenericElement::SetScrollTop(PRInt32 aScrollTop)
{
nsIScrollableFrame* sf = GetScrollFrame();
if (sf) {
nsPoint pt = sf->GetScrollPosition();
sf->ScrollToCSSPixels(nsIntPoint(nsPresContext::AppUnitsToIntCSSPixels(pt.x),
aScrollTop));
sf->ScrollToCSSPixels(nsIntPoint(sf->GetScrollPositionCSSPixels().x, aScrollTop));
}
return NS_OK;
}
@ -637,10 +632,7 @@ PRInt32
nsGenericElement::GetScrollLeft()
{
nsIScrollableFrame* sf = GetScrollFrame();
return sf ?
nsPresContext::AppUnitsToIntCSSPixels(sf->GetScrollPosition().x) :
0;
return sf ? sf->GetScrollPositionCSSPixels().x : 0;
}
NS_IMETHODIMP
@ -656,9 +648,7 @@ nsGenericElement::SetScrollLeft(PRInt32 aScrollLeft)
{
nsIScrollableFrame* sf = GetScrollFrame();
if (sf) {
nsPoint pt = sf->GetScrollPosition();
sf->ScrollToCSSPixels(nsIntPoint(aScrollLeft,
nsPresContext::AppUnitsToIntCSSPixels(pt.y)));
sf->ScrollToCSSPixels(nsIntPoint(aScrollLeft, sf->GetScrollPositionCSSPixels().y));
}
return NS_OK;
}
@ -2810,7 +2800,7 @@ static const char*
GetFullScreenError(nsIDocument* aDoc)
{
nsCOMPtr<nsPIDOMWindow> win = aDoc->GetWindow();
if (win && win->IsInAppOrigin()) {
if (aDoc->NodePrincipal()->GetAppStatus() >= nsIPrincipal::APP_STATUS_INSTALLED) {
// Request is in a web app and in the same origin as the web app.
// Don't enforce as strict security checks for web apps, the user
// is supposed to have trust in them. However documents cross-origin

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

@ -52,6 +52,7 @@ CPPSRCS += \
WebGLExtensionLoseContext.cpp \
WebGLTexelConversions.cpp \
WebGLExtensionCompressedTextureS3TC.cpp \
WebGLExtensionDepthTexture.cpp \
$(NULL)
DEFINES += -DUSE_ANGLE

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

@ -668,8 +668,8 @@ void WebGLContext::LoseOldestWebGLContextIfLimitExceeded()
uint64_t oldestIndex = UINT64_MAX;
uint64_t oldestIndexThisPrincipal = UINT64_MAX;
const WebGLContext *oldestContext = nsnull;
const WebGLContext *oldestContextThisPrincipal = nsnull;
const WebGLContext *oldestContext = nullptr;
const WebGLContext *oldestContextThisPrincipal = nullptr;
size_t numContexts = 0;
size_t numContextsThisPrincipal = 0;
@ -1007,6 +1007,18 @@ bool WebGLContext::IsExtensionSupported(WebGLExtensionID ext)
isSupported = true;
}
break;
case WEBGL_depth_texture:
if (gl->IsGLES2() &&
gl->IsExtensionSupported(GLContext::OES_packed_depth_stencil) &&
gl->IsExtensionSupported(GLContext::OES_depth_texture))
{
isSupported = true;
} else if (!gl->IsGLES2() &&
gl->IsExtensionSupported(GLContext::EXT_packed_depth_stencil))
{
isSupported = true;
}
break;
default:
MOZ_ASSERT(false, "should not get there.");
}
@ -1072,6 +1084,12 @@ WebGLContext::GetExtension(const nsAString& aName)
if (IsExtensionSupported(WEBGL_compressed_texture_s3tc))
ext = WEBGL_compressed_texture_s3tc;
}
else if (aName.Equals(NS_LITERAL_STRING("MOZ_WEBGL_depth_texture"),
nsCaseInsensitiveStringComparator()))
{
if (IsExtensionSupported(WEBGL_depth_texture))
ext = WEBGL_depth_texture;
}
if (ext == WebGLExtensionID_unknown_extension) {
return nullptr;
@ -1091,6 +1109,9 @@ WebGLContext::GetExtension(const nsAString& aName)
case WEBGL_compressed_texture_s3tc:
mExtensions[ext] = new WebGLExtensionCompressedTextureS3TC(this);
break;
case WEBGL_depth_texture:
mExtensions[ext] = new WebGLExtensionDepthTexture(this);
break;
default:
// create a generic WebGLExtension object for any extensions that don't
// have any additional tokens or methods. We still need these to be separate
@ -1667,6 +1688,8 @@ WebGLContext::GetSupportedExtensions(Nullable< nsTArray<nsString> > &retval)
arr.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_lose_context"));
if (IsExtensionSupported(WEBGL_compressed_texture_s3tc))
arr.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_compressed_texture_s3tc"));
if (IsExtensionSupported(WEBGL_depth_texture))
arr.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_depth_texture"));
}
NS_IMETHODIMP

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

@ -111,11 +111,14 @@ enum WebGLTexelFormat
// 1-channel formats
R8,
A8,
D16, // used for WEBGL_depth_texture extension
D32, // used for WEBGL_depth_texture extension
R32F, // used for OES_texture_float extension
A32F, // used for OES_texture_float extension
// 2-channel formats
RA8,
RA32F,
D24S8, // used for WEBGL_depth_texture extension
// 3-channel formats
RGB8,
BGRX8, // used for DOM elements. Source format only.
@ -461,6 +464,7 @@ class WebGLContext :
friend class WebGLExtensionCompressedTextureS3TC;
friend class WebGLContextUserData;
friend class WebGLMemoryPressureObserver;
friend class WebGLExtensionDepthTexture;
public:
WebGLContext();
@ -1147,6 +1151,7 @@ protected:
EXT_texture_filter_anisotropic,
WEBGL_lose_context,
WEBGL_compressed_texture_s3tc,
WEBGL_depth_texture,
WebGLExtensionID_number_of_extensions,
WebGLExtensionID_unknown_extension
};
@ -2697,8 +2702,28 @@ public:
!thisRect->Height())
return false;
if (mTexturePtr)
return mAttachmentPoint == LOCAL_GL_COLOR_ATTACHMENT0;
if (mTexturePtr) {
if (!mTexturePtr->HasImageInfoAt(0, 0))
return false;
WebGLenum format = mTexturePtr->ImageInfoAt(0).Format();
switch (mAttachmentPoint)
{
case LOCAL_GL_COLOR_ATTACHMENT0:
return format == LOCAL_GL_ALPHA ||
format == LOCAL_GL_LUMINANCE ||
format == LOCAL_GL_LUMINANCE_ALPHA ||
format == LOCAL_GL_RGB ||
format == LOCAL_GL_RGBA;
case LOCAL_GL_DEPTH_ATTACHMENT:
return format == LOCAL_GL_DEPTH_COMPONENT;
case LOCAL_GL_DEPTH_STENCIL_ATTACHMENT:
return format == LOCAL_GL_DEPTH_STENCIL;
default:
MOZ_NOT_REACHED("Invalid WebGL texture format?");
}
}
if (mRenderbufferPtr) {
WebGLenum format = mRenderbufferPtr->InternalFormat();
@ -2944,6 +2969,9 @@ public:
// generate the INVALID_FRAMEBUFFER_OPERATION that we need here
if (HasDepthStencilConflict())
return false;
if (HasIncompleteAttachment())
return false;
if (!mColorAttachment.HasUninitializedRenderbuffer() &&
!mDepthAttachment.HasUninitializedRenderbuffer() &&

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

@ -1037,6 +1037,10 @@ WebGLContext::CopyTexImage2D(WebGLenum target,
return ErrorInvalidOperation("copyTexImage2D: texture format requires an alpha channel "
"but the framebuffer doesn't have one");
if (internalformat == LOCAL_GL_DEPTH_COMPONENT ||
internalformat == LOCAL_GL_DEPTH_STENCIL)
return ErrorInvalidOperation("copyTexImage2D: a base internal format of DEPTH_COMPONENT or DEPTH_STENCIL isn't supported");
if (mBoundFramebuffer)
if (!mBoundFramebuffer->CheckAndInitializeRenderbuffers())
return ErrorInvalidFramebufferOperation("copyTexImage2D: incomplete framebuffer");
@ -1158,6 +1162,10 @@ WebGLContext::CopyTexSubImage2D(WebGLenum target,
return ErrorInvalidOperation("copyTexSubImage2D: texture format requires an alpha channel "
"but the framebuffer doesn't have one");
if (format == LOCAL_GL_DEPTH_COMPONENT ||
format == LOCAL_GL_DEPTH_STENCIL)
return ErrorInvalidOperation("copyTexSubImage2D: a base internal format of DEPTH_COMPONENT or DEPTH_STENCIL isn't supported");
if (mBoundFramebuffer)
if (!mBoundFramebuffer->CheckAndInitializeRenderbuffers())
return ErrorInvalidFramebufferOperation("copyTexSubImage2D: incomplete framebuffer");
@ -2130,6 +2138,12 @@ WebGLContext::GenerateMipmap(WebGLenum target)
if (IsTextureFormatCompressed(format))
return ErrorInvalidOperation("generateMipmap: Texture data at level zero is compressed.");
if (IsExtensionEnabled(WEBGL_depth_texture) &&
(format == LOCAL_GL_DEPTH_COMPONENT || format == LOCAL_GL_DEPTH_STENCIL))
return ErrorInvalidOperation("generateMipmap: "
"A texture that has a base internal format of "
"DEPTH_COMPONENT or DEPTH_STENCIL isn't supported");
if (!tex->AreAllLevel0ImageInfosEqual())
return ErrorInvalidOperation("generateMipmap: The six faces of this cube map have different dimensions, format, or type.");
@ -5616,6 +5630,8 @@ WebGLContext::TexImage2D_base(WebGLenum target, WebGLint level, WebGLenum intern
case LOCAL_GL_ALPHA:
case LOCAL_GL_LUMINANCE:
case LOCAL_GL_LUMINANCE_ALPHA:
case LOCAL_GL_DEPTH_COMPONENT:
case LOCAL_GL_DEPTH_STENCIL:
break;
default:
return ErrorInvalidEnumInfo("texImage2D: internal format", internalformat);
@ -5637,6 +5653,20 @@ WebGLContext::TexImage2D_base(WebGLenum target, WebGLint level, WebGLenum intern
if (border != 0)
return ErrorInvalidValue("texImage2D: border must be 0");
if (format == LOCAL_GL_DEPTH_COMPONENT || format == LOCAL_GL_DEPTH_STENCIL) {
if (IsExtensionEnabled(WEBGL_depth_texture)) {
if (target != LOCAL_GL_TEXTURE_2D || data != NULL || level != 0)
return ErrorInvalidOperation("texImage2D: "
"with format of DEPTH_COMPONENT or DEPTH_STENCIL "
"target must be TEXTURE_2D, "
"data must be NULL, "
"level must be zero");
}
else
return ErrorInvalidEnumInfo("texImage2D: internal format", internalformat);
}
uint32_t dstTexelSize = 0;
if (!ValidateTexFormatAndType(format, type, jsArrayType, &dstTexelSize, "texImage2D"))
return;
@ -5849,6 +5879,11 @@ WebGLContext::TexSubImage2D_base(WebGLenum target, WebGLint level,
return ErrorInvalidValue("texSubImage2D: with level > 0, width and height must be powers of two");
}
if (IsExtensionEnabled(WEBGL_depth_texture) &&
(format == LOCAL_GL_DEPTH_COMPONENT || format == LOCAL_GL_DEPTH_STENCIL)) {
return ErrorInvalidOperation("texSubImage2D: format");
}
uint32_t dstTexelSize = 0;
if (!ValidateTexFormatAndType(format, type, jsArrayType, &dstTexelSize, "texSubImage2D"))
return;
@ -6117,6 +6152,30 @@ BaseTypeAndSizeFromUniformType(WebGLenum uType, WebGLenum *baseType, WebGLint *u
WebGLTexelFormat mozilla::GetWebGLTexelFormat(GLenum format, GLenum type)
{
//
// WEBGL_depth_texture
if (format == LOCAL_GL_DEPTH_COMPONENT) {
switch (type) {
case LOCAL_GL_UNSIGNED_SHORT:
return WebGLTexelConversions::D16;
case LOCAL_GL_UNSIGNED_INT:
return WebGLTexelConversions::D32;
default:
MOZ_NOT_REACHED("Invalid WebGL texture format/type?");
return WebGLTexelConversions::BadFormat;
}
} else if (format == LOCAL_GL_DEPTH_STENCIL) {
switch (type) {
case LOCAL_GL_UNSIGNED_INT_24_8_EXT:
return WebGLTexelConversions::D24S8;
default:
MOZ_NOT_REACHED("Invalid WebGL texture format/type?");
NS_ABORT_IF_FALSE(false, "Coding mistake?! Should never reach this point.");
return WebGLTexelConversions::BadFormat;
}
}
if (type == LOCAL_GL_UNSIGNED_BYTE) {
switch (format) {
case LOCAL_GL_RGBA:
@ -6174,6 +6233,18 @@ InternalFormatForFormatAndType(WebGLenum format, WebGLenum type, bool isGLES2)
if (isGLES2)
return format;
if (format == LOCAL_GL_DEPTH_COMPONENT) {
if (type == LOCAL_GL_UNSIGNED_SHORT)
return LOCAL_GL_DEPTH_COMPONENT16;
else if (type == LOCAL_GL_UNSIGNED_INT)
return LOCAL_GL_DEPTH_COMPONENT32;
}
if (format == LOCAL_GL_DEPTH_STENCIL) {
if (type == LOCAL_GL_UNSIGNED_INT_24_8_EXT)
return LOCAL_GL_DEPTH24_STENCIL8;
}
switch (type) {
case LOCAL_GL_UNSIGNED_BYTE:
case LOCAL_GL_UNSIGNED_SHORT_4_4_4_4:

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

@ -25,3 +25,4 @@ DOMCI_DATA(WebGLExtensionStandardDerivatives, void)
DOMCI_DATA(WebGLExtensionTextureFilterAnisotropic, void)
DOMCI_DATA(WebGLExtensionLoseContext, void)
DOMCI_DATA(WebGLExtensionCompressedTextureS3TC, void)
DOMCI_DATA(WebGLExtensionDepthTexture, void)

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

@ -190,6 +190,8 @@ WebGLContext::IsTextureFormatCompressed(GLenum format)
case LOCAL_GL_ALPHA:
case LOCAL_GL_LUMINANCE:
case LOCAL_GL_LUMINANCE_ALPHA:
case LOCAL_GL_DEPTH_COMPONENT:
case LOCAL_GL_DEPTH_STENCIL:
return false;
case LOCAL_GL_COMPRESSED_RGB_S3TC_DXT1_EXT:

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

@ -456,6 +456,16 @@ uint32_t WebGLContext::GetBitsPerTexel(WebGLenum format, WebGLenum type)
return 0;
}
if (format == LOCAL_GL_DEPTH_COMPONENT) {
if (type == LOCAL_GL_UNSIGNED_SHORT)
return 2;
else if (type == LOCAL_GL_UNSIGNED_INT)
return 4;
} else if (format == LOCAL_GL_DEPTH_STENCIL) {
if (type == LOCAL_GL_UNSIGNED_INT_24_8_EXT)
return 4;
}
if (type == LOCAL_GL_UNSIGNED_BYTE || type == LOCAL_GL_FLOAT) {
int multiplier = type == LOCAL_GL_FLOAT ? 32 : 8;
switch (format) {
@ -491,6 +501,48 @@ uint32_t WebGLContext::GetBitsPerTexel(WebGLenum format, WebGLenum type)
bool WebGLContext::ValidateTexFormatAndType(WebGLenum format, WebGLenum type, int jsArrayType,
uint32_t *texelSize, const char *info)
{
if (IsExtensionEnabled(WEBGL_depth_texture)) {
if (format == LOCAL_GL_DEPTH_COMPONENT) {
if (jsArrayType != -1) {
if ((type == LOCAL_GL_UNSIGNED_SHORT && jsArrayType != js::ArrayBufferView::TYPE_UINT16) ||
(type == LOCAL_GL_UNSIGNED_INT && jsArrayType != js::ArrayBufferView::TYPE_UINT32)) {
ErrorInvalidOperation("%s: invalid typed array type for given texture data type", info);
return false;
}
}
switch(type) {
case LOCAL_GL_UNSIGNED_SHORT:
*texelSize = 2;
break;
case LOCAL_GL_UNSIGNED_INT:
*texelSize = 4;
break;
default:
ErrorInvalidOperation("%s: invalid type 0x%x", info, type);
return false;
}
return true;
} else if (format == LOCAL_GL_DEPTH_STENCIL) {
if (type != LOCAL_GL_UNSIGNED_INT_24_8_EXT) {
ErrorInvalidOperation("%s: invalid format 0x%x", info, format);
return false;
}
if (jsArrayType != -1) {
if (jsArrayType != js::ArrayBufferView::TYPE_UINT32) {
ErrorInvalidOperation("%s: invalid typed array type for given texture data type", info);
return false;
}
}
*texelSize = 4;
return true;
}
}
if (type == LOCAL_GL_UNSIGNED_BYTE ||
(IsExtensionEnabled(OES_texture_float) && type == LOCAL_GL_FLOAT))
{

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

@ -0,0 +1,32 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* 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 "WebGLContext.h"
#include "WebGLExtensions.h"
using namespace mozilla;
WebGLExtensionDepthTexture::WebGLExtensionDepthTexture(WebGLContext* context) :
WebGLExtension(context)
{
}
WebGLExtensionDepthTexture::~WebGLExtensionDepthTexture()
{
}
NS_IMPL_ADDREF_INHERITED(WebGLExtensionDepthTexture, WebGLExtension)
NS_IMPL_RELEASE_INHERITED(WebGLExtensionDepthTexture, WebGLExtension)
DOMCI_DATA(WebGLExtensionDepthTexture, WebGLExtensionDepthTexture)
NS_INTERFACE_MAP_BEGIN(WebGLExtensionDepthTexture)
NS_INTERFACE_MAP_ENTRY(nsIWebGLExtensionDepthTexture)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, WebGLExtension)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(WebGLExtensionDepthTexture)
NS_INTERFACE_MAP_END_INHERITING(WebGLExtension)

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

@ -56,6 +56,18 @@ public:
NS_DECL_NSIWEBGLEXTENSION
};
class WebGLExtensionDepthTexture :
public nsIWebGLExtensionDepthTexture,
public WebGLExtension
{
public:
WebGLExtensionDepthTexture(WebGLContext* context);
virtual ~WebGLExtensionDepthTexture();
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIWEBGLEXTENSION
};
}
#endif // WEBGLEXTENSIONS_H_

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

@ -109,6 +109,7 @@ inline size_t TexelBytesForFormat(int format) {
case WebGLTexelConversions::RGBA5551:
case WebGLTexelConversions::RGBA4444:
case WebGLTexelConversions::RGB565:
case WebGLTexelConversions::D16:
return 2;
case WebGLTexelConversions::RGB8:
return 3;
@ -117,6 +118,8 @@ inline size_t TexelBytesForFormat(int format) {
case WebGLTexelConversions::BGRX8:
case WebGLTexelConversions::R32F:
case WebGLTexelConversions::A32F:
case WebGLTexelConversions::D32:
case WebGLTexelConversions::D24S8:
return 4;
case WebGLTexelConversions::RA32F:
return 8;

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

@ -4645,23 +4645,20 @@ nsCanvasRenderingContext2DAzure::GetCanvasLayer(nsDisplayListBuilder* aBuilder,
return nullptr;
}
CanvasRenderingContext2DUserDataAzure *userData = nullptr;
if (aBuilder->IsPaintingToWindow()) {
// Make the layer tell us whenever a transaction finishes (including
// the current transaction), so we can clear our invalidation state and
// start invalidating again. We need to do this for the layer that is
// being painted to a window (there shouldn't be more than one at a time,
// and if there is, flushing the invalidation state more often than
// necessary is harmless).
// Make the layer tell us whenever a transaction finishes (including
// the current transaction), so we can clear our invalidation state and
// start invalidating again. We need to do this for all layers since
// callers of DrawWindow may be expecting to receive normal invalidation
// notifications after this paint.
// The layer will be destroyed when we tear down the presentation
// (at the latest), at which time this userData will be destroyed,
// releasing the reference to the element.
// The userData will receive DidTransactionCallbacks, which flush the
// the invalidation state to indicate that the canvas is up to date.
userData = new CanvasRenderingContext2DUserDataAzure(this);
canvasLayer->SetDidTransactionCallback(
CanvasRenderingContext2DUserDataAzure::DidTransactionCallback, userData);
}
// The layer will be destroyed when we tear down the presentation
// (at the latest), at which time this userData will be destroyed,
// releasing the reference to the element.
// The userData will receive DidTransactionCallbacks, which flush the
// the invalidation state to indicate that the canvas is up to date.
userData = new CanvasRenderingContext2DUserDataAzure(this);
canvasLayer->SetDidTransactionCallback(
CanvasRenderingContext2DUserDataAzure::DidTransactionCallback, userData);
canvasLayer->SetUserData(&g2DContextLayerUserData, userData);
CanvasLayer::Data data;

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

@ -5,4 +5,5 @@ oes-vertex-array-object.html
webgl-debug-renderer-info.html
webgl-debug-shaders.html
--min-version 1.0.2 webgl-compressed-texture-s3tc.html
--min-version 1.0.2 webgl-depth-texture.html

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

@ -0,0 +1,343 @@
<!--
/*
** Copyright (c) 2012 The Khronos Group Inc.
**
** Permission is hereby granted, free of charge, to any person obtaining a
** copy of this software and/or associated documentation files (the
** "Materials"), to deal in the Materials without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Materials, and to
** permit persons to whom the Materials are furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be included
** in all copies or substantial portions of the Materials.
**
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
*/
-->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="../../resources/js-test-style.css"/>
<script src="../../resources/js-test-pre.js"></script>
<script src="../resources/webgl-test.js"></script>
<script src="../resources/webgl-test-utils.js"></script>
<title>WebGL WEBGL_depth_texture Conformance Tests</title>
</head>
<body>
<script id="vshader" type="x-shader/x-vertex">
attribute vec4 a_position;
void main()
{
gl_Position = a_position;
}
</script>
<script id="fshader" type="x-shader/x-fragment">
precision mediump float;
uniform sampler2D u_texture;
uniform vec2 u_resolution;
void main()
{
vec2 texcoord = gl_FragCoord.xy / u_resolution;
gl_FragColor = texture2D(u_texture, texcoord);
}
</script>
<div id="description"></div>
<div id="console"></div>
<canvas id="canvas" width="8" height="8" style="width: 8px; height: 8px;"></canvas>
<script>
if (window.initNonKhronosFramework) {
window.initNonKhronosFramework(false);
}
description("This test verifies the functionality of the WEBGL_depth_texture extension, if it is available.");
debug("");
var wtu = WebGLTestUtils;
var canvas = document.getElementById("canvas");
var gl = wtu.create3DContext(canvas, {antialias: false});
var program = wtu.setupTexturedQuad(gl);
var ext = null;
var vao = null;
var tex;
var name;
var supportedFormats;
if (!gl) {
testFailed("WebGL context does not exist");
} else {
testPassed("WebGL context exists");
// Run tests with extension disabled
runTestDisabled();
// Query the extension and store globally so shouldBe can access it
ext = wtu.getExtensionWithKnownPrefixes(gl, "WEBGL_depth_texture");
if (!ext) {
testPassed("No WEBGL_depth_texture support -- this is legal");
runSupportedTest(false);
} else {
testPassed("Successfully enabled WEBGL_depth_texture extension");
runSupportedTest(true);
runTestExtension();
}
}
function runSupportedTest(extensionEnabled) {
var name = wtu.getSupportedExtensionWithKnownPrefixes(gl, "WEBGL_depth_texture");
if (name !== undefined) {
if (extensionEnabled) {
testPassed("WEBGL_depth_texture listed as supported and getExtension succeeded");
} else {
testFailed("WEBGL_depth_texture listed as supported but getExtension failed");
}
} else {
if (extensionEnabled) {
testFailed("WEBGL_depth_texture not listed as supported but getExtension succeeded");
} else {
testPassed("WEBGL_depth_texture not listed as supported and getExtension failed -- this is legal");
}
}
}
function runTestDisabled() {
debug("Testing binding enum with extension disabled");
var tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
shouldGenerateGLError(gl, gl.INVALID_ENUM, 'gl.texImage2D(gl.TEXTURE_2D, 0, gl.DEPTH_COMPONENT, 1, 1, 0, gl.DEPTH_COMPONENT, gl.UNSIGNED_SHORT, null)');
shouldGenerateGLError(gl, gl.INVALID_ENUM, 'gl.texImage2D(gl.TEXTURE_2D, 0, gl.DEPTH_COMPONENT, 1, 1, 0, gl.DEPTH_COMPONENT, gl.UNSIGNED_INT, null)');
}
function dumpIt(gl, res, msg) {
return; // comment out to debug
debug(msg);
var actualPixels = new Uint8Array(res * res * 4);
gl.readPixels(0, 0, res, res, gl.RGBA, gl.UNSIGNED_BYTE, actualPixels);
for (var yy = 0; yy < res; ++yy) {
var strs = [];
for (var xx = 0; xx < res; ++xx) {
var actual = (yy * res + xx) * 4;
strs.push("(" + actualPixels[actual] + "," + actualPixels[actual+1] + "," + actualPixels[actual + 2] + "," + actualPixels[actual + 3] + ")");
}
debug(strs.join(" "));
}
}
function runTestExtension() {
debug("Testing WEBGL_depth_texture");
var res = 8;
// make canvas for testing.
canvas2 = document.createElement("canvas");
canvas2.width = res;
canvas2.height = res;
var ctx = canvas2.getContext("2d");
ctx.fillStyle = "blue";
ctx.fillRect(0, 0, canvas2.width, canvas2.height);
var program = wtu.setupProgram(gl, ['vshader', 'fshader'], ['a_position']);
gl.useProgram(program);
gl.uniform2f(gl.getUniformLocation(program, "u_resolution"), res, res);
var buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(
gl.ARRAY_BUFFER,
new Float32Array(
[ 1, 1, 1,
-1, 1, 0,
-1, -1, -1,
1, 1, 1,
-1, -1, -1,
1, -1, 0,
]),
gl.STATIC_DRAW);
gl.enableVertexAttribArray(0);
gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
var types = [
{obj: 'gl', attachment: 'DEPTH_ATTACHMENT', format: 'DEPTH_COMPONENT', type: 'UNSIGNED_SHORT', data: 'new Uint16Array(1)' },
{obj: 'gl', attachment: 'DEPTH_ATTACHMENT', format: 'DEPTH_COMPONENT', type: 'UNSIGNED_INT', data: 'new Uint32Array(1)' },
{obj: 'ext', attachment: 'DEPTH_STENCIL_ATTACHMENT', format: 'DEPTH_STENCIL', type: 'UNSIGNED_INT_24_8_WEBGL', data: 'new Uint32Array(1)' }
];
for (var ii = 0; ii < types.length; ++ii) {
var typeInfo = types[ii];
var type = typeInfo.type;
var typeStr = typeInfo.obj + '.' + type;
debug("");
debug("testing: " + type);
// check that cubemaps are not allowed.
var cubeTex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_CUBE_MAP, cubeTex);
var targets = [
'TEXTURE_CUBE_MAP_POSITIVE_X',
'TEXTURE_CUBE_MAP_NEGATIVE_X',
'TEXTURE_CUBE_MAP_POSITIVE_Y',
'TEXTURE_CUBE_MAP_NEGATIVE_Y',
'TEXTURE_CUBE_MAP_POSITIVE_Z',
'TEXTURE_CUBE_MAP_NEGATIVE_Z'
];
for (var tt = 0; tt < targets.length; ++tt) {
shouldGenerateGLError(gl, gl.INVALID_OPERATION, 'gl.texImage2D(gl.' + targets[ii] + ', 1, gl.' + typeInfo.format + ', 1, 1, 0, gl.' + typeInfo.format + ', ' + typeStr + ', null)');
}
// check 2d textures.
tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
// test level > 0
shouldGenerateGLError(gl, gl.INVALID_OPERATION, 'gl.texImage2D(gl.TEXTURE_2D, 1, gl.' + typeInfo.format + ', 1, 1, 0, gl.' + typeInfo.format + ', ' + typeStr + ', null)');
// test with data
shouldGenerateGLError(gl, gl.INVALID_OPERATION, 'gl.texImage2D(gl.TEXTURE_2D, 0, gl.' + typeInfo.format + ', 1, 1, 0, gl.' + typeInfo.format + ', ' + typeStr + ', ' + typeInfo.data + ')');
// test with canvas
shouldGenerateGLError(gl, [gl.INVALID_VALUE, gl.INVALID_ENUM, gl.INVALID_OPERATION], 'gl.texImage2D(gl.TEXTURE_2D, 0, gl.' + typeInfo.format + ', gl.' + typeInfo.format + ', ' + typeStr + ', canvas2)');
// test copyTexImage2D
shouldGenerateGLError(gl, [gl.INVALID_ENUM, gl.INVALID_OPERATION], 'gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.' + typeInfo.format + ', 0, 0, 1, 1, 0)');
// test real thing
shouldGenerateGLError(gl, gl.NO_ERROR, 'gl.texImage2D(gl.TEXTURE_2D, 0, gl.' + typeInfo.format + ', ' + res + ', ' + res + ', 0, gl.' + typeInfo.format + ', ' + typeStr + ', null)');
// test texSubImage2D
shouldGenerateGLError(gl, gl.INVALID_OPERATION, 'gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 1, 1, gl.' + typeInfo.format + ', ' + typeStr + ', ' + typeInfo.data + ')');
// test copyTexSubImage2D
shouldGenerateGLError(gl, gl.INVALID_OPERATION, 'gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1)');
// test generateMipmap
shouldGenerateGLError(gl, gl.INVALID_OPERATION, 'gl.generateMipmap(gl.TEXTURE_2D)');
var fbo = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl[typeInfo.attachment], gl.TEXTURE_2D, tex, 0);
// TODO: remove this check if the spec is updated to require these combinations to work.
if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE)
{
// try adding a color buffer.
var colorTex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, colorTex);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, res, res, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, colorTex, 0);
shouldBe('gl.checkFramebufferStatus(gl.FRAMEBUFFER)', 'gl.FRAMEBUFFER_COMPLETE');
}
// use the default texture to render with while we return to the depth texture.
gl.bindTexture(gl.TEXTURE_2D, null);
// render the z-quad
gl.enable(gl.DEPTH_TEST);
gl.clearColor(1, 0, 0, 1);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.drawArrays(gl.TRIANGLES, 0, 6);
dumpIt(gl, res, "--first--");
// render the depth texture.
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.clearColor(0, 0, 1, 1);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.drawArrays(gl.TRIANGLES, 0, 6);
var actualPixels = new Uint8Array(res * res * 4);
gl.readPixels(0, 0, res, res, gl.RGBA, gl.UNSIGNED_BYTE, actualPixels);
dumpIt(gl, res, "--depth--");
// Check that each pixel's RGB are the same and that it's value is less
// than the previous pixel in either direction. Basically verify we have a
// gradient.
var success = true;
for (var yy = 0; yy < res; ++yy) {
for (var xx = 0; xx < res; ++xx) {
var actual = (yy * res + xx) * 4;
var left = actual - 4;
var down = actual - res * 4;
if (actualPixels[actual + 0] != actualPixels[actual + 1]) {
testFailed('R != G');
success = false;
}
if (actualPixels[actual + 0] != actualPixels[actual + 2]) {
testFailed('R != B');
success = false;
}
// ALPHA is implementation dependent
if (actualPixels[actual + 3] != 0xFF && actualPixels[actual + 3] != actualPixels[actual + 0]) {
testFailed('A != 255 && A != R');
success = false;
}
if (xx > 0) {
if (actualPixels[actual] <= actualPixels[left]) {
testFailed("actual(" + actualPixels[actual] + ") < left(" + actualPixels[left] + ")");
success = false;
}
}
if (yy > 0) {
if (actualPixels[actual] <= actualPixels[down]) {
testFailed("actual(" + actualPixels[actual] + ") < down(" + actualPixels[down] + ")");
success = false;
}
}
}
}
// Check that bottom left corner is vastly different thatn top right.
if (actualPixels[(res * res - 1) * 4] - actualPixels[0] < 0xC0) {
testFailed("corners are not different enough");
success = false;
}
if (success) {
testPassed("depth texture rendered correctly.");
}
// check limitations
gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl[typeInfo.attachment], gl.TEXTURE_2D, null, 0);
var badAttachment = typeInfo.attachment == 'DEPTH_ATTACHMENT' ? 'DEPTH_STENCIL_ATTACHMENT' : 'DEPTH_ATTACHMENT';
shouldGenerateGLError(gl, gl.NO_ERROR, 'gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.' + badAttachment + ', gl.TEXTURE_2D, tex, 0)');
shouldNotBe('gl.checkFramebufferStatus(gl.FRAMEBUFFER)', 'gl.FRAMEBUFFER_COMPLETE');
shouldGenerateGLError(gl, gl.INVALID_FRAMEBUFFER_OPERATION, 'gl.clear(gl.DEPTH_BUFFER_BIT)');
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
shouldBe('gl.getError()', 'gl.NO_ERROR');
}
}
debug("");
successfullyParsed = true;
</script>
<script src="../../resources/js-test-post.js"></script>
</body>
</html>

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

@ -163,7 +163,7 @@ nsDOMTouchList::GetLength(PRUint32* aLength)
NS_IMETHODIMP
nsDOMTouchList::Item(PRUint32 aIndex, nsIDOMTouch** aRetVal)
{
NS_IF_ADDREF(*aRetVal = mPoints.SafeElementAt(aIndex, nsnull));
NS_IF_ADDREF(*aRetVal = mPoints.SafeElementAt(aIndex, nullptr));
return NS_OK;
}

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

@ -114,7 +114,7 @@ public:
nsIDOMTouch* GetItemAt(PRUint32 aIndex)
{
return mPoints.SafeElementAt(aIndex, nsnull);
return mPoints.SafeElementAt(aIndex, nullptr);
}
protected:

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

@ -869,7 +869,7 @@ nsEventDispatcher::CreateEvent(nsPresContext* aPresContext,
if (aEventType.LowerCaseEqualsLiteral("mozsmsevent"))
return NS_NewDOMSmsEvent(aDOMEvent, aPresContext, nullptr);
if (aEventType.LowerCaseEqualsLiteral("storageevent")) {
return NS_NewDOMStorageEvent(aDOMEvent, aPresContext, nsnull);
return NS_NewDOMStorageEvent(aDOMEvent, aPresContext, nullptr);
}

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

@ -332,7 +332,6 @@ public:
static DeltaValues AccelerateWheelDelta(widget::WheelEvent* aEvent,
bool aAllowScrollSpeedOverride);
static bool IsAccelerationEnabled();
enum {
kScrollSeriesTimeout = 80
@ -588,12 +587,6 @@ nsMouseWheelTransaction::GetIgnoreMoveDelayTime()
return Preferences::GetUint("mousewheel.transaction.ignoremovedelay", 100);
}
bool
nsMouseWheelTransaction::IsAccelerationEnabled()
{
return GetAccelerationStart() >= 0 && GetAccelerationFactor() > 0;
}
DeltaValues
nsMouseWheelTransaction::AccelerateWheelDelta(widget::WheelEvent* aEvent,
bool aAllowScrollSpeedOverride)
@ -2465,7 +2458,7 @@ nsEventStateManager::DoScrollZoom(nsIFrame *aTargetFrame,
nsIContent *content = aTargetFrame->GetContent();
if (content &&
!content->IsNodeOfType(nsINode::eHTML_FORM_CONTROL) &&
!content->IsXUL())
!content->OwnerDoc()->IsXUL())
{
// positive adjustment to decrease zoom, negative to increase
PRInt32 change = (adjustment > 0) ? -1 : 1;

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

@ -71,6 +71,8 @@ MOCHITEST_FILES = \
test_bug656379-1.html \
test_bug656379-2.html \
test_bug656954.html \
test_bug659071.html \
window_bug659071.html \
test_bug659350.html \
test_bug662678.html \
test_bug667919-1.html \

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

@ -0,0 +1,38 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=659071
-->
<head>
<title>Test for Bug 659071</title>
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=659071">Mozilla Bug 659071</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
/** Test for Bug 659071 **/
SimpleTest.waitForExplicitFinish();
var subWin = window.open("window_bug659071.html", "_blank",
"width=500,height=500");
function finish()
{
subWin.close();
SimpleTest.finish();
}
</script>
</pre>
</body>
</html>

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

@ -0,0 +1,60 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for Bug 659071</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<video id="v" controls></video>
<script type="application/javascript">
SimpleTest.waitForFocus(runTests, window);
function is()
{
window.opener.is.apply(window.opener, arguments);
}
function isnot()
{
window.opener.isnot.apply(window.opener, arguments);
}
function hitEventLoop(aFunc, aTimes)
{
if (--aTimes) {
setTimeout(hitEventLoop, 0, aFunc, aTimes);
} else {
setTimeout(aFunc, 20);
}
}
function runTests()
{
SpecialPowers.setIntPref("mousewheel.with_control.action", 3);
SpecialPowers.setFullZoom(window, 1.0);
var video = document.getElementById("v");
hitEventLoop(function () {
is(SpecialPowers.getFullZoom(window), 1.0,
"failed to reset zoom");
synthesizeWheel(video, 10, 10,
{ deltaMode: WheelEvent.DOM_DELTA_LINE, ctrlKey: true,
deltaX: 0, deltaY: 1.0, lineOrPageDeltaX: 0, lineOrPageDeltaY: 1 });
hitEventLoop(function () {
isnot(SpecialPowers.getFullZoom(window), 1.0,
"failed to zoom by ctrl+wheel");
SpecialPowers.setFullZoom(window, 1.0);
SpecialPowers.clearUserPref("mousewheel.with_control.action");
hitEventLoop(window.opener.finish, 20);
}, 20);
}, 20);
}
</script>
</body>
</html>

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

@ -61,7 +61,6 @@ var observers = os.enumerateObservers("invalidformsubmit");
*/
if (observers.hasMoreElements()) {
document.getElementById('av').addEventListener("invalid", function(aEvent) {
aEvent.target.removeAttribute("invalid", arguments.callee, false);
ok(true, "formnovalidate should not apply on if not set on the submit " +
@ -133,6 +132,8 @@ if (observers.hasMoreElements()) {
SimpleTest.waitForFocus(function() {
document.getElementById('a').click();
});
} else {
todo(false, "No 'invalidformsubmit' observers. Skip test.");
}
</script>

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

@ -98,6 +98,8 @@ if (observers.hasMoreElements()) {
checkPseudoClass(textarea, false);
checkPseudoClass(input, false);
checkPseudoClass(select, false);
} else {
todo(false, "No 'invalidformsubmit' observers. Skip test.");
}
</script>

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

@ -104,6 +104,8 @@ if (observers.hasMoreElements()) {
checkPseudoClass(textarea, false);
checkPseudoClass(input, false);
checkPseudoClass(select, false);
} else {
todo(false, "No 'invalidformsubmit' observers. Skip test.");
}
</script>

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

@ -27,7 +27,7 @@ NS_IMPL_THREADSAFE_ISUPPORTS1(MediaEngineDefaultVideoSource, nsITimerCallback)
*/
MediaEngineDefaultVideoSource::MediaEngineDefaultVideoSource()
: mTimer(nsnull), mState(kReleased)
: mTimer(nullptr), mState(kReleased)
{}
MediaEngineDefaultVideoSource::~MediaEngineDefaultVideoSource()

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

@ -28,7 +28,7 @@ class SerializedLoadContext
public:
SerializedLoadContext()
{
Init(nsnull);
Init(nullptr);
}
SerializedLoadContext(nsILoadContext* aLoadContext);

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

@ -2846,7 +2846,10 @@ nsDocShell::CanAccessItem(nsIDocShellTreeItem* aTargetItem,
// window with javascript
// Bug 408052: Adopt "ancestor" frame navigation policy
// Now do a security check
// Now do a security check.
//
// Disallow navigation if the two frames are not part of the same app, or if
// they have different is-in-browser-element states.
//
// Allow navigation if
// 1) aAccessingItem can script aTargetItem or one of its ancestors in
@ -2857,7 +2860,29 @@ nsDocShell::CanAccessItem(nsIDocShellTreeItem* aTargetItem,
if (aTargetItem == aAccessingItem) {
// A frame is allowed to navigate itself.
return true;
return true;
}
nsCOMPtr<nsIDocShell> targetDS = do_QueryInterface(aTargetItem);
nsCOMPtr<nsIDocShell> accessingDS = do_QueryInterface(aAccessingItem);
if (!!targetDS != !!accessingDS) {
// We must be able to convert both or neither to nsIDocShell.
return false;
}
if (targetDS && accessingDS) {
bool targetInBrowser = false, accessingInBrowser = false;
targetDS->GetIsInBrowserElement(&targetInBrowser);
accessingDS->GetIsInBrowserElement(&accessingInBrowser);
PRUint32 targetAppId = 0, accessingAppId = 0;
targetDS->GetAppId(&targetAppId);
accessingDS->GetAppId(&accessingAppId);
if (targetInBrowser != accessingInBrowser ||
targetAppId != accessingAppId) {
return false;
}
}
nsCOMPtr<nsIDocShellTreeItem> accessingRoot;

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

@ -27,7 +27,7 @@ class nsDOMNavigationTiming;
[ptr] native nsIViewPtr(nsIView);
[ptr] native nsDOMNavigationTimingPtr(nsDOMNavigationTiming);
[scriptable, builtinclass, uuid(26b2380b-4a1a-46cd-b7d8-7600e41c1688)]
[scriptable, builtinclass, uuid(b9d92b8b-5623-4079-ae11-36bb341f322e)]
interface nsIContentViewer : nsISupports
{
@ -134,10 +134,10 @@ interface nsIContentViewer : nsISupports
*/
void clearHistoryEntry();
/*
/**
* Change the layout to view the document with page layout (like print preview), but
* dynamic and editable (like Galley layout).
*/
*/
void setPageMode(in boolean aPageMode, in nsIPrintSettings aPrintSettings);
/**
@ -146,7 +146,7 @@ interface nsIContentViewer : nsISupports
*/
readonly attribute nsISHEntry historyEntry;
/*
/**
* Indicates when we're in a state where content shouldn't be allowed to
* trigger a tab-modal prompt (as opposed to a window-modal prompt) because
* we're part way through some operation (eg beforeunload) that shouldn't be
@ -155,6 +155,11 @@ interface nsIContentViewer : nsISupports
*/
readonly attribute boolean isTabModalPromptAllowed;
/**
* Returns whether this content viewer is in a hidden state.
*/
readonly attribute boolean isHidden;
[noscript] readonly attribute nsIPresShellPtr presShell;
[noscript] readonly attribute nsPresContextPtr presContext;
// aDocument must not be null.

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

@ -608,9 +608,22 @@ interface nsIDocShell : nsISupports
readonly attribute boolean isInBrowserElement;
/**
* Returns true iif the docshell is inside an application.
* However, it will return false if the docshell is inside a browser element
* that is inside an application.
* Returns true iif the docshell is inside an application. However, it will
* return false if the docshell is inside a browser element that is inside
* an application.
*
* Note: Do not use this method for permissions checks! An app may contain
* an <iframe> pointing at arbitrary web code. This iframe's docshell will
* have isInApp() == true, but the iframe's content is not "app code", and
* so should not be granted more trust than vanilla web content.
*
* (For example, suppose when web content calls API method X, we show a
* permission prompt, but when "app code" calls method X, we don't. In this
* case, it would be /incorrect/ to show the permission prompt if
* !isInApp().)
*
* If you're doing a security check, use the content's principal instead of
* this method.
*/
readonly attribute boolean isInApp;

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

@ -75,12 +75,8 @@
function retryThis(buttonEl)
{
// If this is the "Offline mode" page, go online!
if (getErrorCode() == "netOffline") {
window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindowUtils)
.goOnline();
}
// Note: The application may wish to handle switching off "offline mode"
// before this event handler runs, but using a capturing event handler.
// Session history has the URL of the page that failed
// to load, not the one of the error page. So, just call

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

@ -154,11 +154,9 @@ AlarmsManager.prototype = {
"AlarmsManager:GetAll:Return:OK", "AlarmsManager:GetAll:Return:KO"]);
// Get the manifest URL if this is an installed app
this._manifestURL = null;
let utils = aWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
let app = utils.getApp();
if (app)
this._manifestURL = app.manifestURL;
let appsService = Cc["@mozilla.org/AppsService;1"]
.getService(Ci.nsIAppsService);
this._manifestURL = appsService.getManifestURLByLocalId(principal.appId);
},
// Called from DOMRequestIpcHelper.

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

@ -54,6 +54,8 @@
#include "nsIDOMGlobalPropertyInitializer.h"
using namespace mozilla::dom::power;
// This should not be in the namespace.
DOMCI_DATA(Navigator, mozilla::dom::Navigator)
@ -1029,11 +1031,11 @@ Navigator::GetMozPower(nsIDOMMozPowerManager** aPower)
*aPower = nullptr;
if (!mPowerManager) {
nsCOMPtr<nsPIDOMWindow> win = do_QueryReferent(mWindow);
NS_ENSURE_TRUE(win, NS_OK);
nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
NS_ENSURE_TRUE(window, NS_OK);
mPowerManager = new power::PowerManager();
mPowerManager->Init(win);
mPowerManager = PowerManager::CheckPermissionAndCreateInstance(window);
NS_ENSURE_TRUE(mPowerManager, NS_OK);
}
nsCOMPtr<nsIDOMMozPowerManager> power(mPowerManager);

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

@ -540,6 +540,7 @@ using mozilla::dom::indexedDB::IDBWrapperCache;
#include "LockedFile.h"
#include "GeneratedEvents.h"
#include "mozilla/Likely.h"
#include "nsDebug.h"
#undef None // something included above defines this preprocessor symbol, maybe Xlib headers
#include "WebGLContext.h"
@ -1580,6 +1581,9 @@ static nsDOMClassInfoData sClassInfoData[] = {
NS_DEFINE_CLASSINFO_DATA(WebGLExtensionCompressedTextureS3TC, WebGLExtensionSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS |
nsIXPCScriptable::WANT_ADDPROPERTY)
NS_DEFINE_CLASSINFO_DATA(WebGLExtensionDepthTexture, WebGLExtensionSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS |
nsIXPCScriptable::WANT_ADDPROPERTY)
NS_DEFINE_CLASSINFO_DATA(PaintRequest, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
@ -2073,8 +2077,10 @@ SetParentToWindow(nsGlobalWindow *win, JSObject **parent)
if (MOZ_UNLIKELY(!*parent)) {
// The only known case where this can happen is when the inner window has
// been torn down. See bug 691178 comment 11.
MOZ_ASSERT(win->IsClosedOrClosing());
// been torn down. See bug 691178 comment 11. Should be a fatal MOZ_ASSERT,
// but we've found a way to hit it too often in mochitests. See bugs 777875
// 778424, 781078.
NS_ASSERTION(win->IsClosedOrClosing(), "win should be closed or closing");
return NS_ERROR_FAILURE;
}
return NS_OK;
@ -4276,6 +4282,10 @@ nsDOMClassInfo::Init()
DOM_CLASSINFO_MAP_ENTRY(nsIWebGLExtensionCompressedTextureS3TC)
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(WebGLExtensionDepthTexture, nsIWebGLExtensionDepthTexture)
DOM_CLASSINFO_MAP_ENTRY(nsIWebGLExtensionDepthTexture)
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(PaintRequest, nsIDOMPaintRequest)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMPaintRequest)
DOM_CLASSINFO_MAP_END

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

@ -463,6 +463,7 @@ DOMCI_CLASS(WebGLExtensionStandardDerivatives)
DOMCI_CLASS(WebGLExtensionTextureFilterAnisotropic)
DOMCI_CLASS(WebGLExtensionLoseContext)
DOMCI_CLASS(WebGLExtensionCompressedTextureS3TC)
DOMCI_CLASS(WebGLExtensionDepthTexture)
DOMCI_CLASS(PaintRequest)
DOMCI_CLASS(PaintRequestList)

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

@ -64,7 +64,6 @@
#include "sampler.h"
#include "nsDOMBlobBuilder.h"
#include "nsIDOMFileHandle.h"
#include "nsIDOMApplicationRegistry.h"
using namespace mozilla;
using namespace mozilla::dom;
@ -2288,6 +2287,22 @@ nsDOMWindowUtils::CheckAndClearPaintedState(nsIDOMElement* aElement, bool* aResu
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::PreventFurtherDialogs()
{
// Permanently disable further dialogs for this window.
if (!IsUniversalXPConnectCapable()) {
return NS_ERROR_DOM_SECURITY_ERR;
}
nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
static_cast<nsGlobalWindow*>(window.get())->PreventFurtherDialogs(true);
return NS_OK;
}
static nsresult
GetFileOrBlob(const nsAString& aName, const jsval& aBlobParts,
const jsval& aParameters, JSContext* aCx,
@ -2562,47 +2577,6 @@ nsDOMWindowUtils::SetScrollPositionClampingScrollPortSize(float aWidth, float aH
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::SetIsApp(bool aValue)
{
if (!IsUniversalXPConnectCapable()) {
return NS_ERROR_DOM_SECURITY_ERR;
}
nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
static_cast<nsGlobalWindow*>(window.get())->SetIsApp(aValue);
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::SetApp(const nsAString& aManifestURL)
{
if (!IsUniversalXPConnectCapable()) {
return NS_ERROR_DOM_SECURITY_ERR;
}
nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
return static_cast<nsGlobalWindow*>(window.get())->SetApp(aManifestURL);
}
NS_IMETHODIMP
nsDOMWindowUtils::GetApp(mozIDOMApplication** aApplication)
{
if (!IsUniversalXPConnectCapable()) {
return NS_ERROR_DOM_SECURITY_ERR;
}
nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
return static_cast<nsGlobalWindow*>(window.get())->GetApp(aApplication);
}
nsresult
nsDOMWindowUtils::RemoteFrameFullscreenChanged(nsIDOMElement* aFrameElement,
const nsAString& aNewOrigin)

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

@ -671,7 +671,6 @@ nsGlobalWindow::nsGlobalWindow(nsGlobalWindow *aOuterWindow)
mShowFocusRingForContent(false),
mFocusByKeyOccurred(false),
mNotifiedIDDestroyed(false),
mIsApp(TriState_Unknown),
mTimeoutInsertionPoint(nullptr),
mTimeoutPublicIdCounter(1),
mTimeoutFiringDepth(0),
@ -685,7 +684,8 @@ nsGlobalWindow::nsGlobalWindow(nsGlobalWindow *aOuterWindow)
mCleanedUp(false),
mCallCleanUpAfterModalDialogCloses(false),
mDialogAbuseCount(0),
mDialogDisabled(false)
mStopAbuseDialogs(false),
mDialogsPermanentlyDisabled(false)
{
nsLayoutStatics::AddRef();
@ -2552,67 +2552,80 @@ nsGlobalWindow::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
}
bool
nsGlobalWindow::DialogOpenAttempted()
nsGlobalWindow::DialogsAreBlocked(bool *aBeingAbused)
{
*aBeingAbused = false;
nsGlobalWindow *topWindow = GetScriptableTop();
if (!topWindow) {
NS_ERROR("DialogOpenAttempted() called without a top window?");
return false;
NS_ERROR("DialogsAreBlocked() called without a top window?");
return true;
}
topWindow = topWindow->GetCurrentInnerWindowInternal();
if (!topWindow ||
topWindow->mLastDialogQuitTime.IsNull() ||
if (!topWindow) {
return true;
}
if (topWindow->mDialogsPermanentlyDisabled) {
return true;
}
// Dialogs are blocked if the content viewer is hidden
if (mDocShell) {
nsCOMPtr<nsIContentViewer> cv;
mDocShell->GetContentViewer(getter_AddRefs(cv));
bool isHidden;
cv->GetIsHidden(&isHidden);
if (isHidden) {
return true;
}
}
*aBeingAbused = topWindow->DialogsAreBeingAbused();
return topWindow->mStopAbuseDialogs && *aBeingAbused;
}
bool
nsGlobalWindow::DialogsAreBeingAbused()
{
NS_ASSERTION(GetScriptableTop() &&
GetScriptableTop()->GetCurrentInnerWindowInternal() == this,
"DialogsAreBeingAbused called with invalid window");
if (mLastDialogQuitTime.IsNull() ||
nsContentUtils::CallerHasUniversalXPConnect()) {
return false;
}
TimeDuration dialogInterval(TimeStamp::Now() - mLastDialogQuitTime);
if (dialogInterval.ToSeconds() <
Preferences::GetInt("dom.successive_dialog_time_limit",
DEFAULT_SUCCESSIVE_DIALOG_TIME_LIMIT)) {
mDialogAbuseCount++;
TimeDuration dialogDuration(TimeStamp::Now() -
topWindow->mLastDialogQuitTime);
if (dialogDuration.ToSeconds() <
Preferences::GetInt("dom.successive_dialog_time_limit",
SUCCESSIVE_DIALOG_TIME_LIMIT)) {
topWindow->mDialogAbuseCount++;
return (topWindow->GetPopupControlState() > openAllowed ||
topWindow->mDialogAbuseCount > MAX_DIALOG_COUNT);
return GetPopupControlState() > openAllowed ||
mDialogAbuseCount > MAX_SUCCESSIVE_DIALOG_COUNT;
}
topWindow->mDialogAbuseCount = 0;
// Reset the abuse counter
mDialogAbuseCount = 0;
return false;
}
bool
nsGlobalWindow::AreDialogsBlocked()
nsGlobalWindow::ConfirmDialogIfNeeded()
{
nsGlobalWindow *topWindow = GetScriptableTop();
if (!topWindow) {
NS_ASSERTION(!mDocShell, "AreDialogsBlocked() called without a top window?");
return true;
}
topWindow = topWindow->GetCurrentInnerWindowInternal();
return !topWindow ||
(topWindow->mDialogDisabled &&
(topWindow->GetPopupControlState() > openAllowed ||
topWindow->mDialogAbuseCount >= MAX_DIALOG_COUNT));
}
bool
nsGlobalWindow::ConfirmDialogAllowed()
{
FORWARD_TO_OUTER(ConfirmDialogAllowed, (), false);
FORWARD_TO_OUTER(ConfirmDialogIfNeeded, (), false);
NS_ENSURE_TRUE(mDocShell, false);
nsCOMPtr<nsIPromptService> promptSvc =
do_GetService("@mozilla.org/embedcomp/prompt-service;1");
if (!DialogOpenAttempted() || !promptSvc) {
if (!promptSvc) {
return true;
}
@ -2629,7 +2642,7 @@ nsGlobalWindow::ConfirmDialogAllowed()
"ScriptDialogPreventTitle", title);
promptSvc->Confirm(this, title.get(), label.get(), &disableDialog);
if (disableDialog) {
PreventFurtherDialogs();
PreventFurtherDialogs(false);
return false;
}
@ -2637,19 +2650,21 @@ nsGlobalWindow::ConfirmDialogAllowed()
}
void
nsGlobalWindow::PreventFurtherDialogs()
nsGlobalWindow::PreventFurtherDialogs(bool aPermanent)
{
nsGlobalWindow *topWindow = GetScriptableTop();
if (!topWindow) {
NS_ERROR("PreventFurtherDialogs() called without a top window?");
return;
}
topWindow = topWindow->GetCurrentInnerWindowInternal();
if (topWindow)
topWindow->mDialogDisabled = true;
if (topWindow) {
topWindow->mStopAbuseDialogs = true;
if (aPermanent) {
topWindow->mDialogsPermanentlyDisabled = true;
}
}
}
nsresult
@ -4322,11 +4337,13 @@ nsGlobalWindow::GetScrollXY(PRInt32* aScrollX, PRInt32* aScrollY,
return GetScrollXY(aScrollX, aScrollY, true);
}
if (aScrollX)
*aScrollX = nsPresContext::AppUnitsToIntCSSPixels(scrollPos.x);
if (aScrollY)
*aScrollY = nsPresContext::AppUnitsToIntCSSPixels(scrollPos.y);
nsIntPoint scrollPosCSSPixels = sf->GetScrollPositionCSSPixels();
if (aScrollX) {
*aScrollX = scrollPosCSSPixels.x;
}
if (aScrollY) {
*aScrollY = scrollPosCSSPixels.y;
}
return NS_OK;
}
@ -4791,12 +4808,10 @@ nsGlobalWindow::Alert(const nsAString& aString)
{
FORWARD_TO_OUTER(Alert, (aString), NS_ERROR_NOT_INITIALIZED);
if (AreDialogsBlocked())
bool needToPromptForAbuse;
if (DialogsAreBlocked(&needToPromptForAbuse)) {
return NS_ERROR_NOT_AVAILABLE;
// We have to capture this now so as not to get confused with the
// popup state we push next
bool shouldEnableDisableDialog = DialogOpenAttempted();
}
// Reset popup state while opening a modal dialog, and firing events
// about the dialog, to prevent the current state from being active
@ -4843,7 +4858,7 @@ nsGlobalWindow::Alert(const nsAString& aString)
nsAutoSyncOperation sync(GetCurrentInnerWindowInternal() ?
GetCurrentInnerWindowInternal()->mDoc :
nullptr);
if (shouldEnableDisableDialog) {
if (needToPromptForAbuse) {
bool disallowDialog = false;
nsXPIDLString label;
nsContentUtils::GetLocalizedString(nsContentUtils::eCOMMON_DIALOG_PROPERTIES,
@ -4852,7 +4867,7 @@ nsGlobalWindow::Alert(const nsAString& aString)
rv = prompt->AlertCheck(title.get(), final.get(), label.get(),
&disallowDialog);
if (disallowDialog)
PreventFurtherDialogs();
PreventFurtherDialogs(false);
} else {
rv = prompt->Alert(title.get(), final.get());
}
@ -4865,12 +4880,10 @@ nsGlobalWindow::Confirm(const nsAString& aString, bool* aReturn)
{
FORWARD_TO_OUTER(Confirm, (aString, aReturn), NS_ERROR_NOT_INITIALIZED);
if (AreDialogsBlocked())
bool needToPromptForAbuse;
if (DialogsAreBlocked(&needToPromptForAbuse)) {
return NS_ERROR_NOT_AVAILABLE;
// We have to capture this now so as not to get confused with the popup state
// we push next
bool shouldEnableDisableDialog = DialogOpenAttempted();
}
// Reset popup state while opening a modal dialog, and firing events
// about the dialog, to prevent the current state from being active
@ -4912,7 +4925,7 @@ nsGlobalWindow::Confirm(const nsAString& aString, bool* aReturn)
nsAutoSyncOperation sync(GetCurrentInnerWindowInternal() ?
GetCurrentInnerWindowInternal()->mDoc :
nullptr);
if (shouldEnableDisableDialog) {
if (needToPromptForAbuse) {
bool disallowDialog = false;
nsXPIDLString label;
nsContentUtils::GetLocalizedString(nsContentUtils::eCOMMON_DIALOG_PROPERTIES,
@ -4921,7 +4934,7 @@ nsGlobalWindow::Confirm(const nsAString& aString, bool* aReturn)
rv = prompt->ConfirmCheck(title.get(), final.get(), label.get(),
&disallowDialog, aReturn);
if (disallowDialog)
PreventFurtherDialogs();
PreventFurtherDialogs(false);
} else {
rv = prompt->Confirm(title.get(), final.get(), aReturn);
}
@ -4938,12 +4951,10 @@ nsGlobalWindow::Prompt(const nsAString& aMessage, const nsAString& aInitial,
SetDOMStringToNull(aReturn);
if (AreDialogsBlocked())
bool needToPromptForAbuse;
if (DialogsAreBlocked(&needToPromptForAbuse)) {
return NS_ERROR_NOT_AVAILABLE;
// We have to capture this now so as not to get confused with the popup state
// we push next
bool shouldEnableDisableDialog = DialogOpenAttempted();
}
// Reset popup state while opening a modal dialog, and firing events
// about the dialog, to prevent the current state from being active
@ -4986,7 +4997,7 @@ nsGlobalWindow::Prompt(const nsAString& aMessage, const nsAString& aInitial,
bool disallowDialog = false;
nsXPIDLString label;
if (shouldEnableDisableDialog) {
if (needToPromptForAbuse) {
nsContentUtils::GetLocalizedString(nsContentUtils::eCOMMON_DIALOG_PROPERTIES,
"ScriptDialogLabel", label);
}
@ -4999,7 +5010,7 @@ nsGlobalWindow::Prompt(const nsAString& aMessage, const nsAString& aInitial,
&inoutValue, label.get(), &disallowDialog, &ok);
if (disallowDialog) {
PreventFurtherDialogs();
PreventFurtherDialogs(false);
}
NS_ENSURE_SUCCESS(rv, rv);
@ -5257,8 +5268,14 @@ nsGlobalWindow::Print()
if (Preferences::GetBool("dom.disable_window_print", false))
return NS_ERROR_NOT_AVAILABLE;
if (AreDialogsBlocked() || !ConfirmDialogAllowed())
bool needToPromptForAbuse;
if (DialogsAreBlocked(&needToPromptForAbuse)) {
return NS_ERROR_NOT_AVAILABLE;
}
if (needToPromptForAbuse && !ConfirmDialogIfNeeded()) {
return NS_ERROR_NOT_AVAILABLE;
}
nsCOMPtr<nsIWebBrowserPrint> webBrowserPrint;
if (NS_SUCCEEDED(GetInterface(NS_GET_IID(nsIWebBrowserPrint),
@ -7189,8 +7206,14 @@ nsGlobalWindow::ShowModalDialog(const nsAString& aURI, nsIVariant *aArgs,
// pending reflows.
EnsureReflowFlushAndPaint();
if (AreDialogsBlocked() || !ConfirmDialogAllowed())
bool needToPromptForAbuse;
if (DialogsAreBlocked(&needToPromptForAbuse)) {
return NS_ERROR_NOT_AVAILABLE;
}
if (needToPromptForAbuse && !ConfirmDialogIfNeeded()) {
return NS_ERROR_NOT_AVAILABLE;
}
nsCOMPtr<nsIDOMWindow> dlgWin;
nsAutoString options(NS_LITERAL_STRING("-moz-internal-modal=1,status=1"));
@ -9036,7 +9059,7 @@ nsGlobalWindow::CloneStorageEvent(const nsAString& aType,
aEvent->GetUrl(url);
aEvent->GetStorageArea(getter_AddRefs(storageArea));
NS_NewDOMStorageEvent(getter_AddRefs(domEvent), nsnull, nsnull);
NS_NewDOMStorageEvent(getter_AddRefs(domEvent), nullptr, nullptr);
aEvent = do_QueryInterface(domEvent);
return aEvent->InitStorageEvent(aType, canBubble, cancelable,
key, oldValue, newValue,
@ -9163,8 +9186,15 @@ nsGlobalWindow::OpenInternal(const nsAString& aUrl, const nsAString& aName,
NS_ASSERTION(mDocShell, "Must have docshell here");
// Popups from apps are never blocked.
bool isApp = false;
if (mDoc) {
isApp = mDoc->NodePrincipal()->GetAppStatus() >=
nsIPrincipal::APP_STATUS_INSTALLED;
}
const bool checkForPopup = !nsContentUtils::IsCallerChrome() &&
!IsPartOfApp() && !aDialog && !WindowExists(aName, !aCalledNoScript);
!isApp && !aDialog && !WindowExists(aName, !aCalledNoScript);
// Note: it's very important that this be an nsXPIDLCString, since we want
// .get() on it to return nullptr until we write stuff to it. The window
@ -10671,112 +10701,6 @@ nsGlobalWindow::SizeOfIncludingThis(nsWindowSizes* aWindowSizes) const
mNavigator->SizeOfIncludingThis(aWindowSizes->mMallocSizeOf) : 0;
}
void
nsGlobalWindow::SetIsApp(bool aValue)
{
FORWARD_TO_OUTER_VOID(SetIsApp, (aValue));
// You shouldn't call SetIsApp() more than once.
MOZ_ASSERT(mIsApp == TriState_Unknown);
mIsApp = aValue ? TriState_True : TriState_False;
}
bool
nsGlobalWindow::IsInAppOrigin()
{
FORWARD_TO_OUTER(IsInAppOrigin, (), false);
nsIPrincipal* principal = GetPrincipal();
NS_ENSURE_TRUE(principal != nullptr, false);
// We go trough all window parents until we find one with |mIsApp| set to
// something. If none is found, we are not part of an application.
for (nsGlobalWindow* w = static_cast<nsGlobalWindow*>(this); w;
w = static_cast<nsGlobalWindow*>(w->GetParentInternal())) {
if (w->mIsApp == TriState_True) {
// The window should be part of an application.
MOZ_ASSERT(w->mApp);
bool sameOrigin = false;
return w->mAppPrincipal &&
principal &&
NS_SUCCEEDED(principal->Equals(w->mAppPrincipal, &sameOrigin)) &&
sameOrigin;
} else if (w->mIsApp == TriState_False) {
return false;
}
}
return false;
}
bool
nsGlobalWindow::IsPartOfApp()
{
nsCOMPtr<mozIDOMApplication> app;
return NS_SUCCEEDED(GetApp(getter_AddRefs(app))) ? app != nullptr : false;
}
nsresult
nsGlobalWindow::SetApp(const nsAString& aManifestURL)
{
// SetIsApp(true) should be called before calling SetApp().
if (mIsApp != TriState_True) {
MOZ_ASSERT(false);
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIAppsService> appsService = do_GetService(APPS_SERVICE_CONTRACTID);
if (!appsService) {
NS_ERROR("Apps Service is not available!");
return NS_ERROR_FAILURE;
}
nsCOMPtr<mozIDOMApplication> app;
appsService->GetAppByManifestURL(aManifestURL, getter_AddRefs(app));
if (!app) {
NS_WARNING("No application found with the specified manifest URL");
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIURI> uri;
nsresult res = NS_NewURI(getter_AddRefs(uri), aManifestURL);
NS_ENSURE_SUCCESS(res, res);
nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
res = ssm->GetSimpleCodebasePrincipal(uri, getter_AddRefs(mAppPrincipal));
NS_ENSURE_SUCCESS(res, res);
mApp = app.forget();
return NS_OK;
}
nsresult
nsGlobalWindow::GetApp(mozIDOMApplication** aApplication)
{
*aApplication = nullptr;
FORWARD_TO_OUTER(GetApp, (aApplication), NS_OK);
// We go trough all window parents until we find one with |mIsApp| set to
// something. If none is found, we are not part of an application.
for (nsGlobalWindow* w = this; w;
w = static_cast<nsGlobalWindow*>(w->GetParentInternal())) {
if (w->mIsApp == TriState_True) {
// The window should be part of an application.
MOZ_ASSERT(w->mApp);
NS_IF_ADDREF(*aApplication = w->mApp);
return NS_OK;
} else if (w->mIsApp == TriState_False) {
return NS_OK;
}
}
return NS_OK;
}
// nsGlobalChromeWindow implementation
NS_IMPL_CYCLE_COLLECTION_CLASS(nsGlobalChromeWindow)

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

@ -74,11 +74,11 @@
// Amount of time allowed between alert/prompt/confirm before enabling
// the stop dialog checkbox.
#define SUCCESSIVE_DIALOG_TIME_LIMIT 3 // 3 sec
#define DEFAULT_SUCCESSIVE_DIALOG_TIME_LIMIT 3 // 3 sec
// During click or mousedown events (and others, see nsDOMEvent) we allow modal
// dialogs up to this limit, even if they were disabled.
#define MAX_DIALOG_COUNT 10
// Maximum number of successive dialogs before we prompt users to disable
// dialogs for this window.
#define MAX_SUCCESSIVE_DIALOG_COUNT 5
// Idle fuzz time upper limit
#define MAX_IDLE_FUZZ_TIME_MS 90000
@ -384,8 +384,6 @@ public:
virtual NS_HIDDEN_(bool) DispatchCustomEvent(const char *aEventName);
virtual NS_HIDDEN_(void) RefreshCompartmentPrincipal();
virtual NS_HIDDEN_(nsresult) SetFullScreenInternal(bool aIsFullScreen, bool aRequireTrust);
virtual NS_HIDDEN_(bool) IsPartOfApp();
virtual NS_HIDDEN_(bool) IsInAppOrigin();
// nsIDOMStorageIndexedDB
NS_DECL_NSIDOMSTORAGEINDEXEDDB
@ -440,22 +438,22 @@ public:
return nullptr;
}
// Call this when a modal dialog is about to be opened. Returns
// true if we've reached the state in this top level window where we
// ask the user if further dialogs should be blocked.
bool DialogOpenAttempted();
// Returns true if dialogs need to be prevented from appearings for this
// window. beingAbused returns whether dialogs are being abused.
bool DialogsAreBlocked(bool *aBeingAbused);
// Returns true if dialogs have already been blocked for this
// window.
bool AreDialogsBlocked();
// Returns true if we've reached the state in this top level window where we
// ask the user if further dialogs should be blocked. This method must only
// be called on the scriptable top inner window.
bool DialogsAreBeingAbused();
// Ask the user if further dialogs should be blocked. This is used
// in the cases where we have no modifiable UI to show, in that case
// we show a separate dialog when asking this question.
bool ConfirmDialogAllowed();
// Ask the user if further dialogs should be blocked, if dialogs are currently
// being abused. This is used in the cases where we have no modifiable UI to
// show, in that case we show a separate dialog to ask this question.
bool ConfirmDialogIfNeeded();
// Prevent further dialogs in this (top level) window
void PreventFurtherDialogs();
void PreventFurtherDialogs(bool aPermanent);
virtual void SetHasAudioAvailableEventListeners();
@ -626,12 +624,6 @@ protected:
friend class HashchangeCallback;
friend class nsBarProp;
enum TriState {
TriState_Unknown = -1,
TriState_False,
TriState_True
};
// Object Management
virtual ~nsGlobalWindow();
void CleanUp(bool aIgnoreModalDialog);
@ -898,10 +890,6 @@ protected:
nsresult CloneStorageEvent(const nsAString& aType,
nsCOMPtr<nsIDOMStorageEvent>& aEvent);
void SetIsApp(bool aValue);
nsresult SetApp(const nsAString& aManifestURL);
nsresult GetApp(mozIDOMApplication** aApplication);
// Implements Get{Real,Scriptable}Top.
nsresult GetTopImpl(nsIDOMWindow **aWindow, bool aScriptable);
@ -977,14 +965,6 @@ protected:
// whether we've sent the destroy notification for our window id
bool mNotifiedIDDestroyed : 1;
// Whether the window is the window of an application frame.
// This is TriState_Unknown if the object is the content window of an
// iframe which is neither mozBrowser nor mozApp.
TriState mIsApp : 2;
// Principal of the web app running in this window, if any.
nsCOMPtr<nsIPrincipal> mAppPrincipal;
nsCOMPtr<nsIScriptContext> mContext;
nsWeakPtr mOpener;
nsCOMPtr<nsIControllers> mControllers;
@ -1062,17 +1042,27 @@ protected:
nsCOMPtr<nsIIDBFactory> mIndexedDB;
// In the case of a "trusted" dialog (@see PopupControlState), we
// set this counter to ensure a max of MAX_DIALOG_LIMIT
// This counts the number of windows that have been opened in rapid succession
// (i.e. within dom.successive_dialog_time_limit of each other). It is reset
// to 0 once a dialog is opened after dom.successive_dialog_time_limit seconds
// have elapsed without any other dialogs.
PRUint32 mDialogAbuseCount;
// This holds the time when the last modal dialog was shown, if two
// dialogs are shown within CONCURRENT_DIALOG_TIME_LIMIT the
// checkbox is shown. In the case of ShowModalDialog another Confirm
// dialog will be shown, the result of the checkbox/confirm dialog
// will be stored in mDialogDisabled variable.
// This holds the time when the last modal dialog was shown. If more than
// MAX_DIALOG_LIMIT dialogs are shown within the time span defined by
// dom.successive_dialog_time_limit, we show a checkbox or confirmation prompt
// to allow disabling of further dialogs from this window.
TimeStamp mLastDialogQuitTime;
bool mDialogDisabled;
// This is set to true once the user has opted-in to preventing further
// dialogs for this window. Subsequent dialogs may still open if
// mDialogAbuseCount gets reset.
bool mStopAbuseDialogs;
// This flag gets set when dialogs should be permanently disabled for this
// window (e.g. when we are closing the tab and therefore are guaranteed to be
// destroying this window).
bool mDialogsPermanentlyDisabled;
nsRefPtr<nsDOMMozURLProperty> mURLProperty;
@ -1080,10 +1070,6 @@ protected:
nsTArray<PRUint32> mEnabledSensors;
// The application associated with this window.
// This should only be non-null if mIsApp's value is TriState_True.
nsCOMPtr<mozIDOMApplication> mApp;
friend class nsDOMScriptableHelper;
friend class nsDOMWindowUtils;
friend class PostMessageEvent;

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

@ -48,8 +48,8 @@ class nsIArray;
class nsPIWindowRoot;
#define NS_PIDOMWINDOW_IID \
{ 0x0c4d0b84, 0xb524, 0x4572, \
{ 0x8e, 0xd1, 0x7f, 0x78, 0x14, 0x7c, 0x4d, 0xf1 } }
{0x05995519, 0xde6e, 0x428c, \
{0x9e, 0x96, 0x61, 0xd6, 0x0f, 0x34, 0x45, 0x3e}}
class nsPIDOMWindow : public nsIDOMWindowInternal
{
@ -609,19 +609,6 @@ public:
*/
virtual void RefreshCompartmentPrincipal() = 0;
/**
* Returns if the window is part of an application.
* It will check for the window app state and its parents until a window has
* an app state different from |TriState_Unknown|.
*/
virtual bool IsPartOfApp() = 0;
/**
* Returns true if this window is part of a web app and has the same origin
* (principal) as the app.
*/
virtual bool IsInAppOrigin() = 0;
protected:
// The nsPIDOMWindow constructor. The aOuterWindow argument should
// be null if and only if the created window itself is an outer

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

@ -353,29 +353,46 @@ nsScreen::MozLockOrientation(const nsAString& aOrientation, bool* aReturn)
return NS_OK;
}
if (!GetOwner()) {
return NS_OK;
}
// Determine whether we can lock the screen orientation.
bool canLockOrientation = false;
do {
nsCOMPtr<nsPIDOMWindow> owner = GetOwner();
if (!owner) {
break;
}
// Chrome code and apps can always lock the screen orientation.
if (!IsChromeType(GetOwner()->GetDocShell()) &&
!static_cast<nsGlobalWindow*>(GetOwner())->IsPartOfApp()) {
nsCOMPtr<nsIDOMDocument> doc;
GetOwner()->GetDocument(getter_AddRefs(doc));
// Chrome can always lock the screen orientation.
if (IsChromeType(owner->GetDocShell())) {
canLockOrientation = true;
break;
}
nsCOMPtr<nsIDOMDocument> domDoc;
owner->GetDocument(getter_AddRefs(domDoc));
nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
if (!doc) {
return NS_OK;
break;
}
// Non-apps content can lock orientation only if fullscreen.
// Apps can always lock the screen orientation.
if (doc->NodePrincipal()->GetAppStatus() >=
nsIPrincipal::APP_STATUS_INSTALLED) {
canLockOrientation = true;
break;
}
// Other content must be full-screen in order to lock orientation.
bool fullscreen;
doc->GetMozFullScreen(&fullscreen);
domDoc->GetMozFullScreen(&fullscreen);
if (!fullscreen) {
return NS_OK;
break;
}
nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(GetOwner());
// If we're full-screen, register a listener so we learn when we leave
// full-screen.
nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(owner);
if (!target) {
return NS_OK;
break;
}
if (!mEventListener) {
@ -383,10 +400,14 @@ nsScreen::MozLockOrientation(const nsAString& aOrientation, bool* aReturn)
}
target->AddSystemEventListener(NS_LITERAL_STRING("mozfullscreenchange"),
mEventListener, true);
mEventListener, /* useCapture = */ true);
canLockOrientation = true;
} while(0);
if (canLockOrientation) {
*aReturn = hal::LockScreenOrientation(orientation);
}
*aReturn = hal::LockScreenOrientation(orientation);
return NS_OK;
}

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

@ -64,6 +64,11 @@ NS_IMPL_RELEASE_INHERITED(BluetoothAdapter, nsDOMEventTargetHelper)
BluetoothAdapter::BluetoothAdapter(nsPIDOMWindow* aOwner, const BluetoothValue& aValue)
: BluetoothPropertyContainer(BluetoothObjectType::TYPE_ADAPTER)
, mEnabled(false)
, mDiscoverable(false)
, mDiscovering(false)
, mPairable(false)
, mPowered(false)
, mJsUuids(nullptr)
, mJsDeviceAddresses(nullptr)
, mIsRooted(false)
@ -358,7 +363,7 @@ BluetoothAdapter::SetName(const nsAString& aName,
nsIDOMDOMRequest** aRequest)
{
if (mName.Equals(aName)) {
return NS_OK;
return FirePropertyAlreadySet(GetOwner(), aRequest);
}
nsString name(aName);
BluetoothValue value(name);
@ -371,7 +376,7 @@ BluetoothAdapter::SetDiscoverable(const bool aDiscoverable,
nsIDOMDOMRequest** aRequest)
{
if (aDiscoverable == mDiscoverable) {
return NS_OK;
return FirePropertyAlreadySet(GetOwner(), aRequest);
}
BluetoothValue value(aDiscoverable);
BluetoothNamedValue property(NS_LITERAL_STRING("Discoverable"), value);
@ -383,7 +388,7 @@ BluetoothAdapter::SetDiscoverableTimeout(const PRUint32 aDiscoverableTimeout,
nsIDOMDOMRequest** aRequest)
{
if (aDiscoverableTimeout == mDiscoverableTimeout) {
return NS_OK;
return FirePropertyAlreadySet(GetOwner(), aRequest);
}
BluetoothValue value(aDiscoverableTimeout);
BluetoothNamedValue property(NS_LITERAL_STRING("DiscoverableTimeout"), value);

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

@ -13,15 +13,26 @@
USING_BLUETOOTH_NAMESPACE
nsresult
BluetoothPropertyContainer::GetProperties()
BluetoothPropertyContainer::FirePropertyAlreadySet(nsIDOMWindow* aOwner,
nsIDOMDOMRequest** aRequest)
{
BluetoothService* bs = BluetoothService::Get();
if (!bs) {
NS_WARNING("Bluetooth service not available!");
nsCOMPtr<nsIDOMRequestService> rs = do_GetService("@mozilla.org/dom/dom-request-service;1");
if (!rs) {
NS_WARNING("No DOMRequest Service!");
return NS_ERROR_FAILURE;
}
nsRefPtr<BluetoothReplyRunnable> task = new GetPropertiesTask(this, NULL);
return bs->GetProperties(mObjectType, mPath, task);
nsCOMPtr<nsIDOMDOMRequest> req;
nsresult rv = rs->CreateRequest(aOwner, getter_AddRefs(req));
if (NS_FAILED(rv)) {
NS_WARNING("Can't create DOMRequest!");
return NS_ERROR_FAILURE;
}
rs->FireSuccess(req, JSVAL_VOID);
req.forget(aRequest);
return NS_OK;
}
nsresult
@ -56,21 +67,3 @@ BluetoothPropertyContainer::SetProperty(nsIDOMWindow* aOwner,
req.forget(aRequest);
return NS_OK;
}
bool
BluetoothPropertyContainer::GetPropertiesTask::ParseSuccessfulReply(jsval* aValue)
{
*aValue = JSVAL_VOID;
BluetoothValue& v = mReply->get_BluetoothReplySuccess().value();
if (v.type() != BluetoothValue::TArrayOfBluetoothNamedValue) {
NS_WARNING("Not a BluetoothNamedValue array!");
return false;
}
const InfallibleTArray<BluetoothNamedValue>& values =
mReply->get_BluetoothReplySuccess().value().get_ArrayOfBluetoothNamedValue();
for (uint32_t i = 0; i < values.Length(); ++i) {
mPropObjPtr->SetPropertyByValue(values[i]);
}
return true;
}

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

@ -20,7 +20,8 @@ class BluetoothNamedValue;
class BluetoothPropertyContainer
{
public:
nsresult GetProperties();
nsresult FirePropertyAlreadySet(nsIDOMWindow* aOwner,
nsIDOMDOMRequest** aRequest);
nsresult SetProperty(nsIDOMWindow* aOwner,
const BluetoothNamedValue& aProperty,
nsIDOMDOMRequest** aRequest);
@ -42,29 +43,6 @@ protected:
~BluetoothPropertyContainer()
{}
class GetPropertiesTask : public BluetoothReplyRunnable
{
public:
GetPropertiesTask(BluetoothPropertyContainer* aPropObj, nsIDOMDOMRequest* aReq) :
BluetoothReplyRunnable(aReq),
mPropObjPtr(aPropObj)
{
MOZ_ASSERT(aReq && aPropObj);
}
virtual bool ParseSuccessfulReply(jsval* aValue);
void
ReleaseMembers()
{
BluetoothReplyRunnable::ReleaseMembers();
mPropObjPtr = nullptr;
}
private:
BluetoothPropertyContainer* mPropObjPtr;
};
nsString mPath;
BluetoothObjectType mObjectType;

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

@ -243,7 +243,7 @@ RunDBusCallback(DBusMessage* aMsg, void* aBluetoothReplyRunnable,
nsString replyError;
BluetoothValue v;
aFunc(aMsg, nsnull, v, replyError);
aFunc(aMsg, nullptr, v, replyError);
DispatchBluetoothReply(replyRunnable, v, replyError);
}

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

@ -70,6 +70,10 @@ BrowserElementChild.prototype = {
debug("Starting up.");
sendAsyncMsg("hello");
// Set the docshell's name according to our <iframe>'s name attribute.
docShell.QueryInterface(Ci.nsIDocShellTreeItem).name =
sendSyncMsg('get-name')[0];
BrowserElementPromptService.mapWindowToBrowserElementChild(content, this);
docShell.QueryInterface(Ci.nsIWebProgress)
@ -87,26 +91,6 @@ BrowserElementChild.prototype = {
.createInstance(Ci.nsISecureBrowserUI);
securityUI.init(content);
// A mozbrowser iframe contained inside a mozapp iframe should return false
// for nsWindowUtils::IsPartOfApp (unless the mozbrowser iframe is itself
// also mozapp). That is, mozapp is transitive down to its children, but
// mozbrowser serves as a barrier.
//
// This is because mozapp iframes have some privileges which we don't want
// to extend to untrusted mozbrowser content.
//
// Get the app manifest from the parent, if our frame has one.
let appManifestURL = sendSyncMsg('get-mozapp-manifest-url')[0];
let windowUtils = content.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils);
if (!!appManifestURL) {
windowUtils.setIsApp(true);
windowUtils.setApp(appManifestURL);
} else {
windowUtils.setIsApp(false);
}
// A cache of the menuitem dom objects keyed by the id we generate
// and pass to the embedder
this._ctxHandlers = {};

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

@ -29,7 +29,7 @@ namespace {
* aOpenerFrameElement.
*/
already_AddRefed<nsHTMLIFrameElement>
CreateIframe(Element* aOpenerFrameElement)
CreateIframe(Element* aOpenerFrameElement, const nsAString& aName)
{
nsNodeInfoManager *nodeInfoManager =
aOpenerFrameElement->OwnerDoc()->NodeInfoManager();
@ -54,6 +54,10 @@ CreateIframe(Element* aOpenerFrameElement)
mozapp, /* aNotify = */ false);
}
// Copy the window name onto the iframe.
popupFrameElement->SetAttr(kNameSpaceID_None, nsGkAtoms::name,
aName, /* aNotify = */ false);
return popupFrameElement.forget();
}
@ -131,7 +135,7 @@ BrowserElementParent::OpenWindowOOP(mozilla::dom::TabParent* aOpenerTabParent,
do_QueryInterface(aOpenerTabParent->GetOwnerElement());
NS_ENSURE_TRUE(openerFrameElement, false);
nsRefPtr<nsHTMLIFrameElement> popupFrameElement =
CreateIframe(openerFrameElement);
CreateIframe(openerFrameElement, aName);
// Normally an <iframe> element will try to create a frameLoader when the
// page touches iframe.contentWindow or sets iframe.src.
@ -189,7 +193,7 @@ BrowserElementParent::OpenWindowInProcess(nsIDOMWindow* aOpenerWindow,
do_QueryInterface(openerFrameDOMElement);
nsRefPtr<nsHTMLIFrameElement> popupFrameElement =
CreateIframe(openerFrameElement);
CreateIframe(openerFrameElement, aName);
NS_ENSURE_TRUE(popupFrameElement, false);
nsCAutoString spec;

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

@ -157,6 +157,7 @@ function BrowserElementParent(frameLoader, hasRemoteFrame) {
}
addMessageListener("hello", this._recvHello);
addMessageListener("get-name", this._recvGetName);
addMessageListener("contextmenu", this._fireCtxMenuEvent);
addMessageListener("locationchange", this._fireEventFromMsg);
addMessageListener("loadstart", this._fireEventFromMsg);
@ -167,7 +168,6 @@ function BrowserElementParent(frameLoader, hasRemoteFrame) {
addMessageListener("securitychange", this._fireEventFromMsg);
addMessageListener("error", this._fireEventFromMsg);
addMessageListener("scroll", this._fireEventFromMsg);
addMessageListener("get-mozapp-manifest-url", this._sendMozAppManifestURL);
addMessageListener("keyevent", this._fireKeyEvent);
addMessageListener("showmodalprompt", this._handleShowModalPrompt);
addMessageListener('got-screenshot', this._gotDOMRequestResult);
@ -262,6 +262,10 @@ BrowserElementParent.prototype = {
}
},
_recvGetName: function(data) {
return this._frameElement.getAttribute('name');
},
_fireCtxMenuEvent: function(data) {
let evtName = data.name.substring('browser-element-api:'.length);
let detail = data.json;
@ -362,10 +366,6 @@ BrowserElementParent.prototype = {
cancelable: cancelable });
},
_sendMozAppManifestURL: function(data) {
return this._frameElement.getAttribute('mozapp');
},
/**
* Kick off a DOMRequest in the child process.
*

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

@ -33,6 +33,12 @@ MOCHITEST_FILES = \
test_browserElement_inproc_Titlechange.html \
browserElement_TopBarrier.js \
test_browserElement_inproc_TopBarrier.html \
browserElement_AppWindowNamespace.js \
test_browserElement_inproc_AppWindowNamespace.html \
file_browserElement_AppWindowNamespace.html \
browserElement_BrowserWindowNamespace.js \
test_browserElement_inproc_BrowserWindowNamespace.html \
file_browserElement_BrowserWindowNamespace.html \
browserElement_Iconchange.js \
test_browserElement_inproc_Iconchange.html \
browserElement_GetScreenshot.js \
@ -66,6 +72,9 @@ MOCHITEST_FILES = \
browserElement_TargetTop.js \
test_browserElement_inproc_TargetTop.html \
file_browserElement_TargetTop.html \
browserElement_ForwardName.js \
test_browserElement_inproc_ForwardName.html \
file_browserElement_ForwardName.html \
browserElement_PromptCheck.js \
test_browserElement_inproc_PromptCheck.html \
browserElement_PromptConfirm.js \
@ -88,6 +97,10 @@ MOCHITEST_FILES = \
browserElement_OpenWindowDifferentOrigin.js \
test_browserElement_inproc_OpenWindowDifferentOrigin.html \
file_browserElement_OpenWindowDifferentOrigin.html \
browserElement_OpenNamed.js \
test_browserElement_inproc_OpenNamed.html \
file_browserElement_OpenNamed.html \
file_browserElement_OpenNamed2.html \
browserElement_SecurityChange.js \
test_browserElement_inproc_SecurityChange.html \
file_browserElement_SecurityChange.html \
@ -118,6 +131,8 @@ MOCHITEST_FILES += \
test_browserElement_oop_DataURI.html \
test_browserElement_oop_ErrorSecurity.html \
test_browserElement_oop_Titlechange.html \
test_browserElement_oop_AppWindowNamespace.html \
test_browserElement_oop_BrowserWindowNamespace.html \
test_browserElement_oop_TopBarrier.html \
test_browserElement_oop_Iconchange.html \
test_browserElement_oop_GetScreenshot.html \
@ -131,6 +146,7 @@ MOCHITEST_FILES += \
test_browserElement_oop_Alert.html \
test_browserElement_oop_AlertInFrame.html \
test_browserElement_oop_TargetTop.html \
test_browserElement_oop_ForwardName.html \
test_browserElement_oop_PromptCheck.html \
test_browserElement_oop_PromptConfirm.html \
test_browserElement_oop_Close.html \
@ -139,6 +155,7 @@ MOCHITEST_FILES += \
test_browserElement_oop_OpenWindowInFrame.html \
test_browserElement_oop_OpenWindowRejected.html \
test_browserElement_oop_OpenWindowDifferentOrigin.html \
test_browserElement_oop_OpenNamed.html \
test_browserElement_oop_SecurityChange.html \
test_browserElement_oop_BackForward.html \
test_browserElement_oop_Reload.html \

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

@ -0,0 +1,44 @@
/* Any copyright is dedicated to the public domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Bug 780351 - Test that mozapp divides the window name namespace.
"use strict";
SimpleTest.waitForExplicitFinish();
function runTest() {
browserElementTestHelpers.setEnabledPref(true);
browserElementTestHelpers.addToWhitelist();
var iframe1 = document.createElement('iframe');
iframe1.mozbrowser = true;
iframe1.setAttribute('mozapp', 'http://example.org/manifest.webapp');
// Two mozapp frames for different apps with the same code both do the same
// window.open("foo", "bar") call. We should get two mozbrowseropenwindow
// events.
iframe1.addEventListener('mozbrowseropenwindow', function(e) {
ok(true, "Got first mozbrowseropenwindow event.");
document.body.appendChild(e.detail.frameElement);
SimpleTest.executeSoon(function() {
var iframe2 = document.createElement('iframe');
iframe2.mozbrowser = true;
iframe2.setAttribute('mozapp', 'http://example.com/manifest.webapp');
iframe2.addEventListener('mozbrowseropenwindow', function(e) {
ok(true, "Got second mozbrowseropenwindow event.");
SimpleTest.finish();
});
document.body.appendChild(iframe2);
iframe2.src = 'http://example.com/tests/dom/browser-element/mochitest/file_browserElement_AppWindowNamespace.html';
});
});
document.body.appendChild(iframe1);
iframe1.src = 'http://example.org/tests/dom/browser-element/mochitest/file_browserElement_AppWindowNamespace.html';
}
runTest();

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

@ -0,0 +1,54 @@
/* Any copyright is dedicated to the public domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Bug 780351 - Test that mozbrowser does /not/ divide the window name namespace.
// Multiple mozbrowsers inside the same app are like multiple browser tabs;
// they share a window name namespace.
"use strict";
SimpleTest.waitForExplicitFinish();
function runTest() {
browserElementTestHelpers.setEnabledPref(true);
browserElementTestHelpers.addToWhitelist();
var iframe1 = document.createElement('iframe');
iframe1.mozbrowser = true;
// Two mozbrowser frames with the same code both do the same
// window.open("foo", "bar") call. We should only get one
// mozbrowseropenwindow event.
iframe1.addEventListener('mozbrowseropenwindow', function(e) {
ok(true, "Got first mozbrowseropenwindow event.");
document.body.appendChild(e.detail.frameElement);
e.detail.frameElement.addEventListener('mozbrowserlocationchange', function(e) {
if (e.detail == "http://example.com/#2") {
ok(true, "Got locationchange to http://example.com/#2");
SimpleTest.finish();
}
else {
ok(true, "Got locationchange to " + e.detail);
}
});
SimpleTest.executeSoon(function() {
var iframe2 = document.createElement('iframe');
iframe2.mozbrowser = true;
iframe2.addEventListener('mozbrowseropenwindow', function(e) {
ok(false, "Got second mozbrowseropenwindow event.");
});
document.body.appendChild(iframe2);
iframe2.src = 'file_browserElement_BrowserWindowNamespace.html#2';
});
});
document.body.appendChild(iframe1);
iframe1.src = 'file_browserElement_BrowserWindowNamespace.html#1';
}
runTest();

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

@ -0,0 +1,44 @@
/* Any copyright is dedicated to the public domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Bug 781320 - Test that the name in <iframe mozbrowser name="foo"> is
// forwarded down to remote mozbrowsers.
"use strict";
SimpleTest.waitForExplicitFinish();
function runTest() {
browserElementTestHelpers.setEnabledPref(true);
browserElementTestHelpers.addToWhitelist();
var iframe = document.createElement('iframe');
iframe.mozbrowser = true;
iframe.setAttribute('name', 'foo');
iframe.addEventListener("mozbrowseropenwindow", function(e) {
ok(false, 'Got mozbrowseropenwindow, but should not have.');
});
iframe.addEventListener('mozbrowserlocationchange', function(e) {
ok(true, "Got locationchange to " + e.detail);
if (e.detail.endsWith("ForwardName.html#finish")) {
SimpleTest.finish();
}
});
// The file sends us messages via alert() that start with "success:" or
// "failure:".
iframe.addEventListener('mozbrowsershowmodalprompt', function(e) {
ok(e.detail.message.startsWith('success:'), e.detail.message);
});
document.body.appendChild(iframe);
// This file does window.open('file_browserElement_ForwardName.html#finish',
// 'foo'); That should open in the curent window, because the window should
// be named foo.
iframe.src = 'file_browserElement_ForwardName.html';
}
runTest();

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

@ -0,0 +1,58 @@
/* Any copyright is dedicated to the public domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Bug 742944 - In <iframe mozbrowser>, test that if we call window.open twice
// with the same name, we get only one mozbrowseropenwindow event.
"use strict";
SimpleTest.waitForExplicitFinish();
var iframe;
var popupFrame;
function runTest() {
browserElementTestHelpers.setEnabledPref(true);
browserElementTestHelpers.addToWhitelist();
iframe = document.createElement('iframe');
iframe.mozbrowser = true;
var gotPopup = false;
iframe.addEventListener('mozbrowseropenwindow', function(e) {
is(gotPopup, false, 'Should get just one popup.');
gotPopup = true;
popupFrame = e.detail.frameElement;
is(popupFrame.getAttribute('name'), 'OpenNamed');
// Called when file_browserElement_OpenNamed2.html loads into popupFrame.
popupFrame.addEventListener('mozbrowsershowmodalprompt', function promptlistener(e) {
popupFrame.removeEventListener('mozbrowsershowmodalprompt', promptlistener);
ok(gotPopup, 'Got openwindow event before showmodalprompt event.');
is(e.detail.message, 'success: loaded');
SimpleTest.executeSoon(test2);
});
document.body.appendChild(popupFrame);
});
// OpenNamed.html will call
//
// window.open('file_browserElement_OpenNamed2.html', 'OpenNamed').
//
// Once that popup loads, we reload OpenNamed.html. That will call
// window.open again, but we shouldn't get another openwindow event, because
// we're opening into the same named window.
iframe.src = 'file_browserElement_OpenNamed.html';
document.body.appendChild(iframe);
}
function test2() {
popupFrame.addEventListener('mozbrowsershowmodalprompt', function(e) {
is(e.detail.message, 'success: loaded');
SimpleTest.finish();
});
iframe.src = 'file_browserElement_OpenNamed.html?test2';
}
runTest();

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

@ -59,7 +59,7 @@ def add_to_makefile(filenames):
the file.
"""
lines_to_write = ['', '# MOVE THESE:'] + [n + ' \\' for n in filenames]
lines_to_write = [''] + ['\t\t%s \\' % n for n in filenames]
with open('Makefile.in', 'a') as f:
f.write('\n'.join(lines_to_write))

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

@ -0,0 +1,7 @@
<html>
<body>
<script>
window.open("http://example.com", "foo");
</script>
</body>
</html>

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

@ -0,0 +1,7 @@
<html>
<body>
<script>
window.open("http://example.com/" + location.hash, "foo");
</script>
</body>
</html>

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

@ -0,0 +1,15 @@
<html>
<body>
<script>
if (window.name == 'foo') {
alert("success:window.name == 'foo'");
}
else {
alert("failure:window.name == '" + window.name + "', expected 'foo'");
}
window.open('file_browserElement_ForwardName.html#finish', 'foo');
</script>
</body>
</html>

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

@ -0,0 +1,7 @@
<html>
<body>
<script>
window.open('file_browserElement_OpenNamed2.html', 'OpenNamed');
</script>
</body>
</html>

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

@ -0,0 +1,7 @@
<html>
<body>
<script>
alert('success: loaded');
</script>
</body>
</html>

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

@ -0,0 +1,13 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for Bug 780351</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="browserElementTestHelpers.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<script type="application/javascript;version=1.7" src="browserElement_AppWindowNamespace.js">
</script>
</body>
</html>

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

@ -0,0 +1,13 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for Bug 780351</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="browserElementTestHelpers.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<script type="application/javascript;version=1.7" src="browserElement_BrowserWindowNamespace.js">
</script>
</body>
</html>

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

@ -0,0 +1,13 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for Bug 781320</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="browserElementTestHelpers.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<script type="application/javascript;version=1.7" src="browserElement_ForwardName.js">
</script>
</body>
</html>

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

@ -0,0 +1,13 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test of browser element.</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="browserElementTestHelpers.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<script type="application/javascript;version=1.7" src="browserElement_OpenNamed.js">
</script>
</body>
</html>

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

@ -0,0 +1,13 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for Bug 780351</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="browserElementTestHelpers.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<script type="application/javascript;version=1.7" src="browserElement_AppWindowNamespace.js">
</script>
</body>
</html>

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

@ -0,0 +1,13 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for Bug 780351</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="browserElementTestHelpers.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<script type="application/javascript;version=1.7" src="browserElement_BrowserWindowNamespace.js">
</script>
</body>
</html>

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

@ -0,0 +1,13 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for Bug 781320</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="browserElementTestHelpers.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<script type="application/javascript;version=1.7" src="browserElement_ForwardName.js">
</script>
</body>
</html>

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

@ -0,0 +1,13 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test of browser element.</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="browserElementTestHelpers.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<script type="application/javascript;version=1.7" src="browserElement_OpenNamed.js">
</script>
</body>
</html>

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

@ -847,7 +847,7 @@ public:
&NS_GET_IID(nsIDOMDeviceStorageStat));
mRequest->FireSuccess(result);
mRequest = nsnull;
mRequest = nullptr;
return NS_OK;
}

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

@ -789,7 +789,7 @@ IndexedDatabaseManager::EnsureOriginIsInitialized(const nsACString& aOrigin,
if (aPrivilege != Chrome) {
rv = ss->SetQuotaForFilenamePattern(pattern,
GetIndexedDBQuotaMB() * 1024 * 1024,
mQuotaCallbackSingleton, nsnull);
mQuotaCallbackSingleton, nullptr);
NS_ENSURE_SUCCESS(rv, rv);
}

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

@ -38,9 +38,8 @@ interface nsIDOMFile;
interface nsIFile;
interface nsIDOMTouch;
interface nsIDOMClientRect;
interface mozIDOMApplication;
[scriptable, uuid(97548ee0-9def-421a-ab2a-c6c98efa9a3c)]
[scriptable, uuid(5fc61d7b-a303-4f34-adfe-b7828675ba45)]
interface nsIDOMWindowUtils : nsISupports {
/**
@ -1186,25 +1185,8 @@ interface nsIDOMWindowUtils : nsISupports {
void setScrollPositionClampingScrollPortSize(in float aWidth, in float aHeight);
/**
* Mark if the window is an application window or not.
* This should only be set for top-level mozApp or mozBrowser frames.
* It should not be set for other frames unless you want a frame (and its
* children) to have a different value for IsPartOfApp than the frame's
* parent.
* Prevent this window (and any child windows) from displaying any further
* dialogs (e.g. window.alert()).
*/
void setIsApp(in boolean value);
/**
* Associate the window with an application by passing the URL of the
* application's manifest.
*
* This method will throw an exception if the manifest URL isn't a valid URL
* or isn't the manifest URL of an installed application.
*/
void setApp(in DOMString manifestURL);
/**
* Retrieves the Application object associated to this window.
* Can be null if |setApp()| has not been called.
*/
mozIDOMApplication getApp();
void preventFurtherDialogs();
};

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

@ -155,6 +155,12 @@ interface nsIWebGLExtensionCompressedTextureS3TC : nsIWebGLExtension
const WebGLenum COMPRESSED_RGBA_S3TC_DXT5_EXT = 0x83F3;
};
[scriptable, builtinclass, uuid(ef36f000-c1b2-11e1-afa7-0800200c9a66)]
interface nsIWebGLExtensionDepthTexture : nsIWebGLExtension
{
const WebGLenum UNSIGNED_INT_24_8_WEBGL = 0x84FA;
};
[scriptable, builtinclass, uuid(a1fdfb76-6a08-4a1a-b0c9-d92ef3357cb9)]
interface nsIDOMWebGLRenderingContext : nsISupports
{

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

@ -16,7 +16,7 @@ class Principal {
friend struct ParamTraits<Principal>;
public:
Principal() : mPrincipal(nsnull) {}
Principal() : mPrincipal(nullptr) {}
Principal(nsIPrincipal* aPrincipal) : mPrincipal(aPrincipal) {}
operator nsIPrincipal*() const { return mPrincipal.get(); }

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