Merge mozilla-central to fx-team

This commit is contained in:
Carsten "Tomcat" Book 2015-05-21 15:16:40 +02:00
commit d71257a4ce
278 changed files with 22888 additions and 3193 deletions

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="5a7f87b1505ba89b586372cbbbe9507d1016c40c"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="208ec11c33c9bd2fab7fcf8647bc162c9f3d484f"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="fffc68521ebb1501d6b015c6d1c4a17a04fdb2e2"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="5a7f87b1505ba89b586372cbbbe9507d1016c40c"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="208ec11c33c9bd2fab7fcf8647bc162c9f3d484f"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="fffc68521ebb1501d6b015c6d1c4a17a04fdb2e2"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

View File

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="5a7f87b1505ba89b586372cbbbe9507d1016c40c"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="208ec11c33c9bd2fab7fcf8647bc162c9f3d484f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="fffc68521ebb1501d6b015c6d1c4a17a04fdb2e2"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="22664edc4c73e5fe8f5095ff1d5549db78a2bc10"/>

View File

@ -17,7 +17,7 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="5a7f87b1505ba89b586372cbbbe9507d1016c40c"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="208ec11c33c9bd2fab7fcf8647bc162c9f3d484f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="fffc68521ebb1501d6b015c6d1c4a17a04fdb2e2"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="deb1d684da56376a10d900e08d3f4139f3ace885"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="5a7f87b1505ba89b586372cbbbe9507d1016c40c"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="208ec11c33c9bd2fab7fcf8647bc162c9f3d484f"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="fffc68521ebb1501d6b015c6d1c4a17a04fdb2e2"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
@ -131,7 +131,7 @@
<project name="device_generic_goldfish" path="device/generic/goldfish" remote="b2g" revision="f390788a00706c06e5248edfd8d27b365387e84a"/>
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="fbd2becab3825c49e756db5149552f85049c66e2"/>
<project name="platform/external/libnfc-nci" path="external/libnfc-nci" revision="f37bd545063039e30a92f2550ae78c0e6e4e2d08"/>
<project name="platform_external_wpa_supplicant_8" path="external/wpa_supplicant_8" remote="b2g" revision="9a725b0f5aa715282f8854ac56e5b63efc9cd077"/>
<project name="platform_external_wpa_supplicant_8" path="external/wpa_supplicant_8" remote="b2g" revision="0c6a6547cd1fd302fa2b0f6e375654df36bf0ec4"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="42f61f665e7a9857da8cd14b455e15bae98e6b44"/>
<project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="d82e00fb6380b4f6cea7a96213913ee9eb441239"/>
<project name="platform/development" path="development" revision="5968ff4e13e0d696ad8d972281fc27ae5a12829b"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="61e82f99bb8bc78d52b5717e9a2481ec7267fa33">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="5a7f87b1505ba89b586372cbbbe9507d1016c40c"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="208ec11c33c9bd2fab7fcf8647bc162c9f3d484f"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="fffc68521ebb1501d6b015c6d1c4a17a04fdb2e2"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
@ -144,7 +144,7 @@
<project name="device_generic_goldfish" path="device/generic/goldfish" remote="b2g" revision="48132ec0b0dfe9fc29c7c3f0e799066be8999198"/>
<!-- external/qemu for emulator-l need to be updated in bug-1121378 -->
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="7639c5c496ffd207bb627f2a59b2c5203ae6fefc"/>
<project name="platform_external_wpa_supplicant_8" path="external/wpa_supplicant_8" remote="b2g" revision="326450198720862ade868801cc2f43597f3c1fd8"/>
<project name="platform_external_wpa_supplicant_8" path="external/wpa_supplicant_8" remote="b2g" revision="cbda29a58abc4ea1f7f4611fe354ab67b606219d"/>
<project name="platform/development" path="development" revision="0c51f6e0aa2ee57fcb75ec3b2ff6bf754cece63e"/>
<project name="android-sdk" path="sdk" remote="b2g" revision="ff4190dc603f62a7caa48342aa268acf99863c5c"/>
<!-- hardware-ril for emulator-l need to be updated in bug-1113054 -->

View File

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="5a7f87b1505ba89b586372cbbbe9507d1016c40c"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="208ec11c33c9bd2fab7fcf8647bc162c9f3d484f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="fffc68521ebb1501d6b015c6d1c4a17a04fdb2e2"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="22664edc4c73e5fe8f5095ff1d5549db78a2bc10"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="5a7f87b1505ba89b586372cbbbe9507d1016c40c"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="208ec11c33c9bd2fab7fcf8647bc162c9f3d484f"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="fffc68521ebb1501d6b015c6d1c4a17a04fdb2e2"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

View File

@ -1,9 +1,9 @@
{
"git": {
"git_revision": "5a7f87b1505ba89b586372cbbbe9507d1016c40c",
"git_revision": "208ec11c33c9bd2fab7fcf8647bc162c9f3d484f",
"remote": "https://git.mozilla.org/releases/gaia.git",
"branch": ""
},
"revision": "85b4fb5a2fd0040b3726a4f1e4218f2dbfd4edce",
"revision": "2c0b8b5fdcd8bf1f06b25d58fe941a29dc26a2f3",
"repo_path": "integration/gaia-central"
}

View File

@ -17,7 +17,7 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="5a7f87b1505ba89b586372cbbbe9507d1016c40c"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="208ec11c33c9bd2fab7fcf8647bc162c9f3d484f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="fffc68521ebb1501d6b015c6d1c4a17a04fdb2e2"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="deb1d684da56376a10d900e08d3f4139f3ace885"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="61e82f99bb8bc78d52b5717e9a2481ec7267fa33">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="5a7f87b1505ba89b586372cbbbe9507d1016c40c"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="208ec11c33c9bd2fab7fcf8647bc162c9f3d484f"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="fffc68521ebb1501d6b015c6d1c4a17a04fdb2e2"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

View File

@ -6,19 +6,27 @@
var FullScreen = {
_XULNS: "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
_MESSAGES: [
"DOMFullscreen:Entered",
"DOMFullscreen:NewOrigin",
"DOMFullscreen:Exited"
],
init: function() {
// called when we go into full screen, even if initiated by a web page script
window.addEventListener("fullscreen", this, true);
window.messageManager.addMessageListener("MozEnteredDomFullscreen", this);
window.messageManager.addMessageListener("MozExitedDomFullscreen", this);
for (let type of this._MESSAGES) {
window.messageManager.addMessageListener(type, this);
}
if (window.fullScreen)
this.toggle();
},
uninit: function() {
window.messageManager.removeMessageListener("MozEnteredDomFullscreen", this);
window.messageManager.removeMessageListener("MozExitedDomFullscreen", this);
for (let type of this._MESSAGES) {
window.messageManager.removeMessageListener(type, this);
}
this.cleanup();
},
@ -93,34 +101,45 @@ var FullScreen = {
},
receiveMessage: function(aMessage) {
if (aMessage.name == "MozEnteredDomFullscreen") {
// If we're a multiprocess browser, then the request to enter fullscreen
// did not bubble up to the root browser document - it stopped at the root
// of the content document. That means we have to kick off the switch to
// fullscreen here at the operating system level in the parent process
// ourselves.
let data = aMessage.data;
let browser = aMessage.target;
if (gMultiProcessBrowser && browser.getAttribute("remote") == "true") {
let windowUtils = window.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils);
windowUtils.remoteFrameFullscreenChanged(browser, data.origin);
let browser = aMessage.target;
switch (aMessage.name) {
case "DOMFullscreen:Entered": {
// If we're a multiprocess browser, then the request to enter
// fullscreen did not bubble up to the root browser document -
// it stopped at the root of the content document. That means
// we have to kick off the switch to fullscreen here at the
// operating system level in the parent process ourselves.
if (this._isRemoteBrowser(browser)) {
this._windowUtils.remoteFrameFullscreenChanged(browser);
}
this.enterDomFullscreen(browser);
break;
}
this.enterDomFullscreen(browser, data.origin);
} else if (aMessage.name == "MozExitedDomFullscreen") {
document.documentElement.removeAttribute("inDOMFullscreen");
this.cleanupDomFullscreen();
this.showNavToolbox();
// If we are still in fullscreen mode, re-hide
// the toolbox with animation.
if (window.fullScreen) {
this._shouldAnimate = true;
this.hideNavToolbox();
case "DOMFullscreen:NewOrigin": {
this.showWarning(aMessage.data.origin);
break;
}
case "DOMFullscreen:Exited": {
// Like entering DOM fullscreen, we also need to exit fullscreen
// at the operating system level in the parent process here.
if (this._isRemoteBrowser(browser)) {
this._windowUtils.remoteFrameFullscreenReverted();
}
document.documentElement.removeAttribute("inDOMFullscreen");
this.cleanupDomFullscreen();
this.showNavToolbox();
// If we are still in fullscreen mode, re-hide
// the toolbox with animation.
if (window.fullScreen) {
this._shouldAnimate = true;
this.hideNavToolbox();
}
break;
}
}
},
enterDomFullscreen : function(aBrowser, aOrigin) {
enterDomFullscreen : function(aBrowser) {
if (!document.mozFullScreen)
return;
@ -146,8 +165,6 @@ var FullScreen = {
if (gFindBarInitialized)
gFindBar.close();
this.showWarning(aOrigin);
// Exit DOM full-screen mode upon open, close, or change tab.
gBrowser.tabContainer.addEventListener("TabOpen", this.exitDomFullScreen);
gBrowser.tabContainer.addEventListener("TabClose", this.exitDomFullScreen);
@ -186,7 +203,16 @@ var FullScreen = {
window.removeEventListener("activate", this);
window.messageManager
.broadcastAsyncMessage("DOMFullscreen:Cleanup");
.broadcastAsyncMessage("DOMFullscreen:CleanUp");
},
_isRemoteBrowser: function (aBrowser) {
return gMultiProcessBrowser && aBrowser.getAttribute("remote") == "true";
},
get _windowUtils() {
return window.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils);
},
getMouseTargetRect: function()

View File

@ -591,8 +591,9 @@ let DOMFullscreenHandler = {
init: function() {
addMessageListener("DOMFullscreen:Approved", this);
addMessageListener("DOMFullscreen:CleanUp", this);
addEventListener("MozEnteredDomFullscreen", this);
addEventListener("MozExitedDomFullscreen", this);
addEventListener("MozDOMFullscreen:Entered", this);
addEventListener("MozDOMFullscreen:NewOrigin", this);
addEventListener("MozDOMFullscreen:Exited", this);
},
receiveMessage: function(aMessage) {
@ -606,6 +607,9 @@ let DOMFullscreenHandler = {
break;
}
case "DOMFullscreen:CleanUp": {
let utils = content.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils);
utils.exitFullscreen();
this._fullscreenDoc = null;
break;
}
@ -613,13 +617,22 @@ let DOMFullscreenHandler = {
},
handleEvent: function(aEvent) {
if (aEvent.type == "MozEnteredDomFullscreen") {
this._fullscreenDoc = aEvent.target;
sendAsyncMessage("MozEnteredDomFullscreen", {
origin: this._fullscreenDoc.nodePrincipal.origin,
});
} else if (aEvent.type == "MozExitedDomFullscreen") {
sendAsyncMessage("MozExitedDomFullscreen");
switch (aEvent.type) {
case "MozDOMFullscreen:Entered": {
sendAsyncMessage("DOMFullscreen:Entered");
break;
}
case "MozDOMFullscreen:NewOrigin": {
this._fullscreenDoc = aEvent.target;
sendAsyncMessage("DOMFullscreen:NewOrigin", {
origin: this._fullscreenDoc.nodePrincipal.origin,
});
break;
}
case "MozDOMFullscreen:Exited": {
sendAsyncMessage("DOMFullscreen:Exited");
break;
}
}
}
};

View File

@ -74,7 +74,7 @@ let SessionStorageInternal = {
// Get the root domain of the current history entry
// and use that as a key for the per-host storage data.
let origin = principal.jarPrefix + principal.origin;
let origin = principal.jarPrefix + principal.originNoSuffix;
if (visitedOrigins.has(origin)) {
// Don't read a host twice.
return;

View File

@ -19,7 +19,7 @@ MOZ_ARG_WITH_BOOL(system-icu,
if test -n "$MOZ_NATIVE_ICU"; then
PKG_CHECK_MODULES(MOZ_ICU, icu-i18n >= 50.1)
MOZ_SHARED_ICU=1
elif test -n "$gonkdir" -a "$ANDROID_VERSION" -ge 17; then
elif test -n "$gonkdir" && test "$ANDROID_VERSION" -ge 17; then
dnl Use system's ICU since version is 50.1+.
if test -d "$gonkdir/external/icu/icu4c/source"; then
dnl gonk-L (API version is 21)

View File

@ -276,9 +276,24 @@ class B2GRemoteAutomation(Automation):
if 'b2g' not in session:
raise Exception("bad session value %s returned by start_session" % session)
if self.context_chrome:
self.marionette.set_context(self.marionette.CONTEXT_CHROME)
else:
self.marionette.set_context(self.marionette.CONTEXT_CHROME)
self.marionette.execute_script("""
let SECURITY_PREF = "security.turn_off_all_security_so_that_viruses_can_take_over_this_computer";
Components.utils.import("resource://gre/modules/Services.jsm");
Services.prefs.setBoolPref(SECURITY_PREF, true);
if (!testUtils.hasOwnProperty("specialPowersObserver")) {
let loader = Components.classes["@mozilla.org/moz/jssubscript-loader;1"]
.getService(Components.interfaces.mozIJSSubScriptLoader);
loader.loadSubScript("chrome://specialpowers/content/SpecialPowersObserver.js",
testUtils);
testUtils.specialPowersObserver = new testUtils.SpecialPowersObserver();
testUtils.specialPowersObserver.init();
testUtils.specialPowersObserver._loadFrameScript();
}
""")
if not self.context_chrome:
self.marionette.set_context(self.marionette.CONTEXT_CONTENT)
# run the script that starts the tests

View File

@ -8,29 +8,69 @@
#include "nsIObjectInputStream.h"
#include "nsIObjectOutputStream.h"
#include "nsPrincipal.h"
#include "nsNetUtil.h"
#include "nsNullPrincipal.h"
#include "nsScriptSecurityManager.h"
#include "mozilla/dom/ToJSValue.h"
namespace mozilla {
void
BasePrincipal::OriginAttributes::Serialize(nsIObjectOutputStream* aStream) const
OriginAttributes::CreateSuffix(nsACString& aStr)
{
aStr.Truncate();
MOZ_RELEASE_ASSERT(mAppId != nsIScriptSecurityManager::UNKNOWN_APP_ID);
int attrCount = 0;
if (mAppId != nsIScriptSecurityManager::NO_APP_ID) {
aStr.Append(attrCount++ ? "&appId=" : "!appId=");
aStr.AppendInt(mAppId);
}
if (mInBrowser) {
aStr.Append(attrCount++ ? "&inBrowser=1" : "!inBrowser=1");
}
}
void
OriginAttributes::Serialize(nsIObjectOutputStream* aStream) const
{
aStream->Write32(mAppId);
aStream->WriteBoolean(mIsInBrowserElement);
aStream->WriteBoolean(mInBrowser);
}
nsresult
BasePrincipal::OriginAttributes::Deserialize(nsIObjectInputStream* aStream)
OriginAttributes::Deserialize(nsIObjectInputStream* aStream)
{
nsresult rv = aStream->Read32(&mAppId);
NS_ENSURE_SUCCESS(rv, rv);
rv = aStream->ReadBoolean(&mIsInBrowserElement);
rv = aStream->ReadBoolean(&mInBrowser);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
NS_IMETHODIMP
BasePrincipal::GetOrigin(nsACString& aOrigin)
{
nsresult rv = GetOriginInternal(aOrigin);
NS_ENSURE_SUCCESS(rv, rv);
nsAutoCString suffix;
mOriginAttributes.CreateSuffix(suffix);
aOrigin.Append(suffix);
return NS_OK;
}
NS_IMETHODIMP
BasePrincipal::GetOriginNoSuffix(nsACString& aOrigin)
{
return GetOriginInternal(aOrigin);
}
bool
BasePrincipal::Subsumes(nsIPrincipal* aOther, DocumentDomainConsideration aConsideration)
{
@ -104,6 +144,31 @@ BasePrincipal::GetJarPrefix(nsACString& aJarPrefix)
return NS_OK;
}
NS_IMETHODIMP
BasePrincipal::GetOriginAttributes(JSContext* aCx, JS::MutableHandle<JS::Value> aVal)
{
if (NS_WARN_IF(!ToJSValue(aCx, mOriginAttributes, aVal))) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}
NS_IMETHODIMP
BasePrincipal::GetOriginSuffix(nsACString& aOriginAttributes)
{
mOriginAttributes.CreateSuffix(aOriginAttributes);
return NS_OK;
}
NS_IMETHODIMP
BasePrincipal::GetCookieJar(nsACString& aCookieJar)
{
// We just forward to .jarPrefix for now, which is a nice compact
// stringification of the (appId, inBrowser) tuple. This will eventaully be
// swapped out for an origin attribute - see the comment in nsIPrincipal.idl.
return GetJarPrefix(aCookieJar);
}
NS_IMETHODIMP
BasePrincipal::GetAppStatus(uint16_t* aAppStatus)
{
@ -144,4 +209,36 @@ BasePrincipal::GetUnknownAppId(bool* aUnknownAppId)
return NS_OK;
}
already_AddRefed<BasePrincipal>
BasePrincipal::CreateCodebasePrincipal(nsIURI* aURI, OriginAttributes& aAttrs)
{
// If the URI is supposed to inherit the security context of whoever loads it,
// we shouldn't make a codebase principal for it.
bool inheritsPrincipal;
nsresult rv = NS_URIChainHasFlags(aURI, nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT,
&inheritsPrincipal);
nsCOMPtr<nsIPrincipal> principal;
if (NS_FAILED(rv) || inheritsPrincipal) {
return nsNullPrincipal::Create();
}
// Check whether the URI knows what its principal is supposed to be.
nsCOMPtr<nsIURIWithPrincipal> uriPrinc = do_QueryInterface(aURI);
if (uriPrinc) {
nsCOMPtr<nsIPrincipal> principal;
uriPrinc->GetPrincipal(getter_AddRefs(principal));
if (!principal) {
return nsNullPrincipal::Create();
}
nsRefPtr<BasePrincipal> concrete = Cast(principal);
return concrete.forget();
}
// Mint a codebase principal.
nsRefPtr<nsPrincipal> codebase = new nsPrincipal();
rv = codebase->Init(aURI, aAttrs);
NS_ENSURE_SUCCESS(rv, nullptr);
return codebase.forget();
}
} // namespace mozilla

View File

@ -11,11 +11,42 @@
#include "nsIScriptSecurityManager.h"
#include "nsJSPrincipals.h"
#include "mozilla/dom/SystemDictionariesBinding.h"
class nsIObjectOutputStream;
class nsIObjectInputStream;
namespace mozilla {
class OriginAttributes : public dom::OriginAttributesDictionary
{
public:
OriginAttributes() {}
OriginAttributes(uint32_t aAppId, bool aInBrowser)
{
mAppId = aAppId;
mInBrowser = aInBrowser;
}
bool operator==(const OriginAttributes& aOther) const
{
return mAppId == aOther.mAppId &&
mInBrowser == aOther.mInBrowser;
}
bool operator!=(const OriginAttributes& aOther) const
{
return !(*this == aOther);
}
// Serializes non-default values into the suffix format, i.e.
// |!key1=value1&key2=value2|. If there are no non-default attributes, this
// returns an empty string.
void CreateSuffix(nsACString& aStr);
void Serialize(nsIObjectOutputStream* aStream) const;
nsresult Deserialize(nsIObjectInputStream* aStream);
};
/*
* Base class from which all nsIPrincipal implementations inherit. Use this for
* default implementations and other commonalities between principal
@ -31,6 +62,8 @@ public:
enum DocumentDomainConsideration { DontConsiderDocumentDomain, ConsiderDocumentDomain};
bool Subsumes(nsIPrincipal* aOther, DocumentDomainConsideration aConsideration);
NS_IMETHOD GetOrigin(nsACString& aOrigin) final;
NS_IMETHOD GetOriginNoSuffix(nsACString& aOrigin) final;
NS_IMETHOD Equals(nsIPrincipal* other, bool* _retval) final;
NS_IMETHOD EqualsConsideringDomain(nsIPrincipal* other, bool* _retval) final;
NS_IMETHOD Subsumes(nsIPrincipal* other, bool* _retval) final;
@ -39,6 +72,9 @@ public:
NS_IMETHOD SetCsp(nsIContentSecurityPolicy* aCsp) override;
NS_IMETHOD GetIsNullPrincipal(bool* aIsNullPrincipal) override;
NS_IMETHOD GetJarPrefix(nsACString& aJarPrefix) final;
NS_IMETHOD GetOriginAttributes(JSContext* aCx, JS::MutableHandle<JS::Value> aVal) final;
NS_IMETHOD GetOriginSuffix(nsACString& aOriginSuffix) final;
NS_IMETHOD GetCookieJar(nsACString& aCookieJar) final;
NS_IMETHOD GetAppStatus(uint16_t* aAppStatus) final;
NS_IMETHOD GetAppId(uint32_t* aAppStatus) final;
NS_IMETHOD GetIsInBrowserElement(bool* aIsInBrowserElement) final;
@ -47,38 +83,16 @@ public:
virtual bool IsOnCSSUnprefixingWhitelist() override { return false; }
static BasePrincipal* Cast(nsIPrincipal* aPrin) { return static_cast<BasePrincipal*>(aPrin); }
struct OriginAttributes {
// NB: If you add any members here, you need to update Serialize/Deserialize
// and bump the CIDs of all the principal implementations that invoke those
// methods.
uint32_t mAppId;
bool mIsInBrowserElement;
OriginAttributes() : mAppId(nsIScriptSecurityManager::NO_APP_ID), mIsInBrowserElement(false) {}
OriginAttributes(uint32_t aAppId, bool aIsInBrowserElement)
: mAppId(aAppId), mIsInBrowserElement(aIsInBrowserElement) {}
bool operator==(const OriginAttributes& aOther) const
{
return mAppId == aOther.mAppId &&
mIsInBrowserElement == aOther.mIsInBrowserElement;
}
bool operator!=(const OriginAttributes& aOther) const
{
return !(*this == aOther);
}
void Serialize(nsIObjectOutputStream* aStream) const;
nsresult Deserialize(nsIObjectInputStream* aStream);
};
static already_AddRefed<BasePrincipal> CreateCodebasePrincipal(nsIURI* aURI, OriginAttributes& aAttrs);
const OriginAttributes& OriginAttributesRef() { return mOriginAttributes; }
uint32_t AppId() const { return mOriginAttributes.mAppId; }
bool IsInBrowserElement() const { return mOriginAttributes.mIsInBrowserElement; }
bool IsInBrowserElement() const { return mOriginAttributes.mInBrowser; }
protected:
virtual ~BasePrincipal() {}
virtual nsresult GetOriginInternal(nsACString& aOrigin) = 0;
virtual bool SubsumesInternal(nsIPrincipal* aOther, DocumentDomainConsideration aConsider) = 0;
nsCOMPtr<nsIContentSecurityPolicy> mCSP;

View File

@ -20,7 +20,7 @@ interface nsIContentSecurityPolicy;
[ptr] native JSPrincipals(JSPrincipals);
[ptr] native PrincipalArray(nsTArray<nsCOMPtr<nsIPrincipal> >);
[scriptable, builtinclass, uuid(7e024afa-afd4-48e7-ba11-1c7b9620b1b2)]
[scriptable, builtinclass, uuid(749f21f5-8ade-4d0b-a590-2b1d18e890d5)]
interface nsIPrincipal : nsISerializable
{
/**
@ -65,15 +65,6 @@ interface nsIPrincipal : nsISerializable
*/
[noscript] attribute nsIURI domain;
/**
* The origin of this principal's codebase URI.
* An origin is defined as: scheme + host + port.
*/
// XXXcaa this should probably be turned into an nsIURI.
// The system principal's origin should be some caps namespace
// with a chrome URI. All of chrome should probably be the same.
readonly attribute ACString origin;
/**
* Returns whether the other principal is equal to or weaker than this
* principal. Principals are equal if they are the same object or they
@ -157,6 +148,79 @@ interface nsIPrincipal : nsISerializable
*/
readonly attribute AUTF8String jarPrefix;
/**
* A dictionary of the non-default origin attributes associated with this
* nsIPrincipal.
*
* Attributes are tokens that are taken into account when determining whether
* two principals are same-origin - if any attributes differ, the principals
* are cross-origin, even if the scheme, host, and port are the same.
* Attributes should also be considered for all security and bucketing decisions,
* even those which make non-standard comparisons (like cookies, which ignore
* scheme, or quotas, which ignore subdomains).
*
* If you're looking for an easy-to-use canonical stringification of the origin
* attributes, see |originSuffix| below.
*/
[implicit_jscontext]
readonly attribute jsval originAttributes;
/**
* A canonical representation of the origin for this principal. This
* consists of a base string (which, for codebase principals, is of the
* format scheme://host:port), concatenated with |originAttributes| (see
* below).
*
* We maintain the invariant that principalA.equals(principalB) if and only
* if principalA.origin == principalB.origin.
*/
readonly attribute ACString origin;
/**
* The base part of |origin| without the concatenation with |originSuffix|.
* This doesn't have the important invariants described above with |origin|,
* and as such should only be used for legacy situations.
*/
readonly attribute ACString originNoSuffix;
/**
* A string of the form !key1=value1&key2=value2, where each pair represents
* an attribute with a non-default value. If all attributes have default
* values, this is the empty string.
*
* The value of .originSuffix is automatically serialized into .origin, so any
* consumers using that are automatically origin-attribute-aware. Consumers with
* special requirements must inspect and compare .originSuffix manually.
*
* originsuffix are intended to be a replacement for jarPrefix, which will
* eventually be removed.
*/
readonly attribute AUTF8String originSuffix;
/**
* Opaque string token representing the "cookie jar" associated with this
* principal. Cookie jars are intended to be a tag associated with persistent
* data (like cookies, localStorage data, etc) such that all data associated
* with a given cookie jar can be quickly located and (for example) deleted.
* Code from many origins may share a given cookie jar, so callers still need
* to consult .origin (or equivalent) to compartmentalize data - the cookie
* jar should _only_ be used as a tag in the manner described above.
*
* If two principals are in different cookie jars, they must be cross-origin.
* As such, the information making up the cookie jar token must be contained
* in the originAttributes (i.e. cookieJar must be a function of / derivable
* from originAttributes). Long term, the intention is for the cookie jar
* identifier to simply be an origin attribute. But we don't have that
* attribute yet, and we also need to concatenate the appId and inBrowser
* attributes until those go away.
*
* This getter is designed to hide these details from consumers so that they
* don't need to be updated when we swap out the implementation. For that
* reason, callers should treat the string as opaque and not rely on the
* current format.
*/
readonly attribute ACString cookieJar;
/**
* The base domain of the codebase URI to which this principal pertains
* (generally the document URI), handling null principals and

View File

@ -26,7 +26,7 @@ class DomainPolicyClone;
[ptr] native JSObjectPtr(JSObject);
[ptr] native DomainPolicyClonePtr(mozilla::dom::DomainPolicyClone);
[scriptable, uuid(ba602ca6-dc7a-457e-a57a-ee5b343fd863)]
[scriptable, uuid(f4c578b8-5bac-4ba1-9582-f1140e09a3b4)]
interface nsIScriptSecurityManager : nsISupports
{
/**
@ -179,12 +179,28 @@ interface nsIScriptSecurityManager : nsISupports
nsIPrincipal getNoAppCodebasePrincipal(in nsIURI uri);
/**
* Legacy name for getNoAppCodebasePrincipal.
* Legacy method for getting a principal with no origin attributes.
*
* @deprecated use getNoAppCodebasePrincipal instead.
* @deprecated use createCodebasePrincipal instead.
*/
[deprecated] nsIPrincipal getCodebasePrincipal(in nsIURI uri);
/**
* Returns a principal whose origin is composed of |uri| and |originAttributes|.
* See nsIPrincipal.h for a description of origin attributes, and
* SystemDictionaries.webidl for a list of origin attributes and their defaults.
*/
[implicit_jscontext]
nsIPrincipal createCodebasePrincipal(in nsIURI uri, in jsval originAttributes);
/**
* Returns a unique nonce principal with |originAttributes|.
* See nsIPrincipal.h for a description of origin attributes, and
* SystemDictionaries.webidl for a list of origin attributes and their defaults.
*/
[implicit_jscontext]
nsIPrincipal createNullPrincipal(in jsval originAttributes);
/**
* Returns OK if aSourceURI and target have the same "origin"
* (scheme, host, and port).

View File

@ -102,8 +102,8 @@ nsNullPrincipal::SetDomain(nsIURI* aDomain)
return NS_ERROR_NOT_AVAILABLE;
}
NS_IMETHODIMP
nsNullPrincipal::GetOrigin(nsACString& aOrigin)
nsresult
nsNullPrincipal::GetOriginInternal(nsACString& aOrigin)
{
return mURI->GetSpec(aOrigin);
}

View File

@ -44,19 +44,19 @@ public:
NS_IMETHOD GetURI(nsIURI** aURI) override;
NS_IMETHOD GetDomain(nsIURI** aDomain) override;
NS_IMETHOD SetDomain(nsIURI* aDomain) override;
NS_IMETHOD GetOrigin(nsACString& aOrigin) override;
NS_IMETHOD CheckMayLoad(nsIURI* uri, bool report, bool allowIfInheritsPrincipal) override;
NS_IMETHOD GetIsNullPrincipal(bool* aIsNullPrincipal) override;
NS_IMETHOD GetBaseDomain(nsACString& aBaseDomain) override;
nsresult GetOriginInternal(nsACString& aOrigin) override;
// Returns null on failure.
static already_AddRefed<nsNullPrincipal> CreateWithInheritedAttributes(nsIPrincipal *aInheritFrom);
// Returns null on failure.
static already_AddRefed<nsNullPrincipal>
Create(const OriginAttributes& aOriginAttributes = OriginAttributes());
Create(const mozilla::OriginAttributes& aOriginAttributes = mozilla::OriginAttributes());
nsresult Init(const OriginAttributes& aOriginAttributes = OriginAttributes());
nsresult Init(const mozilla::OriginAttributes& aOriginAttributes = mozilla::OriginAttributes());
virtual void GetScriptLocation(nsACString &aStr) override;

View File

@ -149,8 +149,8 @@ nsPrincipal::GetOriginForURI(nsIURI* aURI, nsACString& aOrigin)
return NS_OK;
}
NS_IMETHODIMP
nsPrincipal::GetOrigin(nsACString& aOrigin)
nsresult
nsPrincipal::GetOriginInternal(nsACString& aOrigin)
{
return GetOriginForURI(mCodebase, aOrigin);
}
@ -660,8 +660,8 @@ nsExpandedPrincipal::SetDomain(nsIURI* aDomain)
return NS_OK;
}
NS_IMETHODIMP
nsExpandedPrincipal::GetOrigin(nsACString& aOrigin)
nsresult
nsExpandedPrincipal::GetOriginInternal(nsACString& aOrigin)
{
aOrigin.AssignLiteral("[Expanded Principal [");
for (size_t i = 0; i < mPrincipals.Length(); ++i) {

View File

@ -26,15 +26,15 @@ public:
NS_IMETHOD GetURI(nsIURI** aURI) override;
NS_IMETHOD GetDomain(nsIURI** aDomain) override;
NS_IMETHOD SetDomain(nsIURI* aDomain) override;
NS_IMETHOD GetOrigin(nsACString& aOrigin) override;
NS_IMETHOD CheckMayLoad(nsIURI* uri, bool report, bool allowIfInheritsPrincipal) override;
NS_IMETHOD GetBaseDomain(nsACString& aBaseDomain) override;
virtual bool IsOnCSSUnprefixingWhitelist() override;
nsresult GetOriginInternal(nsACString& aOrigin) override;
nsPrincipal();
// Init() must be called before the principal is in a usable state.
nsresult Init(nsIURI* aCodebase, const OriginAttributes& aOriginAttributes);
nsresult Init(nsIURI* aCodebase, const mozilla::OriginAttributes& aOriginAttributes);
virtual void GetScriptLocation(nsACString& aStr) override;
void SetURI(nsIURI* aURI);
@ -94,11 +94,11 @@ public:
NS_IMETHOD GetURI(nsIURI** aURI) override;
NS_IMETHOD GetDomain(nsIURI** aDomain) override;
NS_IMETHOD SetDomain(nsIURI* aDomain) override;
NS_IMETHOD GetOrigin(nsACString& aOrigin) override;
NS_IMETHOD CheckMayLoad(nsIURI* uri, bool report, bool allowIfInheritsPrincipal) override;
NS_IMETHOD GetBaseDomain(nsACString& aBaseDomain) override;
virtual bool IsOnCSSUnprefixingWhitelist() override;
virtual void GetScriptLocation(nsACString &aStr) override;
nsresult GetOriginInternal(nsACString& aOrigin) override;
protected:
virtual ~nsExpandedPrincipal();

View File

@ -19,6 +19,7 @@
#include "nsINestedURI.h"
#include "nspr.h"
#include "nsJSPrincipals.h"
#include "mozilla/BasePrincipal.h"
#include "nsSystemPrincipal.h"
#include "nsPrincipal.h"
#include "nsNullPrincipal.h"
@ -280,29 +281,21 @@ nsScriptSecurityManager::AppStatusForPrincipal(nsIPrincipal *aPrin)
NS_ENSURE_SUCCESS(app->GetAppStatus(&status),
nsIPrincipal::APP_STATUS_NOT_INSTALLED);
nsAutoCString origin;
NS_ENSURE_SUCCESS(aPrin->GetOrigin(origin),
nsIPrincipal::APP_STATUS_NOT_INSTALLED);
nsString appOrigin;
NS_ENSURE_SUCCESS(app->GetOrigin(appOrigin),
nsIPrincipal::APP_STATUS_NOT_INSTALLED);
// We go from string -> nsIURI -> origin to be sure we
// compare two punny-encoded origins.
nsCOMPtr<nsIURI> appURI;
NS_ENSURE_SUCCESS(NS_NewURI(getter_AddRefs(appURI), appOrigin),
nsIPrincipal::APP_STATUS_NOT_INSTALLED);
nsAutoCString appOriginPunned;
NS_ENSURE_SUCCESS(nsPrincipal::GetOriginForURI(appURI, appOriginPunned),
nsIPrincipal::APP_STATUS_NOT_INSTALLED);
if (!appOriginPunned.Equals(origin)) {
return nsIPrincipal::APP_STATUS_NOT_INSTALLED;
}
return status;
// The app could contain a cross-origin iframe - make sure that the content
// is actually same-origin with the app.
MOZ_ASSERT(inMozBrowser == false, "Checked this above");
OriginAttributes attrs(appId, false);
nsCOMPtr<nsIPrincipal> appPrin = BasePrincipal::CreateCodebasePrincipal(appURI, attrs);
NS_ENSURE_TRUE(appPrin, nsIPrincipal::APP_STATUS_NOT_INSTALLED);
return aPrin->Equals(appPrin) ? status
: nsIPrincipal::APP_STATUS_NOT_INSTALLED;
}
/*
@ -378,8 +371,10 @@ nsScriptSecurityManager::GetChannelURIPrincipal(nsIChannel* aChannel,
return GetLoadContextCodebasePrincipal(uri, loadContext, aPrincipal);
}
return GetCodebasePrincipalInternal(uri, UNKNOWN_APP_ID,
/* isInBrowserElement */ false, aPrincipal);
OriginAttributes attrs(UNKNOWN_APP_ID, false);
nsCOMPtr<nsIPrincipal> prin = BasePrincipal::CreateCodebasePrincipal(uri, attrs);
prin.forget(aPrincipal);
return *aPrincipal ? NS_OK : NS_ERROR_FAILURE;
}
NS_IMETHODIMP
@ -979,55 +974,24 @@ nsScriptSecurityManager::GetSystemPrincipal(nsIPrincipal **result)
return NS_OK;
}
nsresult
nsScriptSecurityManager::CreateCodebasePrincipal(nsIURI* aURI, uint32_t aAppId,
bool aInMozBrowser,
nsIPrincipal **result)
{
// I _think_ it's safe to not create null principals here based on aURI.
// At least all the callers would do the right thing in those cases, as far
// as I can tell. --bz
nsCOMPtr<nsIURIWithPrincipal> uriPrinc = do_QueryInterface(aURI);
if (uriPrinc) {
nsCOMPtr<nsIPrincipal> principal;
uriPrinc->GetPrincipal(getter_AddRefs(principal));
if (!principal) {
principal = nsNullPrincipal::Create();
NS_ENSURE_TRUE(principal, NS_ERROR_FAILURE);
}
principal.forget(result);
return NS_OK;
}
BasePrincipal::OriginAttributes attrs(aAppId, aInMozBrowser);
nsRefPtr<nsPrincipal> codebase = new nsPrincipal();
nsresult rv = codebase->Init(aURI, attrs);
if (NS_FAILED(rv))
return rv;
NS_ADDREF(*result = codebase);
return NS_OK;
}
NS_IMETHODIMP
nsScriptSecurityManager::GetSimpleCodebasePrincipal(nsIURI* aURI,
nsIPrincipal** aPrincipal)
{
return GetCodebasePrincipalInternal(aURI,
nsIScriptSecurityManager::UNKNOWN_APP_ID,
false, aPrincipal);
OriginAttributes attrs(UNKNOWN_APP_ID, false);
nsCOMPtr<nsIPrincipal> prin = BasePrincipal::CreateCodebasePrincipal(aURI, attrs);
prin.forget(aPrincipal);
return *aPrincipal ? NS_OK : NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsScriptSecurityManager::GetNoAppCodebasePrincipal(nsIURI* aURI,
nsIPrincipal** aPrincipal)
{
return GetCodebasePrincipalInternal(aURI, nsIScriptSecurityManager::NO_APP_ID,
false, aPrincipal);
OriginAttributes attrs(NO_APP_ID, false);
nsCOMPtr<nsIPrincipal> prin = BasePrincipal::CreateCodebasePrincipal(aURI, attrs);
prin.forget(aPrincipal);
return *aPrincipal ? NS_OK : NS_ERROR_FAILURE;
}
NS_IMETHODIMP
@ -1037,6 +1001,33 @@ nsScriptSecurityManager::GetCodebasePrincipal(nsIURI* aURI,
return GetNoAppCodebasePrincipal(aURI, aPrincipal);
}
NS_IMETHODIMP
nsScriptSecurityManager::CreateCodebasePrincipal(nsIURI* aURI, JS::Handle<JS::Value> aOriginAttributes,
JSContext* aCx, nsIPrincipal** aPrincipal)
{
OriginAttributes attrs;
if (!aOriginAttributes.isObject() || !attrs.Init(aCx, aOriginAttributes)) {
return NS_ERROR_INVALID_ARG;
}
nsCOMPtr<nsIPrincipal> prin = BasePrincipal::CreateCodebasePrincipal(aURI, attrs);
prin.forget(aPrincipal);
return *aPrincipal ? NS_OK : NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsScriptSecurityManager::CreateNullPrincipal(JS::Handle<JS::Value> aOriginAttributes,
JSContext* aCx, nsIPrincipal** aPrincipal)
{
OriginAttributes attrs;
if (!aOriginAttributes.isObject() || !attrs.Init(aCx, aOriginAttributes)) {
return NS_ERROR_INVALID_ARG;
}
nsCOMPtr<nsIPrincipal> prin = nsNullPrincipal::Create(attrs);
NS_ENSURE_TRUE(prin, NS_ERROR_FAILURE);
prin.forget(aPrincipal);
return NS_OK;
}
NS_IMETHODIMP
nsScriptSecurityManager::GetAppCodebasePrincipal(nsIURI* aURI,
uint32_t aAppId,
@ -1046,7 +1037,10 @@ nsScriptSecurityManager::GetAppCodebasePrincipal(nsIURI* aURI,
NS_ENSURE_TRUE(aAppId != nsIScriptSecurityManager::UNKNOWN_APP_ID,
NS_ERROR_INVALID_ARG);
return GetCodebasePrincipalInternal(aURI, aAppId, aInMozBrowser, aPrincipal);
OriginAttributes attrs(aAppId, aInMozBrowser);
nsCOMPtr<nsIPrincipal> prin = BasePrincipal::CreateCodebasePrincipal(aURI, attrs);
prin.forget(aPrincipal);
return *aPrincipal ? NS_OK : NS_ERROR_FAILURE;
}
NS_IMETHODIMP
@ -1055,14 +1049,13 @@ nsScriptSecurityManager::
nsILoadContext* aLoadContext,
nsIPrincipal** aPrincipal)
{
uint32_t appId;
aLoadContext->GetAppId(&appId);
bool isInBrowserElement;
aLoadContext->GetIsInBrowserElement(&isInBrowserElement);
return GetCodebasePrincipalInternal(aURI,
appId,
isInBrowserElement,
aPrincipal);
// XXXbholley - Make this more general in bug 1165466.
OriginAttributes attrs;
aLoadContext->GetAppId(&attrs.mAppId);
aLoadContext->GetIsInBrowserElement(&attrs.mInBrowser);
nsCOMPtr<nsIPrincipal> prin = BasePrincipal::CreateCodebasePrincipal(aURI, attrs);
prin.forget(aPrincipal);
return *aPrincipal ? NS_OK : NS_ERROR_FAILURE;
}
NS_IMETHODIMP
@ -1070,37 +1063,11 @@ nsScriptSecurityManager::GetDocShellCodebasePrincipal(nsIURI* aURI,
nsIDocShell* aDocShell,
nsIPrincipal** aPrincipal)
{
return GetCodebasePrincipalInternal(aURI,
aDocShell->GetAppId(),
aDocShell->GetIsInBrowserElement(),
aPrincipal);
}
nsresult
nsScriptSecurityManager::GetCodebasePrincipalInternal(nsIURI *aURI,
uint32_t aAppId,
bool aInMozBrowser,
nsIPrincipal **result)
{
NS_ENSURE_ARG(aURI);
bool inheritsPrincipal;
nsresult rv =
NS_URIChainHasFlags(aURI,
nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT,
&inheritsPrincipal);
nsCOMPtr<nsIPrincipal> principal;
if (NS_FAILED(rv) || inheritsPrincipal) {
principal = nsNullPrincipal::Create();
NS_ENSURE_TRUE(principal, NS_ERROR_FAILURE);
} else {
rv = CreateCodebasePrincipal(aURI, aAppId, aInMozBrowser,
getter_AddRefs(principal));
NS_ENSURE_SUCCESS(rv, rv);
}
principal.forget(result);
return NS_OK;
// XXXbholley - Make this more general in bug 1165466.
OriginAttributes attrs(aDocShell->GetAppId(), aDocShell->GetIsInBrowserElement());
nsCOMPtr<nsIPrincipal> prin = BasePrincipal::CreateCodebasePrincipal(aURI, attrs);
prin.forget(aPrincipal);
return *aPrincipal ? NS_OK : NS_ERROR_FAILURE;
}
// static

View File

@ -22,6 +22,10 @@ class nsIIOService;
class nsIStringBundle;
class nsSystemPrincipal;
namespace mozilla {
class OriginAttributes;
}
/////////////////////////////
// nsScriptSecurityManager //
/////////////////////////////
@ -99,15 +103,6 @@ private:
// should error out at that point.
static nsIPrincipal* doGetObjectPrincipal(JSObject* obj);
nsresult
GetCodebasePrincipalInternal(nsIURI* aURI, uint32_t aAppId,
bool aInMozBrowser,
nsIPrincipal** result);
nsresult
CreateCodebasePrincipal(nsIURI* aURI, uint32_t aAppId, bool aInMozBrowser,
nsIPrincipal** result);
nsresult
Init();

View File

@ -61,8 +61,8 @@ nsSystemPrincipal::GetURI(nsIURI** aURI)
return NS_OK;
}
NS_IMETHODIMP
nsSystemPrincipal::GetOrigin(nsACString& aOrigin)
nsresult
nsSystemPrincipal::GetOriginInternal(nsACString& aOrigin)
{
aOrigin.AssignLiteral(SYSTEM_PRINCIPAL_SPEC);
return NS_OK;

View File

@ -29,11 +29,11 @@ public:
NS_IMETHOD GetURI(nsIURI** aURI) override;
NS_IMETHOD GetDomain(nsIURI** aDomain) override;
NS_IMETHOD SetDomain(nsIURI* aDomain) override;
NS_IMETHOD GetOrigin(nsACString& aOrigin) override;
NS_IMETHOD CheckMayLoad(nsIURI* uri, bool report, bool allowIfInheritsPrincipal) override;
NS_IMETHOD GetCsp(nsIContentSecurityPolicy** aCsp) override;
NS_IMETHOD SetCsp(nsIContentSecurityPolicy* aCsp) override;
NS_IMETHOD GetBaseDomain(nsACString& aBaseDomain) override;
nsresult GetOriginInternal(nsACString& aOrigin) override;
nsSystemPrincipal() {}

View File

@ -1,14 +1,101 @@
var Cu = Components.utils;
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/BrowserUtils.jsm");
var ssm = Services.scriptSecurityManager;
function makeURI(uri) { return Services.io.newURI(uri, null, null); }
function checkThrows(f) {
var threw = false;
try { f(); } catch (e) { threw = true }
do_check_true(threw);
}
function checkCrossOrigin(a, b) {
do_check_false(a.equals(b));
do_check_false(a.equalsConsideringDomain(b));
do_check_false(a.subsumes(b));
do_check_false(a.subsumesConsideringDomain(b));
do_check_false(b.subsumes(a));
do_check_false(b.subsumesConsideringDomain(a));
do_check_eq(a.cookieJar === b.cookieJar,
a.originAttributes.appId == b.originAttributes.appId &&
a.originAttributes.inBrowser == b.originAttributes.inBrowser);
}
function checkOriginAttributes(prin, appId, inBrowser, suffix) {
do_check_eq(prin.originAttributes.appId, appId || 0);
do_check_eq(prin.originAttributes.inBrowser, inBrowser || false);
do_check_eq(prin.originSuffix, suffix || '');
if (!prin.isNullPrincipal && !prin.origin.startsWith('[')) {
do_check_true(BrowserUtils.principalFromOrigin(prin.origin).equals(prin));
} else {
checkThrows(() => BrowserUtils.principalFromOrigin(prin.origin));
}
}
function run_test() {
do_check_eq(Cu.getObjectPrincipal({}).origin, '[System Principal]');
var exampleOrg = Cu.getObjectPrincipal(new Cu.Sandbox('http://example.org'));
// Attributeless origins.
do_check_eq(ssm.getSystemPrincipal().origin, '[System Principal]');
checkOriginAttributes(ssm.getSystemPrincipal());
var exampleOrg = ssm.createCodebasePrincipal(makeURI('http://example.org'), {});
do_check_eq(exampleOrg.origin, 'http://example.org');
var exampleCom = Cu.getObjectPrincipal(new Cu.Sandbox('https://www.example.com:123'));
checkOriginAttributes(exampleOrg);
var exampleCom = ssm.createCodebasePrincipal(makeURI('https://www.example.com:123'), {});
do_check_eq(exampleCom.origin, 'https://www.example.com:123');
checkOriginAttributes(exampleCom);
var nullPrin = Cu.getObjectPrincipal(new Cu.Sandbox(null));
do_check_true(/^moz-nullprincipal:\{([0-9]|[a-z]|\-){36}\}$/.test(nullPrin.origin));
checkOriginAttributes(nullPrin);
var ep = Cu.getObjectPrincipal(new Cu.Sandbox([exampleCom, nullPrin, exampleOrg]));
checkOriginAttributes(ep);
checkCrossOrigin(exampleCom, exampleOrg);
checkCrossOrigin(exampleOrg, nullPrin);
// Origins should be in lexical order.
// nsEP origins should be in lexical order.
do_check_eq(ep.origin, `[Expanded Principal [${exampleOrg.origin}, ${exampleCom.origin}, ${nullPrin.origin}]]`);
// Make sure createCodebasePrincipal does what the rest of gecko does.
do_check_true(exampleOrg.equals(Cu.getObjectPrincipal(new Cu.Sandbox('http://example.org'))));
//
// Test origin attributes.
//
// Just app.
var exampleOrg_app = ssm.createCodebasePrincipal(makeURI('http://example.org'), {appId: 42});
var nullPrin_app = ssm.createNullPrincipal({appId: 42});
checkOriginAttributes(exampleOrg_app, 42, false, '!appId=42');
checkOriginAttributes(nullPrin_app, 42, false, '!appId=42');
do_check_eq(exampleOrg_app.origin, 'http://example.org!appId=42');
// Just browser.
var exampleOrg_browser = ssm.createCodebasePrincipal(makeURI('http://example.org'), {inBrowser: true});
var nullPrin_browser = ssm.createNullPrincipal({inBrowser: true});
checkOriginAttributes(exampleOrg_browser, 0, true, '!inBrowser=1');
checkOriginAttributes(nullPrin_browser, 0, true, '!inBrowser=1');
do_check_eq(exampleOrg_browser.origin, 'http://example.org!inBrowser=1');
// App and browser.
var exampleOrg_appBrowser = ssm.createCodebasePrincipal(makeURI('http://example.org'), {inBrowser: true, appId: 42});
var nullPrin_appBrowser = ssm.createNullPrincipal({inBrowser: true, appId: 42});
checkOriginAttributes(exampleOrg_appBrowser, 42, true, '!appId=42&inBrowser=1');
checkOriginAttributes(nullPrin_appBrowser, 42, true, '!appId=42&inBrowser=1');
do_check_eq(exampleOrg_appBrowser.origin, 'http://example.org!appId=42&inBrowser=1');
// App and browser, different domain.
var exampleCom_appBrowser = ssm.createCodebasePrincipal(makeURI('https://www.example.com:123'), {appId: 42, inBrowser: true});
checkOriginAttributes(exampleCom_appBrowser, 42, true, '!appId=42&inBrowser=1');
do_check_eq(exampleCom_appBrowser.origin, 'https://www.example.com:123!appId=42&inBrowser=1');
// Check that all of the above are cross-origin.
checkCrossOrigin(exampleOrg_app, exampleOrg);
checkCrossOrigin(exampleOrg_app, nullPrin_app);
checkCrossOrigin(exampleOrg_browser, exampleOrg_app);
checkCrossOrigin(exampleOrg_browser, nullPrin_browser);
checkCrossOrigin(exampleOrg_appBrowser, exampleOrg_app);
checkCrossOrigin(exampleOrg_appBrowser, nullPrin_appBrowser);
checkCrossOrigin(exampleOrg_appBrowser, exampleCom_appBrowser);
}

View File

@ -1,11 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifdef __cplusplus
extern "C"
#endif
void *__dso_handle;
/* Begin all files as hidden visibility */
#pragma GCC visibility push(hidden)

View File

@ -1305,7 +1305,7 @@ ifndef MOZ_DEBUG
endif
endif
@echo 'Packaging $(XPI_PKGNAME).xpi...'
cd $(FINAL_TARGET) && $(ZIP) -qr ../$(XPI_PKGNAME).xpi *
$(call py_action,zip,-C $(FINAL_TARGET) ../$(XPI_PKGNAME).xpi '*')
endif
# See comment above about moving this out of the tools tier.

View File

@ -412,8 +412,18 @@ MOZ_TOOL_VARIABLES
MOZ_CHECK_COMPILER_WRAPPER
MOZ_PATH_PROG(RUSTC, rustc)
if test -n "$RUSTC"; then
AC_MSG_CHECKING([rustc version])
RUSTC_VERSION=`$RUSTC --version | cut -d ' ' -f 2`
# Parse out semversion elements.
_RUSTC_MAJOR_VERSION=`echo ${RUSTC_VERSION} | cut -d . -f 1`
_RUSTC_MINOR_VERSION=`echo ${RUSTC_VERSION} | cut -d . -f 2`
_RUSTC_EXTRA_VERSION=`echo ${RUSTC_VERSION} | cut -d . -f 3 | cut -d + -f 1`
_RUSTC_PATCH_VERSION=`echo ${_RUSTC_EXTRA_VERSION} | cut -d '-' -f 1`
AC_MSG_RESULT([$RUSTC_VERSION (v${_RUSTC_MAJOR_VERSION}.${_RUSTC_MINOR_VERSION}.${_RUSTC_PATCH_VERSION})])
fi
MOZ_ARG_ENABLE_BOOL([rust],
[ --enable-rust Include rust language sources],
[ --enable-rust Include rust language sources],
[MOZ_RUST=1],
[MOZ_RUST= ])
if test -z "$RUSTC" -a -n "$MOZ_RUST"; then
@ -421,6 +431,14 @@ if test -z "$RUSTC" -a -n "$MOZ_RUST"; then
To compile rust language sources, you must have 'rustc' in your path.
See http://www.rust-lang.org/ for more information.])
fi
if test -n "$MOZ_RUST" -a -z "$_RUSTC_MAJOR_VERSION" -o \
"$_RUSTC_MAJOR_VERSION" -lt 1; then
AC_MSG_ERROR([Rust compiler ${RUSTC_VERSION} is too old.
To compile rust language sources please install at least
version 1.0 of the 'rustc' toolchain and make sure it is
first in your path.
You can verify this by typing 'rustc --version'.])
fi
AC_SUBST(MOZ_RUST)
dnl ========================================================
@ -447,6 +465,24 @@ esac
AC_SUBST(MACOSX_DEPLOYMENT_TARGET)
dnl ========================================================
dnl Special MacOS X checks
dnl ========================================================
if test -n "$MACOSX_DEPLOYMENT_TARGET" -a -n "$MOZ_RUST"; then
AC_MSG_CHECKING([MacOS X compatibility with rust])
# rustc doesn't support MacOS X 10.6 or earlier.
# https://github.com/rust-lang/rust/issues/25342
_MACOSX_TARGET_MINOR=`echo "$MACOSX_DEPLOYMENT_TARGET" | cut -d. -f2`
if test "$_MACOSX_TARGET_MINOR" -lt 7; then
AC_MSG_ERROR([rustc does not support MacOS X $MACOSX_DEPLOYMENT_TARGET
Add 'ac_add_options --enable-macos-target=10.7' (or later)
to mozconfig, or disable rust support.])
else
AC_MSG_RESULT([$MACOSX_DEPLOYMENT_TARGET is ok])
fi
fi
dnl ========================================================
dnl Special win32 checks
dnl ========================================================
@ -2626,14 +2662,7 @@ if test "$GNU_CC" -a "$OS_TARGET" != WINNT; then
VISIBILITY_FLAGS='-fvisibility=hidden'
;;
*)
case $GCC_VERSION in
4.6*)
VISIBILITY_FLAGS='-I$(DIST)/system_wrappers -include $(MOZILLA_DIR)/config/gcc_hidden_dso_handle.h'
;;
*)
VISIBILITY_FLAGS='-I$(DIST)/system_wrappers -include $(MOZILLA_DIR)/config/gcc_hidden.h'
;;
esac
VISIBILITY_FLAGS='-I$(DIST)/system_wrappers -include $(MOZILLA_DIR)/config/gcc_hidden.h'
WRAP_SYSTEM_INCLUDES=1
;;
esac
@ -3904,6 +3933,7 @@ NSS_NO_LIBPKIX=
MOZ_CONTENT_SANDBOX=
MOZ_GMP_SANDBOX=
MOZ_SANDBOX=1
MOZ_BINARY_EXTENSIONS=
case "$target_os" in
mingw*)
@ -8523,6 +8553,10 @@ AC_SUBST(MOZ_POST_DSO_LIB_COMMAND)
AC_SUBST(MOZ_POST_PROGRAM_COMMAND)
AC_SUBST(MOZ_LINKER_EXTRACT)
if test -n "$MOZ_BINARY_EXTENSIONS"; then
AC_DEFINE(MOZ_BINARY_EXTENSIONS)
fi
AC_SUBST(MOZ_JSDOWNLOADS)
if test -n "$MOZ_JSDOWNLOADS"; then
AC_DEFINE(MOZ_JSDOWNLOADS)

View File

@ -238,7 +238,12 @@ this.UserCustomizations = {
}
try {
Services.scriptloader.loadSubScript(aScript, sandbox, "UTF-8");
let options = {
target: sandbox,
charset: "UTF-8",
async: true
}
Services.scriptloader.loadSubScriptWithOptions(aScript, options);
if (!this._loaded[manifestURL]) {
this._loaded[manifestURL] = { css: [], scripts: [] };
}

View File

@ -549,7 +549,8 @@ WebappsApplication.prototype = {
},
get enabled() {
return this._proxy.enabled;
let value = this._proxy.enabled;
return (value === undefined ? true : value);
},
download: function() {

View File

@ -1,4 +1,4 @@
document.addEventListener("DOMContentLoaded", function() {
var head = document.getElementById("header");
head.innerHTML = "Hello World!";
}, false);
}, false);

View File

@ -1,4 +1,4 @@
document.addEventListener("DOMContentLoaded", function() {
var head = document.getElementById("header2");
head.innerHTML = "Customized content";
}, false);
}, false);

View File

@ -929,6 +929,13 @@ BlobImplBase::SetMutable(bool aMutable)
return rv;
}
/* static */ uint64_t
BlobImplBase::NextSerialNumber()
{
static Atomic<uint64_t> nextSerialNumber;
return nextSerialNumber++;
}
////////////////////////////////////////////////////////////////////////////
// BlobImplFile implementation

View File

@ -301,6 +301,14 @@ public:
virtual void GetType(nsAString& aType) = 0;
/**
* An effectively-unique serial number identifying this instance of FileImpl.
*
* Implementations should obtain a serial number from
* FileImplBase::NextSerialNumber().
*/
virtual uint64_t GetSerialNumber() const = 0;
already_AddRefed<BlobImpl>
Slice(const Optional<int64_t>& aStart, const Optional<int64_t>& aEnd,
const nsAString& aContentType, ErrorResult& aRv);
@ -368,6 +376,7 @@ public:
, mStart(0)
, mLength(aLength)
, mLastModificationDate(aLastModifiedDate)
, mSerialNumber(NextSerialNumber())
{
// Ensure non-null mContentType by default
mContentType.SetIsVoid(false);
@ -382,6 +391,7 @@ public:
, mStart(0)
, mLength(aLength)
, mLastModificationDate(INT64_MAX)
, mSerialNumber(NextSerialNumber())
{
// Ensure non-null mContentType by default
mContentType.SetIsVoid(false);
@ -394,6 +404,7 @@ public:
, mStart(0)
, mLength(aLength)
, mLastModificationDate(INT64_MAX)
, mSerialNumber(NextSerialNumber())
{
// Ensure non-null mContentType by default
mContentType.SetIsVoid(false);
@ -407,6 +418,7 @@ public:
, mStart(aStart)
, mLength(aLength)
, mLastModificationDate(INT64_MAX)
, mSerialNumber(NextSerialNumber())
{
NS_ASSERTION(aLength != UINT64_MAX,
"Must know length when creating slice");
@ -434,6 +446,8 @@ public:
virtual void GetType(nsAString& aType) override;
virtual uint64_t GetSerialNumber() const override { return mSerialNumber; }
virtual already_AddRefed<BlobImpl>
CreateSlice(uint64_t aStart, uint64_t aLength,
const nsAString& aContentType, ErrorResult& aRv) override
@ -521,6 +535,13 @@ public:
protected:
virtual ~BlobImplBase() {}
/**
* Returns a new, effectively-unique serial number. This should be used
* by implementations to obtain a serial number for GetSerialNumber().
* The implementation is thread safe.
*/
static uint64_t NextSerialNumber();
indexedDB::FileInfo* GetFileInfo() const
{
NS_ASSERTION(IsStoredFile(), "Should only be called on stored files!");
@ -541,6 +562,8 @@ protected:
int64_t mLastModificationDate;
const uint64_t mSerialNumber;
// Protected by IndexedDatabaseManager::FileMutex()
nsTArray<nsRefPtr<indexedDB::FileInfo>> mFileInfos;
};

View File

@ -3072,15 +3072,14 @@ nsDOMWindowUtils::SetContentDocumentFixedPositionMargins(float aTop, float aRigh
}
nsresult
nsDOMWindowUtils::RemoteFrameFullscreenChanged(nsIDOMElement* aFrameElement,
const nsAString& aNewOrigin)
nsDOMWindowUtils::RemoteFrameFullscreenChanged(nsIDOMElement* aFrameElement)
{
MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome());
nsCOMPtr<nsIDocument> doc = GetDocument();
NS_ENSURE_STATE(doc);
doc->RemoteFrameFullscreenChanged(aFrameElement, aNewOrigin);
doc->RemoteFrameFullscreenChanged(aFrameElement);
return NS_OK;
}

View File

@ -1713,11 +1713,8 @@ nsDocument::~nsDocument()
// Kill the subdocument map, doing this will release its strong
// references, if any.
if (mSubDocuments) {
PL_DHashTableDestroy(mSubDocuments);
mSubDocuments = nullptr;
}
delete mSubDocuments;
mSubDocuments = nullptr;
// Destroy link map now so we don't waste time removing
// links one by one
@ -2121,10 +2118,8 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDocument)
tmp->mStyleSheetSetList = nullptr;
}
if (tmp->mSubDocuments) {
PL_DHashTableDestroy(tmp->mSubDocuments);
tmp->mSubDocuments = nullptr;
}
delete tmp->mSubDocuments;
tmp->mSubDocuments = nullptr;
tmp->mFrameRequestCallbacks.Clear();
@ -2320,11 +2315,8 @@ nsDocument::ResetToURI(nsIURI *aURI, nsILoadGroup *aLoadGroup,
// Delete references to sub-documents and kill the subdocument map,
// if any. It holds strong references
if (mSubDocuments) {
PL_DHashTableDestroy(mSubDocuments);
mSubDocuments = nullptr;
}
delete mSubDocuments;
mSubDocuments = nullptr;
// Destroy link map now so we don't waste time removing
// links one by one
@ -4005,7 +3997,7 @@ nsDocument::SetSubDocumentFor(Element* aElement, nsIDocument* aSubDoc)
SubDocInitEntry
};
mSubDocuments = PL_NewDHashTable(&hash_table_ops, sizeof(SubDocMapEntry));
mSubDocuments = new PLDHashTable2(&hash_table_ops, sizeof(SubDocMapEntry));
}
// Add a mapping to the hash table
@ -11099,35 +11091,6 @@ nsIDocument::ExitFullscreen(nsIDocument* aDoc, bool aRunAsync)
nsDocument::ExitFullscreen(aDoc);
}
// Returns true if the document is a direct child of a cross process parent
// mozbrowser iframe or TabParent. This is the case when the document has
// a null parent and its DocShell reports that it is a browser frame, or
// we can get a TabChild from it.
static bool
HasCrossProcessParent(nsIDocument* aDocument)
{
if (XRE_GetProcessType() != GeckoProcessType_Content) {
return false;
}
if (aDocument->GetParentDocument() != nullptr) {
return false;
}
nsPIDOMWindow* win = aDocument->GetWindow();
if (!win) {
return false;
}
nsCOMPtr<nsIDocShell> docShell = win->GetDocShell();
if (!docShell) {
return false;
}
TabChild* tabChild(TabChild::GetFrom(docShell));
if (!tabChild) {
return false;
}
return true;
}
static bool
CountFullscreenSubDocuments(nsIDocument* aDoc, void* aData)
{
@ -11167,21 +11130,6 @@ ResetFullScreen(nsIDocument* aDocument, void* aData)
NS_ASSERTION(!aDocument->IsFullScreenDoc(), "Should reset full-screen");
nsTArray<nsIDocument*>* changed = reinterpret_cast<nsTArray<nsIDocument*>*>(aData);
changed->AppendElement(aDocument);
if (HasCrossProcessParent(aDocument)) {
// We're at the top of the content-process side doc tree. Ask the parent
// process to exit fullscreen.
nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
os->NotifyObservers(aDocument, "ask-parent-to-exit-fullscreen", nullptr);
}
// Dispatch a notification so that if this document has any
// cross-process subdocuments, they'll be notified to exit fullscreen.
// The BrowserElementParent listens for this event and performs the
// cross process notification if it has a remote child process.
nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
os->NotifyObservers(aDocument, "ask-children-to-exit-fullscreen", nullptr);
aDocument->EnumerateSubDocuments(ResetFullScreen, aData);
}
return true;
@ -11219,11 +11167,13 @@ ExitFullscreenInDocTree(nsIDocument* aMaybeNotARootDoc)
NS_ASSERTION(!root->IsFullScreenDoc(),
"Fullscreen root should no longer be a fullscreen doc...");
// Dispatch MozExitedDomFullscreen to the last document in
// Dispatch MozDOMFullscreen:Exited to the last document in
// the list since we want this event to follow the same path
// MozEnteredDomFullscreen dispatched.
nsRefPtr<AsyncEventDispatcher> asyncDispatcher = new AsyncEventDispatcher(
changed.LastElement(), NS_LITERAL_STRING("MozExitedDomFullscreen"), true, true);
// MozDOMFullscreen:Entered dispatched.
nsRefPtr<AsyncEventDispatcher> asyncDispatcher =
new AsyncEventDispatcher(changed.LastElement(),
NS_LITERAL_STRING("MozDOMFullscreen:Exited"),
true, true);
asyncDispatcher->PostDOMEvent();
// Move the top-level window out of fullscreen mode.
SetWindowFullScreen(root, false);
@ -11303,12 +11253,6 @@ nsDocument::RestorePreviousFullScreenState()
nsCOMPtr<nsIDocument> fullScreenDoc = GetFullscreenLeaf(this);
// The fullscreen document may contain a <iframe mozbrowser> element which
// has a cross process child. So send a notification so that its browser
// parent will send a message to its child process to also exit fullscreen.
nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
os->NotifyObservers(fullScreenDoc, "ask-children-to-exit-fullscreen", nullptr);
// Clear full-screen stacks in all descendant in process documents, bottom up.
nsIDocument* doc = fullScreenDoc;
while (doc != this) {
@ -11326,12 +11270,6 @@ nsDocument::RestorePreviousFullScreenState()
UnlockPointer();
DispatchFullScreenChange(doc);
if (static_cast<nsDocument*>(doc)->mFullScreenStack.IsEmpty()) {
if (HasCrossProcessParent(doc)) {
// Send notification to the parent process to tell it to rollback to
// the previous fullscreen elements in its fullscreen element stacks.
nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
os->NotifyObservers(doc, "ask-parent-to-rollback-fullscreen", nullptr);
}
// Full-screen stack in document is empty. Go back up to the parent
// document. We'll pop the containing element off its stack, and use
// its next full-screen element as the full-screen element.
@ -11349,25 +11287,12 @@ nsDocument::RestorePreviousFullScreenState()
(!nsContentUtils::IsSitePermAllow(doc->NodePrincipal(), "fullscreen") &&
!static_cast<nsDocument*>(doc)->mIsApprovedForFullscreen)) {
nsRefPtr<AsyncEventDispatcher> asyncDispatcher =
new AsyncEventDispatcher(doc,
NS_LITERAL_STRING("MozEnteredDomFullscreen"),
true,
true);
new AsyncEventDispatcher(
doc, NS_LITERAL_STRING("MozDOMFullscreen:NewOrigin"),
/* Bubbles */ true, /* ChromeOnly */ true);
asyncDispatcher->PostDOMEvent();
}
}
if (!nsContentUtils::HaveEqualPrincipals(doc, fullScreenDoc)) {
// The origin which is fullscreen changed. Send a notification to
// the root process so that a warning or approval UI can be shown
// as necessary.
nsAutoString origin;
nsContentUtils::GetUTFOrigin(doc->NodePrincipal(), origin);
nsIDocument* root = nsContentUtils::GetRootDocument(doc);
nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
os->NotifyObservers(root, "fullscreen-origin-change", origin.get());
}
break;
}
}
@ -11378,7 +11303,7 @@ nsDocument::RestorePreviousFullScreenState()
NS_ASSERTION(!nsContentUtils::GetRootDocument(this)->IsFullScreenDoc(),
"Should have cleared all docs' stacks");
nsRefPtr<AsyncEventDispatcher> asyncDispatcher = new AsyncEventDispatcher(
this, NS_LITERAL_STRING("MozExitedDomFullscreen"), true, true);
this, NS_LITERAL_STRING("MozDOMFullscreen:Exited"), true, true);
asyncDispatcher->PostDOMEvent();
SetWindowFullScreen(this, false);
}
@ -11630,32 +11555,17 @@ IsInActiveTab(nsIDocument* aDoc)
return activeWindow == rootWin;
}
nsresult nsDocument::RemoteFrameFullscreenChanged(nsIDOMElement* aFrameElement,
const nsAString& aOrigin)
nsresult nsDocument::RemoteFrameFullscreenChanged(nsIDOMElement* aFrameElement)
{
// Ensure the frame element is the fullscreen element in this document.
// If the frame element is already the fullscreen element in this document,
// this has no effect.
nsCOMPtr<nsIContent> content(do_QueryInterface(aFrameElement));
FullScreenOptions opts;
RequestFullScreen(content->AsElement(),
opts,
RequestFullScreen(content->AsElement(), opts,
/* aWasCallerChrome */ false,
/* aNotifyOnOriginChange */ false);
// Origin changed in child process, send notifiction, so that chrome can
// update the UI to reflect the fullscreen origin change if necessary.
// The BrowserElementChild listens on this, and forwards it over its
// parent process, where it is redispatched. Chrome (in the root process,
// which could be *this* process) listens for this notification so that
// it can show a warning or approval UI.
if (!aOrigin.IsEmpty()) {
nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
os->NotifyObservers(nsContentUtils::GetRootDocument(this),
"fullscreen-origin-change",
PromiseFlatString(aOrigin).get());
}
return NS_OK;
}
@ -11818,19 +11728,32 @@ nsDocument::RequestFullScreen(Element* aElement,
nsContentUtils::IsSitePermAllow(NodePrincipal(), "fullscreen");
}
// If this document, or a document with the same principal has not
// already been approved for fullscreen this fullscreen-session, dispatch
// an event so that chrome knows to pop up a warning/approval UI.
// Note previousFullscreenDoc=nullptr upon first entry, so we always
// take this path on the first time we enter fullscreen in a fullscreen
// session.
if (!mIsApprovedForFullscreen ||
// If it is the first entry of the fullscreen, trigger an event so
// that the UI can response to this change, e.g. hide chrome, or
// notifying parent process to enter fullscreen. Note that chrome
// code may also want to listen to MozDOMFullscreen:NewOrigin event
// to pop up warning/approval UI.
if (!previousFullscreenDoc) {
nsRefPtr<AsyncEventDispatcher> asyncDispatcher =
new AsyncEventDispatcher(
this, NS_LITERAL_STRING("MozDOMFullscreen:Entered"),
/* Bubbles */ true, /* ChromeOnly */ true);
asyncDispatcher->PostDOMEvent();
}
// The origin which is fullscreen gets changed. Trigger an event so
// that the chrome knows to pop up a warning/approval UI. Note that
// previousFullscreenDoc == nullptr upon first entry, so we always
// take this path on the first entry. Also note that, in a multi-
// process browser, the code in content process is responsible for
// sending message with the origin to its parent, and the parent
// shouldn't rely on this event itself.
if (aNotifyOnOriginChange &&
!nsContentUtils::HaveEqualPrincipals(previousFullscreenDoc, this)) {
nsRefPtr<AsyncEventDispatcher> asyncDispatcher =
new AsyncEventDispatcher(this,
NS_LITERAL_STRING("MozEnteredDomFullscreen"),
true,
true);
new AsyncEventDispatcher(
this, NS_LITERAL_STRING("MozDOMFullscreen:NewOrigin"),
/* Bubbles */ true, /* ChromeOnly */ true);
asyncDispatcher->PostDOMEvent();
}
@ -11847,21 +11770,6 @@ nsDocument::RequestFullScreen(Element* aElement,
"GetMozFullScreenElement should match GetFullScreenElement()");
#endif
// The origin which is fullscreen changed, send a notifiction so that the
// root document knows the origin of the document which requested fullscreen.
// This is used for the fullscreen approval UI. If we're in a child
// process, the root BrowserElementChild listens for this notification,
// and forwards it across to its BrowserElementParent, which
// re-broadcasts the message for the root document in its process.
if (aNotifyOnOriginChange &&
!nsContentUtils::HaveEqualPrincipals(previousFullscreenDoc, this)) {
nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
nsIDocument* root = nsContentUtils::GetRootDocument(this);
nsAutoString origin;
nsContentUtils::GetUTFOrigin(NodePrincipal(), origin);
os->NotifyObservers(root, "fullscreen-origin-change", origin.get());
}
// Make the window full-screen. Note we must make the state changes above
// before making the window full-screen, as then the document reports as
// being in full-screen mode when the chrome "fullscreen" event fires,

View File

@ -1179,8 +1179,8 @@ public:
virtual bool IsFullscreenLeaf() override;
virtual bool IsFullScreenDoc() override;
virtual void SetApprovedForFullscreen(bool aIsApproved) override;
virtual nsresult RemoteFrameFullscreenChanged(nsIDOMElement* aFrameElement,
const nsAString& aNewOrigin) override;
virtual nsresult
RemoteFrameFullscreenChanged(nsIDOMElement* aFrameElement) override;
virtual nsresult RemoteFrameFullscreenReverted() override;
virtual nsIDocument* GetFullscreenRoot() override;
@ -1217,13 +1217,13 @@ public:
// This is called asynchronously by nsIDocument::AsyncRequestFullScreen()
// to move this document into full-screen mode if allowed. aWasCallerChrome
// should be true when nsIDocument::AsyncRequestFullScreen() was called
// by chrome code. aNotifyOnOriginChange denotes whether we should send a
// fullscreen-origin-change notification if requesting fullscreen in this
// by chrome code. aNotifyOnOriginChange denotes whether we should trigger
// a MozFullscreenOriginChanged event if requesting fullscreen in this
// document causes the origin which is fullscreen to change. We may want to
// *not* send this notification if we're calling RequestFullscreen() as part
// *not* send this notification if we're calling RequestFullScreen() as part
// of a continuation of a request in a subdocument, whereupon the caller will
// need to send the notification with the origin of the document which
// originally requested fullscreen, not *this* document's origin.
// need to send some notification itself with the origin of the document
// which originally requested fullscreen, not *this* document's origin.
void RequestFullScreen(Element* aElement,
mozilla::dom::FullScreenOptions& aOptions,
bool aWasCallerChrome,
@ -1518,7 +1518,7 @@ protected:
nsTArray<nsIObserver*> mCharSetObservers;
PLDHashTable *mSubDocuments;
PLDHashTable2 *mSubDocuments;
// Array of owning references to all children
nsAttrAndChildArray mChildren;

View File

@ -464,14 +464,19 @@ nsHostObjectProtocolHandler::Traverse(const nsACString& aUri,
aCallback.NoteXPCOMChild(res->mObject);
}
static nsISupports*
GetDataObjectForSpec(const nsACString& aSpec)
{
DataInfo* info = GetDataInfo(aSpec);
return info ? info->mObject : nullptr;
}
static nsISupports*
GetDataObject(nsIURI* aURI)
{
nsCString spec;
aURI->GetSpec(spec);
DataInfo* info = GetDataInfo(spec);
return info ? info->mObject : nullptr;
return GetDataObjectForSpec(spec);
}
// -----------------------------------------------------------------------
@ -647,6 +652,20 @@ NS_GetBlobForBlobURI(nsIURI* aURI, BlobImpl** aBlob)
return NS_OK;
}
nsresult
NS_GetBlobForBlobURISpec(const nsACString& aSpec, BlobImpl** aBlob)
{
*aBlob = nullptr;
nsCOMPtr<BlobImpl> blob = do_QueryInterface(GetDataObjectForSpec(aSpec));
if (!blob) {
return NS_ERROR_DOM_BAD_URI;
}
blob.forget(aBlob);
return NS_OK;
}
nsresult
NS_GetStreamForBlobURI(nsIURI* aURI, nsIInputStream** aStream)
{

View File

@ -124,6 +124,9 @@ inline bool IsFontTableURI(nsIURI* aUri)
extern nsresult
NS_GetBlobForBlobURI(nsIURI* aURI, mozilla::dom::BlobImpl** aBlob);
extern nsresult
NS_GetBlobForBlobURISpec(const nsACString& aSpec, mozilla::dom::BlobImpl** aBlob);
extern nsresult
NS_GetStreamForBlobURI(nsIURI* aURI, nsIInputStream** aStream);

View File

@ -151,8 +151,8 @@ struct FullScreenOptions {
} // namespace mozilla
#define NS_IDOCUMENT_IID \
{ 0x0b78eabe, 0x8b94, 0x4ea1, \
{ 0x93, 0x31, 0x5d, 0x48, 0xe8, 0x3a, 0xda, 0x95 } }
{ 0xdcfa30f2, 0x2197, 0x421f, \
{ 0xa7, 0x5a, 0x3e, 0x70, 0x18, 0x08, 0xde, 0x81 } }
// Enum for requesting a particular type of document when creating a doc
enum DocumentFlavor {
@ -1094,11 +1094,10 @@ public:
* Called when a frame in a child process has entered fullscreen or when a
* fullscreen frame in a child process changes to another origin.
* aFrameElement is the frame element which contains the child-process
* fullscreen document, and aNewOrigin is the origin of the new fullscreen
* document.
* fullscreen document.
*/
virtual nsresult RemoteFrameFullscreenChanged(nsIDOMElement* aFrameElement,
const nsAString& aNewOrigin) = 0;
virtual nsresult
RemoteFrameFullscreenChanged(nsIDOMElement* aFrameElement) = 0;
/**
* Called when a frame in a remote child document has rolled back fullscreen

View File

@ -57,7 +57,7 @@ public:
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf);
nsCOMPtr<nsIAtom> mName; // property name
PLDHashTable mObjectValueMap; // map of object/value pairs
PLDHashTable2 mObjectValueMap; // map of object/value pairs
NSPropertyDtorFunc mDtorFunc; // property specific value dtor function
void* mDtorData; // pointer to pass to dtor
bool mTransfer; // whether to transfer in
@ -287,21 +287,18 @@ nsPropertyTable::PropertyList::PropertyList(nsIAtom *aName,
void *aDtorData,
bool aTransfer)
: mName(aName),
mObjectValueMap(PL_DHashGetStubOps(), sizeof(PropertyListMapEntry)),
mDtorFunc(aDtorFunc),
mDtorData(aDtorData),
mTransfer(aTransfer),
mNext(nullptr)
{
PL_DHashTableInit(&mObjectValueMap, PL_DHashGetStubOps(),
sizeof(PropertyListMapEntry));
}
nsPropertyTable::PropertyList::~PropertyList()
{
PL_DHashTableFinish(&mObjectValueMap);
}
static PLDHashOperator
DestroyPropertyEnumerator(PLDHashTable *table, PLDHashEntryHdr *hdr,
uint32_t number, void *arg)

View File

@ -1856,9 +1856,7 @@ nsXMLHttpRequest::StreamReaderFunc(nsIInputStream* in,
} else if (xmlHttpRequest->mResponseType == XML_HTTP_RESPONSE_TYPE_DEFAULT &&
xmlHttpRequest->mResponseXML) {
// Copy for our own use
uint32_t previousLength = xmlHttpRequest->mResponseBody.Length();
xmlHttpRequest->mResponseBody.Append(fromRawSegment,count);
if (count > 0 && xmlHttpRequest->mResponseBody.Length() == previousLength) {
if (!xmlHttpRequest->mResponseBody.Append(fromRawSegment, count, fallible)) {
return NS_ERROR_OUT_OF_MEMORY;
}
} else if (xmlHttpRequest->mResponseType == XML_HTTP_RESPONSE_TYPE_DEFAULT ||

View File

@ -126,7 +126,7 @@ public:
class ObexHeaderSet
{
public:
ObexHeaderSet(uint8_t aOpcode) : mOpcode(aOpcode)
ObexHeaderSet()
{
}
@ -252,7 +252,6 @@ public:
}
private:
uint8_t mOpcode;
nsTArray<nsAutoPtr<ObexHeader> > mHeaders;
};

View File

@ -640,6 +640,8 @@ BluetoothHALInterface::GetRemoteDeviceProperty(
if (NS_SUCCEEDED(Convert(aRemoteAddr, remoteAddr)) &&
false /* TODO: we don't support any values for aName currently */) {
// silence uninitialized variable warning for |name|
name = static_cast<bt_property_type_t>(0);
status = mInterface->get_remote_device_property(&remoteAddr, name);
} else {
status = BT_STATUS_PARM_INVALID;

View File

@ -899,10 +899,19 @@ BluetoothOppManager::ServerDataHandler(UnixSocketBuffer* aMessage)
{
MOZ_ASSERT(NS_IsMainThread());
uint8_t opCode;
/**
* Ensure
* - valid access to data[0], i.e., opCode
* - received packet length smaller than max packet length
*/
int receivedLength = aMessage->GetSize();
const uint8_t* data = aMessage->GetData();
if (receivedLength < 1 || receivedLength > MAX_PACKET_LENGTH) {
ReplyError(ObexResponseCode::BadRequest);
return;
}
uint8_t opCode;
const uint8_t* data = aMessage->GetData();
if (mPutPacketReceivedLength > 0) {
opCode = mPutFinalFlag ? ObexRequestCode::PutFinal : ObexRequestCode::Put;
} else {
@ -918,12 +927,13 @@ BluetoothOppManager::ServerDataHandler(UnixSocketBuffer* aMessage)
}
}
ObexHeaderSet pktHeaders(opCode);
ObexHeaderSet pktHeaders;
if (opCode == ObexRequestCode::Connect) {
// Section 3.3.1 "Connect", IrOBEX 1.2
// [opcode:1][length:2][version:1][flags:1][MaxPktSizeWeCanReceive:2]
// [Headers:var]
if (!ParseHeaders(&data[7], receivedLength - 7, &pktHeaders)) {
if (receivedLength < 7 ||
!ParseHeaders(&data[7], receivedLength - 7, &pktHeaders)) {
ReplyError(ObexResponseCode::BadRequest);
return;
}
@ -933,7 +943,8 @@ BluetoothOppManager::ServerDataHandler(UnixSocketBuffer* aMessage)
} else if (opCode == ObexRequestCode::Abort) {
// Section 3.3.5 "Abort", IrOBEX 1.2
// [opcode:1][length:2][Headers:var]
if (!ParseHeaders(&data[3], receivedLength - 3, &pktHeaders)) {
if (receivedLength < 3 ||
!ParseHeaders(&data[3], receivedLength - 3, &pktHeaders)) {
ReplyError(ObexResponseCode::BadRequest);
return;
}
@ -943,7 +954,8 @@ BluetoothOppManager::ServerDataHandler(UnixSocketBuffer* aMessage)
} else if (opCode == ObexRequestCode::Disconnect) {
// Section 3.3.2 "Disconnect", IrOBEX 1.2
// [opcode:1][length:2][Headers:var]
if (!ParseHeaders(&data[3], receivedLength - 3, &pktHeaders)) {
if (receivedLength < 3 ||
!ParseHeaders(&data[3], receivedLength - 3, &pktHeaders)) {
ReplyError(ObexResponseCode::BadRequest);
return;
}
@ -1026,6 +1038,13 @@ BluetoothOppManager::ClientDataHandler(UnixSocketBuffer* aMessage)
{
MOZ_ASSERT(NS_IsMainThread());
// Ensure valid access to data[0], i.e., opCode
int receivedLength = aMessage->GetSize();
if (receivedLength < 1) {
BT_LOGR("Receive empty response packet");
return;
}
const uint8_t* data = aMessage->GetData();
uint8_t opCode = data[0];
@ -1083,6 +1102,13 @@ BluetoothOppManager::ClientDataHandler(UnixSocketBuffer* aMessage)
AfterOppConnected();
// Ensure valid access to remote information
if (receivedLength < 7) {
BT_LOGR("The length of connect response packet is invalid");
SendDisconnectRequest();
return;
}
// Keep remote information
mRemoteObexVersion = data[3];
mRemoteConnectionFlags = data[4];

View File

@ -183,17 +183,27 @@ BluetoothPbapManager::ReceiveSocketData(BluetoothSocket* aSocket,
{
MOZ_ASSERT(NS_IsMainThread());
const uint8_t* data = aMessage->GetData();
/**
* Ensure
* - valid access to data[0], i.e., opCode
* - received packet length smaller than max packet length
*/
int receivedLength = aMessage->GetSize();
uint8_t opCode = data[0];
if (receivedLength < 1 || receivedLength > MAX_PACKET_LENGTH) {
ReplyError(ObexResponseCode::BadRequest);
return;
}
ObexHeaderSet pktHeaders(opCode);
const uint8_t* data = aMessage->GetData();
uint8_t opCode = data[0];
ObexHeaderSet pktHeaders;
switch (opCode) {
case ObexRequestCode::Connect:
// Section 3.3.1 "Connect", IrOBEX 1.2
// [opcode:1][length:2][version:1][flags:1][MaxPktSizeWeCanReceive:2]
// [Headers:var]
if (!ParseHeaders(&data[7], receivedLength - 7, &pktHeaders)) {
if (receivedLength < 7 ||
!ParseHeaders(&data[7], receivedLength - 7, &pktHeaders)) {
ReplyError(ObexResponseCode::BadRequest);
return;
}
@ -213,7 +223,8 @@ BluetoothPbapManager::ReceiveSocketData(BluetoothSocket* aSocket,
// Section 3.3.2 "Disconnect" and Section 3.3.5 "Abort", IrOBEX 1.2
// The format of request packet of "Disconnect" and "Abort" are the same
// [opcode:1][length:2][Headers:var]
if (!ParseHeaders(&data[3], receivedLength - 3, &pktHeaders)) {
if (receivedLength < 3 ||
!ParseHeaders(&data[3], receivedLength - 3, &pktHeaders)) {
ReplyError(ObexResponseCode::BadRequest);
return;
}
@ -224,7 +235,8 @@ BluetoothPbapManager::ReceiveSocketData(BluetoothSocket* aSocket,
case ObexRequestCode::SetPath: {
// Section 3.3.6 "SetPath", IrOBEX 1.2
// [opcode:1][length:2][flags:1][contants:1][Headers:var]
if (!ParseHeaders(&data[5], receivedLength - 5, &pktHeaders)) {
if (receivedLength < 5 ||
!ParseHeaders(&data[5], receivedLength - 5, &pktHeaders)) {
ReplyError(ObexResponseCode::BadRequest);
return;
}

View File

@ -983,7 +983,7 @@ BluetoothAdapter::IsBluetoothCertifiedApp()
nsAutoCString appOrigin;
doc->NodePrincipal()->GetAppStatus(&appStatus);
doc->NodePrincipal()->GetOrigin(appOrigin);
doc->NodePrincipal()->GetOriginNoSuffix(appOrigin);
return appStatus == nsIPrincipal::APP_STATUS_CERTIFIED &&
appOrigin.EqualsLiteral(BLUETOOTH_APP_ORIGIN);

View File

@ -878,10 +878,19 @@ BluetoothOppManager::ServerDataHandler(UnixSocketBuffer* aMessage)
{
MOZ_ASSERT(NS_IsMainThread());
uint8_t opCode;
/**
* Ensure
* - valid access to data[0], i.e., opCode
* - received packet length smaller than max packet length
*/
int receivedLength = aMessage->GetSize();
const uint8_t* data = aMessage->GetData();
if (receivedLength < 1 || receivedLength > MAX_PACKET_LENGTH) {
ReplyError(ObexResponseCode::BadRequest);
return;
}
uint8_t opCode;
const uint8_t* data = aMessage->GetData();
if (mPutPacketReceivedLength > 0) {
opCode = mPutFinalFlag ? ObexRequestCode::PutFinal : ObexRequestCode::Put;
} else {
@ -897,12 +906,13 @@ BluetoothOppManager::ServerDataHandler(UnixSocketBuffer* aMessage)
}
}
ObexHeaderSet pktHeaders(opCode);
ObexHeaderSet pktHeaders;
if (opCode == ObexRequestCode::Connect) {
// Section 3.3.1 "Connect", IrOBEX 1.2
// [opcode:1][length:2][version:1][flags:1][MaxPktSizeWeCanReceive:2]
// [Headers:var]
if (!ParseHeaders(&data[7], receivedLength - 7, &pktHeaders)) {
if (receivedLength < 7 ||
!ParseHeaders(&data[7], receivedLength - 7, &pktHeaders)) {
ReplyError(ObexResponseCode::BadRequest);
return;
}
@ -912,7 +922,8 @@ BluetoothOppManager::ServerDataHandler(UnixSocketBuffer* aMessage)
} else if (opCode == ObexRequestCode::Abort) {
// Section 3.3.5 "Abort", IrOBEX 1.2
// [opcode:1][length:2][Headers:var]
if (!ParseHeaders(&data[3], receivedLength - 3, &pktHeaders)) {
if (receivedLength < 3 ||
!ParseHeaders(&data[3], receivedLength - 3, &pktHeaders)) {
ReplyError(ObexResponseCode::BadRequest);
return;
}
@ -922,7 +933,8 @@ BluetoothOppManager::ServerDataHandler(UnixSocketBuffer* aMessage)
} else if (opCode == ObexRequestCode::Disconnect) {
// Section 3.3.2 "Disconnect", IrOBEX 1.2
// [opcode:1][length:2][Headers:var]
if (!ParseHeaders(&data[3], receivedLength - 3, &pktHeaders)) {
if (receivedLength < 3 ||
!ParseHeaders(&data[3], receivedLength - 3, &pktHeaders)) {
ReplyError(ObexResponseCode::BadRequest);
return;
}
@ -1005,6 +1017,13 @@ BluetoothOppManager::ClientDataHandler(UnixSocketBuffer* aMessage)
{
MOZ_ASSERT(NS_IsMainThread());
// Ensure valid access to data[0], i.e., opCode
int receivedLength = aMessage->GetSize();
if (receivedLength < 1) {
BT_LOGR("Receive empty response packet");
return;
}
const uint8_t* data = aMessage->GetData();
uint8_t opCode = data[0];
@ -1062,6 +1081,13 @@ BluetoothOppManager::ClientDataHandler(UnixSocketBuffer* aMessage)
AfterOppConnected();
// Ensure valid access to remote information
if (receivedLength < 7) {
BT_LOGR("The length of connect response packet is invalid");
SendDisconnectRequest();
return;
}
// Keep remote information
mRemoteObexVersion = data[3];
mRemoteConnectionFlags = data[4];

View File

@ -50,9 +50,6 @@ function sendSyncMsg(msg, data) {
let CERTIFICATE_ERROR_PAGE_PREF = 'security.alternate_certificate_error_page';
const OBSERVED_EVENTS = [
'fullscreen-origin-change',
'ask-parent-to-exit-fullscreen',
'ask-parent-to-rollback-fullscreen',
'xpcom-shutdown',
'activity-done'
];
@ -147,6 +144,21 @@ BrowserElementChild.prototype = {
/* useCapture = */ true,
/* wantsUntrusted = */ false);
addEventListener("MozDOMFullscreen:Entered",
this._mozEnteredDomFullscreen.bind(this),
/* useCapture = */ true,
/* wantsUntrusted = */ false);
addEventListener("MozDOMFullscreen:NewOrigin",
this._mozFullscreenOriginChange.bind(this),
/* useCapture = */ true,
/* wantsUntrusted = */ false);
addEventListener("MozDOMFullscreen:Exited",
this._mozExitedDomFullscreen.bind(this),
/* useCapture = */ true,
/* wantsUntrusted = */ false);
addEventListener('DOMMetaAdded',
this._metaChangedHandler.bind(this),
/* useCapture = */ true,
@ -259,15 +271,6 @@ BrowserElementChild.prototype = {
if (topic == 'activity-done' && docShell !== subject)
return;
switch (topic) {
case 'fullscreen-origin-change':
sendAsyncMsg('fullscreen-origin-change', { _payload_: data });
break;
case 'ask-parent-to-exit-fullscreen':
sendAsyncMsg('exit-fullscreen');
break;
case 'ask-parent-to-rollback-fullscreen':
sendAsyncMsg('rollback-fullscreen');
break;
case 'activity-done':
sendAsyncMsg('activitydone', { success: (data == 'activity-success') });
break;
@ -956,6 +959,20 @@ BrowserElementChild.prototype = {
});
},
_mozEnteredDomFullscreen: function(e) {
sendAsyncMsg("entered-dom-fullscreen");
},
_mozFullscreenOriginChange: function(e) {
sendAsyncMsg("fullscreen-origin-change", {
origin: e.target.nodePrincipal.origin
});
},
_mozExitedDomFullscreen: function(e) {
sendAsyncMsg("exited-dom-fullscreen");
},
_getContentDimensions: function() {
return {
width: content.document.body.scrollWidth,

View File

@ -85,7 +85,6 @@ function BrowserElementParent() {
this._pendingSetInputMethodActive = [];
this._nextPaintListeners = [];
Services.obs.addObserver(this, 'ask-children-to-exit-fullscreen', /* ownsWeak = */ true);
Services.obs.addObserver(this, 'oop-frameloader-crashed', /* ownsWeak = */ true);
Services.obs.addObserver(this, 'copypaste-docommand', /* ownsWeak = */ true);
}
@ -130,6 +129,11 @@ BrowserElementParent.prototype = {
BrowserElementPromptService.mapFrameToBrowserElementParent(this._frameElement, this);
this._setupMessageListener();
this._registerAppManifest();
let els = Cc["@mozilla.org/eventlistenerservice;1"]
.getService(Ci.nsIEventListenerService);
els.addSystemEventListener(this._window.document, "mozfullscreenchange",
this._fullscreenChange.bind(this), true);
},
_runPendingAPICall: function() {
@ -191,9 +195,9 @@ BrowserElementParent.prototype = {
"got-contentdimensions": this._gotDOMRequestResult,
"got-can-go-back": this._gotDOMRequestResult,
"got-can-go-forward": this._gotDOMRequestResult,
"fullscreen-origin-change": this._remoteFullscreenOriginChange,
"rollback-fullscreen": this._remoteFrameFullscreenReverted,
"exit-fullscreen": this._exitFullscreen,
"entered-dom-fullscreen": this._enteredDomFullscreen,
"fullscreen-origin-change": this._fullscreenOriginChange,
"exited-dom-fullscreen": this._exitedDomFullscreen,
"got-visible": this._gotDOMRequestResult,
"visibilitychange": this._childVisibilityChange,
"got-set-input-method-active": this._gotDOMRequestResult,
@ -936,19 +940,27 @@ BrowserElementParent.prototype = {
this._fireEventFromMsg(data);
},
_exitFullscreen: function() {
this._windowUtils.exitFullscreen();
_enteredDomFullscreen: function() {
this._windowUtils.remoteFrameFullscreenChanged(this._frameElement);
},
_remoteFullscreenOriginChange: function(data) {
let origin = data.json._payload_;
this._windowUtils.remoteFrameFullscreenChanged(this._frameElement, origin);
_fullscreenOriginChange: function(data) {
Services.obs.notifyObservers(
this._frameElement, "fullscreen-origin-change", data.json.origin);
},
_remoteFrameFullscreenReverted: function(data) {
_exitedDomFullscreen: function(data) {
this._windowUtils.remoteFrameFullscreenReverted();
},
_fullscreenChange: function(evt) {
if (this._isAlive() && evt.target == this._window.document) {
if (!this._window.document.mozFullScreen) {
this._sendAsyncMsg("exit-fullscreen");
}
}
},
_fireFatalError: function() {
let evt = this._createEvent('error', {type: 'fatal'},
/* cancelable = */ false);
@ -962,13 +974,6 @@ BrowserElementParent.prototype = {
this._fireFatalError();
}
break;
case 'ask-children-to-exit-fullscreen':
if (this._isAlive() &&
this._frameElement.ownerDocument == subject &&
this._frameLoader.QueryInterface(Ci.nsIFrameLoader).tabParent) {
this._sendAsyncMsg('exit-fullscreen');
}
break;
case 'copypaste-docommand':
if (this._isAlive() && this._frameElement.isEqualNode(subject.wrappedJSObject)) {
this._sendAsyncMsg('do-command', { command: data });

View File

@ -33,7 +33,7 @@ ManagerId::Create(nsIPrincipal* aPrincipal, ManagerId** aManagerIdOut)
// TODO: consider using QuotaManager's modified origin here (bug 1112071)
nsAutoCString origin;
nsresult rv = aPrincipal->GetOrigin(origin);
nsresult rv = aPrincipal->GetOriginNoSuffix(origin);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
uint32_t appId;

View File

@ -150,7 +150,7 @@ PrincipalVerifier::VerifyOnMainThread()
// is a synthetic [System Principal] string.
if (!ssm->IsSystemPrincipal(principal)) {
nsAutoCString origin;
rv = principal->GetOrigin(origin);
rv = principal->GetOriginNoSuffix(origin);
if (NS_WARN_IF(NS_FAILED(rv))) {
DispatchToInitiatingThread(rv);
return;

View File

@ -146,14 +146,7 @@ this.DataStoreChangeNotifier = {
// No check has to be done when the message is 'child-process-shutdown'.
if (aMessage.name != "child-process-shutdown") {
if (!("principal" in aMessage)) {
return;
}
let secMan = Cc["@mozilla.org/scriptsecuritymanager;1"]
.getService(Ci.nsIScriptSecurityManager);
let uri = Services.io.newURI(aMessage.principal.origin, null, null);
let principal = secMan.getAppCodebasePrincipal(uri,
aMessage.principal.appId, aMessage.principal.isInBrowserElement);
let principal = aMessage.principal;
if (!principal || !dataStoreService.checkPermission(principal)) {
return;
}

View File

@ -92,8 +92,12 @@ function testScriptInitiatedKeyEvents() {
function testNextKey() {
if (!document.mozFullScreen) {
addFullscreenChangeContinuation("enter", reallyTestNextKey);
document.body.mozRequestFullScreen();
// Async request fullscreen to avoid the request be accidentally
// cancelled due to unfinished clean-up of exiting fullscreen.
setTimeout(() => {
addFullscreenChangeContinuation("enter", reallyTestNextKey);
document.body.mozRequestFullScreen();
}, 0);
}
else {
reallyTestNextKey();

View File

@ -20,23 +20,6 @@ function inNormalMode() {
window.outerHeight == normalSize.h;
}
function ok(condition, msg) {
opener.ok(condition, "[rollback] " + msg);
if (!condition) {
opener.finish();
}
}
// On Linux we sometimes receive fullscreenchange events before the window
// has finished transitioning to fullscreen. This can cause problems and
// test failures, so work around it on Linux until we can get a proper fix.
const workAroundFullscreenTransition = navigator.userAgent.indexOf("Linux") != -1;
if (workAroundFullscreenTransition) {
SimpleTest.requestFlakyTimeout("We need to wait an arbitrary and non-zero " +
"amount of time in case of the Linux specific workaround to avoid busy-waiting.");
}
// Adds a listener that will be called once a fullscreen transition
// is complete. When type==='enter', callback is called when we've
// received a fullscreenchange event, and the fullscreen transition is
@ -48,53 +31,39 @@ if (workAroundFullscreenTransition) {
// the current document.
function addFullscreenChangeContinuation(type, callback, inDoc) {
var doc = inDoc || document;
var listener = null;
if (type === "enter") {
// when entering fullscreen, ensure we don't call 'callback' until the
// enter transition is complete.
listener = function(event) {
doc.removeEventListener("mozfullscreenchange", listener, false);
if (!workAroundFullscreenTransition) {
callback(event);
return;
}
if (!inFullscreenMode()) {
opener.todo(false, "fullscreenchange before entering fullscreen complete! " +
" window.fullScreen=" + window.fullScreen +
" normal=(" + normalSize.w + "," + normalSize.h + ")" +
" outerWidth=" + window.outerWidth + " width=" + window.screen.width +
" outerHeight=" + window.outerHeight + " height=" + window.screen.height);
setTimeout(function(){listener(event);}, 100);
return;
}
setTimeout(function(){callback(event)}, 0);
};
} else if (type === "exit") {
listener = function(event) {
doc.removeEventListener("mozfullscreenchange", listener, false);
if (!workAroundFullscreenTransition) {
callback(event);
return;
}
if (!document.mozFullScreenElement && !inNormalMode()) {
opener.todo(false, "fullscreenchange before exiting fullscreen complete! " +
" window.fullScreen=" + window.fullScreen +
" normal=(" + normalSize.w + "," + normalSize.h + ")" +
" outerWidth=" + window.outerWidth + " width=" + window.screen.width +
" outerHeight=" + window.outerHeight + " height=" + window.screen.height);
// 'document' (*not* 'doc') has no fullscreen element, so we're trying
// to completely exit fullscreen mode. Wait until the transition
// to normal mode is complete before calling callback.
setTimeout(function(){listener(event);}, 100);
return;
}
opener.info("[rollback] Exited fullscreen");
setTimeout(function(){callback(event);}, 0);
};
} else {
throw "'type' must be either 'enter', or 'exit'.";
function checkCondition() {
if (type == "enter") {
return inFullscreenMode();
} else if (type == "exit") {
// If we just revert the state to a previous fullscreen state,
// the window won't back to the normal mode. Hence we check
// mozFullScreenElement first here.
return doc.mozFullScreenElement || inNormalMode();
} else {
throw "'type' must be either 'enter', or 'exit'.";
}
}
doc.addEventListener("mozfullscreenchange", listener, false);
function invokeCallback(event) {
// Use async call after a paint to workaround unfinished fullscreen
// change even when the window size has changed on Linux.
requestAnimationFrame(() => setTimeout(() => callback(event), 0), 0);
}
function onFullscreenChange(event) {
doc.removeEventListener("mozfullscreenchange", onFullscreenChange, false);
if (checkCondition()) {
invokeCallback(event);
return;
}
var win = doc.defaultView;
function onResize() {
if (checkCondition()) {
win.removeEventListener("resize", onResize, false);
invokeCallback(event);
}
}
win.addEventListener("resize", onResize, false);
}
doc.addEventListener("mozfullscreenchange", onFullscreenChange, false);
}
// Calls |callback| when the next fullscreenerror is dispatched to inDoc||document.

View File

@ -52,6 +52,10 @@ const isOSXLion = navigator.userAgent.indexOf("Mac OS X 10.7") != -1;
const isOSXMtnLion = navigator.userAgent.indexOf("Mac OS X 10.8") != -1;
const isOSXYosemite = navigator.userAgent.indexOf("Mac OS X 10.10") != -1;
function finish() {
SimpleTest.finish();
}
function nextTest() {
if (isWinXP) {
todo(false, "Can't reliably run full-screen tests on Windows XP due to bug 704010");
@ -73,6 +77,7 @@ function nextTest() {
function runNextTest() {
if (gTestIndex < gTestWindows.length) {
info("Run test " + gTestWindows[gTestIndex]);
testWindow = window.open(gTestWindows[gTestIndex], "", "width=500,height=500");
// We'll wait for the window to load, then make sure our window is refocused
// before starting the test, which will get kicked off on "focus".

View File

@ -277,14 +277,9 @@ this.DOMIdentity = {
if (!aMessage.principal) {
return false;
}
let secMan = Cc["@mozilla.org/scriptsecuritymanager;1"]
.getService(Ci.nsIScriptSecurityManager);
let uri = Services.io.newURI(aMessage.principal.origin, null, null);
let principal = secMan.getAppCodebasePrincipal(uri,
aMessage.principal.appId, aMessage.principal.isInBrowserElement);
let permission =
permissionManager.testPermissionFromPrincipal(principal,
permissionManager.testPermissionFromPrincipal(aMessage.principal,
FXA_PERMISSION);
return permission != Ci.nsIPermissionManager.UNKNOWN_ACTION &&
permission != Ci.nsIPermissionManager.DENY_ACTION;

View File

@ -49,7 +49,7 @@ interface nsIJSRAIIHelper;
interface nsIContentPermissionRequest;
interface nsIObserver;
[scriptable, uuid(34a42cdc-7a04-4e71-8a5c-63e092fba58e)]
[scriptable, uuid(0ce789cc-3fb6-48b8-a58e-32deefc337b4)]
interface nsIDOMWindowUtils : nsISupports {
/**
@ -1183,11 +1183,9 @@ interface nsIDOMWindowUtils : nsISupports {
* Called when the remote child frame has changed its fullscreen state,
* when entering fullscreen, and when the origin which is fullscreen changes.
* aFrameElement is the iframe element which contains the child-process
* fullscreen document, and aNewOrigin is the origin of the new fullscreen
* document.
* fullscreen document.
*/
void remoteFrameFullscreenChanged(in nsIDOMElement aFrameElement,
in AString aNewOrigin);
void remoteFrameFullscreenChanged(in nsIDOMElement aFrameElement);
/**
* Called when the remote frame has popped all fullscreen elements off its

View File

@ -2089,6 +2089,9 @@ public:
virtual void
GetType(nsAString& aType) override;
virtual uint64_t
GetSerialNumber() const override;
virtual already_AddRefed<BlobImpl>
CreateSlice(uint64_t aStart,
uint64_t aLength,
@ -2797,6 +2800,13 @@ RemoteBlobImpl::GetType(nsAString& aType)
mBlobImpl->GetType(aType);
}
uint64_t
BlobParent::
RemoteBlobImpl::GetSerialNumber() const
{
return mBlobImpl->GetSerialNumber();
}
already_AddRefed<BlobImpl>
BlobParent::
RemoteBlobImpl::CreateSlice(uint64_t aStart,

View File

@ -273,7 +273,9 @@ public:
return ((*aData)[4] == 'm' && (*aData)[5] == 'o' && (*aData)[6] == 'o' &&
(*aData)[7] == 'f') ||
((*aData)[4] == 's' && (*aData)[5] == 't' && (*aData)[6] == 'y' &&
(*aData)[7] == 'p');
(*aData)[7] == 'p') ||
((*aData)[4] == 's' && (*aData)[5] == 'i' && (*aData)[6] == 'd' &&
(*aData)[7] == 'x');
}
bool ParseStartAndEndTimestamps(MediaLargeByteBuffer* aData,

View File

@ -2636,7 +2636,7 @@ QuotaManager::GetInfoFromPrincipal(nsIPrincipal* aPrincipal,
}
nsCString origin;
rv = aPrincipal->GetOrigin(origin);
rv = aPrincipal->GetOriginNoSuffix(origin);
NS_ENSURE_SUCCESS(rv, rv);
if (origin.EqualsLiteral(kChromeOrigin)) {

View File

@ -209,7 +209,7 @@ this.RequestSyncService = {
principalToKey: function(aPrincipal) {
return aPrincipal.appId + '|' +
aPrincipal.isInBrowserElement + '|' +
aPrincipal.origin;
aPrincipal.originNoSuffix;
},
// Add a task to the _registrations map and create the timer if it's needed.
@ -287,20 +287,7 @@ this.RequestSyncService = {
}
// The principal is used to validate the message.
if (!aMessage.principal) {
return;
}
let uri = Services.io.newURI(aMessage.principal.origin, null, null);
let principal;
try {
principal = secMan.getAppCodebasePrincipal(uri,
aMessage.principal.appId, aMessage.principal.isInBrowserElement);
} catch(e) {
return;
}
let principal = aMessage.principal;
if (!principal) {
return;
}
@ -398,7 +385,7 @@ this.RequestSyncService = {
let dbKey = aData.task + "|" +
aPrincipal.appId + '|' +
aPrincipal.isInBrowserElement + '|' +
aPrincipal.origin;
aPrincipal.originNoSuffix;
let data = { principal: aPrincipal,
dbKey: dbKey,
@ -514,7 +501,7 @@ this.RequestSyncService = {
}
if (aObj.principal.isInBrowserElement != aData.isInBrowserElement ||
aObj.principal.origin != aData.origin) {
aObj.principal.originNoSuffix != aData.origin) {
return;
}
@ -562,7 +549,7 @@ this.RequestSyncService = {
}
if (aObj.principal.isInBrowserElement != aData.isInBrowserElement ||
aObj.principal.origin != aData.origin) {
aObj.principal.originNoSuffix != aData.origin) {
return;
}
@ -607,7 +594,7 @@ this.RequestSyncService = {
let obj = this.createPartialTaskObject(aObj);
obj.app = { manifestURL: '',
origin: aObj.principal.origin,
origin: aObj.principal.originNoSuffix,
isInBrowserElement: aObj.principal.isInBrowserElement };
let app = appsService.getAppByLocalId(aObj.principal.appId);

View File

@ -61,8 +61,8 @@ function test_registerFailure() {
});
}
function genericError() {
ok(false, "Some promise failed");
function genericError(name, val) {
ok(false, "Promise from " + name + " rejected with value: " + val);
}
function test_register() {
@ -70,7 +70,7 @@ function test_register() {
function() {
ok(true, "navigator.sync.register() worked!");
runTests();
}, genericError);
}, genericError.bind(null, 'register'));
}
function test_unregister() {
@ -78,12 +78,12 @@ function test_unregister() {
function() {
ok(true, "navigator.sync.unregister() worked!");
runTests();
}, genericError);
}, genericError.bind(null, 'unregister'));
}
function test_unregisterDuplicate() {
navigator.sync.unregister('foobar').then(
genericError,
genericError.bind(null, 'unregisterDuplicate'),
function(error) {
ok(true, "navigator.sync.unregister() should throw if the task doesn't exist.");
ok(error, "UnknownTaskError", "Duplicate unregistration error is correct");
@ -97,7 +97,7 @@ function test_registrationEmpty() {
is(results, null, "navigator.sync.registration() should return null.");
runTests();
},
genericError);
genericError.bind(null, 'registrationEmpty'));
}
function test_registration() {
@ -113,7 +113,7 @@ function test_registration() {
ok(!("app" in results), "navigator.sync.registrations().app is correct");
runTests();
},
genericError);
genericError.bind(null, 'registration'));
}
function test_registrationsEmpty() {
@ -122,7 +122,7 @@ function test_registrationsEmpty() {
is(results.length, 0, "navigator.sync.registrations() should return an empty array.");
runTests();
},
genericError);
genericError.bind(null, 'registrationEmpty'));
}
function test_registrations() {
@ -139,7 +139,7 @@ function test_registrations() {
ok(!("app" in results[0]), "navigator.sync.registrations()[0].app is correct");
runTests();
},
genericError);
genericError.bind(null, 'registrations'));
}
function test_managerRegistrationsEmpty() {
@ -148,7 +148,7 @@ function test_managerRegistrationsEmpty() {
is(results.length, 0, "navigator.syncManager.registrations() should return an empty array.");
runTests();
},
genericError);
genericError.bind(null, 'managerRegistrationsEmpty'));
}
function test_managerRegistrations(state, overwrittenMinInterval) {
@ -172,7 +172,7 @@ function test_managerRegistrations(state, overwrittenMinInterval) {
ok("runNow" in results[0], "navigator.sync.registrations()[0].runNow is correct");
runTests();
},
genericError);
genericError.bind(null, 'managerRegistrations'));
}
function test_managerSetPolicy(state, overwrittenMinInterval) {
@ -183,6 +183,6 @@ function test_managerSetPolicy(state, overwrittenMinInterval) {
ok(state, results[0].state, "State matches");
ok(overwrittenMinInterval, results[0].overwrittenMinInterval, "OverwrittenMinInterval matches");
runTests();
}, genericError);
}).catch(genericError);
}, genericError.bind(null, 'managerSetPolicy'));
}).catch(genericError.bind(null, 'managerSetPolicy_catch'));
}

View File

@ -109,8 +109,8 @@ class ResourceUriFileReader:
}
CODE_OPEN_CHANNEL_BY_URI = '''
var Cc = SpecialPowers.Cc;
var Ci = SpecialPowers.Ci;
var Cc = Components.classes;
var Ci = Components.interfaces;
var ios = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
var secMan = Cc["@mozilla.org/scriptsecuritymanager;1"].getService(Ci.nsIScriptSecurityManager);
global.uri = '%(uri)s';
@ -129,8 +129,8 @@ class ResourceUriFileReader:
'''
CODE_READ_CONTENT = '''
var Cc = SpecialPowers.Cc;
var Ci = SpecialPowers.Ci;
var Cc = Components.classes;
var Ci = Components.interfaces;
var zipReader = Cc["@mozilla.org/libjar/zip-reader;1"].createInstance(Ci.nsIZipReader);
var inputStream = Cc["@mozilla.org/scriptableinputstream;1"].createInstance(Ci.nsIScriptableInputStream);
@ -155,7 +155,9 @@ class ResourceUriFileReader:
return cls.URI_PREFIX + cls.URI_PATH[filename]
def __init__(self, marionette):
self.runjs = lambda x: marionette.execute_script(x, new_sandbox=False)
self.runjs = lambda x: marionette.execute_script(x,
new_sandbox=False,
sandbox='system')
def read_file(self, filename):
"""Read file and return the contents as string."""
@ -210,7 +212,9 @@ class JSHintEngine:
for line in config.splitlines()])
# Set global (JSHINT, options, global) in js environment.
self.runjs = lambda x: marionette.execute_script(x, new_sandbox=False)
self.runjs = lambda x: marionette.execute_script(x,
new_sandbox=False,
sandbox='system')
self.runjs(self.CODE_INIT_JSHINT %
{'script': script, 'config_string': repr(config)})

View File

@ -1461,7 +1461,7 @@ TelephonyService.prototype = {
}
// Store unique value in the list.
disconnectedCalls = [...Set(disconnectedCalls)];
disconnectedCalls = [...new Set(disconnectedCalls)];
let callsForStateChanged = [];

View File

@ -2,22 +2,21 @@
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
<!--
Test that "MozEnteredFullscreen" is dispatched to chrome on documents that enter fullscreen.
Test that "MozDOMFullscreen:*" events are dispatched to chrome on documents that use DOM fullscreen.
Test Description:
This chrome window has a browser. The browser's contentDocument (the "outer document")
in turn has an iframe (the "inner document").
We request fullscreen in the outer document, and check that MozEnteredDomFullscreen is
dispatched to chrome, targeted at the outer document.
We request fullscreen in the outer document, and check that MozDOMFullscreen:Entered and
MozDOMFullscreen:NewOrigin are dispatched to chrome, targeted at the outer document.
Then we request fullscreen in the inner document, and check that MozEnteredDomFullscreen
Then we request fullscreen in the inner document, and check that MozDOMFullscreen:NewOrigin
is dispatched to chrome, targeted at the inner document.
Then we cancel fullscreen in the inner document, and check that MozEnteredDomFullscreen is
dispatched again to chrome, targeted at the outer document. This still happens, since the
outer document's domain was never approved for fullscreen.
Then we cancel fullscreen in the inner document, and check that MozDOMFullscreen:NewOrigin is
dispatched again to chrome, targeted at the outer document.
-->
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" onload="start();">
@ -38,39 +37,55 @@ var gBrowser = null;
var gOuterDoc = null;
var gInnerDoc = null;
var gReceivedFullscreenEnteredEvent = false;
var gReceivedNewOriginEvent = false;
function firstEntry(event) {
is(event.target, gOuterDoc, "First MozEnteredDomFullscreen should be targeted at outer doc");
window.removeEventListener("MozEnteredDomFullscreen", firstEntry, false);
if (event.type == "MozDOMFullscreen:Entered") {
window.removeEventListener("MozDOMFullscreen:Entered", firstEntry, false);
ok(!gReceivedFullscreenEnteredEvent, "MozDOMFullscreen:Entered shouldn't have been triggered twice");
gReceivedFullscreenEnteredEvent = true;
} else if (event.type == "MozDOMFullscreen:NewOrigin") {
window.removeEventListener("MozDOMFullscreen:NewOrigin", firstEntry, false);
ok(!gReceivedNewOriginEvent, "MozDOMFullscreen:NewOrigin shouldn't have been triggered twice");
gReceivedNewOriginEvent = true;
} else {
ok(false, "Unknown event received");
}
is(event.target, gOuterDoc, "First " + event.type + " should be targeted at outer doc");
if (!gReceivedFullscreenEnteredEvent || !gReceivedNewOriginEvent) {
return;
}
ok(gOuterDoc.mozFullScreenElement != null, "Outer doc should be in fullscreen");
gInnerDoc = gOuterDoc.getElementById("innerFrame").contentDocument;
window.addEventListener("MozEnteredDomFullscreen", secondEntry, false);
window.addEventListener("MozDOMFullscreen:NewOrigin", secondEntry, false);
gInnerDoc.defaultView.focus();
gInnerDoc.body.mozRequestFullScreen();
}
function secondEntry(event) {
is(event.target, gInnerDoc, "Second MozEnteredDomFullscreen should be targeted at inner doc");
is(event.target, gInnerDoc, "Second MozDOMFullscreen:NewOrigin should be targeted at inner doc");
ok(gInnerDoc.mozFullScreenElement != null, "Inner doc should be in fullscreen");
window.removeEventListener("MozEnteredDomFullscreen", secondEntry, false);
window.addEventListener("MozEnteredDomFullscreen", thirdEntry, false);
window.removeEventListener("MozDOMFullscreen:NewOrigin", secondEntry, false);
window.addEventListener("MozDOMFullscreen:NewOrigin", thirdEntry, false);
gInnerDoc.mozCancelFullScreen();
}
function thirdEntry(event) {
is(event.target, gOuterDoc, "Third MozEnteredDomFullscreen should be targeted at outer doc");
is(event.target, gOuterDoc, "Third MozDOMFullscreen:NewOrigin should be targeted at outer doc");
ok(gOuterDoc.mozFullScreenElement != null, "Outer doc return to fullscreen after cancel fullscreen in inner doc");
window.removeEventListener("MozEnteredDomFullscreen", thirdEntry, false);
window.removeEventListener("MozExitedDomFullscreen", earlyExit, false);
window.addEventListener("MozExitedDomFullscreen", lastExit, false);
window.removeEventListener("MozDOMFullscreen:NewOrigin", thirdEntry, false);
window.removeEventListener("MozDOMFullscreen:Exited", earlyExit, false);
window.addEventListener("MozDOMFullscreen:Exited", lastExit, false);
gOuterDoc.mozCancelFullScreen();
}
function earlyExit(event) {
ok(false, "MozExitedDomFullscreen should only be triggered after cancel all fullscreen");
ok(false, "MozDOMFullscreen:Exited should only be triggered after cancel all fullscreen");
}
function lastExit(event) {
is(event.target, gOuterDoc, "MozExitedDomFullscreen should be targeted at the last exited doc");
is(event.target, gOuterDoc, "MozDOMFullscreen:Exited should be targeted at the last exited doc");
ok(gOuterDoc.mozFullScreenElement == null, "Fullscreen should have been fully exited");
window.opener.wrappedJSObject.done();
}
@ -81,15 +96,14 @@ function start() {
gBrowser = document.getElementById("browser");
gOuterDoc = gBrowser.contentDocument;
gBrowser.contentWindow.focus();
window.addEventListener("MozEnteredDomFullscreen", firstEntry, false);
window.addEventListener("MozExitedDomFullscreen", earlyExit, false);
window.addEventListener("MozDOMFullscreen:Entered", firstEntry, false);
window.addEventListener("MozDOMFullscreen:NewOrigin", firstEntry, false);
gOuterDoc.body.mozRequestFullScreen();
});
}
]]>
</script>
<!-- chrome://mochitests/content/chrome/dom/tests/mochitest/chrome/test_MozEnteredDomFullscreen_event.xul -->
<browser type="content" id="browser" width="400" height="400" src="http://mochi.test:8888/tests/dom/tests/mochitest/general/file_MozDomFullscreen.html"/>
<browser type="content" id="browser" width="400" height="400" src="file_MozDomFullscreen.html"/>
</window>

View File

@ -7,6 +7,7 @@ support-files =
MozDomFullscreen_chrome.xul
child_focus_frame.html
file_DOM_element_instanceof.xul
file_MozDomFullscreen.html
file_bug799299.xul
file_bug800817.xul
file_bug830858.xul

View File

@ -0,0 +1,8 @@
<html>
<head>
</head>
<body style="background-color: blue;">
<p>Outer doc</p>
<iframe id="innerFrame" src="http://mochi.test:8888/"></iframe>
</body>
</html>

View File

@ -1,8 +0,0 @@
<html>
<head>
</head>
<body style="background-color: blue;">
<p>Outer doc</p>
<iframe id="innerFrame" src="data:text/html,<html><body style='background-color: red;'><p>Inner doc</p></body></html>"></iframe>
</body>
</html>

View File

@ -1,7 +1,6 @@
[DEFAULT]
support-files =
497633.html
file_MozDomFullscreen.html
file_bug628069.html
file_clonewrapper.html
file_domWindowUtils_scrollbarSize.html

View File

@ -129,6 +129,21 @@ interface PopupBoxObject : BoxObject
boolean isContextMenu,
Event? triggerEvent);
/**
* Open the popup anchored at a specific screen rectangle. This function is
* similar to openPopup except that that rectangle of the anchor is supplied
* rather than an element. The anchor rectangle arguments are screen
* coordinates.
*/
void openPopupAtScreenRect(optional DOMString position = "",
long x,
long y,
long width,
long height,
boolean isContextMenu,
boolean attributesOverride,
Event? triggerEvent);
/**
* Returns the state of the popup:
* closed - the popup is closed

View File

@ -0,0 +1,22 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/.
*
* Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
* liability, trademark and document use rules apply.
*/
/*
* Used by principals and the script security manager to represent origin
* attributes.
*
* IMPORTANT: If you add any members here, you need to update the
* methods on mozilla::OriginAttributes, and bump the CIDs of all
* the principal implementations that use OriginAttributes in their
* nsISerializable implementations.
*/
dictionary OriginAttributesDictionary {
unsigned long appId = 0;
boolean inBrowser = false;
};

View File

@ -509,6 +509,7 @@ WEBIDL_FILES = [
'SVGViewElement.webidl',
'SVGZoomAndPan.webidl',
'SVGZoomEvent.webidl',
'SystemDictionaries.webidl',
'Telephony.webidl',
'TelephonyCall.webidl',
'TelephonyCallGroup.webidl',

View File

@ -217,9 +217,7 @@ XULDocument::~XULDocument()
mPersistenceIds.Clear();
// Destroy our broadcaster map.
if (mBroadcasterMap) {
PL_DHashTableDestroy(mBroadcasterMap);
}
delete mBroadcasterMap;
delete mTemplateBuilderTable;
@ -767,7 +765,7 @@ XULDocument::AddBroadcastListenerFor(Element& aBroadcaster, Element& aListener,
};
if (! mBroadcasterMap) {
mBroadcasterMap = PL_NewDHashTable(&gOps, sizeof(BroadcasterMapEntry));
mBroadcasterMap = new PLDHashTable2(&gOps, sizeof(BroadcasterMapEntry));
}
BroadcasterMapEntry* entry =

View File

@ -719,7 +719,7 @@ protected:
/**
* A map from a broadcaster element to a list of listener elements.
*/
PLDHashTable* mBroadcasterMap;
PLDHashTable2* mBroadcasterMap;
nsAutoPtr<nsInterfaceHashtable<nsURIHashKey,nsIObserver> > mOverlayLoadObservers;
nsAutoPtr<nsInterfaceHashtable<nsURIHashKey,nsIObserver> > mPendingOverlayLoadNotifications;

View File

@ -156,7 +156,7 @@ GetHostForPrincipal(nsIPrincipal* aPrincipal, nsACString& aHost)
}
// Some entries like "file://" uses the origin.
rv = aPrincipal->GetOrigin(aHost);
rv = aPrincipal->GetOriginNoSuffix(aHost);
if (NS_SUCCEEDED(rv) && !aHost.IsEmpty()) {
return NS_OK;
}

View File

@ -48,7 +48,7 @@ void qcms_transform_data_rgb_out_lut_sse1(qcms_transform *transform,
const __m128 scale = _mm_load_ps(floatScaleX4);
/* working variables */
__m128 vec_r, vec_g, vec_b, result;
__m128 vec_r, vec_g, vec_b, result, result_hi;
/* CYA */
if (!length)
@ -84,9 +84,11 @@ void qcms_transform_data_rgb_out_lut_sse1(qcms_transform *transform,
result = _mm_mul_ps(vec_r, scale);
/* store calc'd output tables indices */
/* Bug 1163740 temporary investigation:
* Write output[0] last, to keep |result| in a register in minidumps */
result_hi = _mm_movehl_ps(result, result);
*((__m64 *)&output[2]) = _mm_cvtps_pi32(result_hi);
*((__m64 *)&output[0]) = _mm_cvtps_pi32(result);
result = _mm_movehl_ps(result, result);
*((__m64 *)&output[2]) = _mm_cvtps_pi32(result) ;
/* load for next loop while store completes */
vec_r = _mm_load_ss(&igtbl_r[src[0]]);
@ -165,7 +167,7 @@ void qcms_transform_data_rgba_out_lut_sse1(qcms_transform *transform,
const __m128 scale = _mm_load_ps(floatScaleX4);
/* working variables */
__m128 vec_r, vec_g, vec_b, result;
__m128 vec_r, vec_g, vec_b, result, result_hi;
unsigned char alpha;
/* CYA */
@ -206,10 +208,11 @@ void qcms_transform_data_rgba_out_lut_sse1(qcms_transform *transform,
vec_r = _mm_min_ps(max, vec_r);
result = _mm_mul_ps(vec_r, scale);
/* store calc'd output tables indices */
/* Bug 1163740 temporary investigation:
* Write output[0] last, to keep |result| in a register in minidumps */
result_hi = _mm_movehl_ps(result, result);
*((__m64 *)&output[2]) = _mm_cvtps_pi32(result_hi);
*((__m64 *)&output[0]) = _mm_cvtps_pi32(result);
result = _mm_movehl_ps(result, result);
*((__m64 *)&output[2]) = _mm_cvtps_pi32(result);
/* load gamma values for next loop while store completes */
vec_r = _mm_load_ss(&igtbl_r[src[0]]);

View File

@ -4,39 +4,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsUnicodeRange.h"
#include "nsGkAtoms.h"
// This table depends on unicode range definitions.
// Each item's index must correspond unicode range value
// eg. x-cyrillic = LangGroupTable[kRangeCyrillic]
static nsIAtom **gUnicodeRangeToLangGroupAtomTable[] =
{
&nsGkAtoms::x_cyrillic,
&nsGkAtoms::el_,
&nsGkAtoms::he,
&nsGkAtoms::ar,
&nsGkAtoms::th,
&nsGkAtoms::ko,
&nsGkAtoms::Japanese,
&nsGkAtoms::zh_cn,
&nsGkAtoms::zh_tw,
&nsGkAtoms::x_devanagari,
&nsGkAtoms::x_tamil,
&nsGkAtoms::x_armn,
&nsGkAtoms::x_beng,
&nsGkAtoms::x_cans,
&nsGkAtoms::x_ethi,
&nsGkAtoms::x_geor,
&nsGkAtoms::x_gujr,
&nsGkAtoms::x_guru,
&nsGkAtoms::x_khmr,
&nsGkAtoms::x_mlym,
&nsGkAtoms::x_orya,
&nsGkAtoms::x_telu,
&nsGkAtoms::x_knda,
&nsGkAtoms::x_sinh,
&nsGkAtoms::x_tibt
};
/**********************************************************************
* Unicode subranges as defined in unicode 3.0
@ -450,12 +417,3 @@ uint32_t FindCharUnicodeRange(uint32_t ch)
// Yet another table to look at : U+0700 - U+16FF : 128 code point blocks
return gUnicodeTertiaryRangeTable[(ch - 0x0700) >> 7];
}
nsIAtom *LangGroupFromUnicodeRange(uint8_t unicodeRange)
{
if (kRangeSpecificItemNum > unicodeRange) {
nsIAtom **atom = gUnicodeRangeToLangGroupAtomTable[unicodeRange];
return *atom;
}
return nullptr;
}

View File

@ -8,8 +8,6 @@
#include <stdint.h>
class nsIAtom;
// The following constants define unicode subranges
// values below kRangeNum must be continuous so that we can map to
// lang group directly.
@ -89,6 +87,5 @@ const uint8_t kRangeTertiaryTable = 145; // leave room for 16 subtable
uint32_t FindCharUnicodeRange(uint32_t ch);
nsIAtom* LangGroupFromUnicodeRange(uint8_t unicodeRange);
#endif

View File

@ -337,7 +337,17 @@ DecodePool::DecodePool()
int32_t prefLimit = gfxPrefs::ImageMTDecodingLimit();
uint32_t limit;
if (prefLimit <= 0) {
limit = max(PR_GetNumberOfProcessors(), 2) - 1;
int32_t numCores = PR_GetNumberOfProcessors();
if (numCores <= 1) {
limit = 1;
} else if (numCores == 2) {
// On an otherwise mostly idle system, having two image decoding threads
// doubles decoding performance, so it's worth doing on dual-core devices,
// even if under load we can't actually get that level of parallelism.
limit = 2;
} else {
limit = numCores - 1;
}
} else {
limit = static_cast<uint32_t>(prefLimit);
}

View File

@ -17,37 +17,67 @@ using namespace dom;
namespace image {
bool
URISchemeIs(ImageURL* aURI, const char* aScheme)
{
bool schemeMatches = false;
if (NS_WARN_IF(NS_FAILED(aURI->SchemeIs(aScheme, &schemeMatches)))) {
return false;
}
return schemeMatches;
}
static Maybe<uint64_t>
BlobSerial(ImageURL* aURI)
{
nsAutoCString spec;
aURI->GetSpec(spec);
nsRefPtr<BlobImpl> blob;
if (NS_SUCCEEDED(NS_GetBlobForBlobURISpec(spec, getter_AddRefs(blob))) &&
blob) {
return Some(blob->GetSerialNumber());
}
return Nothing();
}
ImageCacheKey::ImageCacheKey(nsIURI* aURI)
: mURI(new ImageURL(aURI))
, mIsChrome(URISchemeIs(mURI, "chrome"))
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mURI);
bool isChrome;
mIsChrome = NS_SUCCEEDED(aURI->SchemeIs("chrome", &isChrome)) && isChrome;
if (URISchemeIs(mURI, "blob")) {
mBlobSerial = BlobSerial(mURI);
}
mHash = ComputeHash(mURI);
mHash = ComputeHash(mURI, mBlobSerial);
}
ImageCacheKey::ImageCacheKey(ImageURL* aURI)
: mURI(aURI)
, mIsChrome(URISchemeIs(mURI, "chrome"))
{
MOZ_ASSERT(mURI);
MOZ_ASSERT(aURI);
bool isChrome;
mIsChrome = NS_SUCCEEDED(aURI->SchemeIs("chrome", &isChrome)) && isChrome;
if (URISchemeIs(mURI, "blob")) {
mBlobSerial = BlobSerial(mURI);
}
mHash = ComputeHash(mURI);
mHash = ComputeHash(mURI, mBlobSerial);
}
ImageCacheKey::ImageCacheKey(const ImageCacheKey& aOther)
: mURI(aOther.mURI)
, mBlobSerial(aOther.mBlobSerial)
, mHash(aOther.mHash)
, mIsChrome(aOther.mIsChrome)
{ }
ImageCacheKey::ImageCacheKey(ImageCacheKey&& aOther)
: mURI(Move(aOther.mURI))
, mBlobSerial(Move(aOther.mBlobSerial))
, mHash(aOther.mHash)
, mIsChrome(aOther.mIsChrome)
{ }
@ -55,6 +85,12 @@ ImageCacheKey::ImageCacheKey(ImageCacheKey&& aOther)
bool
ImageCacheKey::operator==(const ImageCacheKey& aOther) const
{
if (mBlobSerial || aOther.mBlobSerial) {
// If at least one of us has a blob serial, just compare those.
return mBlobSerial == aOther.mBlobSerial;
}
// For non-blob URIs, compare the URIs.
return *mURI == *aOther.mURI;
}
@ -65,10 +101,19 @@ ImageCacheKey::Spec() const
}
/* static */ uint32_t
ImageCacheKey::ComputeHash(ImageURL* aURI)
ImageCacheKey::ComputeHash(ImageURL* aURI,
const Maybe<uint64_t>& aBlobSerial)
{
// Since we frequently call Hash() several times in a row on the same
// ImageCacheKey, as an optimization we compute our hash once and store it.
if (aBlobSerial) {
// For blob URIs, we hash the serial number of the underlying blob, so that
// different blob URIs which point to the same blob share a cache entry.
return HashGeneric(*aBlobSerial);
}
// For non-blob URIs, we hash the URI spec.
nsAutoCString spec;
aURI->GetSpec(spec);
return HashString(spec);

View File

@ -10,6 +10,8 @@
#ifndef mozilla_image_src_ImageCacheKey_h
#define mozilla_image_src_ImageCacheKey_h
#include "mozilla/Maybe.h"
class nsIURI;
namespace mozilla {
@ -42,9 +44,11 @@ public:
bool IsChrome() const { return mIsChrome; }
private:
static uint32_t ComputeHash(ImageURL* aURI);
static uint32_t ComputeHash(ImageURL* aURI,
const Maybe<uint64_t>& aBlobSerial);
nsRefPtr<ImageURL> mURI;
Maybe<uint64_t> mBlobSerial;
uint32_t mHash;
bool mIsChrome;
};

View File

@ -4858,41 +4858,15 @@ BytecodeEmitter::emitIf(ParseNode* pn)
}
/*
* pnLet represents one of:
* pnLet represents a let-statement: let (x = y) { ... }
*
* let-expression: (let (x = y) EXPR)
* let-statement: let (x = y) { ... }
*
* For a let-expression 'let (x = a, [y,z] = b) e', EmitLet produces:
*
* bytecode stackDepth srcnotes
* evaluate a +1
* evaluate b +1
* dup +1
* destructure y
* pick 1
* dup +1
* destructure z
* pick 1
* pop -1
* setlocal 2 -1
* setlocal 1 -1
* setlocal 0 -1
* pushblockscope (if needed)
* evaluate e +1
* debugleaveblock
* popblockscope (if needed)
*
* Note that, since pushblockscope simply changes fp->scopeChain and does not
* otherwise touch the stack, evaluation of the let-var initializers must leave
* the initial value in the let-var's future slot.
*/
/*
* Using MOZ_NEVER_INLINE in here is a workaround for llvm.org/pr14047. See
* the comment on emitSwitch.
*/
MOZ_NEVER_INLINE bool
BytecodeEmitter::emitLet(ParseNode* pnLet)
BytecodeEmitter::emitLetBlock(ParseNode* pnLet)
{
MOZ_ASSERT(pnLet->isArity(PN_BINARY));
ParseNode* varList = pnLet->pn_left;
@ -6722,9 +6696,8 @@ BytecodeEmitter::emitConditionalExpression(ConditionalExpression& conditional)
* ignore the value pushed by the first branch. Execution will follow
* only one path, so we must decrement this->stackDepth.
*
* Failing to do this will foil code, such as let expression and block
* code generation, which must use the stack depth to compute local
* stack indexes correctly.
* Failing to do this will foil code, such as let block code generation,
* which must use the stack depth to compute local stack indexes correctly.
*/
MOZ_ASSERT(stackDepth > 0);
stackDepth--;
@ -7542,8 +7515,7 @@ BytecodeEmitter::emitTree(ParseNode* pn)
break;
case PNK_LETBLOCK:
case PNK_LETEXPR:
ok = emitLet(pn);
ok = emitLetBlock(pn);
break;
case PNK_CONST:

View File

@ -490,7 +490,7 @@ struct BytecodeEmitter
bool emitWith(ParseNode* pn);
MOZ_NEVER_INLINE bool emitLabeledStatement(const LabeledStatement* pn);
MOZ_NEVER_INLINE bool emitLet(ParseNode* pnLet);
MOZ_NEVER_INLINE bool emitLetBlock(ParseNode* pnLet);
MOZ_NEVER_INLINE bool emitLexicalScope(ParseNode* pn);
MOZ_NEVER_INLINE bool emitSwitch(ParseNode* pn);
MOZ_NEVER_INLINE bool emitTry(ParseNode* pn);

View File

@ -402,7 +402,6 @@ ContainsHoistedDeclaration(ExclusiveContext* cx, ParseNode* node, bool* result)
case PNK_FALSE:
case PNK_NULL:
case PNK_THIS:
case PNK_LETEXPR:
case PNK_ELISION:
case PNK_NUMBER:
case PNK_NEW:

View File

@ -591,14 +591,6 @@ class FullParseHandler
block->pn_expr = body;
}
ParseNode* newLetExpression(ParseNode* vars, ParseNode* block, const TokenPos& pos) {
ParseNode* letExpr = newBinary(PNK_LETEXPR, vars, block);
if (!letExpr)
return nullptr;
letExpr->pn_pos = pos;
return letExpr;
}
ParseNode* newLetBlock(ParseNode* vars, ParseNode* block, const TokenPos& pos) {
ParseNode* letBlock = newBinary(PNK_LETBLOCK, vars, block);
if (!letBlock)

View File

@ -424,7 +424,6 @@ class NameResolver
case PNK_DIVASSIGN:
case PNK_MODASSIGN:
case PNK_ELEM:
case PNK_LETEXPR:
case PNK_COLON:
case PNK_CASE:
case PNK_SHORTHAND:

View File

@ -266,7 +266,6 @@ PushNodeChildren(ParseNode* pn, NodeStack* stack)
case PNK_MODASSIGN:
// ...and a few others.
case PNK_ELEM:
case PNK_LETEXPR:
case PNK_IMPORT_SPEC:
case PNK_EXPORT_SPEC:
case PNK_COLON:

View File

@ -133,7 +133,6 @@ class UpvarCookie
F(LEXICALSCOPE) \
F(LET) \
F(LETBLOCK) \
F(LETEXPR) \
F(IMPORT) \
F(IMPORT_SPEC_LIST) \
F(IMPORT_SPEC) \

View File

@ -2989,8 +2989,8 @@ Parser<ParseHandler>::reportRedeclaration(Node pn, Definition::Kind redeclKind,
}
/*
* Define a lexical binding in a block, let-expression, or comprehension scope. pc
* must already be in such a scope.
* Define a lexical binding in a block, or comprehension scope. pc must
* already be in such a scope.
*
* Throw a SyntaxError if 'atom' is an invalid name. Otherwise create a
* property for the new variable on the block object, pc->staticScope;
@ -3680,14 +3680,13 @@ Parser<SyntaxParseHandler>::pushLetScope(HandleStaticBlockObject blockObj, StmtI
}
/*
* Parse a let block statement or let expression (determined by 'letContext').
* Parse a let block statement.
* In both cases, bindings are not hoisted to the top of the enclosing block
* and thus must be carefully injected between variables() and the let body.
*/
template <typename ParseHandler>
typename ParseHandler::Node
Parser<ParseHandler>::deprecatedLetBlockOrExpression(YieldHandling yieldHandling,
LetContext letContext)
Parser<ParseHandler>::deprecatedLetBlock(YieldHandling yieldHandling)
{
MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_LET));
@ -3710,82 +3709,22 @@ Parser<ParseHandler>::deprecatedLetBlockOrExpression(YieldHandling yieldHandling
if (!block)
return null();
bool needExprStmt = false;
if (letContext == LetStatement) {
bool matched;
if (!tokenStream.matchToken(&matched, TOK_LC, TokenStream::Operand))
return null();
if (!matched) {
/*
* Strict mode eliminates a grammar ambiguity with unparenthesized
* LetExpressions in an ExpressionStatement. If followed immediately
* by an arguments list, it's ambiguous whether the let expression
* is the callee or the call is inside the let expression body.
*
* function id(x) { return x; }
* var x = "outer";
* // Does this parse as
* // (let (loc = "inner") id)(loc) // "outer"
* // or as
* // let (loc = "inner") (id(loc)) // "inner"
* let (loc = "inner") id(loc);
*
* See bug 569464.
*/
if (!reportWithOffset(ParseStrictError, pc->sc->strict(), begin,
JSMSG_STRICT_CODE_LET_EXPR_STMT))
{
return null();
}
MUST_MATCH_TOKEN(TOK_LC, JSMSG_CURLY_BEFORE_LET);
/*
* If this is really an expression in let statement guise, then we
* need to wrap the PNK_LETEXPR node in a PNK_SEMI node so that we
* pop the return value of the expression.
*/
needExprStmt = true;
letContext = LetExpression;
}
}
Node expr = statements(yieldHandling);
if (!expr)
return null();
MUST_MATCH_TOKEN(TOK_RC, JSMSG_CURLY_AFTER_LET);
Node expr;
if (letContext == LetStatement) {
expr = statements(yieldHandling);
if (!expr)
return null();
MUST_MATCH_TOKEN(TOK_RC, JSMSG_CURLY_AFTER_LET);
addTelemetry(JSCompartment::DeprecatedLetBlock);
if (!report(ParseWarning, pc->sc->strict(), expr, JSMSG_DEPRECATED_LET_BLOCK))
return null();
addTelemetry(JSCompartment::DeprecatedLetBlock);
if (!report(ParseWarning, pc->sc->strict(), expr, JSMSG_DEPRECATED_LET_BLOCK))
return null();
} else {
MOZ_ASSERT(letContext == LetExpression);
expr = assignExpr(InAllowed, yieldHandling);
if (!expr)
return null();
addTelemetry(JSCompartment::DeprecatedLetExpression);
if (!report(ParseWarning, pc->sc->strict(), expr, JSMSG_DEPRECATED_LET_EXPRESSION))
return null();
}
handler.setLexicalScopeBody(block, expr);
PopStatementPC(tokenStream, pc);
TokenPos letPos(begin, pos().end);
if (letContext == LetExpression) {
if (needExprStmt) {
if (!MatchOrInsertSemicolon(tokenStream))
return null();
}
Node letExpr = handler.newLetExpression(vars, block, letPos);
if (!letExpr)
return null();
return needExprStmt ? handler.newExprStatement(letExpr, pos().end) : letExpr;
}
return handler.newLetBlock(vars, block, letPos);
}
@ -4242,24 +4181,17 @@ Parser<FullParseHandler>::letDeclarationOrBlock(YieldHandling yieldHandling)
{
handler.disableSyntaxParser();
/* Check for a let statement or let expression. */
/* Check for a let statement. */
TokenKind tt;
if (!tokenStream.peekToken(&tt))
return null();
if (tt == TOK_LP) {
ParseNode* node =
deprecatedLetBlockOrExpression(yieldHandling, LetStatement);
ParseNode* node = deprecatedLetBlock(yieldHandling);
if (!node)
return nullptr;
if (node->isKind(PNK_LETBLOCK)) {
MOZ_ASSERT(node->isArity(PN_BINARY));
} else {
MOZ_ASSERT(node->isKind(PNK_SEMI));
MOZ_ASSERT(node->pn_kid->isKind(PNK_LETEXPR));
MOZ_ASSERT(node->pn_kid->isArity(PN_BINARY));
}
MOZ_ASSERT(node->isKind(PNK_LETBLOCK));
MOZ_ASSERT(node->isArity(PN_BINARY));
return node;
}
@ -4750,8 +4682,7 @@ Parser<FullParseHandler>::forStatement(YieldHandling yieldHandling)
MUST_MATCH_TOKEN(TOK_LP, JSMSG_PAREN_AFTER_FOR);
/*
* True if we have 'for (var/let/const ...)', except in the oddball case
* where 'let' begins a let-expression in 'for (let (...) ...)'.
* True if we have 'for (var/let/const ...)'.
*/
bool isForDecl = false;
@ -4790,19 +4721,13 @@ Parser<FullParseHandler>::forStatement(YieldHandling yieldHandling)
handler.disableSyntaxParser();
bool constDecl = tt == TOK_CONST;
tokenStream.consumeKnownToken(tt);
if (!tokenStream.peekToken(&tt))
isForDecl = true;
blockObj = StaticBlockObject::create(context);
if (!blockObj)
return null();
if (tt == TOK_LP) {
pn1 = deprecatedLetBlockOrExpression(yieldHandling, LetExpression);
} else {
isForDecl = true;
blockObj = StaticBlockObject::create(context);
if (!blockObj)
return null();
pn1 = variables(yieldHandling,
constDecl ? PNK_CONST : PNK_LET, nullptr, blockObj,
DontHoistVars);
}
pn1 = variables(yieldHandling,
constDecl ? PNK_CONST : PNK_LET, nullptr, blockObj,
DontHoistVars);
} else {
pn1 = expr(InProhibited, yieldHandling);
}
@ -7053,9 +6978,7 @@ LegacyCompExprTransplanter::transplant(ParseNode* pn)
// The one remaining thing to patch up is the block scope depth. We need to
// compute the maximum block scope depth of a function, so we know how much
// space to reserve in the fixed part of a stack frame. Normally this is done
// whenever we leave a statement, via AccumulateBlockScopeDepth. However if the
// head has a let expression, we need to re-assign that depth to the tail of the
// comprehension.
// whenever we leave a statement, via AccumulateBlockScopeDepth.
//
// Thing is, we don't actually know what that depth is, because the only
// information we keep is the maximum nested depth within a statement, so we
@ -7128,10 +7051,9 @@ Parser<FullParseHandler>::legacyComprehensionTail(ParseNode* bodyExpr, unsigned
* the comprehension's block scope. We allocate that id or one above it
* here, by calling PushLexicalScope.
*
* In the case of a comprehension expression that has nested blocks
* (e.g., let expressions), we will allocate a higher blockid but then
* slide all blocks "to the right" to make room for the comprehension's
* block scope.
* In the case of a comprehension expression that has nested blocks,
* we will allocate a higher blockid but then slide all blocks "to the
* right" to make room for the comprehension's block scope.
*/
adjust = pc->blockid();
pn = pushLexicalScope(&stmtInfo);
@ -8219,9 +8141,10 @@ Parser<ParseHandler>::arrayInitializer(YieldHandling yieldHandling)
*
* [i * j for (i in o) for (j in p) if (i != j)]
*
* translates to roughly the following let expression:
* translates to roughly the following code:
*
* let (array = new Array, i, j) {
* {
* let array = new Array, i, j;
* for (i in o) let {
* for (j in p)
* if (i != j)
@ -8651,9 +8574,6 @@ Parser<ParseHandler>::primaryExpr(YieldHandling yieldHandling, TokenKind tt,
case TOK_LC:
return propertyList(yieldHandling, ObjectLiteral);
case TOK_LET:
return deprecatedLetBlockOrExpression(yieldHandling, LetExpression);
case TOK_LP: {
TokenKind next;
if (!tokenStream.peekToken(&next, TokenStream::Operand))

View File

@ -326,7 +326,6 @@ struct BindData;
class CompExprTransplanter;
enum LetContext { LetExpression, LetStatement };
enum VarContext { HoistVars, DontHoistVars };
enum PropListType { ObjectLiteral, ClassBody };
@ -629,7 +628,7 @@ class Parser : private JS::AutoGCRooter, public StrictModeGetter
Node generatorComprehension(uint32_t begin);
bool argumentList(YieldHandling yieldHandling, Node listNode, bool* isSpread);
Node deprecatedLetBlockOrExpression(YieldHandling yieldHandling, LetContext letContext);
Node deprecatedLetBlock(YieldHandling yieldHandling);
Node destructuringExpr(YieldHandling yieldHandling, BindData<ParseHandler>* data,
TokenKind tt);
Node destructuringExprWithoutYield(YieldHandling yieldHandling, BindData<ParseHandler>* data,

View File

@ -258,10 +258,6 @@ class SyntaxParseHandler
Node newLexicalScope(ObjectBox* blockbox) { return NodeGeneric; }
void setLexicalScopeBody(Node block, Node body) {}
Node newLetExpression(Node vars, Node block, const TokenPos& pos) {
return NodeGeneric;
}
Node newLetBlock(Node vars, Node block, const TokenPos& pos) {
return NodeGeneric;
}

View File

@ -1,9 +0,0 @@
// Binary: cache/js-dbg-64-0ba03471b3b0-linux
// Flags:
//
uneval(new Function("\
for(\
((let (functional) x) for each ([] in [])); \
yield x; \
(let (x = true) x));\
"))

View File

@ -1,15 +0,0 @@
// |jit-test| error:ReferenceError
// Binary: cache/js-dbg-32-525d852c622d-linux
// Flags: -j
//
(function() {
let(x)
(function() {
for (let a in [0, x, 0, 0])
(function() {
for (let y in [0, 0]) print
})();
})()
with({}) throw x;
})()

View File

@ -1,18 +0,0 @@
// Binary: cache/js-dbg-32-15c46082297d-linux
// Flags: -j
//
(function() {
(eval("\
(function() {\
let(e)((function() { ((function f(a) {\
if (a < 1) {\
return 1\
}\
x = arguments;\
return f(a - 1) + f(a - 2)\
})(6))\
})())\
})\
"))()
})()
gc()

View File

@ -1,9 +0,0 @@
// Binary: cache/js-dbg-64-7f7dfb33a33e-linux
// Flags:
//
x = Proxy.create((function () {}), (evalcx('')))
try {
(function () {
((let(e = eval) e).call(x, ("\"\"")))
})()
} catch (e) {}

Some files were not shown because too many files have changed in this diff Show More