Merge m-c to b2g-inbound. a=merge

--HG--
rename : dom/telephony/gonk/TelephonyProvider.js => dom/telephony/gonk/TelephonyService.js
This commit is contained in:
Ryan VanderMeulen 2014-06-03 15:22:54 -04:00
commit 8d0739d241
133 changed files with 4259 additions and 1266 deletions

View File

@ -813,7 +813,7 @@ bin/components/@DLL_PREFIX@nkgnomevfs@DLL_SUFFIX@
#endif
@BINPATH@/components/DataStore.manifest
@BINPATH@/components/DataStoreService.js
@BINPATH@/components/DataStoreImpl.js
@BINPATH@/components/dom_datastore.xpt
#ifdef MOZ_WEBSPEECH

View File

@ -85,7 +85,13 @@ add_task(function*() {
ok(otherTB.querySelector("#sync-button"), "Sync button is on other toolbar, too.");
let wasInformedCorrectlyOfAreaDisappearing = false;
let windowClosed = null;
//XXXgijs So we could be using promiseWindowClosed here. However, after
// repeated random oranges, I'm instead relying on onWindowClosed below to
// fire appropriately - it is linked to an unload event as well, and so
// reusing it prevents a potential race between unload handlers where the
// one from promiseWindowClosed could fire before the onWindowClosed
// (and therefore onAreaNodeRegistered) one, causing the test to fail.
let windowCloseDeferred = Promise.defer();
listener = {
onAreaNodeUnregistered: function(aArea, aNode, aReason) {
if (aArea == TOOLBARID) {
@ -96,8 +102,7 @@ add_task(function*() {
},
onWindowClosed: function(aWindow) {
if (aWindow == otherWin) {
info("Got window closed notification for correct window.");
windowClosed = aWindow;
windowCloseDeferred.resolve(aWindow);
} else {
info("Other window was closed!");
info("Other window title: " + (aWindow.document && aWindow.document.title));
@ -106,7 +111,8 @@ add_task(function*() {
},
};
CustomizableUI.addListener(listener);
yield promiseWindowClosed(otherWin);
otherWin.close();
let windowClosed = yield windowCloseDeferred.promise;
is(windowClosed, otherWin, "Window should have sent onWindowClosed notification.");
ok(wasInformedCorrectlyOfAreaDisappearing, "Should be told about window closing.");

View File

@ -249,8 +249,13 @@ function openAndLoadWindow(aOptions, aWaitForDelayedStartup=false) {
}
function promiseWindowClosed(win) {
let deferred = Promise.defer();
win.addEventListener("unload", function onunload() {
win.removeEventListener("unload", onunload);
deferred.resolve();
});
win.close();
return waitForCondition(() => win.closed);
return deferred.promise;
}
function promisePanelShown(win) {

View File

@ -203,6 +203,11 @@ var gPermissionManager = {
{
if (aTopic == "perm-changed") {
var permission = aSubject.QueryInterface(Components.interfaces.nsIPermission);
// Ignore unrelated permission types.
if (permission.type != this._type)
return;
if (aData == "added") {
this._addPermissionToList(permission);
++this._view._rowCount;

View File

@ -8,6 +8,7 @@ const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
this.EXPORTED_SYMBOLS = [ "BingTranslation" ];
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/Log.jsm");
Cu.import("resource://gre/modules/Promise.jsm");
Cu.import("resource://gre/modules/Task.jsm");
@ -327,14 +328,16 @@ let BingTokenManager = {
let params = [
"grant_type=client_credentials",
"scope=" + encodeURIComponent("http://api.microsofttranslator.com"),
"client_id=",
"client_secret="
"client_id=" +
getAuthTokenParam("%BING_API_CLIENTID%", "browser.translation.bing.clientIdOverride"),
"client_secret=" +
getAuthTokenParam("%BING_API_KEY%", "browser.translation.bing.apiKeyOverride")
];
let deferred = Promise.defer();
this._pendingRequest = deferred.promise;
request.post(params.join("&"), function(err) {
this._pendingRequest = null;
BingTokenManager._pendingRequest = null;
if (err) {
deferred.reject(err);
@ -367,3 +370,16 @@ function escapeXML(aStr) {
.replace("<", "&lt;", "g")
.replace(">", "&gt;", "g");
}
/**
* Fetch an auth token (clientID or client secret), which may be overridden by
* a pref if it's set.
*/
function getAuthTokenParam(key, prefName) {
let val;
try {
val = Services.prefs.getCharPref(prefName);
} catch(ex) {}
return encodeURIComponent(Services.urlFormatter.formatURL(val || key));
}

View File

@ -42,10 +42,10 @@
</xul:hbox>
<!-- translating -->
<xul:hbox class="translating-box" pack="center">
<xul:vbox class="translating-box" pack="center">
<xul:label class="translate-infobar-element"
value="&translation.translatingContent.label;"/>
</xul:hbox>
</xul:vbox>
<!-- translated -->
<xul:hbox class="translated-box" align="center">
@ -58,11 +58,13 @@
</xul:menulist>
<xul:label class="translate-infobar-element"
value="&translation.translatedTo.label;"/>
<xul:menulist anonid="toLanguage"
<xul:menulist class="translate-infobar-element"
anonid="toLanguage"
oncommand="document.getBindingParent(this).translate()">
<xul:menupopup/>
</xul:menulist>
<xul:label value="&translation.translatedToSuffix.label;"/>
<xul:label class="translate-infobar-element"
value="&translation.translatedToSuffix.label;"/>
<xul:button anonid="showOriginal"
class="translate-infobar-element"
label="&translation.showOriginal.button;"

View File

@ -113,6 +113,8 @@ skip-if = os == 'win' # bug 1005274
[browser_dbg_break-on-dom-06.js]
[browser_dbg_break-on-dom-07.js]
[browser_dbg_break-on-dom-08.js]
[browser_dbg_break-on-dom-event.js]
skip-if = os == "mac" || e10s # Bug 895426
[browser_dbg_breakpoints-actual-location.js]
[browser_dbg_breakpoints-break-on-last-line-of-script-on-reload.js]
[browser_dbg_breakpoints-button-01.js]
@ -124,6 +126,7 @@ skip-if = os == 'win' # bug 1005274
[browser_dbg_breakpoints-highlight.js]
[browser_dbg_breakpoints-new-script.js]
[browser_dbg_breakpoints-pane.js]
[browser_dbg_chrome-create.js]
[browser_dbg_chrome-debugging.js]
[browser_dbg_clean-exit-window.js]
skip-if = true # Bug 933950 (leaky test)
@ -165,6 +168,8 @@ skip-if = true # Bug 933950 (leaky test)
[browser_dbg_navigation.js]
[browser_dbg_no-page-sources.js]
[browser_dbg_on-pause-highlight.js]
[browser_dbg_on-pause-raise.js]
skip-if = os == "linux" || e10s # Bug 888811 & bug 891176
[browser_dbg_optimized-out-vars.js]
[browser_dbg_panel-size.js]
[browser_dbg_parser-01.js]
@ -298,9 +303,3 @@ skip-if = (os == 'mac' || os == 'win') && (debug == false) # Bug 986166
[browser_dbg_variables-view-webidl.js]
[browser_dbg_watch-expressions-01.js]
[browser_dbg_watch-expressions-02.js]
[browser_dbg_chrome-create.js]
skip-if = true # Test doesn't clean up after itself (bug 918507), but also bug 847558 on Linux
[browser_dbg_on-pause-raise.js]
skip-if = os == "linux" || e10s # Bug 888811 & bug 891176
[browser_dbg_break-on-dom-event.js]
skip-if = os == "mac" || e10s # Bug 895426

View File

@ -51,7 +51,10 @@ registerCleanupFunction(function() {
// Import the GCLI test helper
let testDir = gTestPath.substr(0, gTestPath.lastIndexOf("/"));
Services.scriptloader.loadSubScript(testDir + "../../../commandline/test/helpers.js", this);
testDir = testDir.replace(/\/\//g, '/');
testDir = testDir.replace("chrome:/mochitest", "chrome://mochitest");
let helpersjs = testDir + "/../../commandline/test/helpers.js";
Services.scriptloader.loadSubScript(helpersjs, this);
// Redeclare dbg_assert with a fatal behavior.
function dbg_assert(cond, e) {

View File

@ -857,7 +857,7 @@ bin/libfreebl_32int64_3.so
#endif
@BINPATH@/components/DataStore.manifest
@BINPATH@/components/DataStoreService.js
@BINPATH@/components/DataStoreImpl.js
@BINPATH@/components/dom_datastore.xpt

View File

@ -11,16 +11,16 @@
<!ENTITY color "Text and Background">
<!ENTITY textColor.label "Text:">
<!ENTITY textColor.accesskey "t">
<!ENTITY textColor.accesskey "T">
<!ENTITY backgroundColor.label "Background:">
<!ENTITY backgroundColor.accesskey "b">
<!ENTITY backgroundColor.accesskey "B">
<!ENTITY useSystemColors.label "Use system colors">
<!ENTITY useSystemColors.accesskey "s">
<!ENTITY underlineLinks.label "Underline links">
<!ENTITY underlineLinks.accesskey "u">
<!ENTITY underlineLinks.accesskey "U">
<!ENTITY links "Link Colors">
<!ENTITY linkColor.label "Unvisited Links:">
<!ENTITY linkColor.accesskey "l">
<!ENTITY linkColor.accesskey "L">
<!ENTITY visitedLinkColor.label "Visited Links:">
<!ENTITY visitedLinkColor.accesskey "v">
<!ENTITY visitedLinkColor.accesskey "V">

View File

@ -250,7 +250,7 @@ browser.jar:
skin/classic/browser/devtools/itemArrow-rtl.svg (../shared/devtools/images/itemArrow-rtl.svg)
skin/classic/browser/devtools/itemArrow-ltr.svg (../shared/devtools/images/itemArrow-ltr.svg)
skin/classic/browser/devtools/noise.png (../shared/devtools/images/noise.png)
skin/classic/browser/devtools/dropmarker.png (../shared/devtools/images/dropmarker.png)
skin/classic/browser/devtools/dropmarker.svg (../shared/devtools/images/dropmarker.svg)
skin/classic/browser/devtools/layoutview.css (../shared/devtools/layoutview.css)
skin/classic/browser/devtools/debugger-collapse.png (../shared/devtools/images/debugger-collapse.png)
skin/classic/browser/devtools/debugger-collapse@2x.png (../shared/devtools/images/debugger-collapse@2x.png)

View File

@ -368,7 +368,7 @@ browser.jar:
skin/classic/browser/devtools/itemArrow-rtl.svg (../shared/devtools/images/itemArrow-rtl.svg)
skin/classic/browser/devtools/itemArrow-ltr.svg (../shared/devtools/images/itemArrow-ltr.svg)
skin/classic/browser/devtools/noise.png (../shared/devtools/images/noise.png)
skin/classic/browser/devtools/dropmarker.png (../shared/devtools/images/dropmarker.png)
skin/classic/browser/devtools/dropmarker.svg (../shared/devtools/images/dropmarker.svg)
skin/classic/browser/devtools/layoutview.css (../shared/devtools/layoutview.css)
skin/classic/browser/devtools/debugger-collapse.png (../shared/devtools/images/debugger-collapse.png)
skin/classic/browser/devtools/debugger-collapse@2x.png (../shared/devtools/images/debugger-collapse@2x.png)

View File

@ -153,6 +153,11 @@
/* Debugging pane controls */
#debugging-controls .devtools-toolbarbutton > .toolbarbutton-icon {
width: 16px;
height: 16px;
}
#resume {
list-style-image: url(debugger-play.png);
-moz-image-region: rect(0px,32px,16px,16px);
@ -170,6 +175,25 @@
list-style-image: url(debugger-step-out.png);
}
@media (min-resolution: 2dppx) {
#resume {
list-style-image: url(debugger-play@2x.png);
-moz-image-region: rect(0px,64px,32px,32px);
}
#step-over {
list-style-image: url(debugger-step-over@2x.png);
}
#step-in {
list-style-image: url(debugger-step-in@2x.png);
}
#step-out {
list-style-image: url(debugger-step-out@2x.png);
}
}
#debugging-controls > toolbarbutton {
transition: opacity 0.15s ease-in-out;
}
@ -256,6 +280,12 @@
background-size: 12px;
}
@media (min-resolution: 2dppx) {
.selected .call-item-gutter {
background-image: url("editor-debug-location@2x.png");
}
}
.theme-dark .call-item-gutter {
background-color: #181d20;
color: #5f7387;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 218 B

View File

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="8" height="4" viewBox="0 0 8 4" enable-background="new 0 0 8 4">
<polygon points="0,0 4,4 8,0" fill="#B6BABF" />
</svg>

After

Width:  |  Height:  |  Size: 213 B

View File

@ -96,7 +96,7 @@
-moz-appearance: none;
display: -moz-box;
background-color: transparent;
list-style-image: url("chrome://browser/skin/devtools/dropmarker.png");
list-style-image: url("chrome://browser/skin/devtools/dropmarker.svg");
-moz-box-align: center;
border-width: 0;
min-width: 16px;
@ -122,7 +122,7 @@
.devtools-responsiveui-toolbarbutton[type=menu] > .toolbarbutton-menu-dropmarker,
.devtools-responsiveui-toolbarbutton[type=menu-button] > .toolbarbutton-menubutton-dropmarker {
-moz-appearance: none !important;
list-style-image: url("chrome://browser/skin/devtools/dropmarker.png");
list-style-image: url("chrome://browser/skin/devtools/dropmarker.svg");
-moz-box-align: center;
padding: 0 3px;
}

View File

@ -136,7 +136,7 @@
.devtools-menulist > .menulist-dropmarker {
-moz-appearance: none;
display: -moz-box;
list-style-image: url("chrome://browser/skin/devtools/dropmarker.png");
list-style-image: url("chrome://browser/skin/devtools/dropmarker.svg");
-moz-box-align: center;
min-width: 16px;
}
@ -168,7 +168,7 @@
.devtools-toolbarbutton[type=menu] > .toolbarbutton-menu-dropmarker,
.devtools-toolbarbutton[type=menu-button] > .toolbarbutton-menubutton-dropmarker {
-moz-appearance: none !important;
list-style-image: url("chrome://browser/skin/devtools/dropmarker.png");
list-style-image: url("chrome://browser/skin/devtools/dropmarker.svg");
-moz-box-align: center;
padding: 0 3px;
}

View File

@ -125,6 +125,11 @@ text {
-moz-image-region: rect(0px,16px,16px,0px);
}
#inspector-pane-toggle > .toolbarbutton-icon {
width: 16px;
height: 16px;
}
#inspector-pane-toggle[pane-collapsed] {
list-style-image: url(debugger-expand.png);
}
@ -132,3 +137,18 @@ text {
#inspector-pane-toggle:active {
-moz-image-region: rect(0px,32px,16px,16px);
}
@media (min-resolution: 2dppx) {
#inspector-pane-toggle {
list-style-image: url(debugger-collapse@2x.png);
-moz-image-region: rect(0px,32px,32px,0px);
}
#inspector-pane-toggle[pane-collapsed] {
list-style-image: url(debugger-expand@2x.png);
}
#inspector-pane-toggle:active {
-moz-image-region: rect(0px,64px,32px,32px);
}
}

View File

@ -288,7 +288,7 @@ browser.jar:
skin/classic/browser/devtools/itemArrow-rtl.svg (../shared/devtools/images/itemArrow-rtl.svg)
skin/classic/browser/devtools/itemArrow-ltr.svg (../shared/devtools/images/itemArrow-ltr.svg)
skin/classic/browser/devtools/noise.png (../shared/devtools/images/noise.png)
skin/classic/browser/devtools/dropmarker.png (../shared/devtools/images/dropmarker.png)
skin/classic/browser/devtools/dropmarker.svg (../shared/devtools/images/dropmarker.svg)
skin/classic/browser/devtools/layoutview.css (../shared/devtools/layoutview.css)
skin/classic/browser/devtools/debugger-collapse.png (../shared/devtools/images/debugger-collapse.png)
skin/classic/browser/devtools/debugger-collapse@2x.png (../shared/devtools/images/debugger-collapse@2x.png)
@ -688,7 +688,7 @@ browser.jar:
skin/classic/aero/browser/devtools/itemArrow-rtl.svg (../shared/devtools/images/itemArrow-rtl.svg)
skin/classic/aero/browser/devtools/itemArrow-ltr.svg (../shared/devtools/images/itemArrow-ltr.svg)
skin/classic/aero/browser/devtools/noise.png (../shared/devtools/images/noise.png)
skin/classic/aero/browser/devtools/dropmarker.png (../shared/devtools/images/dropmarker.png)
skin/classic/aero/browser/devtools/dropmarker.svg (../shared/devtools/images/dropmarker.svg)
skin/classic/aero/browser/devtools/layoutview.css (../shared/devtools/layoutview.css)
skin/classic/aero/browser/devtools/debugger-collapse.png (../shared/devtools/images/debugger-collapse.png)
skin/classic/aero/browser/devtools/debugger-collapse@2x.png (../shared/devtools/images/debugger-collapse@2x.png)

View File

@ -814,7 +814,7 @@ class Automation(object):
xrePath = None, certPath = None,
debuggerInfo = None, symbolsPath = None,
timeout = -1, maxTime = None, onLaunch = None,
webapprtChrome = False, screenshotOnFail=False):
webapprtChrome = False, screenshotOnFail=False, testPath=None):
"""
Run the app, log the duration it took to execute, return the status code.
Kills the app if it runs for longer than |maxTime| seconds, or outputs nothing for |timeout| seconds.

View File

@ -9187,6 +9187,7 @@ if test -z "$direct_nspr_config"; then
LDFLAGS="$_SUBDIR_LDFLAGS"
HOST_CC="$_SUBDIR_HOST_CC"
HOST_CFLAGS="$_SUBDIR_HOST_CFLAGS"
HOST_CXXFLAGS="$_SUBDIR_HOST_CXXFLAGS"
HOST_LDFLAGS="$_SUBDIR_HOST_LDFLAGS"
RC=
fi
@ -9289,6 +9290,7 @@ CXXFLAGS="$_SUBDIR_CXXFLAGS"
LDFLAGS="$_SUBDIR_LDFLAGS"
HOST_CC="$_SUBDIR_HOST_CC"
HOST_CFLAGS="$_SUBDIR_HOST_CFLAGS"
HOST_CXXFLAGS="$_SUBDIR_HOST_CXXFLAGS"
HOST_LDFLAGS="$_SUBDIR_HOST_LDFLAGS"
RC=

View File

@ -138,7 +138,8 @@ typedef CallbackObjectHolder<NodeFilter, nsIDOMNodeFilter> NodeFilterHolder;
enum DocumentFlavor {
DocumentFlavorLegacyGuess, // compat with old code until made HTML5-compliant
DocumentFlavorHTML, // HTMLDocument with HTMLness bit set to true
DocumentFlavorSVG // SVGDocument
DocumentFlavorSVG, // SVGDocument
DocumentFlavorPlain, // Just a Document
};
// Document states
@ -2685,7 +2686,8 @@ nsresult
NS_NewHTMLDocument(nsIDocument** aInstancePtrResult, bool aLoadedAsData = false);
nsresult
NS_NewXMLDocument(nsIDocument** aInstancePtrResult, bool aLoadedAsData = false);
NS_NewXMLDocument(nsIDocument** aInstancePtrResult, bool aLoadedAsData = false,
bool aIsPlainDocument = false);
nsresult
NS_NewSVGDocument(nsIDocument** aInstancePtrResult);

View File

@ -12067,7 +12067,7 @@ nsIDocument::Constructor(const GlobalObject& aGlobal,
prin->GetPrincipal(),
true,
global,
DocumentFlavorLegacyGuess);
DocumentFlavorPlain);
if (NS_FAILED(res)) {
rv.Throw(res);
return nullptr;

View File

@ -566,6 +566,7 @@ skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s #bug 904183 # b2g(cl
skip-if = buildapp == 'b2g' || toolkit == 'android' #bug 904183 # b2g(bug 904183) b2g-debug(bug 904183) b2g-desktop(bug 904183)
[test_createHTMLDocument.html]
[test_declare_stylesheet_obsolete.html]
[test_document_constructor.html]
[test_domparser_null_char.html]
[test_domparsing.html]
[test_elementTraversal.html]

View File

@ -0,0 +1,31 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1017932
-->
<head>
<meta charset="utf-8">
<title>Test for Bug 1017932</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript">
/** Test for Bug 1017932 **/
var doc = new Document;
ok(doc instanceof Document, "Should have a document");
ok(!(doc instanceof XMLDocument), "Should not be an XMLDocument");
ok(!("load" in doc), "Should not have a load() method");
is(Object.getPrototypeOf(doc), Document.prototype,
"Should have the right proto");
</script>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1017932">Mozilla Bug 1017932</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
</body>
</html>

View File

@ -50,6 +50,7 @@
#include "mozilla/EventDispatcher.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/XMLDocumentBinding.h"
#include "mozilla/dom/DocumentBinding.h"
using namespace mozilla;
using namespace mozilla::dom;
@ -87,7 +88,10 @@ NS_NewDOMDocument(nsIDOMDocument** aInstancePtrResult,
} else if (aFlavor == DocumentFlavorHTML) {
rv = NS_NewHTMLDocument(getter_AddRefs(d));
isHTML = true;
} else if (aFlavor == DocumentFlavorPlain) {
rv = NS_NewXMLDocument(getter_AddRefs(d), aLoadedAsData, true);
} else if (aDoctype) {
MOZ_ASSERT(aFlavor == DocumentFlavorLegacyGuess);
nsAutoString publicId, name;
aDoctype->GetPublicId(publicId);
if (publicId.IsEmpty()) {
@ -117,6 +121,7 @@ NS_NewDOMDocument(nsIDOMDocument** aInstancePtrResult,
rv = NS_NewXMLDocument(getter_AddRefs(d));
}
} else {
MOZ_ASSERT(aFlavor == DocumentFlavorLegacyGuess);
rv = NS_NewXMLDocument(getter_AddRefs(d));
}
@ -172,7 +177,8 @@ NS_NewDOMDocument(nsIDOMDocument** aInstancePtrResult,
}
nsresult
NS_NewXMLDocument(nsIDocument** aInstancePtrResult, bool aLoadedAsData)
NS_NewXMLDocument(nsIDocument** aInstancePtrResult, bool aLoadedAsData,
bool aIsPlainDocument)
{
nsRefPtr<XMLDocument> doc = new XMLDocument();
@ -184,6 +190,7 @@ NS_NewXMLDocument(nsIDocument** aInstancePtrResult, bool aLoadedAsData)
}
doc->SetLoadedAsData(aLoadedAsData);
doc->mIsPlainDocument = aIsPlainDocument;
doc.forget(aInstancePtrResult);
return NS_OK;
@ -597,6 +604,7 @@ XMLDocument::Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const
// State from XMLDocument
clone->mAsync = mAsync;
clone->mIsPlainDocument = mIsPlainDocument;
return CallQueryInterface(clone.get(), aResult);
}
@ -604,6 +612,10 @@ XMLDocument::Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const
JSObject*
XMLDocument::WrapNode(JSContext *aCx)
{
if (mIsPlainDocument) {
return DocumentBinding::Wrap(aCx, this);
}
return XMLDocumentBinding::Wrap(aCx, this);
}

View File

@ -70,6 +70,9 @@ public:
protected:
virtual JSObject* WrapNode(JSContext *aCx) MOZ_OVERRIDE;
friend nsresult (::NS_NewXMLDocument)(nsIDocument**, bool, bool);
// mChannelIsPending indicates whether we're currently asynchronously loading
// data from mChannel (via document.load() or normal load). It's set to true
// when we first find out about the channel (StartDocumentLoad) and set to
@ -79,6 +82,9 @@ protected:
bool mChannelIsPending;
bool mAsync;
bool mLoopingForSyncLoad;
// If true. we're really a Document, not an XMLDocument
bool mIsPlainDocument;
};
} // namespace dom

View File

@ -82,7 +82,7 @@
#endif
#include "nsIDOMGlobalPropertyInitializer.h"
#include "nsIDataStoreService.h"
#include "mozilla/dom/DataStoreService.h"
#include "nsJSUtils.h"
#include "nsScriptNameSpaceManager.h"
@ -1466,8 +1466,7 @@ Navigator::GetDataStores(nsPIDOMWindow* aWindow,
return nullptr;
}
nsCOMPtr<nsIDataStoreService> service =
do_GetService("@mozilla.org/datastore-service;1");
nsRefPtr<DataStoreService> service = DataStoreService::GetOrCreate();
if (!service) {
aRv.Throw(NS_ERROR_FAILURE);
return nullptr;

View File

@ -4339,13 +4339,7 @@ nsGlobalWindow::GetOwnPropertyNames(JSContext* aCx, nsTArray<nsString>& aNames,
nsGlobalWindow::IsChromeWindow(JSContext* aCx, JSObject* aObj)
{
// For now, have to deal with XPConnect objects here.
nsGlobalWindow* win;
nsresult rv = UNWRAP_OBJECT(Window, aObj, win);
if (NS_FAILED(rv)) {
nsCOMPtr<nsPIDOMWindow> piWin = do_QueryWrapper(aCx, aObj);
win = static_cast<nsGlobalWindow*>(piWin.get());
}
return win->IsChromeWindow();
return xpc::WindowOrNull(aObj)->IsChromeWindow();
}
nsIDOMOfflineResourceList*
@ -4471,9 +4465,9 @@ nsGlobalWindow::GetControllers(nsIControllers** aResult)
}
nsIDOMWindow*
nsGlobalWindow::GetOpener(ErrorResult& aError)
nsGlobalWindow::GetOpenerWindow(ErrorResult& aError)
{
FORWARD_TO_OUTER_OR_THROW(GetOpener, (aError), aError, nullptr);
FORWARD_TO_OUTER_OR_THROW(GetOpenerWindow, (aError), aError, nullptr);
nsCOMPtr<nsPIDOMWindow> opener = do_QueryReferent(mOpener);
if (!opener) {
@ -4512,18 +4506,41 @@ nsGlobalWindow::GetOpener(ErrorResult& aError)
return nullptr;
}
JS::Value
nsGlobalWindow::GetOpener(JSContext* aCx, ErrorResult& aError)
{
nsCOMPtr<nsIDOMWindow> opener = GetOpenerWindow(aError);
if (aError.Failed() || !opener) {
return JS::NullValue();
}
JS::Rooted<JS::Value> val(aCx);
aError = nsContentUtils::WrapNative(aCx, opener, &val);
return val;
}
NS_IMETHODIMP
nsGlobalWindow::GetOpener(nsIDOMWindow** aOpener)
nsGlobalWindow::GetScriptableOpener(JSContext* aCx,
JS::MutableHandle<JS::Value> aOpener)
{
ErrorResult rv;
nsCOMPtr<nsIDOMWindow> opener = GetOpener(rv);
opener.forget(aOpener);
aOpener.set(GetOpener(aCx, rv));
return rv.ErrorCode();
}
NS_IMETHODIMP
nsGlobalWindow::GetOpener(nsIDOMWindow** aOpener)
{
ErrorResult rv;
nsCOMPtr<nsIDOMWindow> opener = GetOpenerWindow(rv);
opener.forget(aOpener);
return rv.ErrorCode();
}
void
nsGlobalWindow::SetOpener(nsIDOMWindow* aOpener, ErrorResult& aError)
nsGlobalWindow::SetOpener(JSContext* aCx, JS::Handle<JS::Value> aOpener,
ErrorResult& aError)
{
// Check if we were called from a privileged chrome script. If not, and if
// aOpener is not null, just define aOpener on our inner window's JS object,
@ -4531,35 +4548,15 @@ nsGlobalWindow::SetOpener(nsIDOMWindow* aOpener, ErrorResult& aError)
// Xray expando object, but don't set it on the outer window, so that it'll
// get reset on navigation. This is just like replaceable properties, but
// we're not quite readonly.
if (aOpener && !nsContentUtils::IsCallerChrome()) {
// JS_WrapObject will outerize, so we don't care if aOpener is an inner.
nsCOMPtr<nsIGlobalObject> glob = do_QueryInterface(aOpener);
if (!glob) {
aError.Throw(NS_ERROR_UNEXPECTED);
return;
}
AutoJSContext cx;
JSAutoRequest ar(cx);
// Note we explicitly do NOT enter any particular compartment here; we want
// the caller compartment in cases when we have a caller, so that we define
// expandos on Xrays as needed.
JS::Rooted<JSObject*> otherObj(cx, glob->GetGlobalJSObject());
if (!otherObj) {
aError.Throw(NS_ERROR_UNEXPECTED);
return;
}
JS::Rooted<JSObject*> thisObj(cx, GetWrapperPreserveColor());
if (!aOpener.isNull() && !nsContentUtils::IsCallerChrome()) {
JS::Rooted<JSObject*> thisObj(aCx, GetWrapperPreserveColor());
if (!thisObj) {
aError.Throw(NS_ERROR_UNEXPECTED);
return;
}
if (!JS_WrapObject(cx, &otherObj) ||
!JS_WrapObject(cx, &thisObj) ||
!JS_DefineProperty(cx, thisObj, "opener", otherObj, JSPROP_ENUMERATE,
if (!JS_WrapObject(aCx, &thisObj) ||
!JS_DefineProperty(aCx, thisObj, "opener", aOpener, JSPROP_ENUMERATE,
JS_PropertyStub, JS_StrictPropertyStub)) {
aError.Throw(NS_ERROR_FAILURE);
}
@ -4567,16 +4564,47 @@ nsGlobalWindow::SetOpener(nsIDOMWindow* aOpener, ErrorResult& aError)
return;
}
SetOpenerWindow(aOpener, false);
if (!aOpener.isObjectOrNull()) {
// Chrome code trying to set some random value as opener
aError.Throw(NS_ERROR_INVALID_ARG);
return;
}
nsGlobalWindow* win = nullptr;
if (aOpener.isObject()) {
JSObject* unwrapped = js::CheckedUnwrap(&aOpener.toObject(),
/* stopAtOuter = */ false);
if (!unwrapped) {
aError.Throw(NS_ERROR_DOM_SECURITY_ERR);
return;
}
win = xpc::WindowOrNull(unwrapped);
if (!win) {
// Wasn't a window
aError.Throw(NS_ERROR_INVALID_ARG);
return;
}
}
SetOpenerWindow(win, false);
}
NS_IMETHODIMP
nsGlobalWindow::SetScriptableOpener(JSContext* aCx,
JS::Handle<JS::Value> aOpener)
{
ErrorResult rv;
SetOpener(aCx, aOpener, rv);
return rv.ErrorCode();
}
NS_IMETHODIMP
nsGlobalWindow::SetOpener(nsIDOMWindow* aOpener)
{
ErrorResult rv;
SetOpener(aOpener, rv);
return rv.ErrorCode();
SetOpenerWindow(aOpener, false);
return NS_OK;
}
void
@ -13699,13 +13727,7 @@ bool
nsGlobalWindow::IsModalContentWindow(JSContext* aCx, JSObject* aGlobal)
{
// For now, have to deal with XPConnect objects here.
nsGlobalWindow* win;
nsresult rv = UNWRAP_OBJECT(Window, aGlobal, win);
if (NS_FAILED(rv)) {
nsCOMPtr<nsPIDOMWindow> piWin = do_QueryWrapper(aCx, aGlobal);
win = static_cast<nsGlobalWindow*>(piWin.get());
}
return win->IsModalContentWindow();
return xpc::WindowOrNull(aGlobal)->IsModalContentWindow();
}
NS_IMETHODIMP

View File

@ -836,8 +836,12 @@ public:
aError = GetScriptableTop(getter_AddRefs(top));
return top.forget();
}
nsIDOMWindow* GetOpener(mozilla::ErrorResult& aError);
void SetOpener(nsIDOMWindow* aOpener, mozilla::ErrorResult& aError);
protected:
nsIDOMWindow* GetOpenerWindow(mozilla::ErrorResult& aError);
public:
JS::Value GetOpener(JSContext* aCx, mozilla::ErrorResult& aError);
void SetOpener(JSContext* aCx, JS::Handle<JS::Value> aOpener,
mozilla::ErrorResult& aError);
using nsIDOMWindow::GetParent;
already_AddRefed<nsIDOMWindow> GetParent(mozilla::ErrorResult& aError);
mozilla::dom::Element* GetFrameElement(mozilla::ErrorResult& aError);

View File

@ -59,6 +59,25 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=868996
is(evalsb("win.opener", sb2), window,
"Navigating a window should have reset the opener in sb2");
win.opener = 5;
evalsb("win.opener = 5", sb1);
evalsb("win.opener = 5", sb2);
is(win.opener, 5, "Should be able to set an opener to a primitive");
is(evalsb("win.opener", sb1), 5,
"Should be able to set the opener to a primitive in a sandbox one");
is(evalsb("win.opener", sb2), 5,
"Should be able to set the opener to a primitive in a sandbox two");
win.location = "data:text/html,<script>opener.setTimeout(opener.continueOpenerTest2, 0, this);</" + "script>";
}
function continueOpenerTest2(win) {
is(win.opener, window,
"Navigating a window again should have reset the opener we stashed on it temporarily");
is(evalsb("win.opener", sb1), window,
"Navigating a window again should have reset the opener in sb1");
is(evalsb("win.opener", sb2), window,
"Navigating a window again should have reset the opener in sb2");
win.opener = null;
is(win.opener, null, "Should be able to set the opener to null");
is(evalsb("win.opener", sb1), null,

View File

@ -86,8 +86,10 @@ CallbackObject::CallSetup::CallSetup(CallbackObject* aCallback,
// GC, so just paper over the necessary dataflow inversion.
JS::AutoSuppressGCAnalysis nogc;
if (mIsMainThread) {
// Now get the global and JSContext for this callback.
nsGlobalWindow* win = xpc::WindowGlobalOrNull(realCallback);
// Now get the global and JSContext for this callback. Note that for the
// case of JS-implemented WebIDL we never have a window here.
nsGlobalWindow* win =
aIsJSImplementedWebIDL ? nullptr : xpc::WindowGlobalOrNull(realCallback);
if (win) {
// Make sure that if this is a window it's the current inner, since the
// nsIScriptContext and hence JSContext are associated with the outer
@ -151,7 +153,9 @@ CallbackObject::CallSetup::CallSetup(CallbackObject* aCallback,
mRootedCallable.construct(cx, aCallback->Callback());
}
if (mIsMainThread) {
// JS-implemented WebIDL is always OK to run, since it runs with Chrome
// privileges anyway.
if (mIsMainThread && !aIsJSImplementedWebIDL) {
// Check that it's ok to run this callback at all.
// Make sure to use realCallback to get the global of the callback object,
// not the wrapper.
@ -220,24 +224,24 @@ CallbackObject::CallSetup::~CallSetup()
// Now, if we have a JSContext, report any pending errors on it, unless we
// were told to re-throw them.
if (mCx) {
bool dealtWithPendingException = false;
bool needToDealWithException = JS_IsExceptionPending(mCx);
if ((mCompartment && mExceptionHandling == eRethrowContentExceptions) ||
mExceptionHandling == eRethrowExceptions) {
// Restore the old context options
JS::ContextOptionsRef(mCx) = mSavedJSContextOptions;
mErrorResult.MightThrowJSException();
if (JS_IsExceptionPending(mCx)) {
if (needToDealWithException) {
JS::Rooted<JS::Value> exn(mCx);
if (JS_GetPendingException(mCx, &exn) &&
ShouldRethrowException(exn)) {
mErrorResult.ThrowJSException(mCx, exn);
JS_ClearPendingException(mCx);
dealtWithPendingException = true;
needToDealWithException = false;
}
}
}
if (!dealtWithPendingException) {
if (needToDealWithException) {
// Either we're supposed to report our exceptions, or we're supposed to
// re-throw them but we failed to JS_GetPendingException. Either way,
// just report the pending exception, if any.

View File

@ -7483,7 +7483,8 @@ class CGMemberJITInfo(CGThing):
return ""
def defineJitInfo(self, infoName, opName, opType, infallible, movable,
aliasSet, hasSlot, slotIndex, returnTypes, args):
aliasSet, alwaysInSlot, lazilyInSlot, slotIndex,
returnTypes, args):
"""
aliasSet is a JSJitInfo::AliasSet value, without the "JSJitInfo::" bit.
@ -7492,7 +7493,7 @@ class CGMemberJITInfo(CGThing):
otherwise an iterable of the arguments for this method.
"""
assert(not movable or aliasSet != "AliasEverything") # Can't move write-aliasing things
assert(not hasSlot or movable) # Things with slots had better be movable
assert(not alwaysInSlot or movable) # Things always in slots had better be movable
def jitInfoInitializer(isTypedMethod):
initializer = fill(
@ -7506,7 +7507,8 @@ class CGMemberJITInfo(CGThing):
${returnType}, /* returnType. Not relevant for setters. */
${isInfallible}, /* isInfallible. False in setters. */
${isMovable}, /* isMovable. Not relevant for setters. */
${isInSlot}, /* isInSlot. Only relevant for getters. */
${isAlwaysInSlot}, /* isAlwaysInSlot. Only relevant for getters. */
${isLazilyCachedInSlot}, /* isLazilyCachedInSlot. Only relevant for getters. */
${isTypedMethod}, /* isTypedMethod. Only relevant for methods. */
${slotIndex} /* Reserved slot index, if we're stored in a slot, else 0. */
}
@ -7519,7 +7521,8 @@ class CGMemberJITInfo(CGThing):
""),
isInfallible=toStringBool(infallible),
isMovable=toStringBool(movable),
isInSlot=toStringBool(hasSlot),
isAlwaysInSlot=toStringBool(alwaysInSlot),
isLazilyCachedInSlot=toStringBool(lazilyInSlot),
isTypedMethod=toStringBool(isTypedMethod),
slotIndex=slotIndex)
return initializer.rstrip()
@ -7568,17 +7571,22 @@ class CGMemberJITInfo(CGThing):
movable = getterpure and getterinfal
getterinfal = getterinfal and infallibleForMember(self.member, self.member.type, self.descriptor)
isInSlot = self.member.getExtendedAttribute("StoreInSlot")
if isInSlot:
isAlwaysInSlot = self.member.getExtendedAttribute("StoreInSlot")
if self.member.slotIndex is not None:
assert isAlwaysInSlot or self.member.getExtendedAttribute("Cached")
isLazilyCachedInSlot = not isAlwaysInSlot
slotIndex = memberReservedSlot(self.member)
# We'll statically assert that this is not too big in
# CGUpdateMemberSlotsMethod
# CGUpdateMemberSlotsMethod, in the case when
# isAlwaysInSlot is true.
else:
isLazilyCachedInSlot = False
slotIndex = "0"
result = self.defineJitInfo(getterinfo, getter, "Getter",
getterinfal, movable, aliasSet,
isInSlot, slotIndex,
isAlwaysInSlot, isLazilyCachedInSlot,
slotIndex,
[self.member.type], None)
if (not self.member.readonly or
self.member.getExtendedAttribute("PutForwards") is not None or
@ -7590,7 +7598,7 @@ class CGMemberJITInfo(CGThing):
# Setters are always fallible, since they have to do a typed unwrap.
result += self.defineJitInfo(setterinfo, setter, "Setter",
False, False, "AliasEverything",
False, "0",
False, False, "0",
[BuiltinTypes[IDLBuiltinType.Types.void]],
None)
return result
@ -7641,7 +7649,8 @@ class CGMemberJITInfo(CGThing):
else:
aliasSet = "AliasEverything"
result = self.defineJitInfo(methodinfo, method, "Method",
methodInfal, movable, aliasSet, False, "0",
methodInfal, movable, aliasSet,
False, False, "0",
[s[0] for s in sigs], args)
return result
raise TypeError("Illegal member type to CGPropertyJITInfo")

View File

@ -1,2 +1,2 @@
component {d193d0e2-c677-4a7b-bb0a-19155b470f2e} DataStoreService.js
contract @mozilla.org/datastore-service;1 {d193d0e2-c677-4a7b-bb0a-19155b470f2e}
component {db5c9602-030f-4bff-a3de-881a8de370f2} DataStoreImpl.js
contract @mozilla.org/dom/datastore;1 {db5c9602-030f-4bff-a3de-881a8de370f2}

View File

@ -0,0 +1,48 @@
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_DataStoreCallbacks_h
#define mozilla_dom_DataStoreCallbacks_h
#include "nsISupports.h"
namespace mozilla {
namespace dom {
class DataStoreDB;
class DataStoreDBCallback
{
public:
NS_IMETHOD_(MozExternalRefCountType) AddRef(void) = 0;
NS_IMETHOD_(MozExternalRefCountType) Release(void) = 0;
virtual void Run(DataStoreDB* aDb, bool aSuccess) = 0;
protected:
virtual ~DataStoreDBCallback()
{
}
};
class DataStoreRevisionCallback
{
public:
NS_IMETHOD_(MozExternalRefCountType) AddRef(void) = 0;
NS_IMETHOD_(MozExternalRefCountType) Release(void) = 0;
virtual void Run(const nsAString& aRevisionID) = 0;
protected:
virtual ~DataStoreRevisionCallback()
{
}
};
} // dom namespace
} // mozilla namespace
#endif // mozilla_dom_DataStoreCallbacks_h

View File

@ -12,9 +12,6 @@ function debug(s) {
//dump('DEBUG DataStoreChangeNotifier: ' + s + '\n');
}
// DataStoreServiceInternal should not be converted into a lazy getter as it
// runs code during initialization.
Cu.import('resource://gre/modules/DataStoreServiceInternal.jsm');
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");

View File

@ -0,0 +1,319 @@
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "DataStoreDB.h"
#include "DataStoreCallbacks.h"
#include "mozilla/dom/IDBDatabaseBinding.h"
#include "mozilla/dom/IDBFactoryBinding.h"
#include "mozilla/dom/indexedDB/IDBDatabase.h"
#include "mozilla/dom/indexedDB/IDBFactory.h"
#include "mozilla/dom/indexedDB/IDBIndex.h"
#include "mozilla/dom/indexedDB/IDBObjectStore.h"
#include "mozilla/dom/indexedDB/IDBRequest.h"
#include "nsIDOMEvent.h"
#define DATASTOREDB_VERSION 1
#define DATASTOREDB_NAME "DataStoreDB"
#define DATASTOREDB_REVISION_INDEX "revisionIndex"
using namespace mozilla::dom::indexedDB;
namespace mozilla {
namespace dom {
NS_IMPL_ISUPPORTS(DataStoreDB, nsIDOMEventListener)
DataStoreDB::DataStoreDB(const nsAString& aManifestURL, const nsAString& aName)
: mState(Inactive)
{
mDatabaseName.Assign(aName);
mDatabaseName.AppendASCII("|");
mDatabaseName.Append(aManifestURL);
}
DataStoreDB::~DataStoreDB()
{
}
nsresult
DataStoreDB::CreateFactoryIfNeeded()
{
if (!mFactory) {
nsresult rv = IDBFactory::Create(nullptr, getter_AddRefs(mFactory));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}
return NS_OK;
}
nsresult
DataStoreDB::Open(IDBTransactionMode aMode, const Sequence<nsString>& aDbs,
DataStoreDBCallback* aCallback)
{
MOZ_ASSERT(mState == Inactive);
nsresult rv = CreateFactoryIfNeeded();
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
ErrorResult error;
mRequest = mFactory->Open(mDatabaseName, DATASTOREDB_VERSION, error);
if (NS_WARN_IF(error.Failed())) {
return error.ErrorCode();
}
rv = AddEventListeners();
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
mState = Active;
mTransactionMode = aMode;
mObjectStores = aDbs;
mCallback = aCallback;
return NS_OK;
}
NS_IMETHODIMP
DataStoreDB::HandleEvent(nsIDOMEvent* aEvent)
{
nsString type;
nsresult rv = aEvent->GetType(type);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (type.EqualsASCII("success")) {
RemoveEventListeners();
mState = Inactive;
rv = DatabaseOpened();
if (NS_WARN_IF(NS_FAILED(rv))) {
mCallback->Run(this, false);
} else {
mCallback->Run(this, true);
}
mRequest = nullptr;
return NS_OK;
}
if (type.EqualsASCII("upgradeneeded")) {
return UpgradeSchema();
}
if (type.EqualsASCII("error") || type.EqualsASCII("blocked")) {
RemoveEventListeners();
mState = Inactive;
mCallback->Run(this, false);
mRequest = nullptr;
return NS_OK;
}
MOZ_ASSUME_UNREACHABLE("This should not happen");
return NS_OK;
}
nsresult
DataStoreDB::UpgradeSchema()
{
MOZ_ASSERT(NS_IsMainThread());
AutoSafeJSContext cx;
ErrorResult error;
JS::Rooted<JS::Value> result(cx, mRequest->GetResult(error));
if (NS_WARN_IF(error.Failed())) {
return error.ErrorCode();
}
MOZ_ASSERT(result.isObject());
IDBDatabase* database = nullptr;
nsresult rv = UNWRAP_OBJECT(IDBDatabase, &result.toObject(), database);
if (NS_FAILED(rv)) {
NS_WARNING("Didn't get the object we expected!");
return rv;
}
{
RootedDictionary<IDBObjectStoreParameters> params(cx);
params.Init(NS_LITERAL_STRING("{ \"autoIncrement\": true }"));
nsRefPtr<IDBObjectStore> store =
database->CreateObjectStore(cx, NS_LITERAL_STRING(DATASTOREDB_NAME),
params, error);
if (NS_WARN_IF(error.Failed())) {
return error.ErrorCode();
}
}
nsRefPtr<IDBObjectStore> store;
{
RootedDictionary<IDBObjectStoreParameters> params(cx);
params.Init(NS_LITERAL_STRING("{ \"autoIncrement\": true, \"keyPath\": \"internalRevisionId\" }"));
store =
database->CreateObjectStore(cx, NS_LITERAL_STRING(DATASTOREDB_REVISION),
params, error);
if (NS_WARN_IF(error.Failed())) {
return error.ErrorCode();
}
}
{
RootedDictionary<IDBIndexParameters> params(cx);
params.Init(NS_LITERAL_STRING("{ \"unique\": true }"));
nsRefPtr<IDBIndex> index =
store->CreateIndex(cx, NS_LITERAL_STRING(DATASTOREDB_REVISION_INDEX),
NS_LITERAL_STRING("revisionId"), params, error);
if (NS_WARN_IF(error.Failed())) {
return error.ErrorCode();
}
}
return NS_OK;
}
nsresult
DataStoreDB::DatabaseOpened()
{
MOZ_ASSERT(NS_IsMainThread());
AutoSafeJSContext cx;
ErrorResult error;
JS::Rooted<JS::Value> result(cx, mRequest->GetResult(error));
if (NS_WARN_IF(error.Failed())) {
return error.ErrorCode();
}
MOZ_ASSERT(result.isObject());
nsresult rv = UNWRAP_OBJECT(IDBDatabase, &result.toObject(), mDatabase);
if (NS_FAILED(rv)) {
NS_WARNING("Didn't get the object we expected!");
return rv;
}
nsRefPtr<IDBTransaction> txn = mDatabase->Transaction(mObjectStores,
mTransactionMode,
error);
if (NS_WARN_IF(error.Failed())) {
return error.ErrorCode();
}
mTransaction = txn.forget();
return NS_OK;
}
nsresult
DataStoreDB::Delete()
{
MOZ_ASSERT(mState == Inactive);
nsresult rv = CreateFactoryIfNeeded();
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
mTransaction = nullptr;
if (mDatabase) {
rv = mDatabase->Close();
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
mDatabase = nullptr;
}
ErrorResult error;
nsRefPtr<IDBOpenDBRequest> request =
mFactory->DeleteDatabase(mDatabaseName, IDBOpenDBOptions(), error);
if (NS_WARN_IF(error.Failed())) {
return error.ErrorCode();
}
return NS_OK;
}
indexedDB::IDBTransaction*
DataStoreDB::Transaction() const
{
MOZ_ASSERT(mTransaction);
MOZ_ASSERT(mTransaction->IsOpen());
return mTransaction;
}
nsresult
DataStoreDB::AddEventListeners()
{
nsresult rv;
rv = mRequest->EventTarget::AddEventListener(NS_LITERAL_STRING("success"),
this, false);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = mRequest->EventTarget::AddEventListener(NS_LITERAL_STRING("upgradeneeded"),
this, false);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = mRequest->EventTarget::AddEventListener(NS_LITERAL_STRING("error"),
this, false);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = mRequest->EventTarget::AddEventListener(NS_LITERAL_STRING("blocked"),
this, false);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
return NS_OK;
}
nsresult
DataStoreDB::RemoveEventListeners()
{
nsresult rv;
rv = mRequest->RemoveEventListener(NS_LITERAL_STRING("success"),
this, false);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = mRequest->RemoveEventListener(NS_LITERAL_STRING("upgradeneeded"),
this, false);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = mRequest->RemoveEventListener(NS_LITERAL_STRING("error"),
this, false);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = mRequest->RemoveEventListener(NS_LITERAL_STRING("blocked"),
this, false);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
return NS_OK;
}
} // namespace dom
} // namespace mozilla

View File

@ -0,0 +1,82 @@
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_DataStoreDB_h
#define mozilla_dom_DataStoreDB_h
#include "mozilla/dom/IDBTransactionBinding.h"
#include "nsAutoPtr.h"
#include "nsIDOMEventListener.h"
#include "nsISupportsImpl.h"
#include "nsString.h"
#define DATASTOREDB_REVISION "revision"
namespace mozilla {
namespace dom {
namespace indexedDB {
class IDBDatabase;
class IDBFactory;
class IDBObjectStore;
class IDBOpenDBRequest;
class IDBTransaction;
}
class DataStoreDBCallback;
class DataStoreDB MOZ_FINAL : public nsIDOMEventListener
{
public:
NS_DECL_ISUPPORTS
DataStoreDB(const nsAString& aManifestURL, const nsAString& aName);
~DataStoreDB();
nsresult Open(IDBTransactionMode aMode, const Sequence<nsString>& aDb,
DataStoreDBCallback* aCallback);
nsresult Delete();
indexedDB::IDBTransaction* Transaction() const;
// nsIDOMEventListener
NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent);
private:
nsresult CreateFactoryIfNeeded();
nsresult UpgradeSchema();
nsresult DatabaseOpened();
nsresult AddEventListeners();
nsresult RemoveEventListeners();
nsString mDatabaseName;
nsRefPtr<indexedDB::IDBFactory> mFactory;
nsRefPtr<indexedDB::IDBOpenDBRequest> mRequest;
nsRefPtr<indexedDB::IDBDatabase> mDatabase;
nsRefPtr<indexedDB::IDBTransaction> mTransaction;
nsRefPtr<DataStoreDBCallback> mCallback;
// Internal state to avoid strange use of this class.
enum StateType {
Inactive,
Active
} mState;
IDBTransactionMode mTransactionMode;
Sequence<nsString> mObjectStores;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_DataStoreDB_h

View File

@ -6,8 +6,6 @@
'use strict'
this.EXPORTED_SYMBOLS = ["DataStore"];
function debug(s) {
//dump('DEBUG DataStore: ' + s + '\n');
}
@ -59,17 +57,16 @@ function validateId(aId) {
}
/* DataStore object */
this.DataStore = function(aWindow, aName, aOwner, aReadOnly) {
function DataStore() {
debug("DataStore created");
this.init(aWindow, aName, aOwner, aReadOnly);
}
this.DataStore.prototype = {
DataStore.prototype = {
classDescription: "DataStore XPCOM Component",
classID: Components.ID("{db5c9602-030f-4bff-a3de-881a8de370f2}"),
contractID: "@mozilla.org/dom/datastore-impl;1",
QueryInterface: XPCOMUtils.generateQI([Components.interfaces.nsISupports,
Components.interfaces.nsIObserver]),
QueryInterface: XPCOMUtils.generateQI([Ci.nsIDataStore, Ci.nsISupports,
Ci.nsIObserver]),
callbacks: [],
@ -536,3 +533,5 @@ this.DataStore.prototype = {
return exposedCursor;
}
};
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([DataStore]);

View File

@ -0,0 +1,102 @@
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "DataStoreRevision.h"
#include "DataStoreCallbacks.h"
#include "DataStoreService.h"
#include "mozilla/dom/DataStoreBinding.h"
#include "mozilla/dom/indexedDB/IDBObjectStore.h"
#include "nsIDOMEvent.h"
namespace mozilla {
namespace dom {
using namespace indexedDB;
NS_IMPL_ISUPPORTS(DataStoreRevision, nsIDOMEventListener)
// Note: this code in it must not assume anything about the compartment cx is
// in.
nsresult
DataStoreRevision::AddRevision(JSContext* aCx,
IDBObjectStore* aStore,
uint32_t aObjectId,
RevisionType aRevisionType,
DataStoreRevisionCallback* aCallback)
{
MOZ_ASSERT(aStore);
MOZ_ASSERT(aCallback);
nsRefPtr<DataStoreService> service = DataStoreService::Get();
if (!service) {
return NS_ERROR_FAILURE;
}
nsString id;
nsresult rv = service->GenerateUUID(mRevisionID);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
DataStoreRevisionData data;
data.mRevisionId = mRevisionID;
data.mObjectId = aObjectId;
switch (aRevisionType) {
case RevisionVoid:
data.mOperation = NS_LITERAL_STRING("void");
break;
default:
MOZ_ASSUME_UNREACHABLE("This should not happen");
break;
}
JS::Rooted<JS::Value> value(aCx);
if (!data.ToObject(aCx, &value)) {
return NS_ERROR_FAILURE;
}
ErrorResult error;
mRequest = aStore->Put(aCx, value, JS::UndefinedHandleValue, error);
if (NS_WARN_IF(error.Failed())) {
return error.ErrorCode();
}
rv = mRequest->EventTarget::AddEventListener(NS_LITERAL_STRING("success"),
this, false);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
mCallback = aCallback;
return NS_OK;
}
NS_IMETHODIMP
DataStoreRevision::HandleEvent(nsIDOMEvent* aEvent)
{
nsString type;
nsresult rv = aEvent->GetType(type);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (!type.EqualsASCII("success")) {
MOZ_ASSUME_UNREACHABLE("This should not happen");
return NS_ERROR_FAILURE;
}
mRequest->RemoveEventListener(NS_LITERAL_STRING("success"), this, false);
mRequest = nullptr;
mCallback->Run(mRevisionID);
return NS_OK;
}
} // dom namespace
} // mozilla namespace

View File

@ -0,0 +1,52 @@
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_DataStoreRevision_h
#define mozilla_dom_DataStoreRevision_h
#include "jsapi.h"
#include "nsAutoPtr.h"
#include "nsIDOMEventListener.h"
#include "nsString.h"
namespace mozilla {
namespace dom {
namespace indexedDB {
class IDBObjectStore;
class IDBRequest;
}
class DataStoreRevisionCallback;
class DataStoreRevision MOZ_FINAL : public nsIDOMEventListener
{
public:
NS_DECL_ISUPPORTS
enum RevisionType {
RevisionVoid
};
nsresult AddRevision(JSContext* aCx,
indexedDB::IDBObjectStore* aStore,
uint32_t aObjectId,
RevisionType aRevisionType,
DataStoreRevisionCallback* aCallback);
// nsIDOMEventListener
NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent);
private:
nsRefPtr<DataStoreRevisionCallback> mCallback;
nsRefPtr<indexedDB::IDBRequest> mRequest;
nsString mRevisionID;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_DataStoreRevision_h

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,110 @@
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_DataStoreService_h
#define mozilla_dom_DataStoreService_h
#include "mozilla/dom/PContent.h"
#include "nsClassHashtable.h"
#include "nsIDataStoreService.h"
#include "nsIObserver.h"
#include "nsRefPtrHashtable.h"
class nsIPrincipal;
class nsIUUIDGenerator;
class nsPIDOMWindow;
namespace mozilla {
namespace dom {
class DataStoreInfo;
class FirstRevisionIdCallback;
class PendingRequest;
class Promise;
class RetrieveRevisionsCounter;
class RevisionAddedEnableStoreCallback;
class DataStoreService MOZ_FINAL : public nsIDataStoreService
, public nsIObserver
{
friend class ContentChild;
friend class FirstRevisionIdCallback;
friend class RetrieveRevisionsCounter;
friend class RevisionAddedEnableStoreCallback;
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
NS_DECL_NSIDATASTORESERVICE
// Returns the DataStoreService singleton. Only to be called from main
// thread.
static already_AddRefed<DataStoreService> GetOrCreate();
static already_AddRefed<DataStoreService> Get();
static void Shutdown();
nsresult GenerateUUID(nsAString& aID);
nsresult GetDataStoresFromIPC(const nsAString& aName,
nsIPrincipal* aPrincipal,
nsTArray<DataStoreSetting>* aValue);
private:
DataStoreService();
~DataStoreService();
nsresult Init();
typedef nsClassHashtable<nsUint32HashKey, DataStoreInfo> HashApp;
nsresult AddPermissions(uint32_t aAppId, const nsAString& aName,
const nsAString& aOriginURL,
const nsAString& aManifestURL,
bool aReadOnly);
nsresult AddAccessPermissions(uint32_t aAppId, const nsAString& aName,
const nsAString& aOriginURL,
const nsAString& aManifestURL,
bool aReadOnly);
nsresult CreateFirstRevisionId(uint32_t aAppId, const nsAString& aName,
const nsAString& aManifestURL);
void GetDataStoresCreate(nsPIDOMWindow* aWindow, Promise* aPromise,
const nsTArray<DataStoreInfo>& aStores);
void GetDataStoresResolve(nsPIDOMWindow* aWindow, Promise* aPromise,
const nsTArray<DataStoreInfo>& aStores);
nsresult GetDataStoreInfos(const nsAString& aName, uint32_t aAppId,
nsTArray<DataStoreInfo>& aStores);
void DeleteDataStores(uint32_t aAppId);
nsresult EnableDataStore(uint32_t aAppId, const nsAString& aName,
const nsAString& aManifestURL);
already_AddRefed<RetrieveRevisionsCounter> GetCounter(uint32_t aId) const;
void RemoveCounter(uint32_t aId);
nsClassHashtable<nsStringHashKey, HashApp> mStores;
nsClassHashtable<nsStringHashKey, HashApp> mAccessStores;
typedef nsTArray<PendingRequest> PendingRequests;
nsClassHashtable<nsStringHashKey, PendingRequests> mPendingRequests;
nsRefPtrHashtable<nsUint32HashKey, RetrieveRevisionsCounter> mPendingCounters;
nsCOMPtr<nsIUUIDGenerator> mUUIDGenerator;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_DataStoreService_h

View File

@ -1,522 +0,0 @@
/* -*- Mode: js2; js2-basic-offset: 2; indent-tabs-mode: nil; -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
'use strict'
/* static functions */
function debug(s) {
//dump('DEBUG DataStoreService: ' + s + '\n');
}
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
Cu.import('resource://gre/modules/Services.jsm');
Cu.import('resource://gre/modules/DataStoreImpl.jsm');
Cu.import("resource://gre/modules/DataStoreDB.jsm");
Cu.import("resource://gre/modules/DOMRequestHelper.jsm");
XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
"@mozilla.org/childprocessmessagemanager;1",
"nsIMessageSender");
XPCOMUtils.defineLazyServiceGetter(this, "ppmm",
"@mozilla.org/parentprocessmessagemanager;1",
"nsIMessageBroadcaster");
XPCOMUtils.defineLazyServiceGetter(this, "permissionManager",
"@mozilla.org/permissionmanager;1",
"nsIPermissionManager");
XPCOMUtils.defineLazyServiceGetter(this, "secMan",
"@mozilla.org/scriptsecuritymanager;1",
"nsIScriptSecurityManager");
/* DataStoreService */
const DATASTORESERVICE_CID = Components.ID('{d193d0e2-c677-4a7b-bb0a-19155b470f2e}');
const REVISION_VOID = "void";
function DataStoreService() {
debug('DataStoreService Constructor');
this.inParent = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime)
.processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
if (this.inParent) {
let obs = Services.obs;
if (!obs) {
debug("DataStore Error: observer-service is null!");
return;
}
obs.addObserver(this, 'webapps-clear-data', false);
}
let self = this;
cpmm.addMessageListener("datastore-first-revision-created",
function(aMsg) { self.receiveMessage(aMsg); });
}
DataStoreService.prototype = {
inParent: false,
// Hash of DataStores
stores: {},
accessStores: {},
pendingRequests: {},
installDataStore: function(aAppId, aName, aOrigin, aOwner, aReadOnly) {
debug('installDataStore - appId: ' + aAppId + ', aName: ' +
aName + ', aOrigin: ' + aOrigin + ', aOwner:' + aOwner +
', aReadOnly: ' + aReadOnly);
this.checkIfInParent();
if (aName in this.stores && aAppId in this.stores[aName]) {
debug('This should not happen');
return;
}
if (!(aName in this.stores)) {
this.stores[aName] = {};
}
// A DataStore is enabled when it has a first valid revision.
this.stores[aName][aAppId] = { origin: aOrigin, owner: aOwner,
readOnly: aReadOnly, enabled: false };
this.addPermissions(aAppId, aName, aOrigin, aOwner, aReadOnly);
this.createFirstRevisionId(aAppId, aName, aOwner);
},
installAccessDataStore: function(aAppId, aName, aOrigin, aOwner, aReadOnly) {
debug('installAccessDataStore - appId: ' + aAppId + ', aName: ' +
aName + ', aOrigin: ' + aOrigin + ', aOwner:' + aOwner +
', aReadOnly: ' + aReadOnly);
this.checkIfInParent();
if (aName in this.accessStores && aAppId in this.accessStores[aName]) {
debug('This should not happen');
return;
}
if (!(aName in this.accessStores)) {
this.accessStores[aName] = {};
}
this.accessStores[aName][aAppId] = { origin: aOrigin, owner: aOwner,
readOnly: aReadOnly };
this.addAccessPermissions(aAppId, aName, aOrigin, aOwner, aReadOnly);
},
checkIfInParent: function() {
if (!this.inParent) {
throw "DataStore can execute this operation just in the parent process";
}
},
createFirstRevisionId: function(aAppId, aName, aOwner) {
debug("createFirstRevisionId database: " + aName);
let self = this;
let db = new DataStoreDB();
db.init(aOwner, aName);
db.revisionTxn(
'readwrite',
function(aTxn, aRevisionStore) {
debug("createFirstRevisionId - transaction success");
let request = aRevisionStore.openCursor(null, 'prev');
request.onsuccess = function(aEvent) {
let cursor = aEvent.target.result;
if (cursor) {
debug("First revision already created.");
self.enableDataStore(aAppId, aName, aOwner);
} else {
// If the revision doesn't exist, let's create the first one.
db.addRevision(aRevisionStore, 0, REVISION_VOID, function() {
debug("First revision created.");
self.enableDataStore(aAppId, aName, aOwner);
});
}
};
}
);
},
enableDataStore: function(aAppId, aName, aOwner) {
if (aName in this.stores && aAppId in this.stores[aName]) {
this.stores[aName][aAppId].enabled = true;
ppmm.broadcastAsyncMessage('datastore-first-revision-created',
{ name: aName, owner: aOwner });
}
},
addPermissions: function(aAppId, aName, aOrigin, aOwner, aReadOnly) {
// When a new DataStore is installed, the permissions must be set for the
// owner app.
let permission = "indexedDB-chrome-" + aName + '|' + aOwner;
this.resetPermissions(aAppId, aOrigin, aOwner, permission, aReadOnly);
// For any app that wants to have access to this DataStore we add the
// permissions.
if (aName in this.accessStores) {
for (let appId in this.accessStores[aName]) {
// ReadOnly is decided by the owner first.
let readOnly = aReadOnly || this.accessStores[aName][appId].readOnly;
this.resetPermissions(appId, this.accessStores[aName][appId].origin,
this.accessStores[aName][appId].owner,
permission, readOnly);
}
}
},
addAccessPermissions: function(aAppId, aName, aOrigin, aOwner, aReadOnly) {
// When an app wants to have access to a DataStore, the permissions must be
// set.
if (!(aName in this.stores)) {
return;
}
for (let appId in this.stores[aName]) {
let permission = "indexedDB-chrome-" + aName + '|' + this.stores[aName][appId].owner;
// The ReadOnly is decied by the owenr first.
let readOnly = this.stores[aName][appId].readOnly || aReadOnly;
this.resetPermissions(aAppId, aOrigin, aOwner, permission, readOnly);
}
},
resetPermissions: function(aAppId, aOrigin, aOwner, aPermission, aReadOnly) {
debug("ResetPermissions - appId: " + aAppId + " - origin: " + aOrigin +
" - owner: " + aOwner + " - permissions: " + aPermission +
" - readOnly: " + aReadOnly);
let uri = Services.io.newURI(aOrigin, null, null);
let principal = secMan.getAppCodebasePrincipal(uri, aAppId, false);
let result = permissionManager.testExactPermissionFromPrincipal(principal,
aPermission + '-write');
if (aReadOnly && result == Ci.nsIPermissionManager.ALLOW_ACTION) {
debug("Write permission removed");
permissionManager.removeFromPrincipal(principal, aPermission + '-write');
} else if (!aReadOnly && result != Ci.nsIPermissionManager.ALLOW_ACTION) {
debug("Write permission added");
permissionManager.addFromPrincipal(principal, aPermission + '-write',
Ci.nsIPermissionManager.ALLOW_ACTION);
}
result = permissionManager.testExactPermissionFromPrincipal(principal,
aPermission + '-read');
if (result != Ci.nsIPermissionManager.ALLOW_ACTION) {
debug("Read permission added");
permissionManager.addFromPrincipal(principal, aPermission + '-read',
Ci.nsIPermissionManager.ALLOW_ACTION);
}
result = permissionManager.testExactPermissionFromPrincipal(principal, aPermission);
if (result != Ci.nsIPermissionManager.ALLOW_ACTION) {
debug("Generic permission added");
permissionManager.addFromPrincipal(principal, aPermission,
Ci.nsIPermissionManager.ALLOW_ACTION);
}
},
getDataStores: function(aWindow, aName) {
debug('getDataStores - aName: ' + aName);
let self = this;
return new aWindow.Promise(function(resolve, reject) {
// If this request comes from the main process, we have access to the
// window, so we can skip the ipc communication.
if (self.inParent) {
let stores = self.getDataStoresInfo(aName, aWindow.document.nodePrincipal.appId);
if (stores === null) {
reject(new aWindow.DOMError("SecurityError", "Access denied"));
return;
}
self.getDataStoreCreate(aWindow, resolve, stores);
} else {
// This method can be called in the child so we need to send a request
// to the parent and create DataStore object here.
new DataStoreServiceChild(aWindow, aName, function(aStores) {
debug("DataStoreServiceChild success callback!");
self.getDataStoreCreate(aWindow, resolve, aStores);
}, function() {
debug("DataStoreServiceChild error callback!");
reject(new aWindow.DOMError("SecurityError", "Access denied"));
});
}
});
},
getDataStoresInfo: function(aName, aAppId) {
debug('GetDataStoresInfo');
let appsService = Cc["@mozilla.org/AppsService;1"]
.getService(Ci.nsIAppsService);
let app = appsService.getAppByLocalId(aAppId);
if (!app) {
return null;
}
let prefName = "dom.testing.datastore_enabled_for_hosted_apps";
if (app.appStatus != Ci.nsIPrincipal.APP_STATUS_CERTIFIED &&
(Services.prefs.getPrefType(prefName) == Services.prefs.PREF_INVALID ||
!Services.prefs.getBoolPref(prefName))) {
return null;
}
let results = [];
if (aName in this.stores) {
if (aAppId in this.stores[aName]) {
results.push({ name: aName,
owner: this.stores[aName][aAppId].owner,
readOnly: false,
enabled: this.stores[aName][aAppId].enabled });
}
for (var i in this.stores[aName]) {
if (i == aAppId) {
continue;
}
let access = this.getDataStoreAccess(aName, aAppId);
if (!access) {
continue;
}
let readOnly = this.stores[aName][i].readOnly || access.readOnly;
results.push({ name: aName,
owner: this.stores[aName][i].owner,
readOnly: readOnly,
enabled: this.stores[aName][i].enabled });
}
}
return results;
},
getDataStoreCreate: function(aWindow, aResolve, aStores) {
debug("GetDataStoreCreate");
let results = new aWindow.Array();
if (!aStores.length) {
aResolve(results);
return;
}
let pendingDataStores = [];
for (let i = 0; i < aStores.length; ++i) {
if (!aStores[i].enabled) {
pendingDataStores.push(aStores[i].owner);
}
}
if (!pendingDataStores.length) {
this.getDataStoreResolve(aWindow, aResolve, aStores);
return;
}
if (!(aStores[0].name in this.pendingRequests)) {
this.pendingRequests[aStores[0].name] = [];
}
this.pendingRequests[aStores[0].name].push({ window: aWindow,
resolve: aResolve,
stores: aStores,
pendingDataStores: pendingDataStores });
},
getDataStoreResolve: function(aWindow, aResolve, aStores) {
debug("GetDataStoreResolve");
let callbackPending = aStores.length;
let results = new aWindow.Array();
if (!callbackPending) {
aResolve(results);
return;
}
for (let i = 0; i < aStores.length; ++i) {
let obj = new DataStore(aWindow, aStores[i].name,
aStores[i].owner, aStores[i].readOnly);
let storeImpl = aWindow.DataStoreImpl._create(aWindow, obj);
let exposedStore = new aWindow.DataStore();
exposedStore.setDataStoreImpl(storeImpl);
obj.exposedObject = exposedStore;
results.push(exposedStore);
obj.retrieveRevisionId(
function() {
--callbackPending;
if (!callbackPending) {
aResolve(results);
}
}
);
}
},
getDataStoreAccess: function(aName, aAppId) {
if (!(aName in this.accessStores) ||
!(aAppId in this.accessStores[aName])) {
return null;
}
return this.accessStores[aName][aAppId];
},
observe: function observe(aSubject, aTopic, aData) {
debug('observe - aTopic: ' + aTopic);
if (aTopic != 'webapps-clear-data') {
return;
}
let params =
aSubject.QueryInterface(Ci.mozIApplicationClearPrivateDataParams);
// DataStore is explosed to apps, not browser content.
if (params.browserOnly) {
return;
}
function isEmpty(aMap) {
for (var key in aMap) {
if (aMap.hasOwnProperty(key)) {
return false;
}
}
return true;
}
for (let key in this.stores) {
if (params.appId in this.stores[key]) {
this.deleteDatabase(key, this.stores[key][params.appId].owner);
delete this.stores[key][params.appId];
}
if (isEmpty(this.stores[key])) {
delete this.stores[key];
}
}
for (let key in this.accessStores) {
if (params.appId in this.accessStores[key]) {
delete this.accessStores[key][params.appId];
}
if (isEmpty(this.accessStores[key])) {
delete this.accessStores[key];
}
}
},
deleteDatabase: function(aName, aOwner) {
debug("delete database: " + aName);
let db = new DataStoreDB();
db.init(aOwner, aName);
db.delete();
},
receiveMessage: function(aMsg) {
debug("receiveMessage");
let data = aMsg.json;
if (!(data.name in this.pendingRequests)) {
return;
}
for (let i = 0; i < this.pendingRequests[data.name].length;) {
let pos = this.pendingRequests[data.name][i].pendingDataStores.indexOf(data.owner);
if (pos != -1) {
this.pendingRequests[data.name][i].pendingDataStores.splice(pos, 1);
if (!this.pendingRequests[data.name][i].pendingDataStores.length) {
this.getDataStoreResolve(this.pendingRequests[data.name][i].window,
this.pendingRequests[data.name][i].resolve,
this.pendingRequests[data.name][i].stores);
this.pendingRequests[data.name].splice(i, 1);
continue;
}
}
++i;
}
if (!this.pendingRequests[data.name].length) {
delete this.pendingRequests[data.name];
}
},
classID : DATASTORESERVICE_CID,
QueryInterface: XPCOMUtils.generateQI([Ci.nsIDataStoreService,
Ci.nsIObserver]),
classInfo: XPCOMUtils.generateCI({
classID: DATASTORESERVICE_CID,
contractID: '@mozilla.org/datastore-service;1',
interfaces: [Ci.nsIDataStoreService, Ci.nsIObserver],
flags: Ci.nsIClassInfo.SINGLETON
})
};
/* DataStoreServiceChild */
function DataStoreServiceChild(aWindow, aName, aSuccessCb, aErrorCb) {
debug("DataStoreServiceChild created");
this.init(aWindow, aName, aSuccessCb, aErrorCb);
}
DataStoreServiceChild.prototype = {
__proto__: DOMRequestIpcHelper.prototype,
init: function(aWindow, aName, aSuccessCb, aErrorCb) {
debug("DataStoreServiceChild init");
this._successCb = aSuccessCb;
this._errorCb = aErrorCb;
this._name = aName;
this.initDOMRequestHelper(aWindow, [ "DataStore:Get:Return:OK",
"DataStore:Get:Return:KO" ]);
cpmm.sendAsyncMessage("DataStore:Get",
{ name: aName }, null, aWindow.document.nodePrincipal );
},
receiveMessage: function(aMessage) {
debug("DataStoreServiceChild receiveMessage");
if (aMessage.data.name != this._name) {
return;
}
switch (aMessage.name) {
case 'DataStore:Get:Return:OK':
this.destroyDOMRequestHelper();
this._successCb(aMessage.data.stores);
break;
case 'DataStore:Get:Return:KO':
this.destroyDOMRequestHelper();
this._errorCb();
break;
}
}
}
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([DataStoreService]);

View File

@ -1,68 +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/. */
"use strict"
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
this.EXPORTED_SYMBOLS = ["DataStoreServiceInternal"];
function debug(s) {
//dump('DEBUG DataStoreServiceInternal: ' + s + '\n');
}
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
XPCOMUtils.defineLazyServiceGetter(this, "ppmm",
"@mozilla.org/parentprocessmessagemanager;1",
"nsIMessageBroadcaster");
XPCOMUtils.defineLazyServiceGetter(this, "dataStoreService",
"@mozilla.org/datastore-service;1",
"nsIDataStoreService");
this.DataStoreServiceInternal = {
init: function() {
debug("init");
let inParent = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime)
.processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
if (inParent) {
ppmm.addMessageListener("DataStore:Get", this);
}
},
receiveMessage: function(aMessage) {
debug("receiveMessage");
if (aMessage.name != 'DataStore:Get') {
return;
}
let prefName = 'dom.testing.datastore_enabled_for_hosted_apps';
if ((Services.prefs.getPrefType(prefName) == Services.prefs.PREF_INVALID ||
!Services.prefs.getBoolPref(prefName)) &&
!aMessage.target.assertAppHasStatus(Ci.nsIPrincipal.APP_STATUS_CERTIFIED)) {
return;
}
let msg = aMessage.data;
if (!aMessage.principal ||
aMessage.principal.appId == Ci.nsIScriptSecurityManager.UNKNOWN_APP_ID) {
aMessage.target.sendAsyncMessage("DataStore:Get:Return:KO");
return;
}
msg.stores = dataStoreService.getDataStoresInfo(msg.name, aMessage.principal.appId);
if (msg.stores === null) {
aMessage.target.sendAsyncMessage("DataStore:Get:Return:KO");
return;
}
aMessage.target.sendAsyncMessage("DataStore:Get:Return:OK", msg);
}
}
DataStoreServiceInternal.init();

View File

@ -5,6 +5,7 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
XPIDL_SOURCES += [
'nsIDataStore.idl',
'nsIDataStoreService.idl',
]
@ -13,11 +14,15 @@ XPIDL_MODULE = 'dom_datastore'
EXPORTS.mozilla.dom += [
'DataStore.h',
'DataStoreCursor.h',
'DataStoreService.h',
]
SOURCES += [
'DataStore.cpp',
'DataStoreCursor.cpp',
'DataStoreDB.cpp',
'DataStoreRevision.cpp',
'DataStoreService.cpp',
]
LOCAL_INCLUDES += [
@ -26,17 +31,18 @@ LOCAL_INCLUDES += [
EXTRA_COMPONENTS += [
'DataStore.manifest',
'DataStoreService.js',
'DataStoreImpl.js',
]
EXTRA_JS_MODULES += [
'DataStoreChangeNotifier.jsm',
'DataStoreCursorImpl.jsm',
'DataStoreDB.jsm',
'DataStoreImpl.jsm',
'DataStoreServiceInternal.jsm',
]
MOCHITEST_MANIFESTS += ['tests/mochitest.ini']
include('/ipc/chromium/chromium-config.mozbuild')
FINAL_LIBRARY = 'xul'
FAIL_ON_WARNINGS = True

View File

@ -0,0 +1,23 @@
/* -*- Mode: C++; 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/. */
#include "nsISupports.idl"
interface nsIDOMWindow;
// NOTE: This is a temporary interface.
// It will be removed in the next patches for rewriting DataStore in C++.
[scriptable, uuid(0b41fef5-14ba-48b0-923c-3d8fb64692ae)]
interface nsIDataStore : nsISupports
{
void init(in nsIDOMWindow window,
in DOMString name,
in DOMString manifestURL,
in boolean readOnly);
attribute jsval exposedObject;
void retrieveRevisionId(in jsval cb);
};

View File

@ -7,7 +7,7 @@
interface nsIDOMWindow;
[scriptable, uuid(bd02d09c-41ab-47b7-9319-57aa8e5059b0)]
[scriptable, uuid(0a050c4f-d292-4a14-8712-09bc1019840a)]
interface nsIDataStoreService : nsISupports
{
void installDataStore(in unsigned long appId,
@ -24,12 +24,4 @@ interface nsIDataStoreService : nsISupports
nsISupports getDataStores(in nsIDOMWindow window,
in DOMString name);
// This is an array of objects composed by:
// - readOnly: boolean
// - name: DOMString
// - owner: DOMString
// - enabled: true/false - true if this dataStore is ready to be used.
jsval getDataStoresInfo(in DOMString name,
in unsigned long appId);
};

View File

@ -0,0 +1,34 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Test for DataStore - bug 1008044</title>
</head>
<body>
<div id="container"></div>
<script type="application/javascript;version=1.7">
function is(a, b, msg) {
alert((a == b ? 'OK' : 'KO') + ' ' + msg)
}
function cbError() {
alert('KO error');
}
function finish() {
alert('DONE');
}
navigator.getDataStores('foo').then(function(stores) {
is (stores.length, 1, "Correct number of Stores");
is (stores[0].name, 'foo', "Correct name is received!");
stores[0].get(42).then(function(something) {
is (something, null, "Correct value");
finish();
}, cbError);
}, cbError);
</script>
</body>
</html>

View File

@ -29,6 +29,7 @@ support-files =
file_basic_common.js
file_sync_common.js
file_bug1008044.html
file_bug957086.html
[test_app_install.html]
[test_readonly.html]
@ -54,3 +55,4 @@ skip-if = (toolkit == 'gonk' && debug) #debug-only failure; time out
[test_oop_events.html]
[test_transactions.html]
[test_bug1008044.html]
[test_bug957086.html]

View File

@ -0,0 +1,135 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Test for DataStore - bug 957086</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<div id="container"></div>
<script type="application/javascript;version=1.7">
var gHostedManifestURL1 = 'http://test/tests/dom/datastore/tests/file_app.sjs?testToken=file_bug957086.html&template=file_app2.template.webapp';
var gHostedManifestURL2 = 'http://example.com/tests/dom/datastore/tests/file_app.sjs?testToken=file_bug957086.html';
var gApps = [];
function cbError() {
ok(false, "Error callback invoked");
finish();
}
function installApp(manifest) {
var request = navigator.mozApps.install(manifest);
request.onerror = cbError;
request.onsuccess = function() {
gApps.push(request.result);
runTest();
}
}
function uninstallApp() {
if (!gApps.length) {
// All done.
info("All done");
runTest();
return;
}
// Uninstall the app.
var request = navigator.mozApps.mgmt.uninstall(gApps.pop());
request.onerror = cbError;
request.onsuccess = uninstallApp;
}
function testApp() {
var ifr = document.createElement('iframe');
ifr.setAttribute('mozbrowser', 'true');
ifr.setAttribute('mozapp', gApps[0].manifestURL);
ifr.setAttribute('src', gApps[0].manifest.launch_path);
var domParent = document.getElementById('container');
// Set us up to listen for messages from the app.
var listener = function(e) {
var message = e.detail.message;
if (/^OK/.exec(message)) {
ok(true, "Message from app: " + message);
} else if (/KO/.exec(message)) {
ok(false, "Message from app: " + message);
} else if (/DONE/.exec(message)) {
ok(true, "Messaging from app complete");
ifr.removeEventListener('mozbrowsershowmodalprompt', listener);
domParent.removeChild(ifr);
runTest();
}
}
// This event is triggered when the app calls "alert".
ifr.addEventListener('mozbrowsershowmodalprompt', listener, false);
domParent.appendChild(ifr);
}
var tests = [
// Permissions
function() {
SpecialPowers.pushPermissions(
[{ "type": "browser", "allow": 1, "context": document },
{ "type": "embed-apps", "allow": 1, "context": document },
{ "type": "webapps-manage", "allow": 1, "context": document }], runTest);
},
// Preferences
function() {
SpecialPowers.pushPrefEnv({"set": [["dom.datastore.enabled", true],
["dom.ipc.browser_frames.oop_by_default", true],
["dom.testing.ignore_ipc_principal", true],
["dom.testing.datastore_enabled_for_hosted_apps", true]]}, runTest);
},
function() {
SpecialPowers.setAllAppsLaunchable(true);
SpecialPowers.setBoolPref("dom.mozBrowserFramesEnabled", true);
runTest();
},
// No confirmation needed when an app is installed
function() {
SpecialPowers.autoConfirmAppInstall(runTest);
},
// Installing the app - access only
function() { installApp(gHostedManifestURL1) },
// Installing the app - owner only
function() { installApp(gHostedManifestURL2) },
// Run tests in app
testApp,
// Uninstall the app
uninstallApp
];
function runTest() {
if (!tests.length) {
finish();
return;
}
var test = tests.shift();
test();
}
function finish() {
SimpleTest.finish();
}
if (SpecialPowers.isMainProcess()) {
SpecialPowers.Cu.import("resource://gre/modules/DataStoreChangeNotifier.jsm");
}
SimpleTest.waitForExplicitFinish();
runTest();
</script>
</body>
</html>

View File

@ -235,9 +235,6 @@ IDBFactory::Create(ContentParent* aContentParent,
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
NS_ASSERTION(nsContentUtils::IsCallerChrome(), "Only for chrome!");
NS_ASSERTION(aContentParent, "Null ContentParent!");
NS_ASSERTION(!nsContentUtils::GetCurrentJSContext(), "Should be called from C++");
// We need to get this information before we push a null principal to avoid
// IsCallerChrome() assertion in quota manager.

View File

@ -75,7 +75,7 @@ public:
IDBFactory** aFactory);
// Called when using IndexedDB from a JS component or a JSM in a different
// process.
// process or from a C++ component.
static nsresult Create(ContentParent* aContentParent,
IDBFactory** aFactory);

View File

@ -327,7 +327,7 @@ IDBRequest::WrapObject(JSContext* aCx)
}
JS::Value
IDBRequest::GetResult(JSContext* aCx, mozilla::ErrorResult& aRv) const
IDBRequest::GetResult(mozilla::ErrorResult& aRv) const
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");

View File

@ -132,7 +132,13 @@ public:
}
JS::Value
GetResult(JSContext* aCx, ErrorResult& aRv) const;
GetResult(ErrorResult& aRv) const;
JS::Value
GetResult(JSContext* aCx, ErrorResult& aRv) const
{
return GetResult(aRv);
}
IDBTransaction*
GetTransaction() const

View File

@ -24,7 +24,7 @@ interface nsIVariant;
* @see <http://www.whatwg.org/html/#window>
*/
[scriptable, uuid(fbefa573-0ba2-4d15-befb-d60277643a0b)]
[scriptable, uuid(d4316591-d16e-405c-8093-b441cbef3230)]
interface nsIDOMWindow : nsISupports
{
// the current browsing context
@ -151,7 +151,11 @@ interface nsIDOMWindow : nsISupports
}
%}
attribute nsIDOMWindow opener;
[implicit_jscontext, binaryname(ScriptableOpener)]
attribute jsval opener;
[noscript, binaryname(Opener)]
attribute nsIDOMWindow openerWindow;
/**
* |frameElement| gets this window's <iframe> or <frame> element, if it has

View File

@ -142,6 +142,7 @@
#include "nsDeviceStorage.h"
#include "AudioChannelService.h"
#include "JavaScriptChild.h"
#include "mozilla/dom/DataStoreService.h"
#include "mozilla/dom/telephony/PTelephonyChild.h"
#include "mozilla/dom/time/DateCacheCleaner.h"
#include "mozilla/net/NeckoMessageUtils.h"
@ -768,6 +769,24 @@ ContentChild::RecvAudioChannelNotify()
return true;
}
bool
ContentChild::RecvDataStoreNotify(const uint32_t& aAppId,
const nsString& aName,
const nsString& aManifestURL)
{
nsRefPtr<DataStoreService> service = DataStoreService::GetOrCreate();
if (NS_WARN_IF(!service)) {
return false;
}
nsresult rv = service->EnableDataStore(aAppId, aName, aManifestURL);
if (NS_WARN_IF(NS_FAILED(rv))) {
return false;
}
return true;
}
bool
ContentChild::DeallocPMemoryReportRequestChild(PMemoryReportRequestChild* actor)
{

View File

@ -157,6 +157,10 @@ public:
virtual bool
RecvAudioChannelNotify() MOZ_OVERRIDE;
virtual bool
RecvDataStoreNotify(const uint32_t& aAppId, const nsString& aName,
const nsString& aManifestURL) MOZ_OVERRIDE;
virtual PTestShellChild* AllocPTestShellChild() MOZ_OVERRIDE;
virtual bool DeallocPTestShellChild(PTestShellChild*) MOZ_OVERRIDE;
virtual bool RecvPTestShellConstructor(PTestShellChild*) MOZ_OVERRIDE;

View File

@ -33,6 +33,7 @@
#include "mozilla/ClearOnShutdown.h"
#include "mozilla/dom/asmjscache/AsmJSCache.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/DataStoreService.h"
#include "mozilla/dom/ExternalHelperAppParent.h"
#include "mozilla/dom/PFileDescriptorSetParent.h"
#include "mozilla/dom/PCycleCollectWithLogsParent.h"
@ -1504,6 +1505,7 @@ ContentParent::InitializeMembers()
mNumDestroyingTabs = 0;
mIsAlive = true;
mSendPermissionUpdates = false;
mSendDataStoreInfos = false;
mCalledClose = false;
mCalledCloseWithError = false;
mCalledKillHard = false;
@ -2085,6 +2087,26 @@ ContentParent::RecvAudioChannelChangeDefVolChannel(const int32_t& aChannel,
return true;
}
bool
ContentParent::RecvDataStoreGetStores(
const nsString& aName,
const IPC::Principal& aPrincipal,
InfallibleTArray<DataStoreSetting>* aValue)
{
nsRefPtr<DataStoreService> service = DataStoreService::GetOrCreate();
if (NS_WARN_IF(!service)) {
return false;
}
nsresult rv = service->GetDataStoresFromIPC(aName, aPrincipal, aValue);
if (NS_WARN_IF(NS_FAILED(rv))) {
return false;
}
mSendDataStoreInfos = true;
return true;
}
bool
ContentParent::RecvBroadcastVolume(const nsString& aVolumeName)
{

View File

@ -162,10 +162,14 @@ public:
int32_t Pid();
bool NeedsPermissionsUpdate() {
bool NeedsPermissionsUpdate() const {
return mSendPermissionUpdates;
}
bool NeedsDataStoreInfos() const {
return mSendDataStoreInfos;
}
BlobParent* GetOrCreateActorForBlob(nsIDOMBlob* aBlob);
/**
@ -532,6 +536,11 @@ private:
virtual bool RecvGetSystemMemory(const uint64_t& getterId) MOZ_OVERRIDE;
virtual bool RecvBroadcastVolume(const nsString& aVolumeName) MOZ_OVERRIDE;
virtual bool RecvDataStoreGetStores(
const nsString& aName,
const IPC::Principal& aPrincipal,
InfallibleTArray<DataStoreSetting>* aValue) MOZ_OVERRIDE;
virtual bool RecvSpeakerManagerGetSpeakerStatus(bool* aValue) MOZ_OVERRIDE;
virtual bool RecvSpeakerManagerForceSpeaker(const bool& aEnable) MOZ_OVERRIDE;
@ -606,6 +615,7 @@ private:
bool mIsAlive;
bool mSendPermissionUpdates;
bool mSendDataStoreInfos;
bool mIsForBrowser;
bool mIsNuwaProcess;

View File

@ -262,6 +262,14 @@ struct PrefSetting {
MaybePrefValue userValue;
};
struct DataStoreSetting {
nsString name;
nsString originURL;
nsString manifestURL;
bool readOnly;
bool enabled;
};
intr protocol PContent
{
parent opens PCompositor;
@ -338,6 +346,9 @@ child:
async SpeakerManagerNotify();
async DataStoreNotify(uint32_t aAppId, nsString aName,
nsString aManifestURL);
/**
* Dump this process's GC and CC logs to the provided files.
*
@ -550,6 +561,9 @@ parent:
async AudioChannelChangedNotification();
async AudioChannelChangeDefVolChannel(int32_t aChannel, bool aHidden);
sync DataStoreGetStores(nsString aName, Principal aPrincipal)
returns (DataStoreSetting[] dataStores);
async FilePathUpdateNotify(nsString aType,
nsString aStorageName,
nsString aFilepath,

View File

@ -108,3 +108,10 @@ dictionary DataStoreTask {
DataStoreKey? id;
any data;
};
// For internal use.
dictionary DataStoreRevisionData {
DOMString revisionId = "";
unsigned long objectId = 0;
DOMString operation = "";
};

View File

@ -54,7 +54,7 @@ typedef any Transferable;
[Replaceable, CrossOriginReadable] readonly attribute unsigned long length;
//[Unforgeable, Throws, CrossOriginReadable] readonly attribute WindowProxy top;
[Unforgeable, Throws, CrossOriginReadable] readonly attribute WindowProxy? top;
[Throws, CrossOriginReadable] attribute WindowProxy? opener;
[Throws, CrossOriginReadable] attribute any opener;
//[Throws] readonly attribute WindowProxy parent;
[Replaceable, Throws, CrossOriginReadable] readonly attribute WindowProxy? parent;
[Throws] readonly attribute Element? frameElement;

View File

@ -141,54 +141,11 @@ gfxUtils::UnpremultiplyDataSurface(DataSourceSurface* aSurface)
return dest;
}
void
gfxUtils::ConvertBGRAtoRGBA(gfxImageSurface *aSourceSurface,
gfxImageSurface *aDestSurface) {
if (!aDestSurface)
aDestSurface = aSourceSurface;
MOZ_ASSERT(aSourceSurface->Format() == aDestSurface->Format() &&
aSourceSurface->Width() == aDestSurface->Width() &&
aSourceSurface->Height() == aDestSurface->Height() &&
aSourceSurface->Stride() == aDestSurface->Stride(),
"Source and destination surfaces don't have identical characteristics");
MOZ_ASSERT(aSourceSurface->Stride() == aSourceSurface->Width() * 4,
"Source surface stride isn't tightly packed");
MOZ_ASSERT(aSourceSurface->Format() == gfxImageFormat::ARGB32 || aSourceSurface->Format() == gfxImageFormat::RGB24,
"Surfaces must be ARGB32 or RGB24");
uint8_t *src = aSourceSurface->Data();
uint8_t *dst = aDestSurface->Data();
uint32_t dim = aSourceSurface->Width() * aSourceSurface->Height();
uint8_t *srcEnd = src + 4*dim;
if (src == dst) {
uint8_t buffer[4];
for (; src != srcEnd; src += 4) {
buffer[0] = src[2];
buffer[1] = src[1];
buffer[2] = src[0];
src[0] = buffer[0];
src[1] = buffer[1];
src[2] = buffer[2];
}
} else {
for (; src != srcEnd; src += 4, dst += 4) {
dst[0] = src[2];
dst[1] = src[1];
dst[2] = src[0];
dst[3] = src[3];
}
}
}
void
gfxUtils::ConvertBGRAtoRGBA(uint8_t* aData, uint32_t aLength)
{
MOZ_ASSERT((aLength % 4) == 0, "Loop below will pass srcEnd!");
uint8_t *src = aData;
uint8_t *srcEnd = src + aLength;

View File

@ -43,8 +43,6 @@ public:
static void PremultiplyDataSurface(DataSourceSurface *aSurface);
static mozilla::TemporaryRef<DataSourceSurface> UnpremultiplyDataSurface(DataSourceSurface* aSurface);
static void ConvertBGRAtoRGBA(gfxImageSurface *aSourceSurface,
gfxImageSurface *aDestSurface = nullptr);
static void ConvertBGRAtoRGBA(uint8_t* aData, uint32_t aLength);
/**

View File

@ -302,6 +302,7 @@ typedef union jsval_layout
uint32_t boo; // Don't use |bool| -- it must be four bytes.
JSString *str;
JSObject *obj;
js::gc::Cell *cell;
void *ptr;
JSWhyMagic why;
size_t word;

View File

@ -19,6 +19,11 @@
#endif
#include "gc/Tracer.h"
/* Perform validation of incremental marking in debug builds but not on B2G. */
#if defined(DEBUG) && !defined(MOZ_B2G)
#define JS_GC_MARKING_VALIDATION
#endif
namespace js {
struct ScriptAndCounts
@ -410,7 +415,7 @@ class GCRuntime
*/
js::gc::ArenaHeader *arenasAllocatedDuringSweep;
#ifdef DEBUG
#ifdef JS_GC_MARKING_VALIDATION
js::gc::MarkingValidator *markingValidator;
#endif

View File

@ -192,6 +192,25 @@ function rsub_object(i) {
return i;
}
var uceFault_mod_number = eval(uneval(uceFault).replace('uceFault', 'uceFault_mod_number'));
function rmod_number(i) {
var x = i % 98;
if (uceFault_mod_number(i) || uceFault_mod_number(i))
assertEq(x, 1); /* 99 % 98 = 1 */
return i;
}
var uceFault_mod_object = eval(uneval(uceFault).replace('uceFault', 'uceFault_mod_object'));
function rmod_object(i) {
var t = i;
var o = { valueOf: function() { return t; } };
var x = o % 98; /* computed with t == i, not 1000 */
t = 1000;
if(uceFault_mod_object(i) || uceFault_mod_object(i))
assertEq(x, 1); /* 99 % 98 = 1 */
return i;
}
for (i = 0; i < 100; i++) {
rbitnot_number(i);
rbitnot_object(i);
@ -212,6 +231,8 @@ for (i = 0; i < 100; i++) {
rsub_number(i);
rsub_float(i);
rsub_object(i);
rmod_number(i);
rmod_object(i);
}
// Test that we can refer multiple time to the same recover instruction, as well

View File

@ -0,0 +1,73 @@
function testSubstrLatin1() {
var s1 = toLatin1("abcdefghijklmnopqrstuvwxyz12345678900000a");
// Static strings.
assertEq(s1.substr(s1.length - 1), "a");
assertEq(s1.substr(s1.length - 2), "0a");
assertEq(s1.substr(26, 3), "123");
// (Fat) inline strings.
var s2 = s1.substr(3, 5);
assertEq(isLatin1(s2), true);
assertEq(s2, "defgh");
s2 = s1.substr(0, 20);
assertEq(isLatin1(s2), true);
assertEq(s2, "abcdefghijklmnopqrst");
// Dependent string.
s2 = s1.substr(1, s1.length - 2);
assertEq(isLatin1(s2), true);
assertEq(s2.length, 39);
assertEq(s2, "bcdefghijklmnopqrstuvwxyz12345678900000");
s2 = s2.substr(2).substr(1);
assertEq(isLatin1(s2), true);
assertEq(s2, "efghijklmnopqrstuvwxyz12345678900000");
}
testSubstrLatin1();
function testSubstrTwoByte() {
// Two byte string.
var s1 = "abcdefghijklmnopqrstuvwxyz12345678900000a\u1480";
assertEq(isLatin1(s1), false);
// Static string.
var s2 = s1.substr(28, 1);
assertEq(s2, "3");
// Inline string.
s2 = s1.substr(3, 5);
assertEq(s2, "defgh");
// Dependent string.
s2 = s1.substr(2);
assertEq(isLatin1(s2), false);
assertEq(s2, "cdefghijklmnopqrstuvwxyz12345678900000a\u1480");
s2 = s2.substr(2).substr(1);
assertEq(isLatin1(s2), false);
assertEq(s2, "fghijklmnopqrstuvwxyz12345678900000a\u1480");
}
testSubstrTwoByte();
function testSubstring() {
var s1 = toLatin1("abcdefghijklmnopqrstuvwxyz123456789000ab");
var s2 = s1.substring(1, 8);
assertEq(isLatin1(s2), true);
assertEq(s2, "bcdefgh");
s2 = s1.substring(0, s1.length - 1);
assertEq(isLatin1(s2), true);
assertEq(s2, "abcdefghijklmnopqrstuvwxyz123456789000a");
}
testSubstring();
function testSlice() {
var s1 = toLatin1("abcdefghijklmnopqrstuvwxyz123456789000ABC");
var s2 = s1.slice(1, 8);
assertEq(isLatin1(s2), true);
assertEq(s2, "bcdefgh");
s2 = s1.slice(0, -2);
assertEq(isLatin1(s2), true);
assertEq(s2, "abcdefghijklmnopqrstuvwxyz123456789000A");
}
testSlice();

View File

@ -0,0 +1,31 @@
var s1 = toLatin1("abcdefg12345");
var s2 = toLatin1('foo"bar');
function test() {
assertEq(s1.valueOf(), s1);
assertEq(s1.bold(), "<b>abcdefg12345</b>");
assertEq(s1.fontsize("twoByte\u1400"), '<font size="twoByte\u1400">abcdefg12345</font>');
assertEq(s1.anchor(s1), '<a name="abcdefg12345">abcdefg12345</a>');
assertEq(s1.link(s2), '<a href="foo&quot;bar">abcdefg12345</a>');
assertEq(s1.concat("abc"), "abcdefg12345abc");
var s3 = s1.concat(s1, s1);
assertEq(isLatin1(s3), true);
assertEq(s3, "abcdefg12345abcdefg12345abcdefg12345");
s3 = s1.concat("twoByte\u1400");
assertEq(isLatin1(s3), false);
assertEq(s3, "abcdefg12345twoByte\u1400");
assertEq(s1.codePointAt(3), 100);
assertEq(s1.codePointAt(10), 52);
assertEq(s1.codePointAt(12), undefined);
s3 = s1.repeat(5);
assertEq(s3, "abcdefg12345abcdefg12345abcdefg12345abcdefg12345abcdefg12345");
assertEq(isLatin1(s3), true);
}
test();
test();

View File

@ -5990,9 +5990,11 @@ static const RegisterSet AllRegsExceptSP =
FloatRegisterSet(FloatRegisters::AllMask));
#if defined(JS_CODEGEN_ARM)
// The ARM system ABI also includes d15 in the non volatile float registers.
// Also exclude lr (a.k.a. r14) as we preserve it manually)
static const RegisterSet NonVolatileRegs =
RegisterSet(GeneralRegisterSet(Registers::NonVolatileMask),
FloatRegisterSet(FloatRegisters::NonVolatileMask | (1 << FloatRegisters::d15)));
RegisterSet(GeneralRegisterSet(Registers::NonVolatileMask &
~(uint32_t(1) << Registers::lr)),
FloatRegisterSet(FloatRegisters::NonVolatileMask | (1 << FloatRegisters::d15)));
#else
static const RegisterSet NonVolatileRegs =
RegisterSet(GeneralRegisterSet(Registers::NonVolatileMask),
@ -6017,7 +6019,7 @@ LoadJSContextFromActivation(MacroAssembler &masm, Register activation, Register
static void
AssertStackAlignment(MacroAssembler &masm)
{
JS_ASSERT((AlignmentAtPrologue + masm.framePushed()) % StackAlignment == 0);
JS_ASSERT((AlignmentAtAsmJSPrologue + masm.framePushed()) % StackAlignment == 0);
#ifdef DEBUG
Label ok;
JS_ASSERT(IsPowerOfTwo(StackAlignment));
@ -6042,7 +6044,7 @@ StackDecrementForCall(MacroAssembler &masm, unsigned bytesToPush)
{
// Include extra padding so that, after pushing the bytesToPush,
// the stack is aligned for a call instruction.
unsigned alreadyPushed = AlignmentAtPrologue + masm.framePushed();
unsigned alreadyPushed = AlignmentAtAsmJSPrologue + masm.framePushed();
return AlignBytes(alreadyPushed + bytesToPush, StackAlignment) - alreadyPushed;
}
@ -6078,6 +6080,14 @@ GenerateEntry(ModuleCompiler &m, const AsmJSModule::ExportedFunction &exportedFu
// NB: GenerateExits assumes that masm.framePushed() == 0 before
// PushRegsInMask(NonVolatileRegs).
masm.setFramePushed(0);
#if defined(JS_CODEGEN_ARM)
// Push lr without incrementing masm.framePushed since this push is
// accounted for by AlignmentAtAsmJSPrologue. The masm.ret at the end will
// pop.
masm.push(lr);
#endif // JS_CODEGEN_ARM
masm.PushRegsInMask(NonVolatileRegs);
JS_ASSERT(masm.framePushed() == FramePushedAfterSave);
@ -6174,7 +6184,7 @@ GenerateEntry(ModuleCompiler &m, const AsmJSModule::ExportedFunction &exportedFu
JS_ASSERT(masm.framePushed() == 0);
masm.move32(Imm32(true), ReturnReg);
masm.abiret();
masm.ret();
return true;
}
@ -6328,8 +6338,12 @@ GenerateFFIInterpreterExit(ModuleCompiler &m, const ModuleCompiler::ExitDescript
masm.align(CodeAlignment);
m.setInterpExitOffset(exitIndex);
masm.setFramePushed(0);
#if defined(JS_CODEGEN_ARM)
masm.Push(lr);
// Push lr without incrementing masm.framePushed since this push is
// accounted for by AlignmentAtAsmJSPrologue. The masm.ret at the end will
// pop.
masm.push(lr);
#endif
MIRType typeArray[] = { MIRType_Pointer, // cx
@ -6346,7 +6360,7 @@ GenerateFFIInterpreterExit(ModuleCompiler &m, const ModuleCompiler::ExitDescript
masm.reserveStack(stackDec);
// Fill the argument array.
unsigned offsetToCallerStackArgs = AlignmentAtPrologue + masm.framePushed();
unsigned offsetToCallerStackArgs = AlignmentAtAsmJSPrologue + masm.framePushed();
unsigned offsetToArgv = StackArgBytes(invokeArgTypes) + MaybeRetAddr;
Register scratch = ABIArgGenerator::NonArgReturnVolatileReg0;
FillArgumentArray(m, exit.sig().args(), offsetToArgv, offsetToCallerStackArgs, scratch);
@ -6499,14 +6513,16 @@ GenerateFFIIonExit(ModuleCompiler &m, const ModuleCompiler::ExitDescriptor &exit
#if defined(JS_CODEGEN_X64)
masm.Push(HeapReg);
#elif defined(JS_CODEGEN_ARM)
// The lr register holds the return address and needs to be saved. The GlobalReg
// (r10) and HeapReg (r11) also need to be restored before returning to asm.js code.
// Push lr without incrementing masm.framePushed since this push is
// accounted for by AlignmentAtAsmJSPrologue. The masm.ret at the end will
// pop.
masm.push(lr);
// The GlobalReg (r10) and HeapReg (r11) also need to be restored before
// returning to asm.js code.
// The NANReg also needs to be restored, but is a constant and is reloaded before
// returning to asm.js code.
masm.PushRegsInMask(RegisterSet(GeneralRegisterSet((1<<GlobalReg.code()) |
(1<<HeapReg.code()) |
(1<<lr.code())),
FloatRegisterSet(uint32_t(0))));
masm.PushRegsInMask(GeneralRegisterSet((1<<GlobalReg.code()) | (1<<HeapReg.code())));
#endif
// The stack frame is used for the call into Ion and also for calls into C for OOL
@ -6700,18 +6716,14 @@ GenerateFFIIonExit(ModuleCompiler &m, const ModuleCompiler::ExitDescriptor &exit
masm.bind(&done);
masm.freeStack(stackDec);
#if defined(JS_CODEGEN_X64)
masm.Pop(HeapReg);
#endif
#if defined(JS_CODEGEN_ARM)
masm.ma_vimm(GenericNaN(), NANReg);
masm.PopRegsInMask(RegisterSet(GeneralRegisterSet((1<<GlobalReg.code()) |
(1<<HeapReg.code()) |
(1<<pc.code())),
FloatRegisterSet(uint32_t(0))));
#else
# if defined(JS_CODEGEN_X64)
masm.Pop(HeapReg);
# endif
masm.ret();
masm.PopRegsInMask(GeneralRegisterSet((1<<GlobalReg.code()) | (1<<HeapReg.code())));
#endif
masm.ret();
JS_ASSERT(masm.framePushed() == 0);
// oolConvert
@ -6751,10 +6763,6 @@ GenerateStackOverflowExit(ModuleCompiler &m, Label *throwLabel)
masm.align(CodeAlignment);
masm.bind(&m.stackOverflowLabel());
// The overflow check always occurs before the initial function-specific
// stack-size adjustment. See CodeGenerator::generateAsmJSPrologue.
masm.setFramePushed(AlignmentMidPrologue - AlignmentAtPrologue);
MIRTypeVector argTypes(m.cx());
argTypes.infallibleAppend(MIRType_Pointer); // cx
@ -6924,7 +6932,7 @@ GenerateThrowExit(ModuleCompiler &m, Label *throwLabel)
JS_ASSERT(masm.framePushed() == 0);
masm.mov(ImmWord(0), ReturnReg);
masm.abiret();
masm.ret();
return !masm.oom();
}

View File

@ -8328,6 +8328,27 @@ CodeGenerator::visitGetDOMProperty(LGetDOMProperty *ins)
const Register PrivateReg = ToRegister(ins->getPrivReg());
const Register ValueReg = ToRegister(ins->getValueReg());
Label haveValue;
if (ins->mir()->valueMayBeInSlot()) {
size_t slot = ins->mir()->domMemberSlotIndex();
// It's a bit annoying to redo these slot calculations, which duplcate
// LSlots and a few other things like that, but I'm not sure there's a
// way to reuse those here.
if (slot < JSObject::MAX_FIXED_SLOTS) {
masm.loadValue(Address(ObjectReg, JSObject::getFixedSlotOffset(slot)),
JSReturnOperand);
} else {
// It's a dynamic slot.
slot -= JSObject::MAX_FIXED_SLOTS;
// Use PrivateReg as a scratch register for the slots pointer.
masm.loadPtr(Address(ObjectReg, JSObject::offsetOfSlots()),
PrivateReg);
masm.loadValue(Address(PrivateReg, slot*sizeof(js::Value)),
JSReturnOperand);
}
masm.branchTestUndefined(Assembler::NotEqual, JSReturnOperand, &haveValue);
}
DebugOnly<uint32_t> initialStack = masm.framePushed();
masm.checkStackAlignment();
@ -8377,6 +8398,8 @@ CodeGenerator::visitGetDOMProperty(LGetDOMProperty *ins)
}
masm.adjustStack(IonDOMExitFrameLayout::Size());
masm.bind(&haveValue);
JS_ASSERT(masm.framePushed() == initialStack);
return true;
}
@ -8660,7 +8683,7 @@ CodeGenerator::visitAsmJSCall(LAsmJSCall *ins)
if (mir->spIncrement())
masm.freeStack(mir->spIncrement());
JS_ASSERT((AlignmentAtPrologue + masm.framePushed()) % StackAlignment == 0);
JS_ASSERT((AlignmentAtAsmJSPrologue + masm.framePushed()) % StackAlignment == 0);
#ifdef DEBUG
Label ok;

View File

@ -8852,9 +8852,9 @@ IonBuilder::getPropTryCommonGetter(bool *emitted, MDefinition *obj, PropertyName
if (isDOM && testShouldDOMCall(objTypes, commonGetter, JSJitInfo::Getter)) {
const JSJitInfo *jitinfo = commonGetter->jitInfo();
MInstruction *get;
if (jitinfo->isInSlot) {
if (jitinfo->isAlwaysInSlot) {
// We can't use MLoadFixedSlot here because it might not have the
// right aliasing behavior; we want to alias DOM setters.
// right aliasing behavior; we want to alias DOM setters as needed.
get = MGetDOMMember::New(alloc(), jitinfo, obj, guard);
} else {
get = MGetDOMProperty::New(alloc(), jitinfo, obj, guard);

View File

@ -251,7 +251,7 @@ class MacroAssembler : public MacroAssemblerSpecific
}
}
// asm.js compilation handles its own IonContet-pushing
// asm.js compilation handles its own IonContext-pushing
struct AsmJSToken {};
explicit MacroAssembler(AsmJSToken)
: enoughMemory_(true),

View File

@ -4549,6 +4549,11 @@ class MMod : public MBinaryArithInstruction
return unsigned_;
}
bool writeRecoverData(CompactBufferWriter &writer) const;
bool canRecoverOnBailout() const {
return specialization_ < MIRType_Object;
}
bool fallible() const;
void computeRange(TempAllocator &alloc);
@ -8660,9 +8665,12 @@ class MGetDOMProperty
return info_->aliasSet();
}
size_t domMemberSlotIndex() const {
MOZ_ASSERT(info_->isInSlot);
MOZ_ASSERT(info_->isAlwaysInSlot || info_->isLazilyCachedInSlot);
return info_->slotIndex;
}
bool valueMayBeInSlot() const {
return info_->isLazilyCachedInSlot;
}
MDefinition *object() {
return getOperand(0);
}

View File

@ -364,6 +364,33 @@ RSub::recover(JSContext *cx, SnapshotIterator &iter) const
return true;
}
bool
MMod::writeRecoverData(CompactBufferWriter &writer) const
{
MOZ_ASSERT(canRecoverOnBailout());
writer.writeUnsigned(uint32_t(RInstruction::Recover_Mod));
return true;
}
RMod::RMod(CompactBufferReader &reader)
{ }
bool
RMod::recover(JSContext *cx, SnapshotIterator &iter) const
{
RootedValue lhs(cx, iter.read());
RootedValue rhs(cx, iter.read());
RootedValue result(cx);
MOZ_ASSERT(!lhs.isObject() && !rhs.isObject());
if (!js::ModValues(cx, &lhs, &rhs, &result))
return false;
iter.storeInstructionResult(result);
return true;
}
bool
MNewObject::writeRecoverData(CompactBufferWriter &writer) const
{

View File

@ -26,6 +26,7 @@ namespace jit {
_(Ursh) \
_(Add) \
_(Sub) \
_(Mod) \
_(NewObject) \
_(NewDerivedTypedObject)
@ -197,6 +198,18 @@ class RSub MOZ_FINAL : public RInstruction
bool recover(JSContext *cx, SnapshotIterator &iter) const;
};
class RMod MOZ_FINAL : public RInstruction
{
public:
RINSTRUCTION_HEADER_(Mod)
virtual uint32_t numOperands() const {
return 2;
}
bool recover(JSContext *cx, SnapshotIterator &iter) const;
};
class RNewObject MOZ_FINAL : public RInstruction
{
private:

View File

@ -139,9 +139,7 @@ static const uint32_t StackAlignment = 8;
static const uint32_t CodeAlignment = 8;
static const bool StackKeptAligned = true;
static const uint32_t NativeFrameSize = sizeof(void*);
static const uint32_t AlignmentAtPrologue = 0;
static const uint32_t AlignmentMidPrologue = 4;
static const uint32_t AlignmentAtAsmJSPrologue = sizeof(void*);
static const Scale ScalePointer = TimesFour;

View File

@ -53,7 +53,7 @@ CodeGeneratorARM::generateAsmJSPrologue(Label *stackOverflowLabel)
{
JS_ASSERT(gen->compilingAsmJS());
masm.Push(lr);
masm.push(lr);
// The asm.js over-recursed handler wants to be able to assume that SP
// points to the return address, so perform the check after pushing lr but
@ -85,18 +85,12 @@ CodeGeneratorARM::generateEpilogue()
}
#endif
if (gen->compilingAsmJS()) {
// Pop the stack we allocated at the start of the function.
if (gen->compilingAsmJS())
masm.freeStack(frameDepth_);
masm.Pop(pc);
JS_ASSERT(masm.framePushed() == 0);
//masm.as_bkpt();
} else {
// Pop the stack we allocated at the start of the function.
else
masm.freeStack(frameSize());
JS_ASSERT(masm.framePushed() == 0);
masm.ma_pop(pc);
}
JS_ASSERT(masm.framePushed() == 0);
masm.pop(pc);
masm.dumpPool();
return true;
}
@ -1047,14 +1041,8 @@ CodeGeneratorARM::toMoveOperand(const LAllocation *a) const
return MoveOperand(ToRegister(a));
if (a->isFloatReg())
return MoveOperand(ToFloatRegister(a));
JS_ASSERT((ToStackOffset(a) & 3) == 0);
int32_t offset = ToStackOffset(a);
// The way the stack slots work, we assume that everything from depth == 0 downwards is writable
// however, since our frame is included in this, ensure that the frame gets skipped
if (gen->compilingAsmJS())
offset -= AlignmentMidPrologue;
JS_ASSERT((offset & 3) == 0);
return MoveOperand(StackPointer, offset);
}

View File

@ -3867,7 +3867,7 @@ void MacroAssemblerARMCompat::checkStackAlignment()
}
void
MacroAssemblerARMCompat::callWithABIPre(uint32_t *stackAdjust)
MacroAssemblerARMCompat::callWithABIPre(uint32_t *stackAdjust, bool callFromAsmJS)
{
JS_ASSERT(inCall_);
@ -3876,8 +3876,11 @@ MacroAssemblerARMCompat::callWithABIPre(uint32_t *stackAdjust)
if (useHardFpABI())
*stackAdjust += 2*((usedFloatSlots_ > NumFloatArgRegs) ? usedFloatSlots_ - NumFloatArgRegs : 0) * sizeof(intptr_t);
#endif
uint32_t alignmentAtPrologue = (callFromAsmJS) ? AlignmentAtAsmJSPrologue : 0;
if (!dynamicAlignment_) {
*stackAdjust += ComputeByteAlignment(framePushed_ + *stackAdjust, StackAlignment);
*stackAdjust += ComputeByteAlignment(framePushed_ + *stackAdjust + alignmentAtPrologue,
StackAlignment);
} else {
// sizeof(intptr_t) account for the saved stack pointer pushed by setupUnalignedABICall
*stackAdjust += ComputeByteAlignment(*stackAdjust + sizeof(intptr_t), StackAlignment);
@ -4021,7 +4024,7 @@ void
MacroAssemblerARMCompat::callWithABI(AsmJSImmPtr imm, MoveOp::Type result)
{
uint32_t stackAdjust;
callWithABIPre(&stackAdjust);
callWithABIPre(&stackAdjust, /* callFromAsmJS = */ true);
call(imm);
callWithABIPost(stackAdjust, result);
}

View File

@ -453,9 +453,9 @@ private:
class MacroAssemblerARMCompat : public MacroAssemblerARM
{
bool inCall_;
// Number of bytes the stack is adjusted inside a call to C. Calls to C may
// not be nested.
bool inCall_;
uint32_t args_;
// The actual number of arguments that were passed, used to assert that
// the initial number of arguments declared was correct.
@ -576,7 +576,9 @@ class MacroAssemblerARMCompat : public MacroAssemblerARM
}
void appendCallSite(const CallSiteDesc &desc) {
enoughMemory_ &= append(CallSite(desc, currentOffset(), framePushed_));
// Add an extra sizeof(void*) to include the return address that was
// pushed by the call instruction (see CallSite::stackDepth).
enoughMemory_ &= append(CallSite(desc, currentOffset(), framePushed_ + sizeof(void*)));
}
void call(const CallSiteDesc &desc, const Register reg) {
@ -1530,7 +1532,7 @@ class MacroAssemblerARMCompat : public MacroAssemblerARM
bool buildOOLFakeExitFrame(void *fakeReturnAddr);
private:
void callWithABIPre(uint32_t *stackAdjust);
void callWithABIPre(uint32_t *stackAdjust, bool callFromAsmJS = false);
void callWithABIPost(uint32_t stackAdjust, MoveOp::Type result);
public:

View File

@ -138,7 +138,7 @@ static const uint32_t CodeAlignment = 4;
static const bool StackKeptAligned = true;
// NativeFrameSize is the size of return adress on stack in AsmJS functions.
static const uint32_t NativeFrameSize = sizeof(void*);
static const uint32_t AlignmentAtPrologue = 0;
static const uint32_t AlignmentAtAsmJSPrologue = 0;
static const uint32_t AlignmentMidPrologue = NativeFrameSize;
static const Scale ScalePointer = TimesFour;

View File

@ -74,7 +74,7 @@ CodeGeneratorShared::CodeGeneratorShared(MIRGenerator *gen, LIRGraph *graph, Mac
bool forceAlign = false;
#endif
if (gen->needsInitialStackAlignment() || forceAlign) {
unsigned alignmentAtCall = AlignmentMidPrologue + frameDepth_;
unsigned alignmentAtCall = AlignmentAtAsmJSPrologue + frameDepth_;
if (unsigned rem = alignmentAtCall % StackAlignment) {
frameInitialAdjustment_ = StackAlignment - rem;
frameDepth_ += frameInitialAdjustment_;

View File

@ -183,8 +183,7 @@ static const uint32_t StackAlignment = 16;
static const bool StackKeptAligned = false;
static const uint32_t CodeAlignment = 8;
static const uint32_t NativeFrameSize = sizeof(void*);
static const uint32_t AlignmentAtPrologue = sizeof(void*);
static const uint32_t AlignmentMidPrologue = AlignmentAtPrologue;
static const uint32_t AlignmentAtAsmJSPrologue = sizeof(void*);
static const Scale ScalePointer = TimesEight;

View File

@ -111,8 +111,7 @@ static const uint32_t StackAlignment = 4;
static const bool StackKeptAligned = false;
static const uint32_t CodeAlignment = 8;
static const uint32_t NativeFrameSize = sizeof(void*);
static const uint32_t AlignmentAtPrologue = sizeof(void*);
static const uint32_t AlignmentMidPrologue = AlignmentAtPrologue;
static const uint32_t AlignmentAtAsmJSPrologue = sizeof(void*);
struct ImmTag : public Imm32
{
ImmTag(JSValueTag mask)

View File

@ -1880,12 +1880,18 @@ struct JSJitInfo {
not be enough (e.g. in cases when it can
throw). */
// XXXbz should we have a JSValueType for the type of the member?
uint32_t isInSlot : 1; /* True if this is a getter that can get a member
from a slot of the "this" object directly. */
uint32_t isAlwaysInSlot : 1; /* True if this is a getter that can always
get the value from a slot of the "this"
object. */
uint32_t isLazilyCachedInSlot : 1; /* True if this is a getter that can
sometimes (if the slot doesn't contain
UndefinedValue()) get the value from a
slot of the "this" object. */
uint32_t isTypedMethod : 1; /* True if this is an instance of
JSTypedMethodJitInfo. */
uint32_t slotIndex : 12; /* If isInSlot is true, the index of the slot to
get the value from. Otherwise 0. */
uint32_t slotIndex : 11; /* If isAlwaysInSlot or isSometimesInSlot is
true, the index of the slot to get the value
from. Otherwise 0. */
};
static_assert(sizeof(JSJitInfo) == (sizeof(void*) + 2 * sizeof(uint32_t)),
@ -1943,7 +1949,7 @@ inline int CheckIsParallelNative(JSParallelNative parallelNative);
*/
#define JS_JITINFO_NATIVE_PARALLEL(infoName, parallelOp) \
const JSJitInfo infoName = \
{{JS_CAST_PARALLEL_NATIVE_TO(parallelOp, JSJitGetterOp)},0,0,JSJitInfo::ParallelNative,JSJitInfo::AliasEverything,JSVAL_TYPE_MISSING,false,false,false,false,0}
{{JS_CAST_PARALLEL_NATIVE_TO(parallelOp, JSJitGetterOp)},0,0,JSJitInfo::ParallelNative,JSJitInfo::AliasEverything,JSVAL_TYPE_MISSING,false,false,false,false,false,0}
#define JS_JITINFO_NATIVE_PARALLEL_THREADSAFE(infoName, wrapperName, serialOp) \
bool wrapperName##_ParallelNativeThreadSafeWrapper(js::ForkJoinContext *cx, unsigned argc, \

View File

@ -1086,7 +1086,7 @@ GCRuntime::GCRuntime(JSRuntime *rt) :
sweepKindIndex(0),
abortSweepAfterCurrentGroup(false),
arenasAllocatedDuringSweep(nullptr),
#ifdef DEBUG
#ifdef JS_GC_MARKING_VALIDATION
markingValidator(nullptr),
#endif
interFrameGC(0),
@ -3159,6 +3159,10 @@ class js::gc::MarkingValidator
BitmapMap map;
};
#endif // DEBUG
#ifdef JS_GC_MARKING_VALIDATION
js::gc::MarkingValidator::MarkingValidator(GCRuntime *gc)
: gc(gc),
initialized(false)
@ -3347,12 +3351,12 @@ js::gc::MarkingValidator::validate()
}
}
#endif
#endif // JS_GC_MARKING_VALIDATION
void
GCRuntime::computeNonIncrementalMarkingForValidation()
{
#ifdef DEBUG
#ifdef JS_GC_MARKING_VALIDATION
JS_ASSERT(!markingValidator);
if (isIncremental && validate)
markingValidator = js_new<MarkingValidator>(this);
@ -3364,7 +3368,7 @@ GCRuntime::computeNonIncrementalMarkingForValidation()
void
GCRuntime::validateIncrementalMarking()
{
#ifdef DEBUG
#ifdef JS_GC_MARKING_VALIDATION
if (markingValidator)
markingValidator->validate();
#endif
@ -3373,7 +3377,7 @@ GCRuntime::validateIncrementalMarking()
void
GCRuntime::finishMarkingValidation()
{
#ifdef DEBUG
#ifdef JS_GC_MARKING_VALIDATION
js_delete(markingValidator);
markingValidator = nullptr;
#endif
@ -3382,7 +3386,7 @@ GCRuntime::finishMarkingValidation()
static void
AssertNeedsBarrierFlagsConsistent(JSRuntime *rt)
{
#ifdef DEBUG
#ifdef JS_GC_MARKING_VALIDATION
bool anyNeedsBarrier = false;
for (ZonesIter zone(rt, WithAtoms); !zone.done(); zone.next())
anyNeedsBarrier |= zone->needsBarrier();

View File

@ -4082,12 +4082,19 @@ js_NewDependentString(JSContext *cx, JSString *baseArg, size_t start, size_t len
if (start == 0 && length == base->length())
return base;
const jschar *chars = base->chars() + start;
if (base->hasTwoByteChars()) {
AutoCheckCannotGC nogc;
const jschar *chars = base->twoByteChars(nogc) + start;
if (JSLinearString *staticStr = cx->staticStrings().lookup(chars, length))
return staticStr;
} else {
AutoCheckCannotGC nogc;
const Latin1Char *chars = base->latin1Chars(nogc) + start;
if (JSLinearString *staticStr = cx->staticStrings().lookup(chars, length))
return staticStr;
}
if (JSLinearString *staticStr = cx->staticStrings().lookup(chars, length))
return staticStr;
return JSDependentString::new_(cx, base, chars, length);
return JSDependentString::new_(cx, base, start, length);
}
template <AllowGC allowGC>

View File

@ -5250,7 +5250,8 @@ static const JSJitInfo dom_x_getterinfo = {
JSVAL_TYPE_UNKNOWN, /* returnType */
true, /* isInfallible. False in setters. */
true, /* isMovable */
false, /* isInSlot */
false, /* isAlwaysInSlot */
false, /* isLazilyCachedInSlot */
false, /* isTypedMethod */
0 /* slotIndex */
};
@ -5264,7 +5265,8 @@ static const JSJitInfo dom_x_setterinfo = {
JSVAL_TYPE_UNKNOWN, /* returnType */
false, /* isInfallible. False in setters. */
false, /* isMovable. */
false, /* isInSlot */
false, /* isAlwaysInSlot */
false, /* isLazilyCachedInSlot */
false, /* isTypedMethod */
0 /* slotIndex */
};
@ -5278,7 +5280,8 @@ static const JSJitInfo doFoo_methodinfo = {
JSVAL_TYPE_UNKNOWN, /* returnType */
false, /* isInfallible. False in setters. */
false, /* isMovable */
false, /* isInSlot */
false, /* isAlwaysInSlot */
false, /* isLazilyCachedInSlot */
false, /* isTypedMethod */
0 /* slotIndex */
};

View File

@ -19,27 +19,37 @@
namespace js {
template <AllowGC allowGC, typename CharT>
static MOZ_ALWAYS_INLINE JSInlineString *
AllocateFatInlineString(ThreadSafeContext *cx, size_t len, CharT **chars)
{
MOZ_ASSERT(JSFatInlineString::lengthFits<CharT>(len));
if (JSInlineString::lengthFits<CharT>(len)) {
JSInlineString *str = JSInlineString::new_<allowGC>(cx);
if (!str)
return nullptr;
*chars = str->init<CharT>(len);
return str;
}
JSFatInlineString *str = JSFatInlineString::new_<allowGC>(cx);
if (!str)
return nullptr;
*chars = str->init<CharT>(len);
return str;
}
template <AllowGC allowGC>
static MOZ_ALWAYS_INLINE JSInlineString *
NewFatInlineString(ThreadSafeContext *cx, JS::Latin1Chars chars)
{
size_t len = chars.length();
JS_ASSERT(JSFatInlineString::twoByteLengthFits(len));
JSInlineString *str;
jschar *p;
if (JSInlineString::twoByteLengthFits(len)) {
str = JSInlineString::new_<allowGC>(cx);
if (!str)
return nullptr;
p = str->initTwoByte(len);
} else {
JSFatInlineString *fatstr = JSFatInlineString::new_<allowGC>(cx);
if (!fatstr)
return nullptr;
p = fatstr->initTwoByte(len);
str = fatstr;
}
JSInlineString *str = AllocateFatInlineString<allowGC>(cx, len, &p);
if (!str)
return nullptr;
for (size_t i = 0; i < len; ++i)
p[i] = static_cast<jschar>(chars[i]);
@ -51,34 +61,39 @@ template <AllowGC allowGC>
static MOZ_ALWAYS_INLINE JSInlineString *
NewFatInlineString(ExclusiveContext *cx, JS::TwoByteChars chars)
{
size_t len = chars.length();
/*
* Don't bother trying to find a static atom; measurement shows that not
* many get here (for one, Atomize is catching them).
*/
JS_ASSERT(JSFatInlineString::twoByteLengthFits(len));
JSInlineString *str;
size_t len = chars.length();
jschar *storage;
if (JSInlineString::twoByteLengthFits(len)) {
str = JSInlineString::new_<allowGC>(cx);
if (!str)
return nullptr;
storage = str->initTwoByte(len);
} else {
JSFatInlineString *fatstr = JSFatInlineString::new_<allowGC>(cx);
if (!fatstr)
return nullptr;
storage = fatstr->initTwoByte(len);
str = fatstr;
}
JSInlineString *str = AllocateFatInlineString<allowGC>(cx, len, &storage);
if (!str)
return nullptr;
mozilla::PodCopy(storage, chars.start().get(), len);
storage[len] = 0;
return str;
}
template <typename CharT>
static MOZ_ALWAYS_INLINE JSInlineString *
NewFatInlineString(ExclusiveContext *cx, Handle<JSLinearString*> base, size_t start, size_t length)
{
MOZ_ASSERT(JSFatInlineString::lengthFits<CharT>(length));
CharT *chars;
JSInlineString *s = AllocateFatInlineString<CanGC>(cx, length, &chars);
if (!s)
return nullptr;
AutoCheckCannotGC nogc;
mozilla::PodCopy(chars, base->chars<CharT>(nogc) + start, length);
chars[length] = 0;
return s;
}
static inline void
StringWriteBarrierPost(js::ThreadSafeContext *maybecx, JSString **strp)
{
@ -139,52 +154,55 @@ JSRope::markChildren(JSTracer *trc)
}
MOZ_ALWAYS_INLINE void
JSDependentString::init(js::ThreadSafeContext *cx, JSLinearString *base, const jschar *chars,
JSDependentString::init(js::ThreadSafeContext *cx, JSLinearString *base, size_t start,
size_t length)
{
JS_ASSERT(!js::IsPoisonedPtr(base));
MOZ_ASSERT(!js::IsPoisonedPtr(base));
MOZ_ASSERT(start + length <= base->length());
d.u1.length = length;
d.u1.flags = DEPENDENT_FLAGS;
d.s.u2.nonInlineCharsTwoByte = chars;
JS::AutoCheckCannotGC nogc;
if (base->hasLatin1Chars()) {
d.u1.flags = DEPENDENT_FLAGS | LATIN1_CHARS_BIT;
d.s.u2.nonInlineCharsLatin1 = base->latin1Chars(nogc) + start;
} else {
d.u1.flags = DEPENDENT_FLAGS;
d.s.u2.nonInlineCharsTwoByte = base->twoByteChars(nogc) + start;
}
d.s.u3.base = base;
js::StringWriteBarrierPost(cx, reinterpret_cast<JSString **>(&d.s.u3.base));
}
MOZ_ALWAYS_INLINE JSLinearString *
JSDependentString::new_(js::ExclusiveContext *cx,
JSLinearString *baseArg, const jschar *chars, size_t length)
JSDependentString::new_(js::ExclusiveContext *cx, JSLinearString *baseArg, size_t start,
size_t length)
{
/* Try to avoid long chains of dependent strings. */
while (baseArg->isDependent())
while (baseArg->isDependent()) {
start += baseArg->asDependent().baseOffset();
baseArg = baseArg->asDependent().base();
JS_ASSERT(baseArg->isFlat());
/*
* The chars we are pointing into must be owned by something in the chain
* of dependent or undepended strings kept alive by our base pointer.
*/
#ifdef DEBUG
for (JSLinearString *b = baseArg; ; b = b->base()) {
if (chars >= b->chars() && chars < b->chars() + b->length() &&
length <= b->length() - (chars - b->chars()))
{
break;
}
}
#endif
MOZ_ASSERT(start + length <= baseArg->length());
MOZ_ASSERT(baseArg->isFlat());
/*
* Do not create a string dependent on inline chars from another string,
* both to avoid the awkward moving-GC hazard this introduces and because it
* is more efficient to immediately undepend here.
*/
if (JSFatInlineString::twoByteLengthFits(length))
return js::NewFatInlineString<js::CanGC>(cx, JS::TwoByteChars(chars, length));
bool useFatInline = baseArg->hasTwoByteChars()
? JSFatInlineString::twoByteLengthFits(length)
: JSFatInlineString::latin1LengthFits(length);
if (useFatInline) {
JS::Rooted<JSLinearString*> base(cx, baseArg);
if (baseArg->hasLatin1Chars())
return js::NewFatInlineString<JS::Latin1Char>(cx, base, start, length);
return js::NewFatInlineString<jschar>(cx, base, start, length);
}
JSDependentString *str = (JSDependentString *)js_NewGCString<js::NoGC>(cx);
if (str) {
str->init(cx, baseArg, chars, length);
str->init(cx, baseArg, start, length);
return str;
}
@ -193,7 +211,7 @@ JSDependentString::new_(js::ExclusiveContext *cx,
str = (JSDependentString *)js_NewGCString<js::CanGC>(cx);
if (!str)
return nullptr;
str->init(cx, base, chars, length);
str->init(cx, base, start, length);
return str;
}
@ -285,6 +303,34 @@ JSFatInlineString::initLatin1(size_t length)
return d.inlineStorageLatin1;
}
template<>
MOZ_ALWAYS_INLINE JS::Latin1Char *
JSInlineString::init<JS::Latin1Char>(size_t length)
{
return initLatin1(length);
}
template<>
MOZ_ALWAYS_INLINE jschar *
JSInlineString::init<jschar>(size_t length)
{
return initTwoByte(length);
}
template<>
MOZ_ALWAYS_INLINE JS::Latin1Char *
JSFatInlineString::init<JS::Latin1Char>(size_t length)
{
return initLatin1(length);
}
template<>
MOZ_ALWAYS_INLINE jschar *
JSFatInlineString::init<jschar>(size_t length)
{
return initTwoByte(length);
}
template <js::AllowGC allowGC>
MOZ_ALWAYS_INLINE JSFatInlineString *
JSFatInlineString::new_(js::ThreadSafeContext *cx)

View File

@ -627,6 +627,10 @@ class JSLinearString : public JSString
MOZ_ALWAYS_INLINE
const jschar *chars() const;
template<typename CharT>
MOZ_ALWAYS_INLINE
const CharT *chars(const JS::AutoCheckCannotGC &nogc) const;
MOZ_ALWAYS_INLINE
const JS::Latin1Char *latin1Chars(const JS::AutoCheckCannotGC &nogc) const;
@ -659,7 +663,7 @@ class JSDependentString : public JSLinearString
friend class JSString;
JSFlatString *undepend(js::ExclusiveContext *cx);
void init(js::ThreadSafeContext *cx, JSLinearString *base, const jschar *chars,
void init(js::ThreadSafeContext *cx, JSLinearString *base, size_t start,
size_t length);
/* Vacuous and therefore unimplemented. */
@ -669,9 +673,22 @@ class JSDependentString : public JSLinearString
/* Hide chars(), nonInlineChars() is more efficient. */
const jschar *chars() const MOZ_DELETE;
/* The offset of this string's chars in base->chars(). */
size_t baseOffset() const {
MOZ_ASSERT(JSString::isDependent());
JS::AutoCheckCannotGC nogc;
size_t offset;
if (hasTwoByteChars())
offset = twoByteChars(nogc) - base()->twoByteChars(nogc);
else
offset = latin1Chars(nogc) - base()->latin1Chars(nogc);
MOZ_ASSERT(offset < base()->length());
return offset;
}
public:
static inline JSLinearString *new_(js::ExclusiveContext *cx, JSLinearString *base,
const jschar *chars, size_t length);
size_t start, size_t length);
};
JS_STATIC_ASSERT(sizeof(JSDependentString) == sizeof(JSString));
@ -770,6 +787,9 @@ class JSInlineString : public JSFlatString
inline jschar *initTwoByte(size_t length);
inline JS::Latin1Char *initLatin1(size_t length);
template <typename CharT>
inline CharT *init(size_t length);
inline void resetLength(size_t length);
MOZ_ALWAYS_INLINE
@ -800,6 +820,9 @@ class JSInlineString : public JSFlatString
return length <= MAX_LENGTH_TWO_BYTE;
}
template<typename CharT>
static bool lengthFits(size_t length);
static size_t offsetOfInlineStorage() {
return offsetof(JSInlineString, d.inlineStorageTwoByte);
}
@ -859,6 +882,9 @@ class JSFatInlineString : public JSInlineString
inline jschar *initTwoByte(size_t length);
inline JS::Latin1Char *initLatin1(size_t length);
template <typename CharT>
inline CharT *init(size_t length);
static bool latin1LengthFits(size_t length) {
return length <= MAX_LENGTH_LATIN1;
}
@ -866,6 +892,9 @@ class JSFatInlineString : public JSInlineString
return length <= MAX_LENGTH_TWO_BYTE;
}
template<typename CharT>
static bool lengthFits(size_t length);
/* Only called by the GC for strings with the FINALIZE_FAT_INLINE_STRING kind. */
MOZ_ALWAYS_INLINE void finalize(js::FreeOp *fop);
@ -1045,7 +1074,8 @@ class StaticStrings
static bool isStatic(JSAtom *atom);
/* Return null if no static atom exists for the given (chars, length). */
JSAtom *lookup(const jschar *chars, size_t length) {
template <typename CharT>
JSAtom *lookup(const CharT *chars, size_t length) {
switch (length) {
case 1:
if (chars[0] < UNIT_STATIC_LIMIT)
@ -1264,6 +1294,48 @@ JSLinearString::nonInlineChars(const JS::AutoCheckCannotGC &nogc) const
return nonInlineLatin1Chars(nogc);
}
template<>
MOZ_ALWAYS_INLINE const jschar *
JSLinearString::chars(const JS::AutoCheckCannotGC &nogc) const
{
return twoByteChars(nogc);
}
template<>
MOZ_ALWAYS_INLINE const JS::Latin1Char *
JSLinearString::chars(const JS::AutoCheckCannotGC &nogc) const
{
return latin1Chars(nogc);
}
template<>
MOZ_ALWAYS_INLINE bool
JSInlineString::lengthFits<JS::Latin1Char>(size_t length)
{
return latin1LengthFits(length);
}
template<>
MOZ_ALWAYS_INLINE bool
JSInlineString::lengthFits<jschar>(size_t length)
{
return twoByteLengthFits(length);
}
template<>
MOZ_ALWAYS_INLINE bool
JSFatInlineString::lengthFits<JS::Latin1Char>(size_t length)
{
return latin1LengthFits(length);
}
template<>
MOZ_ALWAYS_INLINE bool
JSFatInlineString::lengthFits<jschar>(size_t length)
{
return twoByteLengthFits(length);
}
template<>
MOZ_ALWAYS_INLINE void
JSString::setNonInlineChars(const jschar *chars)

View File

@ -1674,6 +1674,10 @@ ContainerState::FindOpaqueBackgroundColorFor(int32_t aThebesLayerIndex)
break;
}
if (item->IsInvisibleInRect(appUnitRect)) {
continue;
}
nscolor color;
if (item->IsUniform(mBuilder, &color) && NS_GET_A(color) == 255)
return color;

View File

@ -1709,6 +1709,15 @@ nsDisplayItem::ZIndex() const
return 0;
}
bool
nsDisplayItem::ComputeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion,
const nsRect& aAllowVisibleRegionExpansion)
{
return !mVisibleRect.IsEmpty() &&
!IsInvisibleInRect(aVisibleRegion->GetBounds());
}
bool
nsDisplayItem::RecomputeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion) {
@ -2646,26 +2655,20 @@ nsDisplayOutline::Paint(nsDisplayListBuilder* aBuilder,
}
bool
nsDisplayOutline::ComputeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion,
const nsRect& aAllowVisibleRegionExpansion) {
if (!nsDisplayItem::ComputeVisibility(aBuilder, aVisibleRegion,
aAllowVisibleRegionExpansion)) {
return false;
}
nsDisplayOutline::IsInvisibleInRect(const nsRect& aRect)
{
const nsStyleOutline* outline = mFrame->StyleOutline();
nsRect borderBox(ToReferenceFrame(), mFrame->GetSize());
if (borderBox.Contains(aVisibleRegion->GetBounds()) &&
if (borderBox.Contains(aRect) &&
!nsLayoutUtils::HasNonZeroCorner(outline->mOutlineRadius)) {
if (outline->mOutlineOffset >= 0) {
// the visible region is entirely inside the border-rect, and the outline
// isn't rendered inside the border-rect, so the outline is not visible
return false;
// aRect is entirely inside the border-rect, and the outline isn't
// rendered inside the border-rect, so the outline is not visible.
return true;
}
}
return true;
return false;
}
void
@ -2725,30 +2728,24 @@ nsDisplayCaret::Paint(nsDisplayListBuilder* aBuilder,
}
bool
nsDisplayBorder::ComputeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion,
const nsRect& aAllowVisibleRegionExpansion) {
if (!nsDisplayItem::ComputeVisibility(aBuilder, aVisibleRegion,
aAllowVisibleRegionExpansion)) {
return false;
}
nsDisplayBorder::IsInvisibleInRect(const nsRect& aRect)
{
nsRect paddingRect = mFrame->GetPaddingRect() - mFrame->GetPosition() +
ToReferenceFrame();
const nsStyleBorder *styleBorder;
if (paddingRect.Contains(aVisibleRegion->GetBounds()) &&
if (paddingRect.Contains(aRect) &&
!(styleBorder = mFrame->StyleBorder())->IsBorderImageLoaded() &&
!nsLayoutUtils::HasNonZeroCorner(styleBorder->mBorderRadius)) {
// the visible region is entirely inside the content rect, and no part
// aRect is entirely inside the content rect, and no part
// of the border is rendered inside the content rect, so we are not
// visible
// Skip this if there's a border-image (which draws a background
// too) or if there is a border-radius (which makes the border draw
// further in).
return false;
return true;
}
return true;
return false;
}
nsDisplayItemGeometry*
@ -2879,6 +2876,24 @@ nsDisplayBoxShadowOuter::GetBoundsInternal() {
ToReferenceFrame();
}
bool
nsDisplayBoxShadowOuter::IsInvisibleInRect(const nsRect& aRect)
{
nsPoint origin = ToReferenceFrame();
nsRect frameRect(origin, mFrame->GetSize());
if (!frameRect.Contains(aRect))
return false;
// the visible region is entirely inside the border-rect, and box shadows
// never render within the border-rect (unless there's a border radius).
nscoord twipsRadii[8];
bool hasBorderRadii = mFrame->GetBorderRadii(twipsRadii);
if (!hasBorderRadii)
return true;
return RoundedRectContainsRect(frameRect, twipsRadii, aRect);
}
bool
nsDisplayBoxShadowOuter::ComputeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion,
@ -2890,21 +2905,7 @@ nsDisplayBoxShadowOuter::ComputeVisibility(nsDisplayListBuilder* aBuilder,
// Store the actual visible region
mVisibleRegion.And(*aVisibleRegion, mVisibleRect);
nsPoint origin = ToReferenceFrame();
nsRect visibleBounds = aVisibleRegion->GetBounds();
nsRect frameRect(origin, mFrame->GetSize());
if (!frameRect.Contains(visibleBounds))
return true;
// the visible region is entirely inside the border-rect, and box shadows
// never render within the border-rect (unless there's a border radius).
nscoord twipsRadii[8];
bool hasBorderRadii = mFrame->GetBorderRadii(twipsRadii);
if (!hasBorderRadii)
return false;
return !RoundedRectContainsRect(frameRect, twipsRadii, visibleBounds);
return true;
}
void

View File

@ -933,6 +933,14 @@ public:
*aSnap = false;
return nsRect(ToReferenceFrame(), Frame()->GetSize());
}
/**
* Returns true if nothing will be rendered inside aRect, false if uncertain.
* aRect is assumed to be contained in this item's bounds.
*/
virtual bool IsInvisibleInRect(const nsRect& aRect)
{
return false;
}
/**
* Returns the result of GetBounds intersected with the item's clip.
* The intersection is approximate since rounded corners are not taking into
@ -1191,8 +1199,7 @@ public:
*/
virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion,
const nsRect& aAllowVisibleRegionExpansion)
{ return !mVisibleRect.IsEmpty(); }
const nsRect& aAllowVisibleRegionExpansion);
/**
* Try to merge with the other item (which is below us in the display
@ -2022,11 +2029,9 @@ public:
}
#endif
virtual bool IsInvisibleInRect(const nsRect& aRect) MOZ_OVERRIDE;
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE;
virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) MOZ_OVERRIDE;
virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion,
const nsRect& aAllowVisibleRegionExpansion) MOZ_OVERRIDE;
NS_DISPLAY_DECL_NAME("Border", TYPE_BORDER)
virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE;
@ -2344,6 +2349,7 @@ public:
virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) MOZ_OVERRIDE;
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE;
virtual bool IsInvisibleInRect(const nsRect& aRect) MOZ_OVERRIDE;
virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion,
const nsRect& aAllowVisibleRegionExpansion) MOZ_OVERRIDE;
@ -2430,11 +2436,9 @@ public:
}
#endif
virtual bool IsInvisibleInRect(const nsRect& aRect) MOZ_OVERRIDE;
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE;
virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) MOZ_OVERRIDE;
virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
nsRegion* aVisibleRegion,
const nsRect& aAllowVisibleRegionExpansion) MOZ_OVERRIDE;
NS_DISPLAY_DECL_NAME("Outline", TYPE_OUTLINE)
};

View File

@ -230,6 +230,8 @@ static void Shutdown();
#include "AudioChannelService.h"
#include "mozilla/dom/DataStoreService.h"
#include "mozilla/dom/power/PowerManagerService.h"
#include "mozilla/dom/alarm/AlarmHalService.h"
#include "mozilla/dom/time/TimeService.h"
@ -589,10 +591,15 @@ NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(Geolocation, Init)
#define NS_AUDIOCHANNEL_SERVICE_CID \
{ 0xf712e983, 0x048a, 0x443f, { 0x88, 0x02, 0xfc, 0xc3, 0xd9, 0x27, 0xce, 0xac }}
#define NS_DATASTORE_SERVICE_CID \
{ 0x0d4285fe, 0xf1b3, 0x49fa, { 0xbc, 0x51, 0xa4, 0xa8, 0x3f, 0x0a, 0xaf, 0x85 }}
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsGeolocationService, nsGeolocationService::GetGeolocationService)
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(AudioChannelService, AudioChannelService::GetAudioChannelService)
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(DataStoreService, DataStoreService::GetOrCreate)
#ifdef MOZ_WEBSPEECH
NS_GENERIC_FACTORY_CONSTRUCTOR(FakeSpeechRecognitionService)
#endif
@ -742,6 +749,7 @@ NS_DEFINE_NAMED_CID(NS_TEXTSERVICESDOCUMENT_CID);
NS_DEFINE_NAMED_CID(NS_GEOLOCATION_SERVICE_CID);
NS_DEFINE_NAMED_CID(NS_GEOLOCATION_CID);
NS_DEFINE_NAMED_CID(NS_AUDIOCHANNEL_SERVICE_CID);
NS_DEFINE_NAMED_CID(NS_DATASTORE_SERVICE_CID);
NS_DEFINE_NAMED_CID(NS_FOCUSMANAGER_CID);
NS_DEFINE_NAMED_CID(CSPSERVICE_CID);
NS_DEFINE_NAMED_CID(NS_CSPCONTEXT_CID);
@ -1030,6 +1038,7 @@ static const mozilla::Module::CIDEntry kLayoutCIDs[] = {
{ &kNS_GEOLOCATION_SERVICE_CID, false, nullptr, nsGeolocationServiceConstructor },
{ &kNS_GEOLOCATION_CID, false, nullptr, GeolocationConstructor },
{ &kNS_AUDIOCHANNEL_SERVICE_CID, false, nullptr, AudioChannelServiceConstructor },
{ &kNS_DATASTORE_SERVICE_CID, false, nullptr, DataStoreServiceConstructor },
{ &kNS_FOCUSMANAGER_CID, false, nullptr, CreateFocusManager },
#ifdef MOZ_WEBSPEECH
{ &kNS_FAKE_SPEECH_RECOGNITION_SERVICE_CID, false, nullptr, FakeSpeechRecognitionServiceConstructor },
@ -1185,6 +1194,7 @@ static const mozilla::Module::ContractIDEntry kLayoutContracts[] = {
{ "@mozilla.org/geolocation/service;1", &kNS_GEOLOCATION_SERVICE_CID },
{ "@mozilla.org/geolocation;1", &kNS_GEOLOCATION_CID },
{ "@mozilla.org/audiochannel/service;1", &kNS_AUDIOCHANNEL_SERVICE_CID },
{ "@mozilla.org/datastore-service;1", &kNS_DATASTORE_SERVICE_CID },
{ "@mozilla.org/focus-manager;1", &kNS_FOCUSMANAGER_CID },
#ifdef MOZ_WEBSPEECH
{ NS_SPEECH_RECOGNITION_SERVICE_CONTRACTID_PREFIX "fake", &kNS_FAKE_SPEECH_RECOGNITION_SERVICE_CID },

View File

@ -65,6 +65,7 @@
#include "ActiveLayerTracker.h"
#include "AudioChannelService.h"
#include "mozilla/dom/DataStoreService.h"
#ifdef MOZ_XUL
#include "nsXULPopupManager.h"
@ -411,6 +412,8 @@ nsLayoutStatics::Shutdown()
AudioChannelService::Shutdown();
DataStoreService::Shutdown();
ContentParent::ShutDown();
nsRefreshDriver::Shutdown();

View File

@ -958,6 +958,24 @@ nsColumnSetFrame::Reflow(nsPresContext* aPresContext,
RemoveStateBits(NS_FRAME_CONTAINS_RELATIVE_HEIGHT);
}
#ifdef DEBUG
nsFrameList::Enumerator oc(GetChildList(kOverflowContainersList));
for (; !oc.AtEnd(); oc.Next()) {
MOZ_ASSERT(!IS_TRUE_OVERFLOW_CONTAINER(oc.get()));
}
nsFrameList::Enumerator eoc(GetChildList(kExcessOverflowContainersList));
for (; !eoc.AtEnd(); eoc.Next()) {
MOZ_ASSERT(!IS_TRUE_OVERFLOW_CONTAINER(eoc.get()));
}
#endif
nsOverflowAreas ocBounds;
nsReflowStatus ocStatus = NS_FRAME_COMPLETE;
if (GetPrevInFlow()) {
ReflowOverflowContainerChildren(aPresContext, aReflowState, ocBounds, 0,
ocStatus);
}
//------------ Handle Incremental Reflow -----------------
ReflowConfig config = ChooseColumnStrategy(aReflowState);
@ -994,15 +1012,19 @@ nsColumnSetFrame::Reflow(nsPresContext* aPresContext,
aStatus = NS_FRAME_COMPLETE;
}
NS_ASSERTION(NS_FRAME_IS_FULLY_COMPLETE(aStatus) ||
aReflowState.AvailableHeight() != NS_UNCONSTRAINEDSIZE,
"Column set should be complete if the available height is unconstrained");
// Merge overflow container bounds and status.
aDesiredSize.mOverflowAreas.UnionWith(ocBounds);
NS_MergeReflowStatusInto(&aStatus, ocStatus);
FinishReflowWithAbsoluteFrames(aPresContext, aDesiredSize, aReflowState, aStatus, false);
aDesiredSize.mCarriedOutBottomMargin = carriedOutBottomMargin;
NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
NS_ASSERTION(NS_FRAME_IS_FULLY_COMPLETE(aStatus) ||
aReflowState.AvailableHeight() != NS_UNCONSTRAINEDSIZE,
"Column set should be complete if the available height is unconstrained");
}
void

View File

@ -7,6 +7,7 @@
#include "mozilla/Attributes.h"
#include "nsContainerFrame.h"
#include "nsIFrameInlines.h" // for methods used by IS_TRUE_OVERFLOW_CONTAINER
class nsColumnSetFrame : public nsContainerFrame {
public:
@ -51,8 +52,11 @@ public:
}
virtual nsresult StealFrame(nsIFrame* aChild, bool aForceNormal) MOZ_OVERRIDE
{ // nsColumnSetFrame keeps overflow containers in main child list
return nsContainerFrame::StealFrame(aChild, true);
{
// nsColumnSetFrame keeps true overflow containers in the normal flow
// child lists (i.e. the principal and overflow lists).
return nsContainerFrame::StealFrame(aChild,
IS_TRUE_OVERFLOW_CONTAINER(aChild));
}
virtual bool IsFrameOfType(uint32_t aFlags) const MOZ_OVERRIDE

View File

@ -1798,22 +1798,9 @@ static void AdjustViews(nsIFrame* aFrame)
}
static bool
CanScrollWithBlitting(nsIFrame* aFrame)
NeedToInvalidateOnScroll(nsIFrame* aFrame)
{
if (aFrame->GetStateBits() & NS_SCROLLFRAME_INVALIDATE_CONTENTS_ON_SCROLL)
return false;
for (nsIFrame* f = aFrame; f;
f = nsLayoutUtils::GetCrossDocParentFrame(f)) {
if (nsSVGIntegrationUtils::UsingEffectsForFrame(f) ||
f->IsFrameOfType(nsIFrame::eSVG) ||
f->GetStateBits() & NS_FRAME_NO_COMPONENT_ALPHA) {
return false;
}
if (nsLayoutUtils::IsPopup(f))
break;
}
return true;
return (aFrame->GetStateBits() & NS_SCROLLFRAME_INVALIDATE_CONTENTS_ON_SCROLL) != 0;
}
bool ScrollFrameHelper::IsIgnoringViewportClipping() const
@ -1900,14 +1887,12 @@ void ScrollFrameHelper::ScrollVisual(nsPoint aOldScrolledFramePos)
AdjustViews(mScrolledFrame);
// We need to call this after fixing up the view positions
// to be consistent with the frame hierarchy.
bool canScrollWithBlitting = CanScrollWithBlitting(mOuter);
bool needToInvalidateOnScroll = NeedToInvalidateOnScroll(mOuter);
mOuter->RemoveStateBits(NS_SCROLLFRAME_INVALIDATE_CONTENTS_ON_SCROLL);
if (IsScrollingActive()) {
if (!canScrollWithBlitting) {
MarkInactive();
}
if (IsScrollingActive() && needToInvalidateOnScroll) {
MarkInactive();
}
if (canScrollWithBlitting) {
if (!needToInvalidateOnScroll) {
MarkActive();
}
@ -2196,9 +2181,8 @@ ScrollFrameHelper::AppendScrollPartsTo(nsDisplayListBuilder* aBuilder,
scrollParts.AppendElement(kid);
}
mozilla::layers::FrameMetrics::ViewID scrollTargetId = aCreateLayer
? nsLayoutUtils::FindOrCreateIDFor(mScrolledFrame->GetContent())
: mozilla::layers::FrameMetrics::NULL_SCROLL_ID;
mozilla::layers::FrameMetrics::ViewID scrollTargetId =
nsLayoutUtils::FindOrCreateIDFor(mScrolledFrame->GetContent());
scrollParts.Sort(HoveredStateComparator());
@ -2216,11 +2200,16 @@ ScrollFrameHelper::AppendScrollPartsTo(nsDisplayListBuilder* aBuilder,
flags |= nsDisplayOwnLayer::HORIZONTAL_SCROLLBAR;
}
// Always create layers for overlay scrollbars so that we don't create a
// giant layer covering the whole scrollport if both scrollbars are visible.
bool isOverlayScrollbar = (flags != 0) && overlayScrollbars;
bool createLayer = aCreateLayer || isOverlayScrollbar;
// DISPLAY_CHILD_FORCE_STACKING_CONTEXT put everything into
// partList.PositionedDescendants().
::AppendToTop(aBuilder, aLists,
partList.PositionedDescendants(), scrollParts[i],
aCreateLayer, flags, scrollTargetId, aPositioned);
createLayer, flags, scrollTargetId, aPositioned);
}
}
@ -2418,7 +2407,7 @@ ScrollFrameHelper::BuildDisplayList(nsDisplayListBuilder* aBuilder,
if (aBuilder->IsPaintingToWindow()) {
mScrollPosAtLastPaint = GetScrollPosition();
if (IsScrollingActive() && !CanScrollWithBlitting(mOuter)) {
if (IsScrollingActive() && NeedToInvalidateOnScroll(mOuter)) {
MarkInactive();
}
if (IsScrollingActive()) {
@ -2469,7 +2458,8 @@ ScrollFrameHelper::BuildDisplayList(nsDisplayListBuilder* aBuilder,
if (addScrollBars) {
// Add overlay scrollbars.
AppendScrollPartsTo(aBuilder, aDirtyRect, aLists, true, true);
AppendScrollPartsTo(aBuilder, aDirtyRect, aLists,
createLayersForScrollbars, true);
}
return;
@ -2661,9 +2651,8 @@ ScrollFrameHelper::BuildDisplayList(nsDisplayListBuilder* aBuilder,
scrolledContent.BorderBackground()->AppendNewToBottom(layerItem);
}
// Now display overlay scrollbars and the resizer, if we have one.
// Always create layers for these, so that we don't create a giant layer
// covering the whole scrollport if both scrollbars are visible.
AppendScrollPartsTo(aBuilder, aDirtyRect, scrolledContent, true, true);
AppendScrollPartsTo(aBuilder, aDirtyRect, scrolledContent,
createLayersForScrollbars, true);
scrolledContent.MoveTo(aLists);
}

View File

@ -473,10 +473,19 @@ int32_t nsCSSSelector::CalcWeightWithoutNegations() const
{
int32_t weight = 0;
MOZ_ASSERT(!IsPseudoElement() ||
mPseudoType >= nsCSSPseudoElements::ePseudo_PseudoElementCount ||
(!mIDList && !mClassList && !mAttrList),
"if pseudo-elements can have ID, class or attribute selectors "
#ifdef MOZ_XUL
MOZ_ASSERT(!(IsPseudoElement() &&
PseudoType() != nsCSSPseudoElements::ePseudo_XULTree &&
mClassList),
"If non-XUL-tree pseudo-elements can have class selectors "
"after them, specificity calculation must be updated");
#else
MOZ_ASSERT(!(IsPseudoElement() && mClassList),
"If pseudo-elements can have class selectors "
"after them, specificity calculation must be updated");
#endif
MOZ_ASSERT(!(IsPseudoElement() && (mIDList || mAttrList)),
"If pseudo-elements can have id or attribute selectors "
"after them, specificity calculation must be updated");
if (nullptr != mCasedTag) {
@ -488,6 +497,13 @@ int32_t nsCSSSelector::CalcWeightWithoutNegations() const
list = list->mNext;
}
list = mClassList;
#ifdef MOZ_XUL
// XUL tree pseudo-elements abuse mClassList to store some private
// data; ignore that.
if (PseudoType() == nsCSSPseudoElements::ePseudo_XULTree) {
list = nullptr;
}
#endif
while (nullptr != list) {
weight += 0x000100;
list = list->mNext;

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