зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-c to b-s.
This commit is contained in:
Коммит
c95d073d8c
|
@ -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(); }
|
||||
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче