diff --git a/b2g/app/b2g.js b/b2g/app/b2g.js index ea78fb7a1472..cea04b8f81af 100644 --- a/b2g/app/b2g.js +++ b/b2g/app/b2g.js @@ -46,7 +46,7 @@ pref("browser.homescreenURL", "file:///data/local/homescreen.html,file:///system #endif // URL for the dialer application. -pref("dom.telephony.app.phone.url", "http://localhost:7777/data/local/apps/dialer/dialer.html"); +pref("dom.telephony.app.phone.url", "http://localhost:7777/data/local/apps/dialer/dialer.html http://localhost:7777/data/local/apps/homescreen/homescreen.html http://localhost:7777/apps/dialer/dialer.html http://localhost:7777/apps/homescreen/homescreen.html"); // Device pixel to CSS px ratio, in percent. Set to -1 to calculate based on display density. pref("browser.viewport.scaleRatio", -1); diff --git a/browser/components/migration/Makefile.in b/browser/components/migration/Makefile.in index f606260619e5..80d21a5d5809 100644 --- a/browser/components/migration/Makefile.in +++ b/browser/components/migration/Makefile.in @@ -43,6 +43,8 @@ include $(DEPTH)/config/autoconf.mk DIRS = public src +TEST_DIRS += tests + include $(topsrcdir)/config/rules.mk # Needed for preprocessor removal of IE Profile Migrator label - bug 236901 diff --git a/browser/components/migration/content/migration.js b/browser/components/migration/content/migration.js index 3bc34c76e877..ffb0c345eb71 100644 --- a/browser/components/migration/content/migration.js +++ b/browser/components/migration/content/migration.js @@ -65,6 +65,7 @@ var MigrationWizard = { this._source = window.arguments[0]; this._migrator = window.arguments[1].QueryInterface(kIMig); this._autoMigrate = window.arguments[2].QueryInterface(kIPStartup); + this._skipImportSourcePage = window.arguments[3]; if (this._autoMigrate) { // Show the "nothing" option in the automigrate case to provide an @@ -94,7 +95,7 @@ var MigrationWizard = { // Reference to the "From File" radio button var fromfile = null; - //XXXquark This function is called before init, so check for bookmarks here + // init is not called when openDialog opens the wizard, so check for bookmarks here. if ("arguments" in window && window.arguments[0] == "bookmarks") { this._bookmarks = true; @@ -151,6 +152,12 @@ var MigrationWizard = { document.getElementById("importBookmarks").hidden = true; document.getElementById("importAll").hidden = true; } + + // Advance to the next page if the caller told us to. + if (this._migrator && this._skipImportSourcePage) { + this._wiz.advance(); + this._wiz.canRewind = false; + } }, onImportSourcePageAdvanced: function () diff --git a/browser/components/migration/src/FirefoxProfileMigrator.js b/browser/components/migration/src/FirefoxProfileMigrator.js index dad4217347bf..7b4a6e4b7725 100644 --- a/browser/components/migration/src/FirefoxProfileMigrator.js +++ b/browser/components/migration/src/FirefoxProfileMigrator.js @@ -227,6 +227,12 @@ FirefoxProfileMigrator.prototype = { this._replaceBookmarks = true; } + // Ensure that aProfile is not the current profile. + if (this._paths.currentProfile.path === this._sourceProfile.path) { + throw new Exception("Source and destination profiles are the same"); + return; + } + Services.obs.notifyObservers(null, "Migration:Started", null); // Reset pending count. If this count becomes 0, "Migration:Ended" @@ -278,6 +284,11 @@ FirefoxProfileMigrator.prototype = { this._sourceProfile.initWithPath(aProfile); let result = 0; + + // Ensure that aProfile is not the current profile. + if (this._paths.currentProfile.path === this._sourceProfile.path) + return result; + if (!this._sourceProfile.exists() || !this._sourceProfile.isReadable()) { Cu.reportError("source profile directory doesn't exist or is not readable"); return result; diff --git a/browser/components/migration/src/ProfileMigrator.js b/browser/components/migration/src/ProfileMigrator.js index b713068cba37..ea6667531937 100644 --- a/browser/components/migration/src/ProfileMigrator.js +++ b/browser/components/migration/src/ProfileMigrator.js @@ -16,10 +16,25 @@ function ProfileMigrator() { } ProfileMigrator.prototype = { - migrate: function PM_migrate(aStartup) { + migrate: function PM_migrate(aStartup, aKey) { // By opening the wizard with a supplied migrator, it will automatically // migrate from it. - let [key, migrator] = this._getDefaultMigrator(); + let key = null, migrator = null; + let skipImportSourcePage = Cc["@mozilla.org/supports-PRBool;1"] + .createInstance(Ci.nsISupportsPRBool); + if (aKey) { + key = aKey; + migrator = this._getMigratorIfSourceExists(key); + if (!migrator) { + Cu.reportError("Invalid migrator key specified or source does not exist."); + return; + } + // If the migrator was passed to us from the caller, use that migrator + // and skip the import source page. + skipImportSourcePage.data = true; + } else { + [key, migrator] = this._getDefaultMigrator(); + } if (!key) return; @@ -27,6 +42,7 @@ ProfileMigrator.prototype = { params.appendElement(this._toCString(key), false); params.appendElement(migrator, false); params.appendElement(aStartup, false); + params.appendElement(skipImportSourcePage, false); Services.ww.openWindow(null, "chrome://browser/content/migration/migration.xul", @@ -43,10 +59,14 @@ ProfileMigrator.prototype = { }, _getMigratorIfSourceExists: function PM__getMigratorIfSourceExists(aKey) { - let cid = "@mozilla.org/profile/migrator;1?app=browser&type=" + aKey; - let migrator = Cc[cid].createInstance(Ci.nsIBrowserProfileMigrator); - if (migrator.sourceExists) - return migrator; + try { + let cid = "@mozilla.org/profile/migrator;1?app=browser&type=" + aKey; + let migrator = Cc[cid].createInstance(Ci.nsIBrowserProfileMigrator); + if (migrator.sourceExists) + return migrator; + } catch (ex) { + Cu.reportError("Could not get migrator: " + ex); + } return null; }, diff --git a/browser/components/migration/src/nsIEProfileMigrator.cpp b/browser/components/migration/src/nsIEProfileMigrator.cpp index f63b230f25d2..636623bb2c38 100644 --- a/browser/components/migration/src/nsIEProfileMigrator.cpp +++ b/browser/components/migration/src/nsIEProfileMigrator.cpp @@ -1412,6 +1412,9 @@ nsIEProfileMigrator::CopyFavoritesBatched(bool aReplace) // Locate the Links toolbar folder, we want to replace the Personal Toolbar // content with Favorites in this folder. + // On versions minor or equal to IE6 the folder name is stored in the + // LinksFolderName registry key, but in newer versions it may be just a + // Links subfolder inside the default Favorites folder. nsCOMPtr regKey = do_CreateInstance("@mozilla.org/windows-registry-key;1"); if (regKey && @@ -1421,9 +1424,14 @@ nsIEProfileMigrator::CopyFavoritesBatched(bool aReplace) nsAutoString linksFolderName; if (NS_SUCCEEDED(regKey->ReadStringValue( NS_LITERAL_STRING("LinksFolderName"), - linksFolderName))) + linksFolderName))) { personalToolbarFolderName = linksFolderName; + } + else { + personalToolbarFolderName.AssignLiteral("Links"); + } } + folder = bookmarksMenuFolderId; } diff --git a/browser/components/migration/tests/Makefile.in b/browser/components/migration/tests/Makefile.in new file mode 100644 index 000000000000..9e62100e0b30 --- /dev/null +++ b/browser/components/migration/tests/Makefile.in @@ -0,0 +1,15 @@ +# 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/. + +DEPTH = ../../../.. +topsrcdir = @top_srcdir@ +srcdir = @srcdir@ +VPATH = @srcdir@ +relativesrcdir = browser/components/migration/tests + +include $(DEPTH)/config/autoconf.mk + +XPCSHELL_TESTS = unit + +include $(topsrcdir)/config/rules.mk diff --git a/browser/components/migration/tests/unit/bookmarks.html b/browser/components/migration/tests/unit/bookmarks.html new file mode 100644 index 000000000000..07b22e9b3fce --- /dev/null +++ b/browser/components/migration/tests/unit/bookmarks.html @@ -0,0 +1,16 @@ + + + +Bookmarks +

Bookmarks Menu

+ +

+

example +

Bookmarks Toolbar

+
Add bookmarks to this folder to see them displayed on the Bookmarks Toolbar +

+

example +

+

diff --git a/browser/components/migration/tests/unit/head_migration.js b/browser/components/migration/tests/unit/head_migration.js new file mode 100644 index 000000000000..f24123ffde9b --- /dev/null +++ b/browser/components/migration/tests/unit/head_migration.js @@ -0,0 +1,28 @@ +/* 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/. */ + +const Cc = Components.classes; +const Ci = Components.interfaces; +const Cu = Components.utils; + +const IMIGRATOR = Ci.nsIBrowserProfileMigrator; + +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); + +XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils", + "resource://gre/modules/PlacesUtils.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "FileUtils", + "resource://gre/modules/FileUtils.jsm"); + +// Initialize profile. +let gProfD = do_get_profile(); + +function newMigratorFor(aKey) { + let cid = "@mozilla.org/profile/migrator;1?app=browser&type=" + aKey; + return Cc[cid].createInstance(Ci.nsIBrowserProfileMigrator); +} + +let (bookmarkshtml = do_get_file("bookmarks.html")) { + bookmarkshtml.copyTo(gProfD, "bookmarks.html"); +} diff --git a/browser/components/migration/tests/unit/test_IE_bookmarks.js b/browser/components/migration/tests/unit/test_IE_bookmarks.js new file mode 100644 index 000000000000..6a3fd8a9b9bb --- /dev/null +++ b/browser/components/migration/tests/unit/test_IE_bookmarks.js @@ -0,0 +1,28 @@ +/* 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/. */ + +function run_test() { + let migrator = newMigratorFor("ie"); + + // Sanity check for the source. + do_check_true(migrator.sourceExists); + + // Ensure bookmarks migration is available. + let availableSources = migrator.getMigrateData("FieldOfFlowers", false); + do_check_true((availableSources & IMIGRATOR.BOOKMARKS) > 0); + + // Needed to enforce bookmarks replacing. + let startup = { + doStartup: function () {}, + get directory() do_get_profile() + } + migrator.migrate(IMIGRATOR.BOOKMARKS, startup, "FieldOfFlowers"); + + // Check that at least two bookmark have been added to the menu and the + // toolbar. The first one comes from bookmarks.html, the others from IE. + do_check_true(PlacesUtils.bookmarks + .getIdForItemAt(PlacesUtils.bookmarksMenuFolderId, 1) > 0); + do_check_true(PlacesUtils.bookmarks + .getIdForItemAt(PlacesUtils.toolbarFolderId, 1) > 0); +} diff --git a/browser/components/migration/tests/unit/xpcshell.ini b/browser/components/migration/tests/unit/xpcshell.ini new file mode 100644 index 000000000000..2704bc2cfbc5 --- /dev/null +++ b/browser/components/migration/tests/unit/xpcshell.ini @@ -0,0 +1,6 @@ +[DEFAULT] +head = head_migration.js +tail = + +[test_IE_bookmarks.js] +skip-if = os != "win" diff --git a/browser/makefiles.sh b/browser/makefiles.sh index d76045f8cfa0..663e677165de 100644 --- a/browser/makefiles.sh +++ b/browser/makefiles.sh @@ -139,6 +139,7 @@ if [ "$ENABLE_TESTS" ]; then browser/components/shell/test/Makefile browser/components/feeds/test/Makefile browser/components/feeds/test/chrome/Makefile + browser/components/migration/tests/Makefile browser/components/places/tests/Makefile browser/components/places/tests/chrome/Makefile browser/components/places/tests/browser/Makefile diff --git a/caps/idl/nsIPrincipal.idl b/caps/idl/nsIPrincipal.idl index 3a09ca8db516..cfc2bac4dfaa 100644 --- a/caps/idl/nsIPrincipal.idl +++ b/caps/idl/nsIPrincipal.idl @@ -52,7 +52,7 @@ interface nsIContentSecurityPolicy; [ptr] native JSContext(JSContext); [ptr] native JSPrincipals(JSPrincipals); -[scriptable, uuid(1f83b0e0-6b63-4bdc-a50a-b9afe256bd25)] +[scriptable, uuid(f8c4c89a-d726-421b-8415-3e34b241175b)] interface nsIPrincipal : nsISerializable { /** @@ -96,12 +96,6 @@ interface nsIPrincipal : nsISerializable */ [noscript] readonly attribute unsigned long hashValue; - /** - * Returns the JS equivalent of the principal. - * @see JSPrincipals.h - */ - [noscript] JSPrincipals getJSPrincipals(in JSContext cx); - /** * The domain security policy of the principal. */ diff --git a/caps/include/nsJSPrincipals.h b/caps/include/nsJSPrincipals.h index 782ac029294e..f983532cecbf 100644 --- a/caps/include/nsJSPrincipals.h +++ b/caps/include/nsJSPrincipals.h @@ -43,14 +43,47 @@ class nsCString; -struct nsJSPrincipals : JSPrincipals +struct nsJSPrincipals : nsIPrincipal, JSPrincipals { - static nsresult Startup(); - nsJSPrincipals(); - nsresult Init(nsIPrincipal* aPrincipal, const nsCString& aCodebase); - ~nsJSPrincipals(void); + static JSBool Subsume(JSPrincipals *jsprin, JSPrincipals *other); + static void Destroy(JSPrincipals *jsprin); + static JSBool Transcode(JSXDRState *xdr, JSPrincipals **jsprinp); - nsIPrincipal *nsIPrincipalPtr; // [WEAK] it owns us. + /* + * Get a weak reference to nsIPrincipal associated with the given JS + * principal. + */ + static nsJSPrincipals* get(JSPrincipals *principals) { + nsJSPrincipals *self = static_cast(principals); + MOZ_ASSERT_IF(self, self->debugToken == DEBUG_TOKEN); + return self; + } + + static nsJSPrincipals* get(nsIPrincipal *principal) { + nsJSPrincipals *self = static_cast(principal); + MOZ_ASSERT_IF(self, self->debugToken == DEBUG_TOKEN); + return self; + } + + nsJSPrincipals() { + refcount = 0; + setDebugToken(DEBUG_TOKEN); + } + + virtual ~nsJSPrincipals() { + setDebugToken(0); + } + + /** + * Return a string that can be used as JS script filename in error reports. + */ + virtual void GetScriptLocation(nsACString &aStr) = 0; + +#ifdef DEBUG + virtual void dumpImpl() = 0; +#endif + + static const uint32_t DEBUG_TOKEN = 0x0bf41760; }; #endif /* nsJSPrincipals_h__ */ diff --git a/caps/include/nsNullPrincipal.h b/caps/include/nsNullPrincipal.h index e342d287bb7c..a2cbe139b0ed 100644 --- a/caps/include/nsNullPrincipal.h +++ b/caps/include/nsNullPrincipal.h @@ -59,16 +59,16 @@ class nsIURI; #define NS_NULLPRINCIPAL_SCHEME "moz-nullprincipal" -class nsNullPrincipal : public nsIPrincipal +class nsNullPrincipal : public nsJSPrincipals { public: nsNullPrincipal(); - // Our refcount is managed by mJSPrincipals. Use this macro to avoid an + // Our refcount is managed by nsJSPrincipals. Use this macro to avoid an // extra refcount member. // FIXME: bug 327245 -- I sorta wish there were a clean way to share the - // mJSPrincipals munging code between the various principal classes without + // nsJSPrincipals munging code between the various principal classes without // giving up the NS_DECL_NSIPRINCIPAL goodness. NS_DECL_ISUPPORTS_INHERITED NS_DECL_NSIPRINCIPAL @@ -76,10 +76,15 @@ public: nsresult Init(); -protected: + virtual void GetScriptLocation(nsACString &aStr) MOZ_OVERRIDE; + +#ifdef DEBUG + virtual void dumpImpl() MOZ_OVERRIDE; +#endif + + protected: virtual ~nsNullPrincipal(); - nsJSPrincipals mJSPrincipals; nsCOMPtr mURI; }; diff --git a/caps/include/nsPrincipal.h b/caps/include/nsPrincipal.h index 8f78db43ef6c..1542dc6ba7de 100644 --- a/caps/include/nsPrincipal.h +++ b/caps/include/nsPrincipal.h @@ -51,7 +51,7 @@ class nsIObjectInputStream; class nsIObjectOutputStream; -class nsPrincipal : public nsIPrincipal +class nsPrincipal : public nsJSPrincipals { public: nsPrincipal(); @@ -60,7 +60,7 @@ protected: virtual ~nsPrincipal(); public: - // Our refcount is managed by mJSPrincipals. Use this macro to avoid + // Our refcount is managed by nsJSPrincipals. Use this macro to avoid // an extra refcount member. NS_DECL_ISUPPORTS_INHERITED public: @@ -100,8 +100,13 @@ public: static const char sInvalid[]; + virtual void GetScriptLocation(nsACString &aStr) MOZ_OVERRIDE; + +#ifdef DEBUG + virtual void dumpImpl() MOZ_OVERRIDE; +#endif + protected: - nsJSPrincipals mJSPrincipals; nsTArray< nsAutoPtr > mAnnotations; nsHashtable* mCapabilities; nsCString mPrefName; diff --git a/caps/include/nsScriptSecurityManager.h b/caps/include/nsScriptSecurityManager.h index ca0a9fb70793..94e5e469a153 100644 --- a/caps/include/nsScriptSecurityManager.h +++ b/caps/include/nsScriptSecurityManager.h @@ -428,6 +428,9 @@ private: jsid id, JSAccessMode mode, jsval *vp); + static JSPrincipals * + ObjectPrincipalFinder(JSObject *obj); + // Decides, based on CSP, whether or not eval() and stuff can be executed. static JSBool ContentSecurityPolicyPermitsJSAction(JSContext *cx); diff --git a/caps/include/nsSystemPrincipal.h b/caps/include/nsSystemPrincipal.h index d9154a6c4b1d..25eaee254276 100644 --- a/caps/include/nsSystemPrincipal.h +++ b/caps/include/nsSystemPrincipal.h @@ -50,23 +50,26 @@ #define NS_SYSTEMPRINCIPAL_CONTRACTID "@mozilla.org/systemprincipal;1" -class nsSystemPrincipal : public nsIPrincipal +class nsSystemPrincipal : public nsJSPrincipals { public: - // Our refcount is managed by mJSPrincipals. Use this macro to avoid + // Our refcount is managed by nsJSPrincipals. Use this macro to avoid // an extra refcount member. NS_DECL_ISUPPORTS_INHERITED NS_DECL_NSIPRINCIPAL NS_DECL_NSISERIALIZABLE - nsresult Init(JSPrincipals **jsprin); - nsSystemPrincipal(); + virtual void GetScriptLocation(nsACString &aStr) MOZ_OVERRIDE; + +#ifdef DEBUG + virtual void dumpImpl() MOZ_OVERRIDE; +#endif + protected: virtual ~nsSystemPrincipal(void); - nsJSPrincipals mJSPrincipals; // XXX Probably unnecessary. See bug 143559. NS_DECL_OWNINGTHREAD }; diff --git a/caps/src/nsJSPrincipals.cpp b/caps/src/nsJSPrincipals.cpp index f86f0d38a333..5907b35ffeac 100644 --- a/caps/src/nsJSPrincipals.cpp +++ b/caps/src/nsJSPrincipals.cpp @@ -50,46 +50,44 @@ #include "nsMemory.h" #include "nsStringBuffer.h" -static JSBool -nsJSPrincipalsSubsume(JSPrincipals *jsprin, JSPrincipals *other) -{ - nsJSPrincipals *nsjsprin = static_cast(jsprin); - nsJSPrincipals *nsother = static_cast(other); +// for mozilla::dom::workers::kJSPrincipalsDebugToken +#include "mozilla/dom/workers/Workers.h" +/* static */ JSBool +nsJSPrincipals::Subsume(JSPrincipals *jsprin, JSPrincipals *other) +{ bool result; - nsresult rv = nsjsprin->nsIPrincipalPtr->Subsumes(nsother->nsIPrincipalPtr, - &result); + nsresult rv = nsJSPrincipals::get(jsprin)->Subsumes(nsJSPrincipals::get(other), &result); return NS_SUCCEEDED(rv) && result; } -static void -nsDestroyJSPrincipals(JSContext *cx, struct JSPrincipals *jsprin) +/* static */ void +nsJSPrincipals::Destroy(JSPrincipals *jsprin) { - nsJSPrincipals *nsjsprin = static_cast(jsprin); + // The JS runtime can call this method during the last GC when + // nsScriptSecurityManager is destroyed. So we must not assume here that + // the security manager still exists. + + nsJSPrincipals *nsjsprin = nsJSPrincipals::get(jsprin); // We need to destroy the nsIPrincipal. We'll do this by adding // to the refcount and calling release - // Note that we don't want to use NS_IF_RELEASE because it will try - // to set nsjsprin->nsIPrincipalPtr to nsnull *after* nsjsprin has - // already been destroyed. #ifdef NS_BUILD_REFCNT_LOGGING // The refcount logging considers AddRef-to-1 to indicate creation, // so trick it into thinking it's otherwise, but balance the // Release() we do below. nsjsprin->refcount++; - nsjsprin->nsIPrincipalPtr->AddRef(); + nsjsprin->AddRef(); nsjsprin->refcount--; #else nsjsprin->refcount++; #endif - nsjsprin->nsIPrincipalPtr->Release(); - // The nsIPrincipal that we release owns the JSPrincipal struct, - // so we don't need to worry about "codebase" + nsjsprin->Release(); } -static JSBool -nsTranscodeJSPrincipals(JSXDRState *xdr, JSPrincipals **jsprinp) +/* static */ JSBool +nsJSPrincipals::Transcode(JSXDRState *xdr, JSPrincipals **jsprinp) { nsresult rv; @@ -107,12 +105,7 @@ nsTranscodeJSPrincipals(JSXDRState *xdr, JSPrincipals **jsprinp) if (NS_SUCCEEDED(rv)) { ::JS_XDRMemResetData(xdr); - // Require that GetJSPrincipals has been called already by the - // code that compiled the script that owns the principals. - nsJSPrincipals *nsjsprin = - static_cast(*jsprinp); - - rv = stream->WriteObject(nsjsprin->nsIPrincipalPtr, true); + rv = stream->WriteObject(nsJSPrincipals::get(*jsprinp), true); } } } else { @@ -141,7 +134,8 @@ nsTranscodeJSPrincipals(JSXDRState *xdr, JSPrincipals **jsprinp) nsMemory::Free(olddata); ::JS_XDRMemSetData(xdr, data, size); - prin->GetJSPrincipals(xdr->cx, jsprinp); + *jsprinp = nsJSPrincipals::get(prin); + JS_HoldPrincipals(*jsprinp); } } } @@ -156,69 +150,22 @@ nsTranscodeJSPrincipals(JSXDRState *xdr, JSPrincipals **jsprinp) return JS_TRUE; } -nsresult -nsJSPrincipals::Startup() +#ifdef DEBUG + +// Defined here so one can do principals->dump() in the debugger +JS_EXPORT_API(void) +JSPrincipals::dump() { - nsCOMPtr rtsvc = nsXPConnect::GetXPConnect(); - if (!rtsvc) - return NS_ERROR_FAILURE; - - JSRuntime *rt; - rtsvc->GetRuntime(&rt); - NS_ASSERTION(rt != nsnull, "no JSRuntime?!"); - - JSSecurityCallbacks *callbacks = JS_GetRuntimeSecurityCallbacks(rt); - NS_ASSERTION(callbacks, "Need a callbacks struct by now!"); - - NS_ASSERTION(!callbacks->principalsTranscoder, - "oops, JS_SetPrincipalsTranscoder wars!"); - - callbacks->principalsTranscoder = nsTranscodeJSPrincipals; - return NS_OK; -} - -nsJSPrincipals::nsJSPrincipals() -{ - codebase = nsnull; - refcount = 0; - destroy = nsDestroyJSPrincipals; - subsume = nsJSPrincipalsSubsume; - nsIPrincipalPtr = nsnull; -} - -nsresult -nsJSPrincipals::Init(nsIPrincipal *aPrincipal, const nsCString& aCodebase) -{ - if (nsIPrincipalPtr) { - NS_ERROR("Init called twice!"); - return NS_ERROR_UNEXPECTED; - } - - nsIPrincipalPtr = aPrincipal; - nsStringBuffer* buf = nsStringBuffer::FromString(aCodebase); - char* data; - if (buf) { - buf->AddRef(); - data = static_cast(buf->Data()); + if (debugToken == nsJSPrincipals::DEBUG_TOKEN) { + static_cast(this)->dumpImpl(); + } else if (debugToken == mozilla::dom::workers::kJSPrincipalsDebugToken) { + fprintf(stderr, "Web Worker principal singleton (%p)\n", this); } else { - PRUint32 len = aCodebase.Length(); - buf = nsStringBuffer::Alloc(len + 1); // addrefs - if (!buf) { - return NS_ERROR_OUT_OF_MEMORY; - } - data = static_cast(buf->Data()); - memcpy(data, aCodebase.get(), len); - data[len] = '\0'; - } - - codebase = data; - - return NS_OK; -} - -nsJSPrincipals::~nsJSPrincipals() -{ - if (codebase) { - nsStringBuffer::FromData(codebase)->Release(); + fprintf(stderr, + "!!! JSPrincipals (%p) is not nsJSPrincipals instance - bad token: " + "actual=0x%x expected=0x%x\n", + this, unsigned(debugToken), unsigned(nsJSPrincipals::DEBUG_TOKEN)); } } + +#endif diff --git a/caps/src/nsNullPrincipal.cpp b/caps/src/nsNullPrincipal.cpp index 8851652d71cb..8f69ade01b5f 100644 --- a/caps/src/nsNullPrincipal.cpp +++ b/caps/src/nsNullPrincipal.cpp @@ -69,8 +69,8 @@ NS_IMPL_CI_INTERFACE_GETTER2(nsNullPrincipal, NS_IMETHODIMP_(nsrefcnt) nsNullPrincipal::AddRef() { - NS_PRECONDITION(PRInt32(mJSPrincipals.refcount) >= 0, "illegal refcnt"); - nsrefcnt count = PR_ATOMIC_INCREMENT(&mJSPrincipals.refcount); + NS_PRECONDITION(PRInt32(refcount) >= 0, "illegal refcnt"); + nsrefcnt count = PR_ATOMIC_INCREMENT(&refcount); NS_LOG_ADDREF(this, count, "nsNullPrincipal", sizeof(*this)); return count; } @@ -78,8 +78,8 @@ nsNullPrincipal::AddRef() NS_IMETHODIMP_(nsrefcnt) nsNullPrincipal::Release() { - NS_PRECONDITION(0 != mJSPrincipals.refcount, "dup release"); - nsrefcnt count = PR_ATOMIC_DECREMENT(&mJSPrincipals.refcount); + NS_PRECONDITION(0 != refcount, "dup release"); + nsrefcnt count = PR_ATOMIC_DECREMENT(&refcount); NS_LOG_RELEASE(this, count, "nsNullPrincipal"); if (count == 0) { delete this; @@ -133,9 +133,24 @@ nsNullPrincipal::Init() mURI = new nsNullPrincipalURI(str); NS_ENSURE_TRUE(mURI, NS_ERROR_OUT_OF_MEMORY); - return mJSPrincipals.Init(this, str); + return NS_OK; } +void +nsNullPrincipal::GetScriptLocation(nsACString &aStr) +{ + mURI->GetSpec(aStr); +} + +#ifdef DEBUG +void nsNullPrincipal::dumpImpl() +{ + nsCAutoString str; + mURI->GetSpec(str); + fprintf(stderr, "nsNullPrincipal (%p) = %s\n", this, str.get()); +} +#endif + /** * nsIPrincipal implementation */ @@ -179,17 +194,6 @@ nsNullPrincipal::GetHashValue(PRUint32 *aResult) return NS_OK; } -NS_IMETHODIMP -nsNullPrincipal::GetJSPrincipals(JSContext *cx, JSPrincipals **aJsprin) -{ - NS_PRECONDITION(mJSPrincipals.nsIPrincipalPtr, - "mJSPrincipals is uninitalized!"); - - JSPRINCIPALS_HOLD(cx, &mJSPrincipals); - *aJsprin = &mJSPrincipals; - return NS_OK; -} - NS_IMETHODIMP nsNullPrincipal::GetSecurityPolicy(void** aSecurityPolicy) { diff --git a/caps/src/nsPrincipal.cpp b/caps/src/nsPrincipal.cpp index 97005d838ad8..e7b0897005e2 100644 --- a/caps/src/nsPrincipal.cpp +++ b/caps/src/nsPrincipal.cpp @@ -93,9 +93,9 @@ NS_IMPL_CI_INTERFACE_GETTER2(nsPrincipal, NS_IMETHODIMP_(nsrefcnt) nsPrincipal::AddRef() { - NS_PRECONDITION(PRInt32(mJSPrincipals.refcount) >= 0, "illegal refcnt"); + NS_PRECONDITION(PRInt32(refcount) >= 0, "illegal refcnt"); // XXXcaa does this need to be threadsafe? See bug 143559. - nsrefcnt count = PR_ATOMIC_INCREMENT(&mJSPrincipals.refcount); + nsrefcnt count = PR_ATOMIC_INCREMENT(&refcount); NS_LOG_ADDREF(this, count, "nsPrincipal", sizeof(*this)); return count; } @@ -103,8 +103,8 @@ nsPrincipal::AddRef() NS_IMETHODIMP_(nsrefcnt) nsPrincipal::Release() { - NS_PRECONDITION(0 != mJSPrincipals.refcount, "dup release"); - nsrefcnt count = PR_ATOMIC_DECREMENT(&mJSPrincipals.refcount); + NS_PRECONDITION(0 != refcount, "dup release"); + nsrefcnt count = PR_ATOMIC_DECREMENT(&refcount); NS_LOG_RELEASE(this, count, "nsPrincipal"); if (count == 0) { delete this; @@ -147,24 +147,10 @@ nsPrincipal::Init(const nsACString& aCertFingerprint, mCodebase = NS_TryToMakeImmutable(aCodebase); mCodebaseImmutable = URIIsImmutable(mCodebase); - nsresult rv; - if (!aCertFingerprint.IsEmpty()) { - rv = SetCertificate(aCertFingerprint, aSubjectName, aPrettyName, aCert); - if (NS_SUCCEEDED(rv)) { - rv = mJSPrincipals.Init(this, mCert->fingerprint); - } - } - else { - nsCAutoString spec; - rv = mCodebase->GetSpec(spec); - if (NS_SUCCEEDED(rv)) { - rv = mJSPrincipals.Init(this, spec); - } - } + if (aCertFingerprint.IsEmpty()) + return NS_OK; - NS_ASSERTION(NS_SUCCEEDED(rv), "nsPrincipal::Init() failed"); - - return rv; + return SetCertificate(aCertFingerprint, aSubjectName, aPrettyName, aCert); } nsPrincipal::~nsPrincipal(void) @@ -173,16 +159,25 @@ nsPrincipal::~nsPrincipal(void) delete mCapabilities; } -NS_IMETHODIMP -nsPrincipal::GetJSPrincipals(JSContext *cx, JSPrincipals **jsprin) +void +nsPrincipal::GetScriptLocation(nsACString &aStr) { - NS_PRECONDITION(mJSPrincipals.nsIPrincipalPtr, "mJSPrincipals is uninitialized!"); - - JSPRINCIPALS_HOLD(cx, &mJSPrincipals); - *jsprin = &mJSPrincipals; - return NS_OK; + if (mCert) { + aStr.Assign(mCert->fingerprint); + } else { + mCodebase->GetSpec(aStr); + } } +#ifdef DEBUG +void nsPrincipal::dumpImpl() +{ + nsCAutoString str; + GetScriptLocation(str); + fprintf(stderr, "nsPrincipal (%p) = %s\n", this, str.get()); +} +#endif + NS_IMETHODIMP nsPrincipal::GetOrigin(char **aOrigin) { @@ -883,9 +878,6 @@ nsPrincipal::InitFromPersistent(const char* aPrefName, mTrusted = aTrusted; } - rv = mJSPrincipals.Init(this, aToken); - NS_ENSURE_SUCCESS(rv, rv); - //-- Save the preference name mPrefName = aPrefName; diff --git a/caps/src/nsScriptSecurityManager.cpp b/caps/src/nsScriptSecurityManager.cpp index bf2b8424a494..169edef4f248 100644 --- a/caps/src/nsScriptSecurityManager.cpp +++ b/caps/src/nsScriptSecurityManager.cpp @@ -517,6 +517,13 @@ NS_IMPL_ISUPPORTS4(nsScriptSecurityManager, /////////////////////////////////////////////////// ///////////////// Security Checks ///////////////// + +/* static */ JSPrincipals * +nsScriptSecurityManager::ObjectPrincipalFinder(JSObject *aObj) +{ + return nsJSPrincipals::get(doGetObjectPrincipal(aObj)); +} + JSBool nsScriptSecurityManager::ContentSecurityPolicyPermitsJSAction(JSContext *cx) { @@ -537,7 +544,7 @@ nsScriptSecurityManager::ContentSecurityPolicyPermitsJSAction(JSContext *cx) if (!subjectPrincipal) { // See bug 553448 for discussion of this case. - NS_ASSERTION(!JS_GetSecurityCallbacks(cx)->findObjectPrincipals, + NS_ASSERTION(!JS_GetSecurityCallbacks(js::GetRuntime(cx))->findObjectPrincipals, "CSP: Should have been able to find subject principal. " "Reluctantly granting access."); return JS_TRUE; @@ -2179,11 +2186,7 @@ nsScriptSecurityManager::GetScriptPrincipal(JSContext *cx, NS_ERROR("Script compiled without principals!"); return nsnull; } - nsJSPrincipals *nsJSPrin = static_cast(jsp); - nsIPrincipal* result = nsJSPrin->nsIPrincipalPtr; - if (!result) - *rv = NS_ERROR_FAILURE; - return result; + return nsJSPrincipals::get(jsp); } // static @@ -3330,7 +3333,6 @@ nsScriptSecurityManager::nsScriptSecurityManager(void) mPrincipals.Init(31); } - nsresult nsScriptSecurityManager::Init() { nsXPConnect* xpconnect = nsXPConnect::GetXPConnect(); @@ -3365,10 +3367,6 @@ nsresult nsScriptSecurityManager::Init() nsRefPtr system = new nsSystemPrincipal(); NS_ENSURE_TRUE(system, NS_ERROR_OUT_OF_MEMORY); - JSPrincipals *jsprin; - rv = system->Init(&jsprin); - NS_ENSURE_SUCCESS(rv, rv); - mSystemPrincipal = system; //-- Register security check callback in the JS engine @@ -3380,20 +3378,19 @@ nsresult nsScriptSecurityManager::Init() rv = runtimeService->GetRuntime(&sRuntime); NS_ENSURE_SUCCESS(rv, rv); - static JSSecurityCallbacks securityCallbacks = { + static const JSSecurityCallbacks securityCallbacks = { CheckObjectAccess, - NULL, - NULL, + nsJSPrincipals::Subsume, + nsJSPrincipals::Transcode, + ObjectPrincipalFinder, ContentSecurityPolicyPermitsJSAction }; -#ifdef DEBUG - JSSecurityCallbacks *oldcallbacks = -#endif - JS_SetRuntimeSecurityCallbacks(sRuntime, &securityCallbacks); - NS_ASSERTION(!oldcallbacks, "Someone else set security callbacks!"); + MOZ_ASSERT(!JS_GetSecurityCallbacks(sRuntime)); + JS_SetSecurityCallbacks(sRuntime, &securityCallbacks); + JS_InitDestroyPrincipalsCallback(sRuntime, nsJSPrincipals::Destroy); - JS_SetTrustedPrincipals(sRuntime, jsprin); + JS_SetTrustedPrincipals(sRuntime, system); return NS_OK; } @@ -3417,7 +3414,7 @@ void nsScriptSecurityManager::Shutdown() { if (sRuntime) { - JS_SetRuntimeSecurityCallbacks(sRuntime, NULL); + JS_SetSecurityCallbacks(sRuntime, NULL); JS_SetTrustedPrincipals(sRuntime, NULL); sRuntime = nsnull; } @@ -3445,13 +3442,6 @@ nsScriptSecurityManager::GetScriptSecurityManager() return nsnull; } - rv = nsJSPrincipals::Startup(); - if (NS_FAILED(rv)) { - NS_WARNING("can't initialize JS engine security protocol glue!"); - delete ssManager; - return nsnull; - } - rv = sXPConnect->SetDefaultSecurityManager(ssManager, nsIXPCSecurityManager::HOOK_ALL); if (NS_FAILED(rv)) { diff --git a/caps/src/nsSystemPrincipal.cpp b/caps/src/nsSystemPrincipal.cpp index c223d07cfb6d..2b3f5b499bca 100644 --- a/caps/src/nsSystemPrincipal.cpp +++ b/caps/src/nsSystemPrincipal.cpp @@ -62,8 +62,8 @@ NS_IMPL_CI_INTERFACE_GETTER2(nsSystemPrincipal, NS_IMETHODIMP_(nsrefcnt) nsSystemPrincipal::AddRef() { - NS_PRECONDITION(PRInt32(mJSPrincipals.refcount) >= 0, "illegal refcnt"); - nsrefcnt count = PR_ATOMIC_INCREMENT(&mJSPrincipals.refcount); + NS_PRECONDITION(PRInt32(refcount) >= 0, "illegal refcnt"); + nsrefcnt count = PR_ATOMIC_INCREMENT(&refcount); NS_LOG_ADDREF(this, count, "nsSystemPrincipal", sizeof(*this)); return count; } @@ -71,8 +71,8 @@ nsSystemPrincipal::AddRef() NS_IMETHODIMP_(nsrefcnt) nsSystemPrincipal::Release() { - NS_PRECONDITION(0 != mJSPrincipals.refcount, "dup release"); - nsrefcnt count = PR_ATOMIC_DECREMENT(&mJSPrincipals.refcount); + NS_PRECONDITION(0 != refcount, "dup release"); + nsrefcnt count = PR_ATOMIC_DECREMENT(&refcount); NS_LOG_RELEASE(this, count, "nsSystemPrincipal"); if (count == 0) { delete this; @@ -81,13 +81,26 @@ nsSystemPrincipal::Release() return count; } +static const char SYSTEM_PRINCIPAL_SPEC[] = "[System Principal]"; + +void +nsSystemPrincipal::GetScriptLocation(nsACString &aStr) +{ + aStr.Assign(SYSTEM_PRINCIPAL_SPEC); +} + +#ifdef DEBUG +void nsSystemPrincipal::dumpImpl() +{ + fprintf(stderr, "nsSystemPrincipal (%p)\n", this); +} +#endif + /////////////////////////////////////// // Methods implementing nsIPrincipal // /////////////////////////////////////// -#define SYSTEM_PRINCIPAL_SPEC "[System Principal]" - NS_IMETHODIMP nsSystemPrincipal::GetPreferences(char** aPrefName, char** aID, char** aSubjectName, @@ -280,16 +293,6 @@ nsSystemPrincipal::SetSecurityPolicy(void* aSecurityPolicy) return NS_OK; } -NS_IMETHODIMP -nsSystemPrincipal::GetJSPrincipals(JSContext *cx, JSPrincipals **jsprin) -{ - NS_PRECONDITION(mJSPrincipals.nsIPrincipalPtr, "mJSPrincipals is uninitialized!"); - - JSPRINCIPALS_HOLD(cx, &mJSPrincipals); - *jsprin = &mJSPrincipals; - return NS_OK; -} - ////////////////////////////////////////// // Methods implementing nsISerializable // @@ -317,24 +320,6 @@ nsSystemPrincipal::nsSystemPrincipal() { } -nsresult -nsSystemPrincipal::Init(JSPrincipals **jsprin) -{ - // Use an nsCString so we only do the allocation once here and then - // share with nsJSPrincipals - nsCString str(SYSTEM_PRINCIPAL_SPEC); - if (!str.EqualsLiteral(SYSTEM_PRINCIPAL_SPEC)) { - NS_WARNING("Out of memory initializing system principal"); - return NS_ERROR_OUT_OF_MEMORY; - } - - nsresult rv = mJSPrincipals.Init(this, str); - NS_ENSURE_SUCCESS(rv, rv); - - *jsprin = &mJSPrincipals; - return NS_OK; -} - -nsSystemPrincipal::~nsSystemPrincipal(void) +nsSystemPrincipal::~nsSystemPrincipal() { } diff --git a/content/base/src/nsFrameMessageManager.cpp b/content/base/src/nsFrameMessageManager.cpp index 179d9af871e5..7cc0d44a8747 100644 --- a/content/base/src/nsFrameMessageManager.cpp +++ b/content/base/src/nsFrameMessageManager.cpp @@ -43,6 +43,7 @@ #include "nsIXPConnect.h" #include "jsapi.h" #include "nsJSUtils.h" +#include "nsJSPrincipals.h" #include "nsNetUtil.h" #include "nsScriptLoader.h" #include "nsIJSContextStack.h" @@ -811,15 +812,13 @@ nsFrameScriptExecutor::LoadFrameScriptInternal(const nsAString& aURL) JSObject* global = nsnull; mGlobal->GetJSObject(&global); if (global) { - JSPrincipals* jsprin = nsnull; - mPrincipal->GetJSPrincipals(mCx, &jsprin); - uint32 oldopts = JS_GetOptions(mCx); JS_SetOptions(mCx, oldopts | JSOPTION_NO_SCRIPT_RVAL); JSScript* script = - JS_CompileUCScriptForPrincipals(mCx, nsnull, jsprin, - (jschar*)dataString.get(), + JS_CompileUCScriptForPrincipals(mCx, nsnull, + nsJSPrincipals::get(mPrincipal), + static_cast(dataString.get()), dataString.Length(), url.get(), 1); @@ -839,8 +838,6 @@ nsFrameScriptExecutor::LoadFrameScriptInternal(const nsAString& aURL) } (void) JS_ExecuteScript(mCx, global, script, nsnull); } - //XXX Argh, JSPrincipals are manually refcounted! - JSPRINCIPALS_DROP(mCx, jsprin); } } JSContext* unused; diff --git a/content/canvas/src/WebGLContextReporter.cpp b/content/canvas/src/WebGLContextReporter.cpp index 8584643770ae..d3bb7098dd65 100644 --- a/content/canvas/src/WebGLContextReporter.cpp +++ b/content/canvas/src/WebGLContextReporter.cpp @@ -70,101 +70,83 @@ NS_IMETHODIMP WebGLMemoryMultiReporter::CollectReports(nsIMemoryMultiReporterCallback* aCb, nsISupports* aClosure) { - aCb->Callback( - EmptyCString(), - NS_LITERAL_CSTRING("webgl-texture-memory"), - nsIMemoryReporter::KIND_OTHER, nsIMemoryReporter::UNITS_BYTES, - WebGLMemoryMultiReporterWrapper::GetTextureMemoryUsed(), - NS_LITERAL_CSTRING("Memory used by WebGL textures.The OpenGL" - " implementation is free to store these textures in either video" - " memory or main memory. This measurement is only a lower bound," - " actual memory usage may be higher for example if the storage" - " is strided."), - aClosure); - - aCb->Callback( - EmptyCString(), - NS_LITERAL_CSTRING("webgl-texture-count"), - nsIMemoryReporter::KIND_OTHER, nsIMemoryReporter::UNITS_COUNT, - WebGLMemoryMultiReporterWrapper::GetTextureCount(), - NS_LITERAL_CSTRING("Number of WebGL textures."), - aClosure); +#define REPORT(_path, _kind, _units, _amount, _desc) \ + do { \ + nsresult rv; \ + rv = aCb->Callback(EmptyCString(), NS_LITERAL_CSTRING(_path), _kind, \ + _units, _amount, NS_LITERAL_CSTRING(_desc), \ + aClosure); \ + NS_ENSURE_SUCCESS(rv, rv); \ + } while (0) - aCb->Callback( - EmptyCString(), - NS_LITERAL_CSTRING("webgl-buffer-memory"), - nsIMemoryReporter::KIND_OTHER, nsIMemoryReporter::UNITS_BYTES, - WebGLMemoryMultiReporterWrapper::GetBufferMemoryUsed(), - NS_LITERAL_CSTRING("Memory used by WebGL buffers. The OpenGL" - " implementation is free to store these buffers in either video" - " memory or main memory. This measurement is only a lower bound," - " actual memory usage may be higher for example if the storage" - " is strided."), - aClosure); - - aCb->Callback( - EmptyCString(), - NS_LITERAL_CSTRING("explicit/webgl/buffer-cache-memory"), - nsIMemoryReporter::KIND_HEAP, nsIMemoryReporter::UNITS_BYTES, - WebGLMemoryMultiReporterWrapper::GetBufferCacheMemoryUsed(), - NS_LITERAL_CSTRING("Memory used by WebGL buffer caches. The WebGL" - " implementation caches the contents of element array buffers" - " only.This adds up with the webgl-buffer-memory value, but" - " contrary to it, this one represents bytes on the heap," - " not managed by OpenGL."), - aClosure); - - aCb->Callback( - EmptyCString(), NS_LITERAL_CSTRING("webgl-buffer-count"), - nsIMemoryReporter::KIND_OTHER, nsIMemoryReporter::UNITS_COUNT, - WebGLMemoryMultiReporterWrapper::GetBufferCount(), - NS_LITERAL_CSTRING("Number of WebGL buffers."), - aClosure); + REPORT("webgl-texture-memory", + nsIMemoryReporter::KIND_OTHER, nsIMemoryReporter::UNITS_BYTES, + WebGLMemoryMultiReporterWrapper::GetTextureMemoryUsed(), + "Memory used by WebGL textures.The OpenGL" + " implementation is free to store these textures in either video" + " memory or main memory. This measurement is only a lower bound," + " actual memory usage may be higher for example if the storage" + " is strided."); - aCb->Callback( - EmptyCString(), - NS_LITERAL_CSTRING("webgl-renderbuffer-memory"), - nsIMemoryReporter::KIND_OTHER, nsIMemoryReporter::UNITS_BYTES, - WebGLMemoryMultiReporterWrapper::GetRenderbufferMemoryUsed(), - NS_LITERAL_CSTRING("Memory used by WebGL renderbuffers. The OpenGL" - " implementation is free to store these renderbuffers in either" - " video memory or main memory. This measurement is only a lower" - " bound, actual memory usage may be higher for example if the" - " storage is strided."), - aClosure); + REPORT("webgl-texture-count", + nsIMemoryReporter::KIND_OTHER, nsIMemoryReporter::UNITS_COUNT, + WebGLMemoryMultiReporterWrapper::GetTextureCount(), + "Number of WebGL textures."); + + REPORT("webgl-buffer-memory", + nsIMemoryReporter::KIND_OTHER, nsIMemoryReporter::UNITS_BYTES, + WebGLMemoryMultiReporterWrapper::GetBufferMemoryUsed(), + "Memory used by WebGL buffers. The OpenGL" + " implementation is free to store these buffers in either video" + " memory or main memory. This measurement is only a lower bound," + " actual memory usage may be higher for example if the storage" + " is strided."); + + REPORT("explicit/webgl/buffer-cache-memory", + nsIMemoryReporter::KIND_HEAP, nsIMemoryReporter::UNITS_BYTES, + WebGLMemoryMultiReporterWrapper::GetBufferCacheMemoryUsed(), + "Memory used by WebGL buffer caches. The WebGL" + " implementation caches the contents of element array buffers" + " only.This adds up with the webgl-buffer-memory value, but" + " contrary to it, this one represents bytes on the heap," + " not managed by OpenGL."); + + REPORT("webgl-buffer-count", + nsIMemoryReporter::KIND_OTHER, nsIMemoryReporter::UNITS_COUNT, + WebGLMemoryMultiReporterWrapper::GetBufferCount(), + "Number of WebGL buffers."); - aCb->Callback( - EmptyCString(), - NS_LITERAL_CSTRING("webgl-renderbuffer-count"), - nsIMemoryReporter::KIND_OTHER, nsIMemoryReporter::UNITS_COUNT, - WebGLMemoryMultiReporterWrapper::GetRenderbufferCount(), - NS_LITERAL_CSTRING("Number of WebGL renderbuffers."), - aClosure); + REPORT("webgl-renderbuffer-memory", + nsIMemoryReporter::KIND_OTHER, nsIMemoryReporter::UNITS_BYTES, + WebGLMemoryMultiReporterWrapper::GetRenderbufferMemoryUsed(), + "Memory used by WebGL renderbuffers. The OpenGL" + " implementation is free to store these renderbuffers in either" + " video memory or main memory. This measurement is only a lower" + " bound, actual memory usage may be higher for example if the" + " storage is strided."); + + REPORT("webgl-renderbuffer-count", + nsIMemoryReporter::KIND_OTHER, nsIMemoryReporter::UNITS_COUNT, + WebGLMemoryMultiReporterWrapper::GetRenderbufferCount(), + "Number of WebGL renderbuffers."); - aCb->Callback( - EmptyCString(), - NS_LITERAL_CSTRING("explicit/webgl/shader"), - nsIMemoryReporter::KIND_HEAP, nsIMemoryReporter::UNITS_BYTES, - WebGLMemoryMultiReporterWrapper::GetShaderSize(), - NS_LITERAL_CSTRING("Combined size of WebGL shader ASCII sources and" - " translation logs cached on the heap."), - aClosure); + REPORT("explicit/webgl/shader", + nsIMemoryReporter::KIND_HEAP, nsIMemoryReporter::UNITS_BYTES, + WebGLMemoryMultiReporterWrapper::GetShaderSize(), + "Combined size of WebGL shader ASCII sources and translation" + " logs cached on the heap."); - aCb->Callback( - EmptyCString(), - NS_LITERAL_CSTRING("webgl-shader-count"), - nsIMemoryReporter::KIND_OTHER, nsIMemoryReporter::UNITS_COUNT, - WebGLMemoryMultiReporterWrapper::GetShaderCount(), - NS_LITERAL_CSTRING("Number of WebGL shaders."), - aClosure); + REPORT("webgl-shader-count", + nsIMemoryReporter::KIND_OTHER, nsIMemoryReporter::UNITS_COUNT, + WebGLMemoryMultiReporterWrapper::GetShaderCount(), + "Number of WebGL shaders."); - aCb->Callback( - EmptyCString(), - NS_LITERAL_CSTRING("webgl-context-count"), - nsIMemoryReporter::KIND_OTHER, nsIMemoryReporter::UNITS_COUNT, - WebGLMemoryMultiReporterWrapper::GetContextCount(), - NS_LITERAL_CSTRING("Number of WebGL contexts."), - aClosure); + REPORT("webgl-context-count", + nsIMemoryReporter::KIND_OTHER, nsIMemoryReporter::UNITS_COUNT, + WebGLMemoryMultiReporterWrapper::GetContextCount(), + "Number of WebGL contexts."); + +#undef REPORT return NS_OK; } diff --git a/content/svg/content/src/nsSVGFilters.cpp b/content/svg/content/src/nsSVGFilters.cpp index 624be8b8da73..f97e8e4035c2 100644 --- a/content/svg/content/src/nsSVGFilters.cpp +++ b/content/svg/content/src/nsSVGFilters.cpp @@ -144,12 +144,12 @@ nsSVGFE::SetupScalingFilter(nsSVGFilterInstance *aInstance, return result; } - float kernelX = aInstance->GetPrimitiveNumber(nsSVGUtils::X, - aKernelUnitLength, - nsSVGNumberPair::eFirst); - float kernelY = aInstance->GetPrimitiveNumber(nsSVGUtils::Y, - aKernelUnitLength, - nsSVGNumberPair::eSecond); + gfxFloat kernelX = aInstance->GetPrimitiveNumber(nsSVGUtils::X, + aKernelUnitLength, + nsSVGNumberPair::eFirst); + gfxFloat kernelY = aInstance->GetPrimitiveNumber(nsSVGUtils::Y, + aKernelUnitLength, + nsSVGNumberPair::eSecond); if (kernelX <= 0 || kernelY <= 0) return result; diff --git a/dom/base/nsJSEnvironment.cpp b/dom/base/nsJSEnvironment.cpp index e867b87b83f3..94b8f64bf738 100644 --- a/dom/base/nsJSEnvironment.cpp +++ b/dom/base/nsJSEnvironment.cpp @@ -518,11 +518,10 @@ NS_ScriptErrorReporter(JSContext *cx, innerWindowID = innerWin->WindowID(); } } - JSPrincipals *prin = report->originPrincipals; - nsIPrincipal *principal = - prin ? static_cast(prin)->nsIPrincipalPtr : nsnull; nsContentUtils::AddScriptRunner( - new ScriptErrorEvent(globalObject, principal, report->lineno, + new ScriptErrorEvent(globalObject, + nsJSPrincipals::get(report->originPrincipals), + report->lineno, report->uctokenptr - report->uclinebuf, report->flags, msg, fileName, sourceLine, report->errorNumber != JSMSG_OUT_OF_MEMORY, @@ -1218,8 +1217,7 @@ nsJSContext::EvaluateStringWithValue(const nsAString& aScript, // Safety first: get an object representing the script's principals, i.e., // the entities who signed this script, or the fully-qualified-domain-name // or "codebase" from which it was loaded. - JSPrincipals *jsprin; - nsIPrincipal *principal = aPrincipal; + nsCOMPtr principal = aPrincipal; nsresult rv; if (!aPrincipal) { nsIScriptGlobalObject *global = GetGlobalObject(); @@ -1234,15 +1232,10 @@ nsJSContext::EvaluateStringWithValue(const nsAString& aScript, return NS_ERROR_FAILURE; } - principal->GetJSPrincipals(mContext, &jsprin); - - // From here on, we must JSPRINCIPALS_DROP(jsprin) before returning... - bool ok = false; rv = sSecurityManager->CanExecuteScripts(mContext, principal, &ok); if (NS_FAILED(rv)) { - JSPRINCIPALS_DROP(mContext, jsprin); return NS_ERROR_FAILURE; } @@ -1253,7 +1246,6 @@ nsJSContext::EvaluateStringWithValue(const nsAString& aScript, nsCOMPtr stack = do_GetService("@mozilla.org/js/xpc/ContextStack;1", &rv); if (NS_FAILED(rv) || NS_FAILED(stack->Push(mContext))) { - JSPRINCIPALS_DROP(mContext, jsprin); return NS_ERROR_FAILURE; } @@ -1273,7 +1265,6 @@ nsJSContext::EvaluateStringWithValue(const nsAString& aScript, JSAutoEnterCompartment ac; if (!ac.enter(mContext, aScopeObject)) { - JSPRINCIPALS_DROP(mContext, jsprin); stack->Pop(nsnull); return NS_ERROR_FAILURE; } @@ -1282,7 +1273,7 @@ nsJSContext::EvaluateStringWithValue(const nsAString& aScript, ok = ::JS_EvaluateUCScriptForPrincipalsVersion(mContext, aScopeObject, - jsprin, + nsJSPrincipals::get(principal), static_cast(PromiseFlatString(aScript).get()), aScript.Length(), aURL, @@ -1301,9 +1292,6 @@ nsJSContext::EvaluateStringWithValue(const nsAString& aScript, } } - // Whew! Finally done with these manually ref-counted things. - JSPRINCIPALS_DROP(mContext, jsprin); - // If all went well, convert val to a string (XXXbe unless undefined?). if (ok) { if (aIsUndefined) { @@ -1427,12 +1415,8 @@ nsJSContext::EvaluateString(const nsAString& aScript, // Safety first: get an object representing the script's principals, i.e., // the entities who signed this script, or the fully-qualified-domain-name // or "codebase" from which it was loaded. - JSPrincipals *jsprin; - nsIPrincipal *principal = aPrincipal; - if (aPrincipal) { - aPrincipal->GetJSPrincipals(mContext, &jsprin); - } - else { + nsCOMPtr principal = aPrincipal; + if (!aPrincipal) { nsCOMPtr objPrincipal = do_QueryInterface(GetGlobalObject()); if (!objPrincipal) @@ -1440,26 +1424,12 @@ nsJSContext::EvaluateString(const nsAString& aScript, principal = objPrincipal->GetPrincipal(); if (!principal) return NS_ERROR_FAILURE; - principal->GetJSPrincipals(mContext, &jsprin); } - JSPrincipals *originJSprin; - if (aOriginPrincipal) { - aOriginPrincipal->GetJSPrincipals(mContext, &originJSprin); - } else { - originJSprin = nsnull; - } - - // From here on, we must JSPRINCIPALS_DROP(jsprin) before returning... - bool ok = false; nsresult rv = sSecurityManager->CanExecuteScripts(mContext, principal, &ok); if (NS_FAILED(rv)) { - JSPRINCIPALS_DROP(mContext, jsprin); - if (originJSprin) { - JSPRINCIPALS_DROP(mContext, originJSprin); - } return NS_ERROR_FAILURE; } @@ -1470,10 +1440,6 @@ nsJSContext::EvaluateString(const nsAString& aScript, nsCOMPtr stack = do_GetService("@mozilla.org/js/xpc/ContextStack;1", &rv); if (NS_FAILED(rv) || NS_FAILED(stack->Push(mContext))) { - JSPRINCIPALS_DROP(mContext, jsprin); - if (originJSprin) { - JSPRINCIPALS_DROP(mContext, originJSprin); - } return NS_ERROR_FAILURE; } @@ -1498,15 +1464,12 @@ nsJSContext::EvaluateString(const nsAString& aScript, JSAutoEnterCompartment ac; if (!ac.enter(mContext, aScopeObject)) { stack->Pop(nsnull); - JSPRINCIPALS_DROP(mContext, jsprin); - if (originJSprin) { - JSPRINCIPALS_DROP(mContext, originJSprin); - } return NS_ERROR_FAILURE; } ok = JS_EvaluateUCScriptForPrincipalsVersionOrigin( - mContext, aScopeObject, jsprin, originJSprin, + mContext, aScopeObject, + nsJSPrincipals::get(principal), nsJSPrincipals::get(aOriginPrincipal), static_cast(PromiseFlatString(aScript).get()), aScript.Length(), aURL, aLineNo, vp, JSVersion(aVersion)); @@ -1519,12 +1482,6 @@ nsJSContext::EvaluateString(const nsAString& aScript, } } - // Whew! Finally done with these manually ref-counted things. - JSPRINCIPALS_DROP(mContext, jsprin); - if (originJSprin) { - JSPRINCIPALS_DROP(mContext, originJSprin); - } - // If all went well, convert val to a string if one is wanted. if (ok) { JSAutoRequest ar(mContext); @@ -1573,47 +1530,38 @@ nsJSContext::CompileScript(const PRUnichar* aText, JSObject* scopeObject = ::JS_GetGlobalObject(mContext); - JSPrincipals *jsprin; - aPrincipal->GetJSPrincipals(mContext, &jsprin); - // From here on, we must JSPRINCIPALS_DROP(jsprin) before returning... - bool ok = false; nsresult rv = sSecurityManager->CanExecuteScripts(mContext, aPrincipal, &ok); if (NS_FAILED(rv)) { - JSPRINCIPALS_DROP(mContext, jsprin); return NS_ERROR_FAILURE; } aScriptObject.drop(); // ensure old object not used on failure... - // SecurityManager said "ok", but don't compile if aVersion is unknown. + // Don't compile if SecurityManager said "not ok" or aVersion is unknown. // Since the caller is responsible for parsing the version strings, we just // check it isn't JSVERSION_UNKNOWN. - if (ok && ((JSVersion)aVersion) != JSVERSION_UNKNOWN) { - JSAutoRequest ar(mContext); + if (!ok || JSVersion(aVersion) == JSVERSION_UNKNOWN) + return NS_OK; + + JSAutoRequest ar(mContext); - JSScript* script = - ::JS_CompileUCScriptForPrincipalsVersion(mContext, - scopeObject, - jsprin, - static_cast(aText), - aTextLength, - aURL, - aLineNo, - JSVersion(aVersion)); - if (script) { - NS_ASSERTION(aScriptObject.getScriptTypeID()==JAVASCRIPT, - "Expecting JS script object holder"); - rv = aScriptObject.set(script); - } else { - rv = NS_ERROR_OUT_OF_MEMORY; - } + JSScript* script = + ::JS_CompileUCScriptForPrincipalsVersion(mContext, + scopeObject, + nsJSPrincipals::get(aPrincipal), + static_cast(aText), + aTextLength, + aURL, + aLineNo, + JSVersion(aVersion)); + if (!script) { + return NS_ERROR_OUT_OF_MEMORY; } - - // Whew! Finally done. - JSPRINCIPALS_DROP(mContext, jsprin); - return rv; + NS_ASSERTION(aScriptObject.getScriptTypeID()==JAVASCRIPT, + "Expecting JS script object holder"); + return aScriptObject.set(script); } nsresult @@ -1836,17 +1784,15 @@ nsJSContext::CompileFunction(JSObject* aTarget, return NS_ERROR_ILLEGAL_VALUE; } - JSPrincipals *jsprin = nsnull; - nsIScriptGlobalObject *global = GetGlobalObject(); + nsCOMPtr principal; if (global) { // XXXbe why the two-step QI? speed up via a new GetGlobalObjectData func? nsCOMPtr globalData = do_QueryInterface(global); if (globalData) { - nsIPrincipal *prin = globalData->GetPrincipal(); - if (!prin) + principal = globalData->GetPrincipal(); + if (!principal) return NS_ERROR_FAILURE; - prin->GetJSPrincipals(mContext, &jsprin); } } @@ -1856,7 +1802,8 @@ nsJSContext::CompileFunction(JSObject* aTarget, JSFunction* fun = ::JS_CompileUCFunctionForPrincipalsVersion(mContext, - aShared ? nsnull : target, jsprin, + aShared ? nsnull : target, + nsJSPrincipals::get(principal), PromiseFlatCString(aName).get(), aArgCount, aArgArray, static_cast(PromiseFlatString(aBody).get()), @@ -1864,8 +1811,6 @@ nsJSContext::CompileFunction(JSObject* aTarget, aURL, aLineNo, JSVersion(aVersion)); - if (jsprin) - JSPRINCIPALS_DROP(mContext, jsprin); if (!fun) return NS_ERROR_FAILURE; @@ -3768,33 +3713,6 @@ SetMemoryGCSliceTimePrefChangedCallback(const char* aPrefName, void* aClosure) return 0; } -static JSPrincipals * -ObjectPrincipalFinder(JSContext *cx, JSObject *obj) -{ - if (!sSecurityManager) - return nsnull; - - nsCOMPtr principal; - nsresult rv = - sSecurityManager->GetObjectPrincipal(cx, obj, - getter_AddRefs(principal)); - - if (NS_FAILED(rv) || !principal) { - return nsnull; - } - - JSPrincipals *jsPrincipals = nsnull; - principal->GetJSPrincipals(cx, &jsPrincipals); - - // nsIPrincipal::GetJSPrincipals() returns a strong reference to the - // JS principals, but the caller of this function expects a weak - // reference. So we need to release here. - - JSPRINCIPALS_DROP(cx, jsPrincipals); - - return jsPrincipals; -} - JSObject* NS_DOMReadStructuredClone(JSContext* cx, JSStructuredCloneReader* reader, @@ -3853,11 +3771,6 @@ nsJSRuntime::Init() sPrevGCSliceCallback = js::SetGCSliceCallback(sRuntime, DOMGCSliceCallback); - JSSecurityCallbacks *callbacks = JS_GetRuntimeSecurityCallbacks(sRuntime); - NS_ASSERTION(callbacks, "SecMan should have set security callbacks!"); - - callbacks->findObjectPrincipals = ObjectPrincipalFinder; - // Set up the structured clone callbacks. static JSStructuredCloneCallbacks cloneCallbacks = { NS_DOMReadStructuredClone, @@ -3955,14 +3868,6 @@ nsJSRuntime::Shutdown() // We're being shutdown, and there are no more contexts // alive, release the JS runtime service and the security manager. - if (sRuntimeService && sSecurityManager) { - JSSecurityCallbacks *callbacks = JS_GetRuntimeSecurityCallbacks(sRuntime); - if (callbacks) { - NS_ASSERTION(callbacks->findObjectPrincipals == ObjectPrincipalFinder, - "Fighting over the findObjectPrincipals callback!"); - callbacks->findObjectPrincipals = NULL; - } - } NS_IF_RELEASE(sRuntimeService); NS_IF_RELEASE(sSecurityManager); } diff --git a/dom/base/nsWindowMemoryReporter.cpp b/dom/base/nsWindowMemoryReporter.cpp index 8d8bd1bdddfb..b94e7afe6834 100644 --- a/dom/base/nsWindowMemoryReporter.cpp +++ b/dom/base/nsWindowMemoryReporter.cpp @@ -90,7 +90,7 @@ AppendWindowURI(nsGlobalWindow *aWindow, nsACString& aStr) NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(DOMStyleMallocSizeOf, "windows") -static void +static nsresult CollectWindowReports(nsGlobalWindow *aWindow, nsWindowSizes *aWindowTotalSizes, nsIMemoryMultiReporterCallback *aCb, @@ -197,9 +197,11 @@ CollectWindowReports(nsGlobalWindow *aWindow, if (_amount > 0) { \ nsCAutoString path(_path1); \ path += _path2; \ - aCb->Callback(EmptyCString(), path, nsIMemoryReporter::KIND_HEAP, \ + nsresult rv; \ + rv = aCb->Callback(EmptyCString(), path, nsIMemoryReporter::KIND_HEAP,\ nsIMemoryReporter::UNITS_BYTES, _amount, \ NS_LITERAL_CSTRING(_desc), aClosure); \ + NS_ENSURE_SUCCESS(rv, rv); \ } \ } while (0) @@ -226,6 +228,8 @@ CollectWindowReports(nsGlobalWindow *aWindow, aWindowTotalSizes->mLayoutTextRuns += windowSizes.mLayoutTextRuns; #undef REPORT + + return NS_OK; } typedef nsTArray< nsRefPtr > WindowArray; @@ -264,15 +268,18 @@ nsWindowMemoryReporter::CollectReports(nsIMemoryMultiReporterCallback* aCb, nsRefPtr *end = w + windows.Length(); nsWindowSizes windowTotalSizes(NULL); for (; w != end; ++w) { - CollectWindowReports(*w, &windowTotalSizes, aCb, aClosure); + nsresult rv = CollectWindowReports(*w, &windowTotalSizes, aCb, aClosure); + NS_ENSURE_SUCCESS(rv, rv); } #define REPORT(_path, _amount, _desc) \ do { \ - aCb->Callback(EmptyCString(), NS_LITERAL_CSTRING(_path), \ - nsIMemoryReporter::KIND_OTHER, \ - nsIMemoryReporter::UNITS_BYTES, _amount, \ - NS_LITERAL_CSTRING(_desc), aClosure); \ + nsresult rv; \ + rv = aCb->Callback(EmptyCString(), NS_LITERAL_CSTRING(_path), \ + nsIMemoryReporter::KIND_OTHER, \ + nsIMemoryReporter::UNITS_BYTES, _amount, \ + NS_LITERAL_CSTRING(_desc), aClosure); \ + NS_ENSURE_SUCCESS(rv, rv); \ } while (0) REPORT("window-objects-dom", windowTotalSizes.mDOM, diff --git a/dom/workers/Principal.cpp b/dom/workers/Principal.cpp index 8427db586b64..678092b32f43 100644 --- a/dom/workers/Principal.cpp +++ b/dom/workers/Principal.cpp @@ -40,31 +40,19 @@ #include "jsapi.h" +BEGIN_WORKERS_NAMESPACE + namespace { -void -PrincipalDestroy(JSContext*, JSPrincipals*) -{ - // nothing -} - -JSBool -PrincipalSubsume(JSPrincipals*, JSPrincipals*) -{ - return JS_TRUE; -} - -const char gPrincipalCodebase[] = "Web Worker"; - JSPrincipals gPrincipal = { - const_cast(gPrincipalCodebase), - 1, PrincipalDestroy, PrincipalSubsume + 1 +#ifdef DEBUG + , kJSPrincipalsDebugToken +#endif }; } // anonymous namespace -BEGIN_WORKERS_NAMESPACE - JSPrincipals* GetWorkerPrincipal() { diff --git a/dom/workers/WorkerPrivate.cpp b/dom/workers/WorkerPrivate.cpp index e827aab9886b..1881f22079ae 100644 --- a/dom/workers/WorkerPrivate.cpp +++ b/dom/workers/WorkerPrivate.cpp @@ -157,6 +157,22 @@ SwapToISupportsArray(SmartPtr& aSrc, NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(JsWorkerMallocSizeOf, "js-worker") +struct WorkerJSRuntimeStats : public JS::RuntimeStats +{ + WorkerJSRuntimeStats() + : JS::RuntimeStats(JsWorkerMallocSizeOf) { } + + virtual void initExtraCompartmentStats(JSCompartment *c, + JS::CompartmentStats *cstats) MOZ_OVERRIDE + { + MOZ_ASSERT(!cstats->extra); + + // ReportJSRuntimeExplicitTreeStats expects that cstats->extra is a char pointer + const char *name = js::IsAtomsCompartment(c) ? "Web Worker Atoms" : "Web Worker"; + cstats->extra = const_cast(name); + } +}; + class WorkerMemoryReporter : public nsIMemoryMultiReporter { WorkerPrivate* mWorkerPrivate; @@ -240,8 +256,7 @@ public: { AssertIsOnMainThread(); - JS::RuntimeStats rtStats(JsWorkerMallocSizeOf, xpc::GetCompartmentName, - xpc::DestroyCompartmentName); + WorkerJSRuntimeStats rtStats; nsresult rv = CollectForRuntime(/* isQuick = */false, &rtStats); if (NS_FAILED(rv)) { return rv; @@ -249,7 +264,10 @@ public: // Always report, even if we're disabled, so that we at least get an entry // in about::memory. - ReportJSRuntimeExplicitTreeStats(rtStats, mPathPrefix, aCallback, aClosure); + rv = ReportJSRuntimeExplicitTreeStats(rtStats, mPathPrefix, aCallback, aClosure); + if (NS_FAILED(rv)) { + return rv; + } return NS_OK; } diff --git a/dom/workers/Workers.h b/dom/workers/Workers.h index 52944c1ee948..4451c2c84730 100644 --- a/dom/workers/Workers.h +++ b/dom/workers/Workers.h @@ -123,6 +123,9 @@ protected: WorkerCrossThreadDispatcher* GetWorkerCrossThreadDispatcher(JSContext* aCx, jsval aWorker); +// Random unique constant to facilitate JSPrincipal debugging +const uint32_t kJSPrincipalsDebugToken = 0x7e2df9d2; + END_WORKERS_NAMESPACE #endif /* mozilla_dom_workers_workers_h__ */ diff --git a/gfx/gl/GLContext.cpp b/gfx/gl/GLContext.cpp index d01a7eb6edd1..6a01ddf73221 100644 --- a/gfx/gl/GLContext.cpp +++ b/gfx/gl/GLContext.cpp @@ -985,7 +985,7 @@ TiledTextureImage::DirectUpdate(gfxASurface* aSurf, const nsIntRegion& aRegion, { nsIntRegion region; - if (mTextureState != Valid || !mGL->CanUploadSubTextures()) { + if (mTextureState != Valid) { nsIntRect bounds = nsIntRect(0, 0, mSize.width, mSize.height); region = nsIntRegion(bounds); } else { @@ -997,10 +997,17 @@ TiledTextureImage::DirectUpdate(gfxASurface* aSurf, const nsIntRegion& aRegion, int xPos = (i % mColumns) * mTileSize; int yPos = (i / mColumns) * mTileSize; nsIntRegion tileRegion; - tileRegion.And(region, nsIntRect(nsIntPoint(xPos,yPos), mImages[i]->GetSize())); // intersect with tile + nsIntRect tileRect = nsIntRect(nsIntPoint(xPos, yPos), mImages[i]->GetSize()); + tileRegion.And(region, tileRect); // intersect with tile if (tileRegion.IsEmpty()) continue; - tileRegion.MoveBy(-xPos, -yPos); // translate into tile local space + if (mGL->CanUploadSubTextures()) { + tileRegion.MoveBy(-xPos, -yPos); // translate into tile local space + } else { + // If sub-textures are unsupported, expand to tile boundaries + tileRect.x = tileRect.y = 0; + tileRegion = nsIntRegion(tileRect); + } result &= mImages[i]->DirectUpdate(aSurf, tileRegion, aFrom + nsIntPoint(xPos, yPos)); diff --git a/gfx/thebes/gfxWindowsPlatform.cpp b/gfx/thebes/gfxWindowsPlatform.cpp index a500897eb08b..e8b04770d371 100644 --- a/gfx/thebes/gfxWindowsPlatform.cpp +++ b/gfx/thebes/gfxWindowsPlatform.cpp @@ -293,29 +293,28 @@ public: FreeLibrary(gdi32Handle); - aCb->Callback(EmptyCString(), - NS_LITERAL_CSTRING("gpu-committed"), - nsIMemoryReporter::KIND_OTHER, - nsIMemoryReporter::UNITS_BYTES, - committedBytesUsed, - NS_LITERAL_CSTRING("Memory committed by the Windows graphics system."), - aClosure); - aCb->Callback(EmptyCString(), - NS_LITERAL_CSTRING("gpu-dedicated"), - nsIMemoryReporter::KIND_OTHER, - nsIMemoryReporter::UNITS_BYTES, - dedicatedBytesUsed, - NS_LITERAL_CSTRING("Out-of-process memory allocated for this process in a " - "physical GPU adapter's memory."), - aClosure); - aCb->Callback(EmptyCString(), - NS_LITERAL_CSTRING("gpu-shared"), - nsIMemoryReporter::KIND_OTHER, - nsIMemoryReporter::UNITS_BYTES, - sharedBytesUsed, - NS_LITERAL_CSTRING("In-process memory that is shared with the GPU."), - aClosure); +#define REPORT(_path, _amount, _desc) \ + do { \ + nsresult rv; \ + rv = aCb->Callback(EmptyCString(), NS_LITERAL_CSTRING(_path), \ + nsIMemoryReporter::KIND_OTHER, \ + nsIMemoryReporter::UNITS_BYTES, _amount, \ + NS_LITERAL_CSTRING(_desc), aClosure); \ + NS_ENSURE_SUCCESS(rv, rv); \ + } while (0) + + REPORT("gpu-committed", committedBytesUsed, + "Memory committed by the Windows graphics system."); + + REPORT("gpu-dedicated", dedicatedBytesUsed, + "Out-of-process memory allocated for this process in a " + "physical GPU adapter's memory."); + + REPORT("gpu-shared", sharedBytesUsed, + "In-process memory that is shared with the GPU."); +#undef REPORT + return NS_OK; } diff --git a/ipc/testshell/XPCShellEnvironment.cpp b/ipc/testshell/XPCShellEnvironment.cpp index 4a5f56e79889..c985744f7d86 100644 --- a/ipc/testshell/XPCShellEnvironment.cpp +++ b/ipc/testshell/XPCShellEnvironment.cpp @@ -67,6 +67,7 @@ #include "nsIXPCScriptable.h" #include "nsJSUtils.h" +#include "nsJSPrincipals.h" #include "nsThreadUtils.h" #include "nsXULAppAPI.h" @@ -1058,7 +1059,7 @@ XPCShellEnvironment::~XPCShellEnvironment() mCxStack = nsnull; if (mJSPrincipals) { - JSPRINCIPALS_DROP(mCx, mJSPrincipals); + JS_DropPrincipals(JS_GetRuntime(mCx), mJSPrincipals); } JSRuntime* rt = gOldContextCallback ? JS_GetRuntime(mCx) : NULL; @@ -1140,10 +1141,8 @@ XPCShellEnvironment::Init() fprintf(stderr, "+++ Failed to obtain SystemPrincipal from ScriptSecurityManager service.\n"); } else { // fetch the JS principals and stick in a global - rv = principal->GetJSPrincipals(cx, &mJSPrincipals); - if (NS_FAILED(rv)) { - fprintf(stderr, "+++ Failed to obtain JS principals from SystemPrincipal.\n"); - } + mJSPrincipals = nsJSPrincipals::get(principal); + JS_HoldPrincipals(mJSPrincipals); secman->SetSystemPrincipal(principal); } } else { diff --git a/js/public/MemoryMetrics.h b/js/public/MemoryMetrics.h index c79f8b9454e1..513db5b5e26b 100644 --- a/js/public/MemoryMetrics.h +++ b/js/public/MemoryMetrics.h @@ -1,4 +1,7 @@ -/* ***** BEGIN LICENSE BLOCK ***** +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * vim: set ts=8 sw=4 et tw=99 ft=cpp: + * + * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version @@ -61,31 +64,13 @@ struct TypeInferenceSizes size_t temporary; }; -typedef void* (* GetNameCallback)(JSRuntime *rt, JSCompartment *c); -typedef void (* DestroyNameCallback)(void *string); - struct CompartmentStats { - CompartmentStats() - { + CompartmentStats() { memset(this, 0, sizeof(*this)); } - void init(void *name_, DestroyNameCallback destroyName) - { - name = name_; - destroyNameCb = destroyName; - } - - ~CompartmentStats() - { - destroyNameCb(name); - } - - // Pointer to an nsCString, which we can't use here. - void *name; - DestroyNameCallback destroyNameCb; - + void *extra; size_t gcHeapArenaHeaders; size_t gcHeapArenaPadding; size_t gcHeapArenaUnused; @@ -119,8 +104,7 @@ struct CompartmentStats struct RuntimeStats { - RuntimeStats(JSMallocSizeOfFun mallocSizeOf, GetNameCallback getNameCb, - DestroyNameCallback destroyNameCb) + RuntimeStats(JSMallocSizeOfFun mallocSizeOf) : runtimeObject(0) , runtimeAtomsTable(0) , runtimeContexts(0) @@ -149,8 +133,6 @@ struct RuntimeStats , compartmentStatsVector() , currCompartmentStats(NULL) , mallocSizeOf(mallocSizeOf) - , getNameCb(getNameCb) - , destroyNameCb(destroyNameCb) {} size_t runtimeObject; @@ -183,8 +165,8 @@ struct RuntimeStats CompartmentStats *currCompartmentStats; JSMallocSizeOfFun mallocSizeOf; - GetNameCallback getNameCb; - DestroyNameCallback destroyNameCb; + + virtual void initExtraCompartmentStats(JSCompartment *c, CompartmentStats *cstats) = 0; }; #ifdef JS_THREADSAFE diff --git a/js/src/MemoryMetrics.cpp b/js/src/MemoryMetrics.cpp index bd96b7f5dcc6..39b4e0111631 100644 --- a/js/src/MemoryMetrics.cpp +++ b/js/src/MemoryMetrics.cpp @@ -63,7 +63,7 @@ StatsCompartmentCallback(JSRuntime *rt, void *data, JSCompartment *compartment) // CollectRuntimeStats reserves enough space. MOZ_ALWAYS_TRUE(rtStats->compartmentStatsVector.growBy(1)); CompartmentStats &cStats = rtStats->compartmentStatsVector.back(); - cStats.init(rtStats->getNameCb(rt, compartment), rtStats->destroyNameCb); + rtStats->initExtraCompartmentStats(compartment, &cStats); rtStats->currCompartmentStats = &cStats; // Get the compartment-level numbers. diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index 29465f3258fa..e40b0023be8e 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -156,9 +156,9 @@ Parser::~Parser() { JSContext *cx = context; if (principals) - JSPRINCIPALS_DROP(cx, principals); + JS_DropPrincipals(cx->runtime, principals); if (originPrincipals) - JSPRINCIPALS_DROP(cx, originPrincipals); + JS_DropPrincipals(cx->runtime, originPrincipals); cx->tempLifoAlloc().release(tempPoolMark); cx->activeCompilations--; } @@ -169,10 +169,10 @@ Parser::setPrincipals(JSPrincipals *prin, JSPrincipals *originPrin) JS_ASSERT(!principals && !originPrincipals); principals = prin; if (principals) - JSPRINCIPALS_HOLD(context, principals); + JS_HoldPrincipals(principals); originPrincipals = originPrin; if (originPrincipals) - JSPRINCIPALS_HOLD(context, originPrincipals); + JS_HoldPrincipals(originPrincipals); } ObjectBox * diff --git a/js/src/frontend/TokenStream.cpp b/js/src/frontend/TokenStream.cpp index 65cdc01ad95f..097f8a8a2ebb 100644 --- a/js/src/frontend/TokenStream.cpp +++ b/js/src/frontend/TokenStream.cpp @@ -158,7 +158,7 @@ TokenStream::TokenStream(JSContext *cx, JSPrincipals *prin, JSPrincipals *origin cx(cx), originPrincipals(JSScript::normalizeOriginPrincipals(prin, originPrin)) { if (originPrincipals) - JSPRINCIPALS_HOLD(cx, originPrincipals); + JS_HoldPrincipals(originPrincipals); } #ifdef _MSC_VER @@ -248,7 +248,7 @@ TokenStream::~TokenStream() if (sourceMap) cx->free_(sourceMap); if (originPrincipals) - JSPRINCIPALS_DROP(cx, originPrincipals); + JS_DropPrincipals(cx->runtime, originPrincipals); } /* Use the fastest available getc. */ diff --git a/js/src/jsapi-tests/testChromeBuffer.cpp b/js/src/jsapi-tests/testChromeBuffer.cpp index fb72c15a4e3a..49a60cc18ee3 100644 --- a/js/src/jsapi-tests/testChromeBuffer.cpp +++ b/js/src/jsapi-tests/testChromeBuffer.cpp @@ -1,18 +1,9 @@ #include "tests.h" -static void -Destroy(JSContext *cx, JSPrincipals *prin); - JSPrincipals system_principals = { - (char *)"", 1, Destroy, NULL + 1 }; -static void -Destroy(JSContext *cx, JSPrincipals *prin) -{ - JS_ASSERT(prin == &system_principals); -} - JSClass global_class = { "global", JSCLASS_IS_GLOBAL | JSCLASS_GLOBAL_FLAGS, diff --git a/js/src/jsapi-tests/testCloneScript.cpp b/js/src/jsapi-tests/testCloneScript.cpp index 13da8a0a56f1..f246348a4107 100644 --- a/js/src/jsapi-tests/testCloneScript.cpp +++ b/js/src/jsapi-tests/testCloneScript.cpp @@ -52,7 +52,7 @@ BEGIN_TEST(test_cloneScript) END_TEST(test_cloneScript) void -DestroyPrincipals(JSContext *cx, JSPrincipals *principals) +DestroyPrincipals(JSPrincipals *principals) { delete principals; } @@ -60,54 +60,38 @@ DestroyPrincipals(JSContext *cx, JSPrincipals *principals) struct Principals : public JSPrincipals { public: - Principals(const char *name) + Principals() { refcount = 0; - codebase = const_cast(name); - destroy = DestroyPrincipals; - subsume = NULL; } }; class AutoDropPrincipals { - JSContext *cx; + JSRuntime *rt; JSPrincipals *principals; public: - AutoDropPrincipals(JSContext *cx, JSPrincipals *principals) - : cx(cx), principals(principals) + AutoDropPrincipals(JSRuntime *rt, JSPrincipals *principals) + : rt(rt), principals(principals) { - JSPRINCIPALS_HOLD(cx, principals); + JS_HoldPrincipals(principals); } ~AutoDropPrincipals() { - JSPRINCIPALS_DROP(cx, principals); + JS_DropPrincipals(rt, principals); } }; -JSBool -TranscodePrincipals(JSXDRState *xdr, JSPrincipals **principalsp) -{ - return JS_XDRBytes(xdr, reinterpret_cast(principalsp), sizeof(*principalsp)); -} - BEGIN_TEST(test_cloneScriptWithPrincipals) { - JSSecurityCallbacks cbs = { - NULL, - TranscodePrincipals, - NULL, - NULL - }; + JS_InitDestroyPrincipalsCallback(rt, DestroyPrincipals); - JS_SetRuntimeSecurityCallbacks(rt, &cbs); - - JSPrincipals *principalsA = new Principals("A"); - AutoDropPrincipals dropA(cx, principalsA); - JSPrincipals *principalsB = new Principals("B"); - AutoDropPrincipals dropB(cx, principalsB); + JSPrincipals *principalsA = new Principals(); + AutoDropPrincipals dropA(rt, principalsA); + JSPrincipals *principalsB = new Principals(); + AutoDropPrincipals dropB(rt, principalsB); JSObject *A, *B; diff --git a/js/src/jsapi-tests/testOriginPrincipals.cpp b/js/src/jsapi-tests/testOriginPrincipals.cpp index ae448e5ab8e9..8ff3fe4ae467 100644 --- a/js/src/jsapi-tests/testOriginPrincipals.cpp +++ b/js/src/jsapi-tests/testOriginPrincipals.cpp @@ -5,28 +5,19 @@ JSPrincipals *sCurrentGlobalPrincipals = NULL; JSPrincipals * -ObjectPrincipalsFinder(JSContext *, JSObject *) +ObjectPrincipalsFinder(JSObject *) { return sCurrentGlobalPrincipals; } -JSSecurityCallbacks seccb = { +static const JSSecurityCallbacks seccb = { + NULL, NULL, NULL, ObjectPrincipalsFinder, NULL }; -static void -Destroy(JSContext *, JSPrincipals *) -{} - -static JSBool -Subsume(JSPrincipals *, JSPrincipals *) -{ - return true; -} - JSPrincipals *sOriginPrincipalsInErrorReporter = NULL; static void @@ -35,14 +26,12 @@ ErrorReporter(JSContext *cx, const char *message, JSErrorReport *report) sOriginPrincipalsInErrorReporter = report->originPrincipals; } -char p1str[] = "principal1"; -JSPrincipals prin1 = { p1str, 0, Destroy, Subsume }; -char p2str[] = "principal2"; -JSPrincipals prin2 = { p2str, 0, Destroy, Subsume }; +JSPrincipals prin1 = { 1 }; +JSPrincipals prin2 = { 1 }; BEGIN_TEST(testOriginPrincipals) { - JS_SetContextSecurityCallbacks(cx, &seccb); + JS_SetSecurityCallbacks(rt, &seccb); /* * Currently, the only way to set a non-trivial originPrincipal is to use diff --git a/js/src/jsapi-tests/testXDR.cpp b/js/src/jsapi-tests/testXDR.cpp index c20b83785659..8a23f9b37117 100644 --- a/js/src/jsapi-tests/testXDR.cpp +++ b/js/src/jsapi-tests/testXDR.cpp @@ -72,23 +72,11 @@ FreezeThaw(JSContext *cx, JSObject *funobj) return FreezeThawImpl(cx, funobj, JS_XDRFunctionObject); } -static JSBool -SubsumePrincipals(JSPrincipals *, JSPrincipals *) -{ - return true; -} - static JSPrincipals testPrincipals[] = { - { const_cast("foo.bar"), 1, NULL, SubsumePrincipals }, - { const_cast("dot.com"), 1, NULL, SubsumePrincipals }, + { 1 }, + { 1 }, }; -static JSBool -CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode, jsval *vp) -{ - return true; -} - static JSBool TranscodePrincipals(JSXDRState *xdr, JSPrincipals **principalsp) { @@ -110,7 +98,7 @@ TranscodePrincipals(JSXDRState *xdr, JSPrincipals **principalsp) if (index >= mozilla::ArrayLength(testPrincipals)) return false; *principalsp = &testPrincipals[index]; - JSPRINCIPALS_HOLD(xdr->cx, *principalsp); + JS_HoldPrincipals(*principalsp); } return true; @@ -118,14 +106,15 @@ TranscodePrincipals(JSXDRState *xdr, JSPrincipals **principalsp) BEGIN_TEST(testXDR_principals) { - static JSSecurityCallbacks seccb = { - CheckAccess, + static const JSSecurityCallbacks seccb = { + NULL, + NULL, TranscodePrincipals, NULL, NULL }; - JS_SetRuntimeSecurityCallbacks(rt, &seccb); + JS_SetSecurityCallbacks(rt, &seccb); JSScript *script; for (int i = TEST_FIRST; i != TEST_END; ++i) { diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 61ae14ce681d..a214fd41fd06 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -696,6 +696,8 @@ JS_IsBuiltinFunctionConstructor(JSFunction *fun) */ static JSBool js_NewRuntimeWasCalled = JS_FALSE; +static const JSSecurityCallbacks NullSecurityCallbacks = { }; + JSRuntime::JSRuntime() : atomsCompartment(NULL), #ifdef JS_THREADSAFE @@ -778,7 +780,8 @@ JSRuntime::JSRuntime() gcHelperThread(thisFromCtor()), #endif debuggerMutations(0), - securityCallbacks(NULL), + securityCallbacks(const_cast(&NullSecurityCallbacks)), + destroyPrincipals(NULL), structuredCloneCallbacks(NULL), telemetryCallback(NULL), propertyRemovals(0), @@ -4451,55 +4454,31 @@ JS_CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode, return CheckAccess(cx, obj, id, mode, vp, attrsp); } -#ifdef JS_THREADSAFE -JS_PUBLIC_API(int) -JS_HoldPrincipals(JSContext *cx, JSPrincipals *principals) +JS_PUBLIC_API(void) +JS_HoldPrincipals(JSPrincipals *principals) { - return JS_ATOMIC_INCREMENT(&principals->refcount); + JS_ATOMIC_INCREMENT(&principals->refcount); } -JS_PUBLIC_API(int) -JS_DropPrincipals(JSContext *cx, JSPrincipals *principals) +JS_PUBLIC_API(void) +JS_DropPrincipals(JSRuntime *rt, JSPrincipals *principals) { int rc = JS_ATOMIC_DECREMENT(&principals->refcount); if (rc == 0) - principals->destroy(cx, principals); - return rc; -} -#endif - -JS_PUBLIC_API(JSSecurityCallbacks *) -JS_SetRuntimeSecurityCallbacks(JSRuntime *rt, JSSecurityCallbacks *callbacks) -{ - JSSecurityCallbacks *oldcallbacks; - - oldcallbacks = rt->securityCallbacks; - rt->securityCallbacks = callbacks; - return oldcallbacks; + rt->destroyPrincipals(principals); } -JS_PUBLIC_API(JSSecurityCallbacks *) -JS_GetRuntimeSecurityCallbacks(JSRuntime *rt) +JS_PUBLIC_API(void) +JS_SetSecurityCallbacks(JSRuntime *rt, const JSSecurityCallbacks *scb) { - return rt->securityCallbacks; + JS_ASSERT(scb != &NullSecurityCallbacks); + rt->securityCallbacks = scb ? scb : &NullSecurityCallbacks; } -JS_PUBLIC_API(JSSecurityCallbacks *) -JS_SetContextSecurityCallbacks(JSContext *cx, JSSecurityCallbacks *callbacks) +JS_PUBLIC_API(const JSSecurityCallbacks *) +JS_GetSecurityCallbacks(JSRuntime *rt) { - JSSecurityCallbacks *oldcallbacks; - - oldcallbacks = cx->securityCallbacks; - cx->securityCallbacks = callbacks; - return oldcallbacks; -} - -JS_PUBLIC_API(JSSecurityCallbacks *) -JS_GetSecurityCallbacks(JSContext *cx) -{ - return cx->securityCallbacks - ? cx->securityCallbacks - : cx->runtime->securityCallbacks; + return (rt->securityCallbacks != &NullSecurityCallbacks) ? rt->securityCallbacks : NULL; } JS_PUBLIC_API(void) @@ -4508,6 +4487,14 @@ JS_SetTrustedPrincipals(JSRuntime *rt, JSPrincipals *prin) rt->setTrustedPrincipals(prin); } +extern JS_PUBLIC_API(void) +JS_InitDestroyPrincipalsCallback(JSRuntime *rt, JSDestroyPrincipalsOp destroyPrincipals) +{ + JS_ASSERT(destroyPrincipals); + JS_ASSERT(!rt->destroyPrincipals); + rt->destroyPrincipals = destroyPrincipals; +} + JS_PUBLIC_API(JSFunction *) JS_NewFunction(JSContext *cx, JSNative native, unsigned nargs, unsigned flags, JSObject *parent, const char *name) diff --git a/js/src/jsapi.h b/js/src/jsapi.h index 536e6aebd7d2..e23ac859a100 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -1520,6 +1520,12 @@ typedef JSBool * Security protocol types. */ +typedef void +(* JSDestroyPrincipalsOp)(JSPrincipals *principals); + +typedef JSBool +(* JSSubsumePrincipalsOp)(JSPrincipals *principals1, JSPrincipals *principals2); + /* * XDR-encode or -decode a principals instance, based on whether xdr->mode is * JSXDR_ENCODE, in which case *principalsp should be encoded; or JSXDR_DECODE, @@ -1539,7 +1545,7 @@ typedef JSBool * callback's implementation. */ typedef JSPrincipals * -(* JSObjectPrincipalsFinder)(JSContext *cx, JSObject *obj); +(* JSObjectPrincipalsFinder)(JSObject *obj); /* * Used to check if a CSP instance wants to disable eval() and friends. @@ -4088,52 +4094,48 @@ JS_SetReservedSlot(JSObject *obj, uint32_t index, jsval v); * Security protocol. */ struct JSPrincipals { - char *codebase; - /* Don't call "destroy"; use reference counting macros below. */ int refcount; - void (* destroy)(JSContext *cx, JSPrincipals *); - JSBool (* subsume)(JSPrincipals *, JSPrincipals *); -}; - -#ifdef JS_THREADSAFE -#define JSPRINCIPALS_HOLD(cx, principals) JS_HoldPrincipals(cx,principals) -#define JSPRINCIPALS_DROP(cx, principals) JS_DropPrincipals(cx,principals) - -extern JS_PUBLIC_API(int) -JS_HoldPrincipals(JSContext *cx, JSPrincipals *principals); - -extern JS_PUBLIC_API(int) -JS_DropPrincipals(JSContext *cx, JSPrincipals *principals); - -#else -#define JSPRINCIPALS_HOLD(cx, principals) (++(principals)->refcount) -#define JSPRINCIPALS_DROP(cx, principals) \ - ((--(principals)->refcount == 0) \ - ? ((*(principals)->destroy)((cx), (principals)), 0) \ - : (principals)->refcount) +#ifdef DEBUG + /* A helper to facilitate principals debugging. */ + uint32_t debugToken; #endif +#ifdef __cplusplus + void setDebugToken(uint32_t token) { +# ifdef DEBUG + debugToken = token; +# endif + } + + /* + * This is not defined by the JS engine but should be provided by the + * embedding. + */ + JS_PUBLIC_API(void) dump(); +#endif +}; + +extern JS_PUBLIC_API(void) +JS_HoldPrincipals(JSPrincipals *principals); + +extern JS_PUBLIC_API(void) +JS_DropPrincipals(JSRuntime *rt, JSPrincipals *principals); struct JSSecurityCallbacks { JSCheckAccessOp checkObjectAccess; + JSSubsumePrincipalsOp subsumePrincipals; JSPrincipalsTranscoder principalsTranscoder; JSObjectPrincipalsFinder findObjectPrincipals; JSCSPEvalChecker contentSecurityPolicyAllows; }; -extern JS_PUBLIC_API(JSSecurityCallbacks *) -JS_SetRuntimeSecurityCallbacks(JSRuntime *rt, JSSecurityCallbacks *callbacks); +extern JS_PUBLIC_API(void) +JS_SetSecurityCallbacks(JSRuntime *rt, const JSSecurityCallbacks *callbacks); -extern JS_PUBLIC_API(JSSecurityCallbacks *) -JS_GetRuntimeSecurityCallbacks(JSRuntime *rt); - -extern JS_PUBLIC_API(JSSecurityCallbacks *) -JS_SetContextSecurityCallbacks(JSContext *cx, JSSecurityCallbacks *callbacks); - -extern JS_PUBLIC_API(JSSecurityCallbacks *) -JS_GetSecurityCallbacks(JSContext *cx); +extern JS_PUBLIC_API(const JSSecurityCallbacks *) +JS_GetSecurityCallbacks(JSRuntime *rt); /* * Code running with "trusted" principals will be given a deeper stack @@ -4150,6 +4152,14 @@ JS_GetSecurityCallbacks(JSContext *cx); extern JS_PUBLIC_API(void) JS_SetTrustedPrincipals(JSRuntime *rt, JSPrincipals *prin); +/* + * Initialize the callback that is called to destroy JSPrincipals instance + * when its reference counter drops to zero. The initialization can be done + * only once per JS runtime. + */ +extern JS_PUBLIC_API(void) +JS_InitDestroyPrincipalsCallback(JSRuntime *rt, JSDestroyPrincipalsOp destroyPrincipals); + /************************************************************************/ /* diff --git a/js/src/jscntxt.cpp b/js/src/jscntxt.cpp index 6e900691ab82..6711f473edfd 100644 --- a/js/src/jscntxt.cpp +++ b/js/src/jscntxt.cpp @@ -988,7 +988,6 @@ JSContext::JSContext(JSRuntime *rt) #ifdef JS_THREADSAFE outstandingRequests(0), #endif - securityCallbacks(NULL), resolveFlags(0), rngSeed(0), iterValue(MagicValue(JS_NO_ITER_VALUE)), diff --git a/js/src/jscntxt.h b/js/src/jscntxt.h index cb8e4cb3b72b..3434c394e320 100644 --- a/js/src/jscntxt.h +++ b/js/src/jscntxt.h @@ -509,11 +509,8 @@ struct JSRuntime : js::RuntimeFriendFields uint32_t debuggerMutations; - /* - * Security callbacks set on the runtime are used by each context unless - * an override is set on the context. - */ - JSSecurityCallbacks *securityCallbacks; + const JSSecurityCallbacks *securityCallbacks; + JSDestroyPrincipalsOp destroyPrincipals; /* Structured data callbacks are runtime-wide. */ const JSStructuredCloneCallbacks *structuredCloneCallbacks; @@ -1013,9 +1010,6 @@ struct JSContext : js::ContextFriendFields #endif /* JSGC_ROOT_ANALYSIS */ - /* Security callbacks that override any defined on the runtime. */ - JSSecurityCallbacks *securityCallbacks; - /* Stored here to avoid passing it around as a parameter. */ unsigned resolveFlags; diff --git a/js/src/jsexn.cpp b/js/src/jsexn.cpp index d05144b38071..3c83f78e55d2 100644 --- a/js/src/jsexn.cpp +++ b/js/src/jsexn.cpp @@ -304,8 +304,7 @@ InitExnPrivate(JSContext *cx, JSObject *exnObject, JSString *message, JS_ASSERT(exnObject->isError()); JS_ASSERT(!exnObject->getPrivate()); - JSSecurityCallbacks *callbacks = JS_GetSecurityCallbacks(cx); - JSCheckAccessOp checkAccess = callbacks ? callbacks->checkObjectAccess : NULL; + JSCheckAccessOp checkAccess = cx->runtime->securityCallbacks->checkObjectAccess; Vector frames(cx); Vector values(cx); @@ -443,7 +442,7 @@ SetExnPrivate(JSContext *cx, JSObject *exnObject, JSExnPrivate *priv) JS_ASSERT(exnObject->isError()); if (JSErrorReport *report = priv->errorReport) { if (JSPrincipals *prin = report->originPrincipals) - JSPRINCIPALS_HOLD(cx, prin); + JS_HoldPrincipals(prin); } exnObject->setPrivate(priv); } @@ -455,7 +454,7 @@ exn_finalize(JSContext *cx, JSObject *obj) if (JSErrorReport *report = priv->errorReport) { /* HOLD called by SetExnPrivate. */ if (JSPrincipals *prin = report->originPrincipals) - JSPRINCIPALS_DROP(cx, prin); + JS_DropPrincipals(cx->runtime, prin); cx->free_(report); } cx->free_(priv); diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index 8ad28fd7b6f5..32e58abb2bb1 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -2915,7 +2915,7 @@ SweepCompartments(JSContext *cx, JSGCInvocationKind gckind) if (callback) JS_ALWAYS_TRUE(callback(cx, compartment, JSCOMPARTMENT_DESTROY)); if (compartment->principals) - JSPRINCIPALS_DROP(cx, compartment->principals); + JS_DropPrincipals(rt, compartment->principals); cx->delete_(compartment); continue; } @@ -3905,7 +3905,7 @@ NewCompartment(JSContext *cx, JSPrincipals *principals) compartment->isSystemCompartment = principals && rt->trustedPrincipals() == principals; if (principals) { compartment->principals = principals; - JSPRINCIPALS_HOLD(cx, principals); + JS_HoldPrincipals(principals); } compartment->setGCLastBytes(8192, 8192, GC_NORMAL); diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index f1eef3864995..e7385d1277ea 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -789,15 +789,15 @@ EvalCacheLookup(JSContext *cx, JSLinearString *str, StackFrame *caller, unsigned JSVersion version = cx->findVersion(); JSScript *script; + JSSubsumePrincipalsOp subsume = cx->runtime->securityCallbacks->subsumePrincipals; while ((script = *scriptp) != NULL) { if (script->savedCallerFun && script->staticLevel == staticLevel && script->getVersion() == version && !script->hasSingletons && - (script->principals == principals || - (principals && script->principals && - principals->subsume(principals, script->principals) && - script->principals->subsume(script->principals, principals)))) { + (!subsume || script->principals == principals || + (subsume(principals, script->principals) && + subsume(script->principals, principals)))) { /* * Get the prior (cache-filling) eval's saved caller function. * See frontend::CompileScript. @@ -1163,12 +1163,14 @@ obj_watch_handler(JSContext *cx, JSObject *obj, jsid id, jsval old, jsval *nvp, void *closure) { JSObject *callable = (JSObject *) closure; - if (JSPrincipals *watcher = callable->principals(cx)) { - if (JSObject *scopeChain = cx->stack.currentScriptedScopeChain()) { - if (JSPrincipals *subject = scopeChain->principals(cx)) { - if (!watcher->subsume(watcher, subject)) { - /* Silently don't call the watch handler. */ - return JS_TRUE; + if (JSSubsumePrincipalsOp subsume = cx->runtime->securityCallbacks->subsumePrincipals) { + if (JSPrincipals *watcher = callable->principals(cx)) { + if (JSObject *scopeChain = cx->stack.currentScriptedScopeChain()) { + if (JSPrincipals *subject = scopeChain->principals(cx)) { + if (!subsume(watcher, subject)) { + /* Silently don't call the watch handler. */ + return true; + } } } } @@ -5881,10 +5883,7 @@ CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode, JSBool writing; JSObject *pobj; JSProperty *prop; - Class *clasp; const Shape *shape; - JSSecurityCallbacks *callbacks; - JSCheckAccessOp check; while (JS_UNLIKELY(obj->isWith())) obj = obj->getProto(); @@ -5948,12 +5947,9 @@ CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode, * hook. This covers precompilation-based sharing and (possibly * unintended) runtime sharing across trust boundaries. */ - clasp = pobj->getClass(); - check = clasp->checkAccess; - if (!check) { - callbacks = JS_GetSecurityCallbacks(cx); - check = callbacks ? callbacks->checkObjectAccess : NULL; - } + JSCheckAccessOp check = pobj->getClass()->checkAccess; + if (!check) + check = cx->runtime->securityCallbacks->checkObjectAccess; return !check || check(cx, pobj, id, mode, vp); } diff --git a/js/src/jsobjinlines.h b/js/src/jsobjinlines.h index a9c8aa4c195d..4f62733e0140 100644 --- a/js/src/jsobjinlines.h +++ b/js/src/jsobjinlines.h @@ -1118,9 +1118,8 @@ JSObject::isCallable() inline JSPrincipals * JSObject::principals(JSContext *cx) { - JSSecurityCallbacks *cb = JS_GetSecurityCallbacks(cx); - if (JSObjectPrincipalsFinder finder = cb ? cb->findObjectPrincipals : NULL) - return finder(cx, this); + if (JSObjectPrincipalsFinder find = cx->runtime->securityCallbacks->findObjectPrincipals) + return find(this); return cx->compartment ? cx->compartment->principals : NULL; } diff --git a/js/src/jsscript.cpp b/js/src/jsscript.cpp index fd4fa7036c29..2440f3656a3d 100644 --- a/js/src/jsscript.cpp +++ b/js/src/jsscript.cpp @@ -703,11 +703,11 @@ XDRScript(JSXDRState *xdr, JSScript **scriptp) JS_ASSERT_IF(script->principals, script->originPrincipals); if (xdr->principals) { script->principals = xdr->principals; - JSPRINCIPALS_HOLD(cx, xdr->principals); + JS_HoldPrincipals(xdr->principals); } if (xdr->originPrincipals) { script->originPrincipals = xdr->originPrincipals; - JSPRINCIPALS_HOLD(cx, xdr->originPrincipals); + JS_HoldPrincipals(xdr->originPrincipals); } } @@ -1256,14 +1256,14 @@ JSScript::NewScriptFromEmitter(JSContext *cx, BytecodeEmitter *bce) script->principals = bce->parser->principals; if (script->principals) - JSPRINCIPALS_HOLD(cx, script->principals); + JS_HoldPrincipals(script->principals); /* Establish invariant: principals implies originPrincipals. */ script->originPrincipals = bce->parser->originPrincipals; if (!script->originPrincipals) script->originPrincipals = script->principals; if (script->originPrincipals) - JSPRINCIPALS_HOLD(cx, script->originPrincipals); + JS_HoldPrincipals(script->originPrincipals); script->sourceMap = (jschar *) bce->parser->tokenStream.releaseSourceMap(); @@ -1462,9 +1462,9 @@ JSScript::finalize(JSContext *cx, bool background) JS_ASSERT_IF(principals, originPrincipals); if (principals) - JSPRINCIPALS_DROP(cx, principals); + JS_DropPrincipals(cx->runtime, principals); if (originPrincipals) - JSPRINCIPALS_DROP(cx, originPrincipals); + JS_DropPrincipals(cx->runtime, originPrincipals); if (types) types->destroy(); diff --git a/js/src/jsxdrapi.cpp b/js/src/jsxdrapi.cpp index cfddb60323ec..29b5572251d4 100644 --- a/js/src/jsxdrapi.cpp +++ b/js/src/jsxdrapi.cpp @@ -559,7 +559,7 @@ XDRPrincipals(JSXDRState *xdr) return false; if (flags & (HAS_PRINCIPALS | HAS_ORIGIN)) { - JSSecurityCallbacks *scb = JS_GetSecurityCallbacks(xdr->cx); + const JSSecurityCallbacks *scb = JS_GetSecurityCallbacks(xdr->cx->runtime); if (xdr->mode == JSXDR_DECODE) { if (!scb || !scb->principalsTranscoder) { JS_ReportErrorNumber(xdr->cx, js_GetErrorMessage, NULL, @@ -581,7 +581,7 @@ XDRPrincipals(JSXDRState *xdr) return false; } else if (xdr->mode == JSXDR_DECODE && xdr->principals) { xdr->originPrincipals = xdr->principals; - JSPRINCIPALS_HOLD(xdr->cx, xdr->principals); + JS_HoldPrincipals(xdr->principals); } } @@ -599,9 +599,9 @@ struct AutoDropXDRPrincipals { ~AutoDropXDRPrincipals() { if (xdr->mode == JSXDR_DECODE) { if (xdr->principals) - JSPRINCIPALS_DROP(xdr->cx, xdr->principals); + JS_DropPrincipals(xdr->cx->runtime, xdr->principals); if (xdr->originPrincipals) - JSPRINCIPALS_DROP(xdr->cx, xdr->originPrincipals); + JS_DropPrincipals(xdr->cx->runtime, xdr->originPrincipals); } xdr->principals = NULL; xdr->originPrincipals = NULL; diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index 77e6732a4f2a..7e5edcc02277 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -4867,22 +4867,11 @@ MaybeOverrideOutFileFromEnv(const char* const envVar, } } -JSBool -ShellPrincipalsSubsume(JSPrincipals *, JSPrincipals *) -{ - return JS_TRUE; -} - -JSPrincipals shellTrustedPrincipals = { - (char *)"[shell trusted principals]", - 1, - NULL, /* nobody should be destroying this */ - ShellPrincipalsSubsume -}; +/* Set the initial counter to 1 so the principal will never be destroyed. */ +JSPrincipals shellTrustedPrincipals = { 1 }; JSBool -CheckObjectAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode, - jsval *vp) +CheckObjectAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode, jsval *vp) { return true; } @@ -4891,6 +4880,7 @@ JSSecurityCallbacks securityCallbacks = { CheckObjectAccess, NULL, NULL, + NULL, NULL }; @@ -5033,7 +5023,7 @@ main(int argc, char **argv, char **envp) JS_SetGCParameter(rt, JSGC_MAX_BYTES, 0xffffffff); JS_SetTrustedPrincipals(rt, &shellTrustedPrincipals); - JS_SetRuntimeSecurityCallbacks(rt, &securityCallbacks); + JS_SetSecurityCallbacks(rt, &securityCallbacks); JS_SetNativeStackQuota(rt, gMaxStackSize); diff --git a/js/src/vm/GlobalObject.cpp b/js/src/vm/GlobalObject.cpp index fa0946724ee3..2b3201e72e03 100644 --- a/js/src/vm/GlobalObject.cpp +++ b/js/src/vm/GlobalObject.cpp @@ -386,15 +386,12 @@ GlobalObject::isRuntimeCodeGenEnabled(JSContext *cx) { HeapSlot &v = getSlotRef(RUNTIME_CODEGEN_ENABLED); if (v.isUndefined()) { - JSSecurityCallbacks *callbacks = JS_GetSecurityCallbacks(cx); - /* * If there are callbacks, make sure that the CSP callback is installed * and that it permits runtime code generation, then cache the result. */ - v.set(this, RUNTIME_CODEGEN_ENABLED, - BooleanValue((!callbacks || !callbacks->contentSecurityPolicyAllows) || - callbacks->contentSecurityPolicyAllows(cx))); + JSCSPEvalChecker allows = cx->runtime->securityCallbacks->contentSecurityPolicyAllows; + v.set(this, RUNTIME_CODEGEN_ENABLED, BooleanValue(!allows || allows(cx))); } return !v.isFalse(); } diff --git a/js/xpconnect/loader/mozJSComponentLoader.cpp b/js/xpconnect/loader/mozJSComponentLoader.cpp index 85eb682d27a0..1cdd03dd8544 100644 --- a/js/xpconnect/loader/mozJSComponentLoader.cpp +++ b/js/xpconnect/loader/mozJSComponentLoader.cpp @@ -80,6 +80,7 @@ #include "nsDOMFile.h" #include "jsxdrapi.h" #include "jsprf.h" +#include "nsJSPrincipals.h" // For reporting errors with the console service #include "nsIScriptError.h" #include "nsIConsoleService.h" @@ -645,17 +646,6 @@ class ANSIFileAutoCloser }; #endif -class JSPrincipalsHolder -{ - public: - JSPrincipalsHolder(JSContext *cx, JSPrincipals *principals) - : mCx(cx), mPrincipals(principals) {} - ~JSPrincipalsHolder() { JSPRINCIPALS_DROP(mCx, mPrincipals); } - private: - JSContext *mCx; - JSPrincipals *mPrincipals; -}; - nsresult mozJSComponentLoader::GlobalForLocation(nsILocalFile *aComponentFile, nsIURI *aURI, @@ -665,7 +655,6 @@ mozJSComponentLoader::GlobalForLocation(nsILocalFile *aComponentFile, { nsresult rv; - JSPrincipals* jsPrincipals = nsnull; JSCLContextHelper cx(this); JS_AbortIfWrongThread(JS_GetRuntime(cx)); @@ -673,11 +662,6 @@ mozJSComponentLoader::GlobalForLocation(nsILocalFile *aComponentFile, // preserve caller's compartment js::AutoPreserveCompartment pc(cx); - rv = mSystemPrincipal->GetJSPrincipals(cx, &jsPrincipals); - NS_ENSURE_SUCCESS(rv, rv); - - JSPrincipalsHolder princHolder(mContext, jsPrincipals); - nsCOMPtr backstagePass; rv = mRuntimeService->GetBackstagePass(getter_AddRefs(backstagePass)); NS_ENSURE_SUCCESS(rv, rv); @@ -837,7 +821,9 @@ mozJSComponentLoader::GlobalForLocation(nsILocalFile *aComponentFile, return NS_ERROR_FAILURE; } - script = JS_CompileScriptForPrincipalsVersion(cx, global, jsPrincipals, buf, fileSize32, nativePath.get(), 1, + script = JS_CompileScriptForPrincipalsVersion(cx, global, + nsJSPrincipals::get(mSystemPrincipal), + buf, fileSize32, nativePath.get(), 1, JSVERSION_LATEST); PR_MemUnmap(buf, fileSize32); @@ -880,7 +866,9 @@ mozJSComponentLoader::GlobalForLocation(nsILocalFile *aComponentFile, NS_WARNING("Failed to read file"); return NS_ERROR_FAILURE; } - script = JS_CompileScriptForPrincipalsVersion(cx, global, jsPrincipals, buf, rlen, nativePath.get(), 1, + script = JS_CompileScriptForPrincipalsVersion(cx, global, + nsJSPrincipals::get(mSystemPrincipal), + buf, rlen, nativePath.get(), 1, JSVERSION_LATEST); free(buf); @@ -917,7 +905,9 @@ mozJSComponentLoader::GlobalForLocation(nsILocalFile *aComponentFile, buf[len] = '\0'; - script = JS_CompileScriptForPrincipalsVersion(cx, global, jsPrincipals, buf, bytesRead, nativePath.get(), 1, + script = JS_CompileScriptForPrincipalsVersion(cx, global, + nsJSPrincipals::get(mSystemPrincipal), + buf, bytesRead, nativePath.get(), 1, JSVERSION_LATEST); } // Propagate the exception, if one exists. Also, don't leave the stale diff --git a/js/xpconnect/loader/mozJSSubScriptLoader.cpp b/js/xpconnect/loader/mozJSSubScriptLoader.cpp index 2eacc2fd9920..10fcb9773e83 100644 --- a/js/xpconnect/loader/mozJSSubScriptLoader.cpp +++ b/js/xpconnect/loader/mozJSSubScriptLoader.cpp @@ -61,6 +61,7 @@ #include "jsapi.h" #include "jsdbgapi.h" #include "jsfriendapi.h" +#include "nsJSPrincipals.h" #include "mozilla/FunctionTimer.h" #include "mozilla/scache/StartupCache.h" @@ -111,7 +112,6 @@ mozJSSubScriptLoader::ReadScript(nsIURI *uri, JSContext *cx, JSObject *target_ob { nsCOMPtr chan; nsCOMPtr instream; - JSPrincipals *jsPrincipals; JSErrorReporter er; nsresult rv; @@ -140,14 +140,6 @@ mozJSSubScriptLoader::ReadScript(nsIURI *uri, JSContext *cx, JSObject *target_ob if (NS_FAILED(rv)) return rv; - /* we can't hold onto jsPrincipals as a module var because the - * JSPRINCIPALS_DROP macro takes a JSContext, which we won't have in the - * destructor */ - rv = principal->GetJSPrincipals(cx, &jsPrincipals); - if (NS_FAILED(rv) || !jsPrincipals) { - return ReportError(cx, LOAD_ERROR_NOPRINCIPALS); - } - /* set our own error reporter so we can report any bad things as catchable * exceptions, including the source/line number */ er = JS_SetErrorReporter(cx, mozJSLoaderErrorReporter); @@ -158,21 +150,18 @@ mozJSSubScriptLoader::ReadScript(nsIURI *uri, JSContext *cx, JSObject *target_ob charset, nsnull, script); if (NS_FAILED(rv)) { - JSPRINCIPALS_DROP(cx, jsPrincipals); return ReportError(cx, LOAD_ERROR_BADCHARSET); } *scriptp = - JS_CompileUCScriptForPrincipals(cx, target_obj, jsPrincipals, + JS_CompileUCScriptForPrincipals(cx, target_obj, nsJSPrincipals::get(principal), reinterpret_cast(script.get()), script.Length(), uriStr, 1); } else { - *scriptp = JS_CompileScriptForPrincipals(cx, target_obj, jsPrincipals, buf.get(), - len, uriStr, 1); + *scriptp = JS_CompileScriptForPrincipals(cx, target_obj, nsJSPrincipals::get(principal), + buf.get(), len, uriStr, 1); } - JSPRINCIPALS_DROP(cx, jsPrincipals); - /* repent for our evil deeds */ JS_SetErrorReporter(cx, er); @@ -204,7 +193,7 @@ mozJSSubScriptLoader::LoadSubScript(const nsAString& url, __LINE__, NS_LossyConvertUTF16toASCII(url).get()); #endif - /* set mJSPrincipals if it's not here already */ + /* set the system principal if it's not here already */ if (!mSystemPrincipal) { nsCOMPtr secman = do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID); diff --git a/js/xpconnect/shell/xpcshell.cpp b/js/xpconnect/shell/xpcshell.cpp index 82a198cf5b94..4ec492f75935 100644 --- a/js/xpconnect/shell/xpcshell.cpp +++ b/js/xpconnect/shell/xpcshell.cpp @@ -81,6 +81,7 @@ #include "nsCOMPtr.h" #include "nsAutoPtr.h" #include "nsIXPCSecurityManager.h" +#include "nsJSPrincipals.h" #include "xpcpublic.h" #ifdef XP_MACOSX #include "xpcshellMacUtils.h" @@ -1739,11 +1740,13 @@ GetCurrentWorkingDirectory(nsAString& workingDirectory) } static JSPrincipals * -FindObjectPrincipals(JSContext *cx, JSObject *obj) +FindObjectPrincipals(JSObject *obj) { return gJSPrincipals; } +static JSSecurityCallbacks shellSecurityCallbacks; + int main(int argc, char **argv, char **envp) { @@ -1905,10 +1908,8 @@ main(int argc, char **argv, char **envp) fprintf(gErrFile, "+++ Failed to obtain SystemPrincipal from ScriptSecurityManager service.\n"); } else { // fetch the JS principals and stick in a global - rv = systemprincipal->GetJSPrincipals(cx, &gJSPrincipals); - if (NS_FAILED(rv)) { - fprintf(gErrFile, "+++ Failed to obtain JS principals from SystemPrincipal.\n"); - } + gJSPrincipals = nsJSPrincipals::get(systemprincipal); + JS_HoldPrincipals(gJSPrincipals); secman->SetSystemPrincipal(systemprincipal); } } else { @@ -1916,10 +1917,11 @@ main(int argc, char **argv, char **envp) } } - JSSecurityCallbacks *cb = JS_GetRuntimeSecurityCallbacks(rt); - NS_ASSERTION(cb, "We are assuming that nsScriptSecurityManager::Init() has been run"); - NS_ASSERTION(!cb->findObjectPrincipals, "Your pigeon is in my hole!"); - cb->findObjectPrincipals = FindObjectPrincipals; + const JSSecurityCallbacks *scb = JS_GetSecurityCallbacks(rt); + NS_ASSERTION(scb, "We are assuming that nsScriptSecurityManager::Init() has been run"); + shellSecurityCallbacks = *scb; + shellSecurityCallbacks.findObjectPrincipals = FindObjectPrincipals; + JS_SetSecurityCallbacks(rt, &shellSecurityCallbacks); #ifdef TEST_TranslateThis nsCOMPtr @@ -2009,7 +2011,7 @@ main(int argc, char **argv, char **envp) xpc->WrapJS(cx, glob, NS_GET_IID(nsIJSContextStack), (void**) getter_AddRefs(bogus)); #endif - JSPRINCIPALS_DROP(cx, gJSPrincipals); + JS_DropPrincipals(rt, gJSPrincipals); JS_ClearScope(cx, glob); JS_GC(cx); JSContext *oldcx; diff --git a/js/xpconnect/src/XPCComponents.cpp b/js/xpconnect/src/XPCComponents.cpp index 66c285f35cb2..a2a110270a42 100644 --- a/js/xpconnect/src/XPCComponents.cpp +++ b/js/xpconnect/src/XPCComponents.cpp @@ -3437,14 +3437,18 @@ xpc_EvalInSandbox(JSContext *cx, JSObject *sandbox, const nsAString& source, NS_ASSERTION(sop, "Invalid sandbox passed"); nsCOMPtr prin = sop->GetPrincipal(); - JSPrincipals *jsPrincipals; - - if (!prin || - NS_FAILED(prin->GetJSPrincipals(cx, &jsPrincipals)) || - !jsPrincipals) { + if (!prin) { return NS_ERROR_FAILURE; } + nsCAutoString filenameBuf; + if (!filename) { + // Default to the spec of the principal. + nsJSPrincipals::get(prin)->GetScriptLocation(filenameBuf); + filename = filenameBuf.get(); + lineNo = 1; + } + JSObject *callingScope; { JSAutoRequest req(cx); @@ -3458,7 +3462,6 @@ xpc_EvalInSandbox(JSContext *cx, JSObject *sandbox, const nsAString& source, nsRefPtr sandcx = new ContextHolder(cx, sandbox); if (!sandcx || !sandcx->GetJSContext()) { JS_ReportError(cx, "Can't prepare context for evalInSandbox"); - JSPRINCIPALS_DROP(cx, jsPrincipals); return NS_ERROR_OUT_OF_MEMORY; } @@ -3471,24 +3474,15 @@ xpc_EvalInSandbox(JSContext *cx, JSObject *sandbox, const nsAString& source, if (!stack->Push(sandcx->GetJSContext())) { JS_ReportError(cx, "Unable to initialize XPConnect with the sandbox context"); - JSPRINCIPALS_DROP(cx, jsPrincipals); return NS_ERROR_FAILURE; } } - if (!filename) { - // Default the filename to the codebase. - filename = jsPrincipals->codebase; - lineNo = 1; - } - nsresult rv = NS_OK; { JSAutoRequest req(sandcx->GetJSContext()); JSAutoEnterCompartment ac; - jsval v; - JSString *str = nsnull; if (!ac.enter(sandcx->GetJSContext(), sandbox)) { if (stack) @@ -3496,9 +3490,11 @@ xpc_EvalInSandbox(JSContext *cx, JSObject *sandbox, const nsAString& source, return NS_ERROR_FAILURE; } + jsval v; + JSString *str = nsnull; JSBool ok = JS_EvaluateUCScriptForPrincipals(sandcx->GetJSContext(), sandbox, - jsPrincipals, + nsJSPrincipals::get(prin), reinterpret_cast (PromiseFlatString(source).get()), source.Length(), filename, lineNo, @@ -3571,8 +3567,6 @@ xpc_EvalInSandbox(JSContext *cx, JSObject *sandbox, const nsAString& source, if (stack) unused << stack->Pop(); - JSPRINCIPALS_DROP(cx, jsPrincipals); - return rv; } diff --git a/js/xpconnect/src/XPCJSRuntime.cpp b/js/xpconnect/src/XPCJSRuntime.cpp index 15cdcc970ecd..1ea2a130b40f 100644 --- a/js/xpconnect/src/XPCJSRuntime.cpp +++ b/js/xpconnect/src/XPCJSRuntime.cpp @@ -60,6 +60,8 @@ #include "jsfriendapi.h" #include "js/MemoryMetrics.h" +#include "nsJSPrincipals.h" + #ifdef MOZ_CRASHREPORTER #include "nsExceptionHandler.h" #endif @@ -1220,153 +1222,43 @@ XPCJSRuntime::~XPCJSRuntime() XPCPerThreadData::ShutDown(); } -static void* -GetCompartmentNameHelper(JSCompartment *c, bool getAddress) +static void +GetCompartmentName(JSCompartment *c, bool getAddress, nsCString &name) { - nsCString* name = new nsCString(); if (js::IsAtomsCompartment(c)) { - name->AssignLiteral("atoms"); + name.AssignLiteral("atoms"); } else if (JSPrincipals *principals = JS_GetCompartmentPrincipals(c)) { - if (principals->codebase) { - name->Assign(principals->codebase); + nsJSPrincipals::get(principals)->GetScriptLocation(name); - // For system compartments we append the location, if there is one. - // And we append the address if |getAddress| is true, so that - // multiple system compartments (and there can be many) can be - // distinguished. - if (js::IsSystemCompartment(c)) { - xpc::CompartmentPrivate *compartmentPrivate = - static_cast(JS_GetCompartmentPrivate(c)); - if (compartmentPrivate && - !compartmentPrivate->location.IsEmpty()) { - name->AppendLiteral(", "); - name->Append(compartmentPrivate->location); - } - - if (getAddress) { - // ample; 64-bit address max is 18 chars - static const int maxLength = 31; - nsPrintfCString address(maxLength, ", 0x%llx", PRUint64(c)); - name->Append(address); - } + // For system compartments we append the location, if there is one. + // And we append the address if |getAddress| is true, so that + // multiple system compartments (and there can be many) can be + // distinguished. + if (js::IsSystemCompartment(c)) { + xpc::CompartmentPrivate *compartmentPrivate = + static_cast(JS_GetCompartmentPrivate(c)); + if (compartmentPrivate && !compartmentPrivate->location.IsEmpty()) { + name.AppendLiteral(", "); + name.Append(compartmentPrivate->location); + } + + if (getAddress) { + // ample; 64-bit address max is 18 chars + const int maxLength = 31; + nsPrintfCString address(maxLength, ", 0x%llx", PRUint64(c)); + name.Append(address); } - - // A hack: replace forward slashes with '\\' so they aren't - // treated as path separators. Users of the reporters - // (such as about:memory) have to undo this change. - name->ReplaceChar('/', '\\'); - } else { - name->AssignLiteral("null-codebase"); } + + // A hack: replace forward slashes with '\\' so they aren't + // treated as path separators. Users of the reporters + // (such as about:memory) have to undo this change. + name.ReplaceChar('/', '\\'); } else { - name->AssignLiteral("null-principal"); + name.AssignLiteral("null-principal"); } - return name; } -static void* -GetCompartmentNameAndAddress(JSRuntime *rt, JSCompartment *c) -{ - return GetCompartmentNameHelper(c, /* get address = */true); -} - -namespace xpc { - -void* -GetCompartmentName(JSRuntime *rt, JSCompartment *c) -{ - return GetCompartmentNameHelper(c, /* get address = */false); -} - -void -DestroyCompartmentName(void *string) -{ - delete static_cast(string); -} - -} // namespace xpc - -namespace { - -template -inline void -ReportMemory(const nsACString &path, PRInt32 kind, PRInt32 units, - PRInt64 amount, const char (&desc)[N], - nsIMemoryMultiReporterCallback *callback, nsISupports *closure) -{ - callback->Callback(NS_LITERAL_CSTRING(""), path, kind, units, amount, - NS_LITERAL_CSTRING(desc), closure); -} - -template -inline void -ReportMemoryBytes(const nsACString &path, PRInt32 kind, PRInt64 amount, - const char (&desc)[N], - nsIMemoryMultiReporterCallback *callback, - nsISupports *closure) -{ - ReportMemory(path, kind, nsIMemoryReporter::UNITS_BYTES, amount, desc, - callback, closure); -} - -template -inline void -ReportMemoryBytes0(const nsCString &path, PRInt32 kind, PRInt64 amount, - const char (&desc)[N], - nsIMemoryMultiReporterCallback *callback, - nsISupports *closure) -{ - if (amount) - ReportMemoryBytes(path, kind, amount, desc, callback, closure); -} - -template -inline void -ReportGCHeapBytes(const nsACString &path, PRInt64 *total, PRInt64 amount, - const char (&desc)[N], - nsIMemoryMultiReporterCallback *callback, - nsISupports *closure) -{ - ReportMemory(path, nsIMemoryReporter::KIND_NONHEAP, nsIMemoryReporter::UNITS_BYTES, amount, - desc, callback, closure); - *total += amount; -} - -template -inline void -ReportGCHeapBytes0(const nsCString &path, PRInt64 *total, PRInt64 amount, - const char (&desc)[N], - nsIMemoryMultiReporterCallback *callback, - nsISupports *closure) -{ - if (amount) - return ReportGCHeapBytes(path, total, amount, desc, callback, closure); -} - -template -inline void -ReportMemoryPercentage(const nsACString &path, PRInt32 kind, PRInt64 amount, - const char (&desc)[N], - nsIMemoryMultiReporterCallback *callback, - nsISupports *closure) -{ - ReportMemory(path, kind, nsIMemoryReporter::UNITS_PERCENTAGE, amount, desc, - callback, closure); -} - -template -inline const nsCString -MakeMemoryReporterPath(const nsACString &pathPrefix, - const JS::CompartmentStats &cStats, - const char (&reporterName)[N]) -{ - return pathPrefix + NS_LITERAL_CSTRING("compartment(") + - *static_cast(cStats.name) + - NS_LITERAL_CSTRING(")/") + nsDependentCString(reporterName); -} - -} // anonymous namespace - // We have per-compartment GC heap totals, so we can't put the total GC heap // size in the explicit allocations tree. But it's a useful figure, so put it // in the "others" list. @@ -1404,340 +1296,357 @@ GetJSUserCompartmentCount() // XPConnectJSCompartmentCount to avoid that problem, but then we couldn't // easily report them via telemetry, so we live with the small risk of // inconsistencies. -NS_MEMORY_REPORTER_IMPLEMENT(XPConnectJSSystemCompartmentCount, - "js-compartments-system", - KIND_OTHER, - nsIMemoryReporter::UNITS_COUNT, - GetJSSystemCompartmentCount, - "The number of JavaScript compartments for system code. The sum of this " - "and 'js-compartments-user' might not match the number of " - "compartments listed under 'js' if a garbage collection occurs at an " - "inopportune time, but such cases should be rare.") +NS_MEMORY_REPORTER_IMPLEMENT( + XPConnectJSSystemCompartmentCount, + "js-compartments-system", + KIND_OTHER, + nsIMemoryReporter::UNITS_COUNT, + GetJSSystemCompartmentCount, + "The number of JavaScript compartments for system code. The sum of this " + "and 'js-compartments-user' might not match the number of compartments " + "listed under 'js' if a garbage collection occurs at an inopportune time, " + "but such cases should be rare.") -NS_MEMORY_REPORTER_IMPLEMENT(XPConnectJSUserCompartmentCount, - "js-compartments-user", - KIND_OTHER, - nsIMemoryReporter::UNITS_COUNT, - GetJSUserCompartmentCount, - "The number of JavaScript compartments for user code. The sum of this " - "and 'js-compartments-system' might not match the number of " - "compartments listed under 'js' if a garbage collection occurs at an " - "inopportune time, but such cases should be rare.") +NS_MEMORY_REPORTER_IMPLEMENT( + XPConnectJSUserCompartmentCount, + "js-compartments-user", + KIND_OTHER, + nsIMemoryReporter::UNITS_COUNT, + GetJSUserCompartmentCount, + "The number of JavaScript compartments for user code. The sum of this " + "and 'js-compartments-system' might not match the number of compartments " + "listed under 'js' if a garbage collection occurs at an inopportune time, " + "but such cases should be rare.") + +// The REPORT* macros do an unconditional report. The REPORT*0 macros only +// report if the value is non-zero. + +#define REPORT(_path, _kind, _units, _amount, _desc) \ + do { \ + nsresult rv; \ + rv = cb->Callback(EmptyCString(), _path, _kind, _units, _amount, \ + NS_LITERAL_CSTRING(_desc), closure); \ + NS_ENSURE_SUCCESS(rv, rv); \ + } while (0) + +#define REPORT0(_path, _kind, _units, _amount, _desc) \ + do { \ + size_t amount = _amount; /* evaluate _amount only once */ \ + if (amount > 0) { \ + nsresult rv; \ + rv = cb->Callback(EmptyCString(), _path, _kind, _units, amount, \ + NS_LITERAL_CSTRING(_desc), closure); \ + NS_ENSURE_SUCCESS(rv, rv); \ + } \ + } while (0) + +#define REPORT_BYTES(_path, _kind, _amount, _desc) \ + REPORT(_path, _kind, nsIMemoryReporter::UNITS_BYTES, _amount, _desc); + +#define REPORT_BYTES0(_path, _kind, _amount, _desc) \ + REPORT0(_path, _kind, nsIMemoryReporter::UNITS_BYTES, _amount, _desc); + +#define REPORT_GC_BYTES(_path, _amount, _desc) \ + do { \ + size_t amount = _amount; /* evaluate _amount only once */ \ + nsresult rv; \ + rv = cb->Callback(EmptyCString(), _path, \ + nsIMemoryReporter::KIND_NONHEAP, \ + nsIMemoryReporter::UNITS_BYTES, amount, \ + NS_LITERAL_CSTRING(_desc), closure); \ + NS_ENSURE_SUCCESS(rv, rv); \ + gcTotal += amount; \ + } while (0) + +#define REPORT_GC_BYTES0(_path, _amount, _desc) \ + do { \ + size_t amount = _amount; /* evaluate _amount only once */ \ + if (amount > 0) { \ + nsresult rv; \ + rv = cb->Callback(EmptyCString(), _path, \ + nsIMemoryReporter::KIND_NONHEAP, \ + nsIMemoryReporter::UNITS_BYTES, amount, \ + NS_LITERAL_CSTRING(_desc), closure); \ + NS_ENSURE_SUCCESS(rv, rv); \ + gcTotal += amount; \ + } \ + } while (0) + +template +inline const nsCString +MakePath(const nsACString &pathPrefix, const JS::CompartmentStats &cStats, + const char (&reporterName)[N]) +{ + const char *name = static_cast(cStats.extra); + if (!name) + name = "error while initializing compartment name"; + return pathPrefix + NS_LITERAL_CSTRING("compartment(") + + nsDependentCString(name) + NS_LITERAL_CSTRING(")/") + + nsDependentCString(reporterName); +} namespace mozilla { namespace xpconnect { namespace memory { -static PRInt64 +static nsresult ReportCompartmentStats(const JS::CompartmentStats &cStats, const nsACString &pathPrefix, - nsIMemoryMultiReporterCallback *callback, - nsISupports *closure) + nsIMemoryMultiReporterCallback *cb, + nsISupports *closure, size_t *gcTotalOut) { - PRInt64 gcTotal = 0; + size_t gcTotal = 0; - ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, cStats, - "gc-heap/arena/headers"), - &gcTotal, cStats.gcHeapArenaHeaders, - "Memory on the compartment's garbage-collected JavaScript heap, within " - "arenas, that is used to hold internal book-keeping information.", - callback, closure); + REPORT_GC_BYTES0(MakePath(pathPrefix, cStats, "gc-heap/arena/headers"), + cStats.gcHeapArenaHeaders, + "Memory on the compartment's garbage-collected JavaScript " + "heap, within arenas, that is used to hold internal " + "book-keeping information."); - ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, cStats, - "gc-heap/arena/padding"), - &gcTotal, cStats.gcHeapArenaPadding, - "Memory on the compartment's garbage-collected JavaScript heap, within " - "arenas, that is unused and present only so that other data is aligned. " - "This constitutes internal fragmentation.", - callback, closure); + REPORT_GC_BYTES0(MakePath(pathPrefix, cStats, "gc-heap/arena/padding"), + cStats.gcHeapArenaPadding, + "Memory on the compartment's garbage-collected JavaScript " + "heap, within arenas, that is unused and present only so " + "that other data is aligned. This constitutes internal " + "fragmentation."); - ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, cStats, - "gc-heap/arena/unused"), - &gcTotal, cStats.gcHeapArenaUnused, - "Memory on the compartment's garbage-collected JavaScript heap, within " - "arenas, that could be holding useful data but currently isn't.", - callback, closure); + REPORT_GC_BYTES0(MakePath(pathPrefix, cStats, "gc-heap/arena/unused"), + cStats.gcHeapArenaUnused, + "Memory on the compartment's garbage-collected JavaScript " + "heap, within arenas, that could be holding useful data " + "but currently isn't."); - ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, cStats, - "gc-heap/objects/non-function"), - &gcTotal, cStats.gcHeapObjectsNonFunction, - "Memory on the compartment's garbage-collected JavaScript heap that holds " - "non-function objects.", - callback, closure); + REPORT_GC_BYTES0(MakePath(pathPrefix, cStats, "gc-heap/objects/non-function"), + cStats.gcHeapObjectsNonFunction, + "Memory on the compartment's garbage-collected JavaScript " + "heap that holds non-function objects."); - ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, cStats, - "gc-heap/objects/function"), - &gcTotal, cStats.gcHeapObjectsFunction, - "Memory on the compartment's garbage-collected JavaScript heap that holds " - "function objects.", - callback, closure); + REPORT_GC_BYTES0(MakePath(pathPrefix, cStats, "gc-heap/objects/function"), + cStats.gcHeapObjectsFunction, + "Memory on the compartment's garbage-collected JavaScript " + "heap that holds function objects."); - ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, cStats, - "gc-heap/strings"), - &gcTotal, cStats.gcHeapStrings, - "Memory on the compartment's garbage-collected JavaScript heap that holds " - "string headers. String headers contain various pieces of information " - "about a string, but do not contain (except in the case of very short " - "strings) the string characters; characters in longer strings are counted " - "under 'gc-heap/string-chars' instead.", - callback, closure); + REPORT_GC_BYTES0(MakePath(pathPrefix, cStats, "gc-heap/strings"), + cStats.gcHeapStrings, + "Memory on the compartment's garbage-collected JavaScript " + "heap that holds string headers. String headers contain " + "various pieces of information about a string, but do not " + "contain (except in the case of very short strings) the " + "string characters; characters in longer strings are " + "counted " "under 'gc-heap/string-chars' instead."); - ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, cStats, - "gc-heap/scripts"), - &gcTotal, cStats.gcHeapScripts, - "Memory on the compartment's garbage-collected JavaScript heap that holds " - "JSScript instances. A JSScript is created for each user-defined function " - "in a script. One is also created for the top-level code in a script.", - callback, closure); + REPORT_GC_BYTES0(MakePath(pathPrefix, cStats, "gc-heap/scripts"), + cStats.gcHeapScripts, + "Memory on the compartment's garbage-collected JavaScript " + "heap that holds JSScript instances. A JSScript is " + "created for each user-defined function in a script. One " + "is also created for the top-level code in a script."); - ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, cStats, - "gc-heap/shapes/tree"), - &gcTotal, cStats.gcHeapShapesTree, - "Memory on the compartment's garbage-collected JavaScript heap that holds " - "shapes that are in a property tree.", - callback, closure); + REPORT_GC_BYTES0(MakePath(pathPrefix, cStats, "gc-heap/shapes/tree"), + cStats.gcHeapShapesTree, + "Memory on the compartment's garbage-collected JavaScript " + "heap that holds shapes that are in a property tree."); - ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, cStats, - "gc-heap/shapes/dict"), - &gcTotal, cStats.gcHeapShapesDict, - "Memory on the compartment's garbage-collected JavaScript heap that holds " - "shapes that are in dictionary mode.", - callback, closure); + REPORT_GC_BYTES0(MakePath(pathPrefix, cStats, "gc-heap/shapes/dict"), + cStats.gcHeapShapesDict, + "Memory on the compartment's garbage-collected JavaScript " + "heap that holds shapes that are in dictionary mode."); - ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, cStats, - "gc-heap/shapes/base"), - &gcTotal, cStats.gcHeapShapesBase, - "Memory on the compartment's garbage-collected JavaScript heap that collates " - "data common to many shapes.", - callback, closure); + REPORT_GC_BYTES0(MakePath(pathPrefix, cStats, "gc-heap/shapes/base"), + cStats.gcHeapShapesBase, + "Memory on the compartment's garbage-collected JavaScript " + "heap that collates data common to many shapes."); - ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, cStats, - "gc-heap/type-objects"), - &gcTotal, cStats.gcHeapTypeObjects, - "Memory on the compartment's garbage-collected JavaScript heap that holds " - "type inference information.", - callback, closure); + REPORT_GC_BYTES0(MakePath(pathPrefix, cStats, "gc-heap/type-objects"), + cStats.gcHeapTypeObjects, + "Memory on the compartment's garbage-collected JavaScript " + "heap that holds type inference information."); - ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, cStats, - "gc-heap/xml"), - &gcTotal, cStats.gcHeapXML, - "Memory on the compartment's garbage-collected JavaScript heap that holds " - "E4X XML objects.", - callback, closure); + REPORT_GC_BYTES0(MakePath(pathPrefix, cStats, "gc-heap/xml"), + cStats.gcHeapXML, + "Memory on the compartment's garbage-collected JavaScript " + "heap that holds E4X XML objects."); - ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, cStats, - "objects/slots"), - nsIMemoryReporter::KIND_HEAP, cStats.objectSlots, - "Memory allocated for the compartment's non-fixed object slot arrays, " - "which are used to represent object properties. Some objects also " - "contain a fixed number of slots which are stored on the compartment's " - "JavaScript heap; those slots are not counted here, but in " - "'gc-heap/objects' instead.", - callback, closure); + REPORT_BYTES0(MakePath(pathPrefix, cStats, "objects/slots"), + nsIMemoryReporter::KIND_HEAP, cStats.objectSlots, + "Memory allocated for the compartment's non-fixed object " + "slot arrays, which are used to represent object properties. " + "Some objects also contain a fixed number of slots which are " + "stored on the compartment's JavaScript heap; those slots " + "are not counted here, but in 'gc-heap/objects' instead."); - ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, cStats, - "objects/elements"), - nsIMemoryReporter::KIND_HEAP, cStats.objectElements, - "Memory allocated for the compartment's object element arrays, " - "which are used to represent indexed object properties.", - callback, closure); + REPORT_BYTES0(MakePath(pathPrefix, cStats, "objects/elements"), + nsIMemoryReporter::KIND_HEAP, cStats.objectElements, + "Memory allocated for the compartment's object element " + "arrays, which are used to represent indexed object " + "properties."); - ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, cStats, - "objects/misc"), - nsIMemoryReporter::KIND_HEAP, cStats.objectMisc, - "Memory allocated for various small, miscellaneous " - "structures that hang off certain kinds of objects.", - callback, closure); + REPORT_BYTES0(MakePath(pathPrefix, cStats, "objects/misc"), + nsIMemoryReporter::KIND_HEAP, cStats.objectMisc, + "Memory allocated for various small, miscellaneous " + "structures that hang off certain kinds of objects."); - ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, cStats, - "string-chars"), - nsIMemoryReporter::KIND_HEAP, cStats.stringChars, - "Memory allocated to hold the compartment's string characters. Sometimes " - "more memory is allocated than necessary, to simplify string " - "concatenation. Each string also includes a header which is stored on the " - "compartment's JavaScript heap; that header is not counted here, but in " - "'gc-heap/strings' instead.", - callback, closure); + REPORT_BYTES0(MakePath(pathPrefix, cStats, "string-chars"), + nsIMemoryReporter::KIND_HEAP, cStats.stringChars, + "Memory allocated to hold the compartment's string " + "characters. Sometimes more memory is allocated than " + "necessary, to simplify string concatenation. Each string " + "also includes a header which is stored on the " + "compartment's JavaScript heap; that header is not counted " + "here, but in 'gc-heap/strings' instead."); - ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, cStats, - "shapes-extra/tree-tables"), - nsIMemoryReporter::KIND_HEAP, cStats.shapesExtraTreeTables, - "Memory allocated for the compartment's property tables that belong to " - "shapes that are in a property tree.", - callback, closure); + REPORT_BYTES0(MakePath(pathPrefix, cStats, "shapes-extra/tree-tables"), + nsIMemoryReporter::KIND_HEAP, cStats.shapesExtraTreeTables, + "Memory allocated for the compartment's property tables " + "that belong to shapes that are in a property tree."); - ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, cStats, - "shapes-extra/dict-tables"), - nsIMemoryReporter::KIND_HEAP, cStats.shapesExtraDictTables, - "Memory allocated for the compartment's property tables that belong to " - "shapes that are in dictionary mode.", - callback, closure); + REPORT_BYTES0(MakePath(pathPrefix, cStats, "shapes-extra/dict-tables"), + nsIMemoryReporter::KIND_HEAP, cStats.shapesExtraDictTables, + "Memory allocated for the compartment's property tables " + "that belong to shapes that are in dictionary mode."); - ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, cStats, - "shapes-extra/tree-shape-kids"), - nsIMemoryReporter::KIND_HEAP, cStats.shapesExtraTreeShapeKids, - "Memory allocated for the compartment's kid hashes that belong to shapes " - "that are in a property tree.", - callback, closure); + REPORT_BYTES0(MakePath(pathPrefix, cStats, "shapes-extra/tree-shape-kids"), + nsIMemoryReporter::KIND_HEAP, cStats.shapesExtraTreeShapeKids, + "Memory allocated for the compartment's kid hashes that " + "belong to shapes that are in a property tree."); - ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, cStats, - "shapes-extra/compartment-tables"), - nsIMemoryReporter::KIND_HEAP, cStats.shapesCompartmentTables, - "Memory used by compartment wide tables storing shape information " - "for use during object construction.", - callback, closure); + REPORT_BYTES0(MakePath(pathPrefix, cStats, "shapes-extra/compartment-tables"), + nsIMemoryReporter::KIND_HEAP, cStats.shapesCompartmentTables, + "Memory used by compartment wide tables storing shape " + "information for use during object construction."); - ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, cStats, - "script-data"), - nsIMemoryReporter::KIND_HEAP, cStats.scriptData, - "Memory allocated for JSScript bytecode and various variable-length " - "tables.", - callback, closure); + REPORT_BYTES0(MakePath(pathPrefix, cStats, "script-data"), + nsIMemoryReporter::KIND_HEAP, cStats.scriptData, + "Memory allocated for JSScript bytecode and various " + "variable-length tables."); #ifdef JS_METHODJIT - ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, cStats, - "mjit/code"), - nsIMemoryReporter::KIND_NONHEAP, cStats.mjitCode, - "Memory used by the method JIT to hold the compartment's generated code.", - callback, closure); + REPORT_BYTES0(MakePath(pathPrefix, cStats, "mjit/code"), + nsIMemoryReporter::KIND_NONHEAP, cStats.mjitCode, + "Memory used by the method JIT to hold the compartment's " + "generated code."); - ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, cStats, - "mjit/data"), - nsIMemoryReporter::KIND_HEAP, cStats.mjitData, - "Memory used by the method JIT for the compartment's compilation data: " - "JITScripts, native maps, and inline cache structs.", - callback, closure); + REPORT_BYTES0(MakePath(pathPrefix, cStats, "mjit/data"), + nsIMemoryReporter::KIND_HEAP, cStats.mjitData, + "Memory used by the method JIT for the compartment's " + "compilation data: JITScripts, native maps, and inline " + "cache structs."); #endif - ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, cStats, - "type-inference/script-main"), - nsIMemoryReporter::KIND_HEAP, - cStats.typeInferenceSizes.scripts, - "Memory used during type inference to store type sets of variables " - "and dynamically observed types.", - callback, closure); + REPORT_BYTES0(MakePath(pathPrefix, cStats, "type-inference/script-main"), + nsIMemoryReporter::KIND_HEAP, + cStats.typeInferenceSizes.scripts, + "Memory used during type inference to store type sets of " + "variables and dynamically observed types."); - ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, cStats, - "type-inference/object-main"), - nsIMemoryReporter::KIND_HEAP, - cStats.typeInferenceSizes.objects, - "Memory used during type inference to store types and possible " - "property types of JS objects.", - callback, closure); + REPORT_BYTES0(MakePath(pathPrefix, cStats, "type-inference/object-main"), + nsIMemoryReporter::KIND_HEAP, + cStats.typeInferenceSizes.objects, + "Memory used during type inference to store types and " + "possible property types of JS objects."); - ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, cStats, - "type-inference/tables"), - nsIMemoryReporter::KIND_HEAP, - cStats.typeInferenceSizes.tables, - "Memory used during type inference for compartment-wide tables.", - callback, closure); + REPORT_BYTES0(MakePath(pathPrefix, cStats, "type-inference/tables"), + nsIMemoryReporter::KIND_HEAP, + cStats.typeInferenceSizes.tables, + "Memory used during type inference for compartment-wide " + "tables."); - ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, cStats, - "analysis-temporary"), - nsIMemoryReporter::KIND_HEAP, - cStats.typeInferenceSizes.temporary, - "Memory used during type inference and compilation to hold transient " - "analysis information. Cleared on GC.", - callback, closure); + REPORT_BYTES0(MakePath(pathPrefix, cStats, "analysis-temporary"), + nsIMemoryReporter::KIND_HEAP, + cStats.typeInferenceSizes.temporary, + "Memory used during type inference and compilation to hold " + "transient analysis information. Cleared on GC."); - return gcTotal; + *gcTotalOut += gcTotal; + + return NS_OK; } -void -ReportJSRuntimeExplicitTreeStats(const JS::RuntimeStats &rtStats, const nsACString &pathPrefix, - nsIMemoryMultiReporterCallback *callback, +nsresult +ReportJSRuntimeExplicitTreeStats(const JS::RuntimeStats &rtStats, + const nsACString &pathPrefix, + nsIMemoryMultiReporterCallback *cb, nsISupports *closure) { - PRInt64 gcTotal = 0; + nsresult rv; + size_t gcTotal = 0; for (size_t index = 0; index < rtStats.compartmentStatsVector.length(); index++) { - gcTotal += ReportCompartmentStats(rtStats.compartmentStatsVector[index], pathPrefix, - callback, closure); + rv = ReportCompartmentStats(rtStats.compartmentStatsVector[index], + pathPrefix, cb, closure, &gcTotal); + NS_ENSURE_SUCCESS(rv, rv); } - ReportMemoryBytes(pathPrefix + NS_LITERAL_CSTRING("runtime/runtime-object"), - nsIMemoryReporter::KIND_HEAP, rtStats.runtimeObject, - "Memory used by the JSRuntime object.", - callback, closure); + REPORT_BYTES(pathPrefix + NS_LITERAL_CSTRING("runtime/runtime-object"), + nsIMemoryReporter::KIND_HEAP, rtStats.runtimeObject, + "Memory used by the JSRuntime object."); - ReportMemoryBytes(pathPrefix + NS_LITERAL_CSTRING("runtime/atoms-table"), - nsIMemoryReporter::KIND_HEAP, rtStats.runtimeAtomsTable, - "Memory used by the atoms table.", - callback, closure); + REPORT_BYTES(pathPrefix + NS_LITERAL_CSTRING("runtime/atoms-table"), + nsIMemoryReporter::KIND_HEAP, rtStats.runtimeAtomsTable, + "Memory used by the atoms table."); - ReportMemoryBytes(pathPrefix + NS_LITERAL_CSTRING("runtime/contexts"), - nsIMemoryReporter::KIND_HEAP, rtStats.runtimeContexts, - "Memory used by JSContext objects and certain structures " - "hanging off them." , - callback, closure); + REPORT_BYTES(pathPrefix + NS_LITERAL_CSTRING("runtime/contexts"), + nsIMemoryReporter::KIND_HEAP, rtStats.runtimeContexts, + "Memory used by JSContext objects and certain structures " + "hanging off them."); - ReportMemoryBytes(pathPrefix + NS_LITERAL_CSTRING("runtime/normal"), - nsIMemoryReporter::KIND_HEAP, rtStats.runtimeNormal, - "Memory used by a JSRuntime, " - "excluding memory that is reported by " - "other reporters under 'explicit/js/runtime/'.", - callback, closure); + REPORT_BYTES(pathPrefix + NS_LITERAL_CSTRING("runtime/normal"), + nsIMemoryReporter::KIND_HEAP, rtStats.runtimeNormal, + "Memory used by a JSRuntime, excluding memory that is " + "reported by other reporters under 'explicit/js/runtime/'."); - ReportMemoryBytes(pathPrefix + NS_LITERAL_CSTRING("runtime/temporary"), - nsIMemoryReporter::KIND_HEAP, rtStats.runtimeTemporary, - "Memory held transiently in JSRuntime and used during " - "compilation. It mostly holds parse nodes.", - callback, closure); + REPORT_BYTES(pathPrefix + NS_LITERAL_CSTRING("runtime/temporary"), + nsIMemoryReporter::KIND_HEAP, rtStats.runtimeTemporary, + "Memory held transiently in JSRuntime and used during " + "compilation. It mostly holds parse nodes."); - ReportMemoryBytes0(pathPrefix + NS_LITERAL_CSTRING("runtime/regexp-code"), - nsIMemoryReporter::KIND_NONHEAP, rtStats.runtimeRegexpCode, - "Memory used by the regexp JIT to hold generated code.", - callback, closure); + REPORT_BYTES(pathPrefix + NS_LITERAL_CSTRING("runtime/regexp-code"), + nsIMemoryReporter::KIND_NONHEAP, rtStats.runtimeRegexpCode, + "Memory used by the regexp JIT to hold generated code."); - ReportMemoryBytes(pathPrefix + NS_LITERAL_CSTRING("runtime/stack-committed"), - nsIMemoryReporter::KIND_NONHEAP, rtStats.runtimeStackCommitted, - "Memory used for the JS call stack. This is the committed portion " - "of the stack; the uncommitted portion is not measured because it " - "hardly costs anything.", - callback, closure); + REPORT_BYTES(pathPrefix + NS_LITERAL_CSTRING("runtime/stack-committed"), + nsIMemoryReporter::KIND_NONHEAP, rtStats.runtimeStackCommitted, + "Memory used for the JS call stack. This is the committed " + "portion of the stack; the uncommitted portion is not " + "measured because it hardly costs anything."); - ReportMemoryBytes(pathPrefix + NS_LITERAL_CSTRING("runtime/gc-marker"), - nsIMemoryReporter::KIND_HEAP, rtStats.runtimeGCMarker, - "Memory used for the GC mark stack and gray roots.", - callback, closure); + REPORT_BYTES(pathPrefix + NS_LITERAL_CSTRING("runtime/gc-marker"), + nsIMemoryReporter::KIND_HEAP, rtStats.runtimeGCMarker, + "Memory used for the GC mark stack and gray roots."); - ReportGCHeapBytes(pathPrefix + - NS_LITERAL_CSTRING("gc-heap-chunk-dirty-unused"), - &gcTotal, rtStats.gcHeapChunkDirtyUnused, - "Memory on the garbage-collected JavaScript heap, within chunks with at " - "least one allocated GC thing, that could be holding useful data but " - "currently isn't. Memory here is mutually exclusive with memory reported" - "under 'explicit/js/gc-heap-decommitted'.", - callback, closure); + REPORT_GC_BYTES(pathPrefix + NS_LITERAL_CSTRING("gc-heap-chunk-dirty-unused"), + rtStats.gcHeapChunkDirtyUnused, + "Memory on the garbage-collected JavaScript heap, within " + "chunks with at least one allocated GC thing, that could " + "be holding useful data but currently isn't. Memory here " + "is mutually exclusive with memory reported under " + "'explicit/js/gc-heap-decommitted'."); - ReportGCHeapBytes(pathPrefix + - NS_LITERAL_CSTRING("gc-heap-chunk-clean-unused"), - &gcTotal, rtStats.gcHeapChunkCleanUnused, - "Memory on the garbage-collected JavaScript heap taken by completely empty " - "chunks, that soon will be released unless claimed for new allocations. " - "Memory here is mutually exclusive with memory reported under " - "'explicit/js/gc-heap-decommitted'.", - callback, closure); + REPORT_GC_BYTES(pathPrefix + NS_LITERAL_CSTRING("gc-heap-chunk-clean-unused"), + rtStats.gcHeapChunkCleanUnused, + "Memory on the garbage-collected JavaScript heap taken by " + "completely empty chunks, that soon will be released " + "unless claimed for new allocations. Memory here is " + "mutually exclusive with memory reported under " + "'explicit/js/gc-heap-decommitted'."); - ReportGCHeapBytes(pathPrefix + - NS_LITERAL_CSTRING("gc-heap-decommitted"), - &gcTotal, - rtStats.gcHeapChunkCleanDecommitted + rtStats.gcHeapChunkDirtyDecommitted, - "Memory in the address space of the garbage-collected JavaScript heap that " - "is currently returned to the OS.", - callback, closure); + REPORT_GC_BYTES(pathPrefix + NS_LITERAL_CSTRING("gc-heap-decommitted"), + rtStats.gcHeapChunkCleanDecommitted + rtStats.gcHeapChunkDirtyDecommitted, + "Memory in the address space of the garbage-collected " + "JavaScript heap that is currently returned to the OS."); - ReportGCHeapBytes(pathPrefix + - NS_LITERAL_CSTRING("gc-heap-chunk-admin"), - &gcTotal, rtStats.gcHeapChunkAdmin, - "Memory on the garbage-collected JavaScript heap, within chunks, that is " - "used to hold internal book-keeping information.", - callback, closure); + REPORT_GC_BYTES(pathPrefix + NS_LITERAL_CSTRING("gc-heap-chunk-admin"), + rtStats.gcHeapChunkAdmin, + "Memory on the garbage-collected JavaScript heap, within " + "chunks, that is used to hold internal book-keeping " + "information."); // gcTotal is the sum of everything we've reported for the GC heap. It // should equal rtStats.gcHeapChunkTotal. - JS_ASSERT(size_t(gcTotal) == rtStats.gcHeapChunkTotal); + JS_ASSERT(gcTotal == rtStats.gcHeapChunkTotal); + + return NS_OK; } } // namespace memory @@ -1761,25 +1670,22 @@ class JSCompartmentsMultiReporter : public nsIMemoryMultiReporter static void CompartmentCallback(JSRuntime *rt, void* data, JSCompartment *c) { + // silently ignore OOM errors Paths *paths = static_cast(data); - nsCString *name = - static_cast(xpc::GetCompartmentName(rt, c)); nsCString path; - if (js::IsSystemCompartment(c)) - path = NS_LITERAL_CSTRING("compartments/system/") + *name; - else - path = NS_LITERAL_CSTRING("compartments/user/") + *name; - if (!paths->append(path)) - return; // silent failure, but it's very unlikely - - xpc::DestroyCompartmentName(name); + GetCompartmentName(c, /* getAddress = */ false, path); + path.Insert(js::IsSystemCompartment(c) + ? NS_LITERAL_CSTRING("compartments/system/") + : NS_LITERAL_CSTRING("compartments/user/"), + 0); + paths->append(path); } - NS_IMETHOD CollectReports(nsIMemoryMultiReporterCallback *callback, + NS_IMETHOD CollectReports(nsIMemoryMultiReporterCallback *cb, nsISupports *closure) { // First we collect the compartment paths. Then we report them. Doing - // the two steps interleaved is a bad idea, because calling |callback| + // the two steps interleaved is a bad idea, because calling |cb| // from within CompartmentCallback() leads to all manner of assertions. // Collect. @@ -1791,10 +1697,10 @@ class JSCompartmentsMultiReporter : public nsIMemoryMultiReporter // Report. for (size_t i = 0; i < paths.length(); i++) // These ones don't need a description, hence the "". - ReportMemory(paths[i], - nsIMemoryReporter::KIND_OTHER, - nsIMemoryReporter::UNITS_COUNT, - 1, "", callback, closure); + REPORT(nsCString(paths[i]), + nsIMemoryReporter::KIND_OTHER, + nsIMemoryReporter::UNITS_COUNT, + 1, ""); return NS_OK; } @@ -1812,6 +1718,23 @@ NS_IMPL_THREADSAFE_ISUPPORTS1(JSCompartmentsMultiReporter , nsIMemoryMultiReporter ) +struct XPCJSRuntimeStats : public JS::RuntimeStats { + XPCJSRuntimeStats() + : JS::RuntimeStats(JsMallocSizeOf) { } + + ~XPCJSRuntimeStats() { + for (size_t i = 0; i != compartmentStatsVector.length(); ++i) + free(compartmentStatsVector[i].extra); + } + + virtual void initExtraCompartmentStats(JSCompartment *c, + JS::CompartmentStats *cstats) MOZ_OVERRIDE { + nsCAutoString name; + GetCompartmentName(c, /* getAddress = */ true, name); + cstats->extra = strdup(name.get()); + } +}; + class JSMemoryMultiReporter : public nsIMemoryMultiReporter { public: @@ -1823,7 +1746,7 @@ public: return NS_OK; } - NS_IMETHOD CollectReports(nsIMemoryMultiReporterCallback *callback, + NS_IMETHOD CollectReports(nsIMemoryMultiReporterCallback *cb, nsISupports *closure) { XPCJSRuntime *xpcrt = nsXPConnect::GetRuntimeInstance(); @@ -1833,8 +1756,7 @@ public: // the callback. Separating these steps is important because the // callback may be a JS function, and executing JS while getting these // stats seems like a bad idea. - JS::RuntimeStats rtStats(JsMallocSizeOf, GetCompartmentNameAndAddress, - xpc::DestroyCompartmentName); + XPCJSRuntimeStats rtStats; if (!JS::CollectRuntimeStats(xpcrt->GetJSRuntime(), &rtStats)) return NS_ERROR_FAILURE; @@ -1847,102 +1769,101 @@ public: // This is the second step (see above). First we report stuff in the // "explicit" tree, then we report other stuff. - ReportJSRuntimeExplicitTreeStats(rtStats, pathPrefix, callback, closure); + nsresult rv = + ReportJSRuntimeExplicitTreeStats(rtStats, pathPrefix, cb, closure); + NS_ENSURE_SUCCESS(rv, rv); - ReportMemoryBytes(pathPrefix + NS_LITERAL_CSTRING("xpconnect"), - nsIMemoryReporter::KIND_HEAP, xpconnect, - "Memory used by XPConnect.", - callback, closure); + REPORT_BYTES(pathPrefix + NS_LITERAL_CSTRING("xpconnect"), + nsIMemoryReporter::KIND_HEAP, xpconnect, + "Memory used by XPConnect."); - ReportMemoryBytes(NS_LITERAL_CSTRING("js-main-runtime-gc-heap-chunk-dirty-unused"), - nsIMemoryReporter::KIND_OTHER, - rtStats.gcHeapChunkDirtyUnused, - "The same as 'explicit/js/gc-heap-chunk-dirty-unused'. Shown here for " - "easy comparison with other 'js-gc' reporters.", - callback, closure); + REPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime-gc-heap-chunk-dirty-unused"), + nsIMemoryReporter::KIND_OTHER, + rtStats.gcHeapChunkDirtyUnused, + "The same as 'explicit/js/gc-heap-chunk-dirty-unused'. " + "Shown here for easy comparison with other 'js-gc' " + "reporters."); - ReportMemoryBytes(NS_LITERAL_CSTRING("js-main-runtime-gc-heap-chunk-clean-unused"), - nsIMemoryReporter::KIND_OTHER, - rtStats.gcHeapChunkCleanUnused, - "The same as 'explicit/js/gc-heap-chunk-clean-unused'. Shown here for " - "easy comparison with other 'js-gc' reporters.", - callback, closure); + REPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime-gc-heap-chunk-clean-unused"), + nsIMemoryReporter::KIND_OTHER, + rtStats.gcHeapChunkCleanUnused, + "The same as 'explicit/js/gc-heap-chunk-clean-unused'. " + "Shown here for easy comparison with other 'js-gc' " + "reporters."); - ReportMemoryBytes(NS_LITERAL_CSTRING("js-main-runtime-gc-heap-decommitted"), - nsIMemoryReporter::KIND_OTHER, - rtStats.gcHeapChunkCleanDecommitted + rtStats.gcHeapChunkDirtyDecommitted, - "The same as 'explicit/js/gc-heap-decommitted'. Shown here for " - "easy comparison with other 'js-gc' reporters.", - callback, closure); + REPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime-gc-heap-decommitted"), + nsIMemoryReporter::KIND_OTHER, + rtStats.gcHeapChunkCleanDecommitted + rtStats.gcHeapChunkDirtyDecommitted, + "The same as 'explicit/js/gc-heap-decommitted'. Shown " + "here for easy comparison with other 'js-gc' reporters."); - ReportMemoryBytes(NS_LITERAL_CSTRING("js-main-runtime-gc-heap-arena-unused"), - nsIMemoryReporter::KIND_OTHER, - rtStats.gcHeapArenaUnused, - "Memory on the main JSRuntime's garbage-collected JavaScript heap, " - "within arenas, that could be holding useful data but currently isn't. " - "This is the sum of all compartments' 'gc-heap/arena-unused' numbers.", - callback, closure); + REPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime-gc-heap-arena-unused"), + nsIMemoryReporter::KIND_OTHER, + rtStats.gcHeapArenaUnused, + "Memory on the main JSRuntime's garbage-collected " + "JavaScript heap, within arenas, that could be holding " + "useful data but currently isn't. This is the sum of all " + "compartments' 'gc-heap/arena-unused' numbers."); - ReportMemoryPercentage(NS_LITERAL_CSTRING("js-main-runtime-gc-heap-unused-fraction"), - nsIMemoryReporter::KIND_OTHER, - rtStats.gcHeapUnusedPercentage, - "Fraction of the main JSRuntime's garbage-collected JavaScript " - "heap that is unused. Computed as ('js-gc-heap-chunk-clean-unused' " - "+ 'js-gc-heap-chunk-dirty-unused' + 'js-gc-heap-decommitted' + " - "'js-gc-heap-arena-unused') / 'js-gc-heap'.", - callback, closure); + REPORT(NS_LITERAL_CSTRING("js-main-runtime-gc-heap-unused-fraction"), + nsIMemoryReporter::KIND_OTHER, + nsIMemoryReporter::UNITS_PERCENTAGE, + rtStats.gcHeapUnusedPercentage, + "Fraction of the main JSRuntime's garbage-collected JavaScript " + "heap that is unused. Computed as " + "('js-gc-heap-chunk-clean-unused' + " + "'js-gc-heap-chunk-dirty-unused' + 'js-gc-heap-decommitted' + " + "'js-gc-heap-arena-unused') / 'js-gc-heap'."); - ReportMemoryBytes(NS_LITERAL_CSTRING("js-main-runtime-objects"), - nsIMemoryReporter::KIND_OTHER, rtStats.totalObjects, - "Memory used for all object-related data in the main JSRuntime. " - "This is the sum of all compartments' 'gc-heap/objects-non-function', " - "'gc-heap/objects-function' and 'object-slots' numbers.", - callback, closure); + REPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime-objects"), + nsIMemoryReporter::KIND_OTHER, rtStats.totalObjects, + "Memory used for all object-related data in the main " + "JSRuntime. This is the sum of all compartments' " + "'gc-heap/objects-non-function', " + "'gc-heap/objects-function' and 'object-slots' numbers."); - ReportMemoryBytes(NS_LITERAL_CSTRING("js-main-runtime-shapes"), - nsIMemoryReporter::KIND_OTHER, rtStats.totalShapes, - "Memory used for all shape-related data in the main JSRuntime. " - "This is the sum of all compartments' 'gc-heap/shapes/tree', " - "'gc-heap/shapes/dict', 'gc-heap/shapes/base', " - "'shapes-extra/tree-tables', 'shapes-extra/dict-tables', " - "'shapes-extra/tree-shape-kids' and 'shapes-extra/empty-shape-arrays'.", - callback, closure); + REPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime-shapes"), + nsIMemoryReporter::KIND_OTHER, rtStats.totalShapes, + "Memory used for all shape-related data in the main " + "JSRuntime. This is the sum of all compartments' " + "'gc-heap/shapes/tree', 'gc-heap/shapes/dict', " + "'gc-heap/shapes/base', 'shapes-extra/tree-tables', " + "'shapes-extra/dict-tables', " + "'shapes-extra/tree-shape-kids' and " + "'shapes-extra/empty-shape-arrays'."); - ReportMemoryBytes(NS_LITERAL_CSTRING("js-main-runtime-scripts"), - nsIMemoryReporter::KIND_OTHER, rtStats.totalScripts, - "Memory used for all script-related data in the main JSRuntime. " - "This is the sum of all compartments' 'gc-heap/scripts' and " - "'script-data' numbers.", - callback, closure); + REPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime-scripts"), + nsIMemoryReporter::KIND_OTHER, rtStats.totalScripts, + "Memory used for all script-related data in the main " + "JSRuntime. This is the sum of all compartments' " + "'gc-heap/scripts' and 'script-data' numbers."); + + REPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime-strings"), + nsIMemoryReporter::KIND_OTHER, rtStats.totalStrings, + "Memory used for all string-related data in the main " + "JSRuntime. This is the sum of all compartments' " + "'gc-heap/strings' and 'string-chars' numbers."); - ReportMemoryBytes(NS_LITERAL_CSTRING("js-main-runtime-strings"), - nsIMemoryReporter::KIND_OTHER, rtStats.totalStrings, - "Memory used for all string-related data in the main JSRuntime. " - "This is the sum of all compartments' 'gc-heap/strings' and " - "'string-chars' numbers.", - callback, closure); #ifdef JS_METHODJIT - ReportMemoryBytes(NS_LITERAL_CSTRING("js-main-runtime-mjit"), - nsIMemoryReporter::KIND_OTHER, rtStats.totalMjit, - "Memory used by the method JIT in the main JSRuntime. " - "This is the sum of all compartments' 'mjit/code', and 'mjit/data' " - "numbers.", - callback, closure); + REPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime-mjit"), + nsIMemoryReporter::KIND_OTHER, rtStats.totalMjit, + "Memory used by the method JIT in the main JSRuntime. " + "This is the sum of all compartments' 'mjit/code', and " + "'mjit/data' numbers."); #endif - ReportMemoryBytes(NS_LITERAL_CSTRING("js-main-runtime-type-inference"), - nsIMemoryReporter::KIND_OTHER, rtStats.totalTypeInference, - "Non-transient memory used by type inference in the main JSRuntime. " - "This is the sum of all compartments' 'gc-heap/type-objects', " - "'type-inference/script-main', 'type-inference/object-main' and " - "'type-inference/tables' numbers.", - callback, closure); + REPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime-type-inference"), + nsIMemoryReporter::KIND_OTHER, rtStats.totalTypeInference, + "Non-transient memory used by type inference in the main " + "JSRuntime. This is the sum of all compartments' " + "'gc-heap/type-objects', 'type-inference/script-main', " + "'type-inference/object-main' and " + "'type-inference/tables' numbers."); - ReportMemoryBytes(NS_LITERAL_CSTRING("js-main-runtime-analysis-temporary"), - nsIMemoryReporter::KIND_OTHER, rtStats.totalAnalysisTemp, - "Memory used transiently during type inference and compilation in the " - "main JSRuntime. This is the sum of all compartments' " - "'analysis-temporary' numbers.", - callback, closure); + REPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime-analysis-temporary"), + nsIMemoryReporter::KIND_OTHER, rtStats.totalAnalysisTemp, + "Memory used transiently during type inference and " + "compilation in the main JSRuntime. This is the sum of " + "all compartments' 'analysis-temporary' numbers."); return NS_OK; } diff --git a/js/xpconnect/src/nsXPConnect.cpp b/js/xpconnect/src/nsXPConnect.cpp index 138f04672833..2912907805c3 100644 --- a/js/xpconnect/src/nsXPConnect.cpp +++ b/js/xpconnect/src/nsXPConnect.cpp @@ -1145,12 +1145,8 @@ CreateNewCompartment(JSContext *cx, JSClass *clasp, nsIPrincipal *principal, // of failure or give ownership to the compartment in case of success (in // that case it will be free'd in CompartmentCallback during GC). nsAutoPtr priv_holder(priv); - JSPrincipals *principals = nsnull; - if (principal) - principal->GetJSPrincipals(cx, &principals); - JSObject *tempGlobal = JS_NewCompartmentAndGlobalObject(cx, clasp, principals); - if (principals) - JSPRINCIPALS_DROP(cx, principals); + JSObject *tempGlobal = + JS_NewCompartmentAndGlobalObject(cx, clasp, nsJSPrincipals::get(principal)); if (!tempGlobal) return false; diff --git a/js/xpconnect/src/xpcpublic.h b/js/xpconnect/src/xpcpublic.h index 46830c44d298..2e72278785a1 100644 --- a/js/xpconnect/src/xpcpublic.h +++ b/js/xpconnect/src/xpcpublic.h @@ -222,9 +222,6 @@ bool Base64Decode(JSContext *cx, JS::Value val, JS::Value *out); bool StringToJsval(JSContext *cx, nsAString &str, JS::Value *rval); bool NonVoidStringToJsval(JSContext *cx, nsAString &str, JS::Value *rval); -void *GetCompartmentName(JSRuntime *rt, JSCompartment *c); -void DestroyCompartmentName(void *string); - #ifdef DEBUG void DumpJSHeap(FILE* file); #endif @@ -238,9 +235,10 @@ namespace memory { // This reports all the stats in |rtStats| that belong in the "explicit" tree, // (which isn't all of them). -void -ReportJSRuntimeExplicitTreeStats(const JS::RuntimeStats &rtStats, const nsACString &pathPrefix, - nsIMemoryMultiReporterCallback *callback, +nsresult +ReportJSRuntimeExplicitTreeStats(const JS::RuntimeStats &rtStats, + const nsACString &pathPrefix, + nsIMemoryMultiReporterCallback *cb, nsISupports *closure); } // namespace memory diff --git a/js/xpconnect/wrappers/AccessCheck.cpp b/js/xpconnect/wrappers/AccessCheck.cpp index 6f0364572cdb..9e17cf49a8a9 100644 --- a/js/xpconnect/wrappers/AccessCheck.cpp +++ b/js/xpconnect/wrappers/AccessCheck.cpp @@ -61,8 +61,7 @@ namespace xpc { nsIPrincipal * GetCompartmentPrincipal(JSCompartment *compartment) { - JSPrincipals *prin = JS_GetCompartmentPrincipals(compartment); - return prin ? static_cast(prin)->nsIPrincipalPtr : nsnull; + return nsJSPrincipals::get(JS_GetCompartmentPrincipals(compartment)); } bool diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp index 7efed1653319..e1f55b2f7391 100644 --- a/layout/base/nsCSSFrameConstructor.cpp +++ b/layout/base/nsCSSFrameConstructor.cpp @@ -7580,7 +7580,14 @@ DoApplyRenderingChangeToTree(nsIFrame* aFrame, // if frame has view, will already be invalidated if (aChange & nsChangeHint_RepaintFrame) { if (aFrame->IsFrameOfType(nsIFrame::eSVG)) { - nsSVGUtils::UpdateGraphic(aFrame); + if (aChange & nsChangeHint_UpdateEffects) { + // Invalidate the frame's old bounds, update its bounds, invalidate its new + // bounds, and then inform anyone observing _us_ that we've changed: + nsSVGUtils::UpdateGraphic(aFrame); + } else { + // Just invalidate our area: + nsSVGUtils::InvalidateCoveredRegion(aFrame); + } } else { aFrame->InvalidateOverflowRect(); } diff --git a/mobile/android/base/sync/CollectionKeys.java b/mobile/android/base/sync/CollectionKeys.java index 8a8f0903c9fc..f3a7a77f6028 100644 --- a/mobile/android/base/sync/CollectionKeys.java +++ b/mobile/android/base/sync/CollectionKeys.java @@ -42,7 +42,6 @@ import java.io.UnsupportedEncodingException; import java.util.HashMap; import java.util.Map.Entry; -import org.json.JSONException; import org.json.simple.JSONArray; import org.json.simple.parser.ParseException; import org.mozilla.apache.commons.codec.binary.Base64; @@ -101,11 +100,6 @@ public class CollectionKeys { /** * Take a pair of values in a JSON array, handing them off to KeyBundle to * produce a usable keypair. - * - * @param array - * @return - * @throws JSONException - * @throws UnsupportedEncodingException */ private static KeyBundle arrayToKeyBundle(JSONArray array) throws UnsupportedEncodingException { String encKeyStr = (String) array.get(0); @@ -168,14 +162,6 @@ public class CollectionKeys { /** * Take a downloaded record, and the Sync Key, decrypting the record and * setting our own keys accordingly. - * - * @param keys - * @param syncKeyBundle - * @throws CryptoException - * @throws IOException - * @throws ParseException - * @throws NonObjectJSONException - * @throws JSONException */ public void setKeyPairsFromWBO(CryptoRecord keys, KeyBundle syncKeyBundle) throws CryptoException, diff --git a/mobile/android/base/sync/HTTPFailureException.java b/mobile/android/base/sync/HTTPFailureException.java index cb7e5845c152..6fbb2a300e18 100644 --- a/mobile/android/base/sync/HTTPFailureException.java +++ b/mobile/android/base/sync/HTTPFailureException.java @@ -51,11 +51,12 @@ public class HTTPFailureException extends SyncException { @Override public String toString() { - String errorMessage = "[unknown error message]"; + String errorMessage; try { errorMessage = this.response.getErrorMessage(); } catch (Exception e) { // Oh well. + errorMessage = "[unknown error message]"; } return ""; diff --git a/mobile/android/base/sync/SyncConfiguration.java b/mobile/android/base/sync/SyncConfiguration.java index b0019136965b..145ae1a58655 100644 --- a/mobile/android/base/sync/SyncConfiguration.java +++ b/mobile/android/base/sync/SyncConfiguration.java @@ -193,9 +193,6 @@ public class SyncConfiguration implements CredentialsSource { /** * Create a new SyncConfiguration instance. Pass in a PrefsSource to * provide access to preferences. - * - * @param prefsPath - * @param prefsSource */ public SyncConfiguration(String prefsPath, PrefsSource prefsSource) { this.prefsPath = prefsPath; @@ -210,7 +207,6 @@ public class SyncConfiguration implements CredentialsSource { /** * Return a convenient accessor for part of prefs. - * @param prefix * @return * A ConfigurationBranch object representing this * section of the preferences space. diff --git a/mobile/android/base/sync/Utils.java b/mobile/android/base/sync/Utils.java index 66e3c4bba1f0..d4d16b88bb22 100644 --- a/mobile/android/base/sync/Utils.java +++ b/mobile/android/base/sync/Utils.java @@ -69,10 +69,11 @@ public class Utils { return new String(encodedBytes).replace("+", "-").replace("/", "_"); } - /* + /** * Helper to generate secure random bytes. * - * @param length Number of bytes to generate. + * @param length + * Number of bytes to generate. */ public static byte[] generateRandomBytes(int length) { byte[] bytes = new byte[length]; @@ -80,10 +81,11 @@ public class Utils { return bytes; } - /* + /** * Helper to generate a random integer in a specified range. * - * @param r Generate an integer between 0 and r-1 inclusive. + * @param r + * Generate an integer between 0 and r-1 inclusive. */ public static BigInteger generateBigIntegerLessThan(BigInteger r) { int maxBytes = (int) Math.ceil(((double) r.bitLength()) / 8); @@ -91,17 +93,15 @@ public class Utils { return randInt.mod(r); } - /* + /** * Helper to reseed the shared secure random number generator. */ public static void reseedSharedRandom() { sharedSecureRandom.setSeed(sharedSecureRandom.generateSeed(8)); } - /* - * Helper to convert Byte Array to a Hex String - * Input: byte[] array - * Output: Hex string + /** + * Helper to convert a byte array to a hex-encoded string */ public static String byte2hex(byte[] b) { // StringBuffer should be used instead. @@ -125,11 +125,6 @@ public class Utils { return hs; } - /* - * Helper for array concatenation. - * Input: At least two byte[] - * Output: A concatenated version of them - */ public static byte[] concatAll(byte[] first, byte[]... rest) { int totalLength = first.length; for (byte[] array : rest) { @@ -163,20 +158,12 @@ public class Utils { return Base64.decodeBase64(base64.getBytes("UTF-8")); } - /* - * Decode a friendly base32 string. - */ public static byte[] decodeFriendlyBase32(String base32) { Base32 converter = new Base32(); final String translated = base32.replace('8', 'l').replace('9', 'o'); return converter.decode(translated.toUpperCase()); } - /* - * Helper to convert Hex String to Byte Array - * Input: Hex string - * Output: byte[] version of hex string - */ public static byte[] hex2Byte(String str) { if (str.length() % 2 == 1) { str = "0" + str; @@ -247,10 +234,6 @@ public class Utils { /** * Yes, an equality method that's null-safe. - * - * @param a - * @param b - * @return */ private static boolean same(Object a, Object b) { if (a == b) { @@ -265,10 +248,6 @@ public class Utils { /** * Return true if the two arrays are both null, or are both arrays * containing the same elements in the same order. - * - * @param a - * @param b - * @return */ public static boolean sameArrays(JSONArray a, JSONArray b) { if (a == b) { diff --git a/mobile/android/base/sync/crypto/KeyBundle.java b/mobile/android/base/sync/crypto/KeyBundle.java index ce149993a3f3..c05fa7870293 100644 --- a/mobile/android/base/sync/crypto/KeyBundle.java +++ b/mobile/android/base/sync/crypto/KeyBundle.java @@ -46,7 +46,6 @@ import javax.crypto.Mac; import org.mozilla.apache.commons.codec.binary.Base64; import org.mozilla.gecko.sync.Utils; -import org.mozilla.gecko.sync.crypto.CryptoException; import java.security.InvalidKeyException; import java.util.Locale; diff --git a/mobile/android/base/sync/jpake/JPakeCrypto.java b/mobile/android/base/sync/jpake/JPakeCrypto.java index d3f5104b71eb..2c4bb6bc4cdf 100644 --- a/mobile/android/base/sync/jpake/JPakeCrypto.java +++ b/mobile/android/base/sync/jpake/JPakeCrypto.java @@ -98,10 +98,6 @@ public class JPakeCrypto { * * Round 1 of J-PAKE protocol. * Generate x1, x2, and ZKP for other party. - * - * @param mySignerId - * @param valuesOut - * @throws NoSuchAlgorithmException */ public static void round1(JPakeParty jp, JPakeNumGenerator gen) throws NoSuchAlgorithmException, UnsupportedEncodingException { // Randomly select x1 from [0,q), x2 from [1,q). @@ -124,16 +120,6 @@ public class JPakeCrypto { * Round 2 of J-PAKE protocol. * Generate A and ZKP for A. * Verify ZKP from other party. Does not check for replay ZKP. - * - * @param mySignerId - * @param valuesOut - * @param secret - * @param gx3 - * @param gx4 - * @param zkp3 - * @param zkp4 - * @throws IncorrectZkpException - * @throws NoSuchAlgorithmException */ public static void round2(BigInteger secretValue, JPakeParty jp, JPakeNumGenerator gen) throws IncorrectZkpException, NoSuchAlgorithmException, @@ -164,13 +150,6 @@ public class JPakeCrypto { /** * Final round of J-PAKE protocol. - * - * @param b - * @param zkp - * @param secret - * - * @return KeyBundle - * @throws IncorrectZkpException */ public static KeyBundle finalRound(BigInteger secretValue, JPakeParty jp) throws IncorrectZkpException, NoSuchAlgorithmException, InvalidKeyException, UnsupportedEncodingException { diff --git a/mobile/android/base/sync/jpake/stage/GetChannelStage.java b/mobile/android/base/sync/jpake/stage/GetChannelStage.java index 7efd92dd3700..5ac2ccfed728 100644 --- a/mobile/android/base/sync/jpake/stage/GetChannelStage.java +++ b/mobile/android/base/sync/jpake/stage/GetChannelStage.java @@ -54,14 +54,12 @@ public class GetChannelStage extends JPakeStage { public void handleFailure(String error) { Logger.error(LOG_TAG, "Got HTTP failure: " + error); jClient.abort(error); - return; } @Override public void handleError(Exception e) { Logger.error(LOG_TAG, "Threw HTTP exception.", e); jClient.abort(Constants.JPAKE_ERROR_CHANNEL); - return; } }; diff --git a/mobile/android/base/sync/jpake/stage/GetRequestStage.java b/mobile/android/base/sync/jpake/stage/GetRequestStage.java index d697e6e624b9..c571e157a783 100644 --- a/mobile/android/base/sync/jpake/stage/GetRequestStage.java +++ b/mobile/android/base/sync/jpake/stage/GetRequestStage.java @@ -75,14 +75,12 @@ public class GetRequestStage extends JPakeStage { public void handleFailure(String error) { Logger.error(LOG_TAG, "Got HTTP failure: " + error); jClient.abort(error); - return; } @Override public void handleError(Exception e) { Logger.error(LOG_TAG, "Threw HTTP exception.", e); jClient.abort(Constants.JPAKE_ERROR_NETWORK); - return; } }; diff --git a/mobile/android/base/sync/jpake/stage/PutRequestStage.java b/mobile/android/base/sync/jpake/stage/PutRequestStage.java index bdf0c2e7fa6e..6264906f857c 100644 --- a/mobile/android/base/sync/jpake/stage/PutRequestStage.java +++ b/mobile/android/base/sync/jpake/stage/PutRequestStage.java @@ -60,14 +60,12 @@ public class PutRequestStage extends JPakeStage { public void handleFailure(String error) { Logger.error(LOG_TAG, "Got HTTP failure: " + error); jClient.abort(error); - return; } @Override public void handleError(Exception e) { Logger.error(LOG_TAG, "HTTP exception.", e); jClient.abort(Constants.JPAKE_ERROR_NETWORK); - return; } }; diff --git a/mobile/android/base/sync/net/BaseResource.java b/mobile/android/base/sync/net/BaseResource.java index 999094df150e..53884ec4aa09 100644 --- a/mobile/android/base/sync/net/BaseResource.java +++ b/mobile/android/base/sync/net/BaseResource.java @@ -82,6 +82,8 @@ import ch.boye.httpclientandroidlib.protocol.HttpContext; * Exposes simple get/post/put/delete methods. */ public class BaseResource implements Resource { + private static final String ANDROID_LOOPBACK_IP = "10.0.2.2"; + public static boolean rewriteLocalhost = true; private static final String LOG_TAG = "BaseResource"; @@ -107,9 +109,9 @@ public class BaseResource implements Resource { public BaseResource(URI uri, boolean rewrite) { if (rewrite && uri.getHost().equals("localhost")) { // Rewrite localhost URIs to refer to the special Android emulator loopback passthrough interface. - Log.d(LOG_TAG, "Rewriting " + uri + " to point to 10.0.2.2."); + Log.d(LOG_TAG, "Rewriting " + uri + " to point to " + ANDROID_LOOPBACK_IP + "."); try { - this.uri = new URI(uri.getScheme(), uri.getUserInfo(), "10.0.2.2", uri.getPort(), uri.getPath(), uri.getQuery(), uri.getFragment()); + this.uri = new URI(uri.getScheme(), uri.getUserInfo(), ANDROID_LOOPBACK_IP, uri.getPort(), uri.getPath(), uri.getQuery(), uri.getFragment()); } catch (URISyntaxException e) { Log.e(LOG_TAG, "Got error rewriting URI for Android emulator.", e); } @@ -167,7 +169,6 @@ public class BaseResource implements Resource { /** * This method exists for test code. - * @return */ public static ClientConnectionManager enablePlainHTTPConnectionManager() { synchronized (connManagerMonitor) { diff --git a/mobile/android/base/sync/net/SyncResponse.java b/mobile/android/base/sync/net/SyncResponse.java index 5a6a8ea2ffad..4d7bb1976756 100644 --- a/mobile/android/base/sync/net/SyncResponse.java +++ b/mobile/android/base/sync/net/SyncResponse.java @@ -148,9 +148,9 @@ public class SyncResponse { } /** - * @return A number of seconds, or -1 if the header was not present. + * @return A number of seconds, or -1 if the 'Retry-After' header was not present. */ - public int retryAfter() throws NumberFormatException { + public int retryAfterInSeconds() throws NumberFormatException { if (!this.hasHeader(HEADER_RETRY_AFTER)) { return -1; } @@ -178,10 +178,39 @@ public class SyncResponse { } } - public int weaveBackoff() throws NumberFormatException { + /** + * @return A number of seconds, or -1 if the 'X-Weave-Backoff' header was not + * present. + */ + public int weaveBackoffInSeconds() throws NumberFormatException { return this.getIntegerHeader("x-weave-backoff"); } + /** + * @return A number of milliseconds, or -1 if neither the 'Retry-After' or + * 'X-Weave-Backoff' header was present. + */ + public int totalBackoffInMilliseconds() { + int retryAfterInSeconds = -1; + try { + retryAfterInSeconds = retryAfterInSeconds(); + } catch (NumberFormatException e) { + } + + int weaveBackoffInSeconds = -1; + try { + weaveBackoffInSeconds = weaveBackoffInSeconds(); + } catch (NumberFormatException e) { + } + + int totalBackoff = Math.max(retryAfterInSeconds, weaveBackoffInSeconds); + if (totalBackoff < 0) { + return -1; + } else { + return 1000 * totalBackoff; + } + } + /** * The timestamp returned from a Sync server is a decimal number of seconds, * e.g., 1323393518.04. diff --git a/mobile/android/base/sync/net/SyncStorageRecordRequest.java b/mobile/android/base/sync/net/SyncStorageRecordRequest.java index bb303249e200..5987ee46aaf3 100644 --- a/mobile/android/base/sync/net/SyncStorageRecordRequest.java +++ b/mobile/android/base/sync/net/SyncStorageRecordRequest.java @@ -90,8 +90,6 @@ public class SyncStorageRecordRequest extends SyncStorageRequest { /** * Helper for turning a JSON object into a payload. - * @param body - * @return * @throws UnsupportedEncodingException */ protected StringEntity jsonEntity(JSONObject body) throws UnsupportedEncodingException { diff --git a/mobile/android/base/sync/repositories/RepositorySession.java b/mobile/android/base/sync/repositories/RepositorySession.java index 443b763c0292..205735b26892 100644 --- a/mobile/android/base/sync/repositories/RepositorySession.java +++ b/mobile/android/base/sync/repositories/RepositorySession.java @@ -209,9 +209,6 @@ public abstract class RepositorySession { * * The Synchronizer most likely wants to bump the bundle timestamp to be a value * return from a fetch call. - * - * @param optional - * @return */ protected RepositorySessionBundle getBundle(RepositorySessionBundle optional) { Logger.debug(LOG_TAG, "RepositorySession.getBundle(optional)."); @@ -225,8 +222,6 @@ public abstract class RepositorySession { /** * Just like finish(), but doesn't do any work that should only be performed * at the end of a successful sync, and can be called any time. - * - * @param delegate */ public void abort(RepositorySessionFinishDelegate delegate) { this.abort(); @@ -267,9 +262,6 @@ public abstract class RepositorySession { /** * Run the provided command if we're active and our delegate queue * is not shut down. - * - * @param command - * @throws InactiveSessionException */ protected synchronized void executeDelegateCommand(Runnable command) throws InactiveSessionException { @@ -389,8 +381,6 @@ public abstract class RepositorySession { * redundantly. * * The default implementation does nothing. - * - * @param record */ protected synchronized void trackRecord(Record record) { } diff --git a/mobile/android/base/sync/repositories/android/AndroidBrowserBookmarksDataAccessor.java b/mobile/android/base/sync/repositories/android/AndroidBrowserBookmarksDataAccessor.java index 35c21e4518dd..e9b623ab1bb6 100644 --- a/mobile/android/base/sync/repositories/android/AndroidBrowserBookmarksDataAccessor.java +++ b/mobile/android/base/sync/repositories/android/AndroidBrowserBookmarksDataAccessor.java @@ -100,10 +100,6 @@ public class AndroidBrowserBookmarksDataAccessor extends AndroidBrowserRepositor /** * Bump the modified time of a record by ID. - * - * @param id - * @param modified - * @return */ public int bumpModified(long id, long modified) { Logger.debug(LOG_TAG, "Bumping modified for " + id + " to " + modified); diff --git a/mobile/android/base/sync/repositories/android/AndroidBrowserBookmarksRepositorySession.java b/mobile/android/base/sync/repositories/android/AndroidBrowserBookmarksRepositorySession.java index 8f0044c04e9b..3fa15fbe5812 100644 --- a/mobile/android/base/sync/repositories/android/AndroidBrowserBookmarksRepositorySession.java +++ b/mobile/android/base/sync/repositories/android/AndroidBrowserBookmarksRepositorySession.java @@ -172,9 +172,6 @@ public class AndroidBrowserBookmarksRepositorySession extends AndroidBrowserRepo /** * Return true if the provided record GUID should be skipped * in child lists or fetch results. - * - * @param recordGUID - * @return */ public static boolean forbiddenGUID(String recordGUID) { return recordGUID == null || diff --git a/mobile/android/base/sync/repositories/android/AndroidBrowserRepositorySession.java b/mobile/android/base/sync/repositories/android/AndroidBrowserRepositorySession.java index 37beaa02972e..8505f423b75a 100644 --- a/mobile/android/base/sync/repositories/android/AndroidBrowserRepositorySession.java +++ b/mobile/android/base/sync/repositories/android/AndroidBrowserRepositorySession.java @@ -101,8 +101,6 @@ public abstract class AndroidBrowserRepositorySession extends StoreTrackingRepos * * Return null if this record should not be processed. * - * @param cur - * @return * @throws NoGuidForIdException * @throws NullCursorException * @throws ParentNotFoundException @@ -114,8 +112,6 @@ public abstract class AndroidBrowserRepositorySession extends StoreTrackingRepos * updated to match the record that we're constructing: for example, the children * of a folder might be repositioned as we generate the folder's record. * - * @param cur - * @return * @throws NoGuidForIdException * @throws NullCursorException * @throws ParentNotFoundException @@ -555,8 +551,6 @@ public abstract class AndroidBrowserRepositorySession extends StoreTrackingRepos * Retrieve a record from the store by GUID, without writing unnecessarily to the * database. * - * @param guid - * @return * @throws NoGuidForIdException * @throws NullCursorException * @throws ParentNotFoundException diff --git a/mobile/android/base/sync/repositories/delegates/RepositorySessionFetchRecordsDelegate.java b/mobile/android/base/sync/repositories/delegates/RepositorySessionFetchRecordsDelegate.java index 5983f13d2794..a27f5a2d4bcd 100644 --- a/mobile/android/base/sync/repositories/delegates/RepositorySessionFetchRecordsDelegate.java +++ b/mobile/android/base/sync/repositories/delegates/RepositorySessionFetchRecordsDelegate.java @@ -1,40 +1,6 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Android Sync Client. - * - * The Initial Developer of the Original Code is - * the Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2011 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Jason Voll - * Richard Newman - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ +/* 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/. */ package org.mozilla.gecko.sync.repositories.delegates; @@ -49,7 +15,7 @@ public interface RepositorySessionFetchRecordsDelegate { /** * Called when all records in this fetch have been returned. * - * @param end + * @param fetchEnd * A millisecond-resolution timestamp indicating the *remote* timestamp * at the end of the range of records. Usually this is the timestamp at * which the request was received. @@ -57,8 +23,19 @@ public interface RepositorySessionFetchRecordsDelegate { */ public void onFetchCompleted(final long fetchEnd); - // Shorthand for calling onFetchedRecord for each record in turn, then - // calling onFetchCompleted. + /** + * Shorthand for calling onFetchedRecord for each record in turn, then + * calling onFetchCompleted. + * + * @param records + * An array of fetched records. Can be empty. + * + * @param fetchEnd + * A millisecond-resolution timestamp indicating the *remote* timestamp + * at the end of the range of records. Usually this is the timestamp at + * which the request was received. + * E.g., the (normalized) value of the X-Weave-Timestamp header. + */ public void onFetchSucceeded(Record[] records, final long fetchEnd); public RepositorySessionFetchRecordsDelegate deferredFetchDelegate(ExecutorService executor); diff --git a/mobile/android/base/sync/repositories/domain/Record.java b/mobile/android/base/sync/repositories/domain/Record.java index 4ce59b4b6c17..c0eae5ab7fc8 100644 --- a/mobile/android/base/sync/repositories/domain/Record.java +++ b/mobile/android/base/sync/repositories/domain/Record.java @@ -118,9 +118,6 @@ public abstract class Record { /** * Return true iff the input is a Record and has the same * collection and guid as this object. - * - * @param o - * @return */ public boolean equalIdentifiers(Object o) { if (o == null || !(o instanceof Record)) { diff --git a/mobile/android/base/sync/repositories/domain/TabsRecord.java b/mobile/android/base/sync/repositories/domain/TabsRecord.java index 4b9b7c47410a..e2726da1958e 100644 --- a/mobile/android/base/sync/repositories/domain/TabsRecord.java +++ b/mobile/android/base/sync/repositories/domain/TabsRecord.java @@ -12,7 +12,6 @@ import org.mozilla.gecko.sync.ExtendedJSONObject; import org.mozilla.gecko.sync.Logger; import org.mozilla.gecko.sync.NonArrayJSONException; import org.mozilla.gecko.sync.Utils; -import org.mozilla.gecko.sync.repositories.domain.Record; /** * Represents a client's collection of tabs. diff --git a/mobile/android/base/sync/setup/activities/AccountActivity.java b/mobile/android/base/sync/setup/activities/AccountActivity.java index 03c749f4ac4c..9809683095e4 100644 --- a/mobile/android/base/sync/setup/activities/AccountActivity.java +++ b/mobile/android/base/sync/setup/activities/AccountActivity.java @@ -213,11 +213,25 @@ public class AccountActivity extends AccountAuthenticatorActivity { userbundle.putString(Constants.OPTION_SERVER, DEFAULT_SERVER); } Log.d(LOG_TAG, "Adding account for " + Constants.ACCOUNTTYPE_SYNC); - boolean result = accountManager.addAccountExplicitly(account, password, userbundle); + boolean result = false; + try { + result = accountManager.addAccountExplicitly(account, password, userbundle); + } catch (SecurityException e) { + final String message = e.getMessage(); + if (message != null && (message.indexOf("is different than the authenticator's uid") > 0)) { + Log.wtf("FirefoxSync", + "Unable to create account. " + + "If you have more than one version of " + + "Firefox/Beta/Aurora/Nightly/Fennec installed, that's why.", + e); + } else { + Log.e("FirefoxSync", "Unable to create account.", e); + } + } Log.d(LOG_TAG, "Account: " + account + " added successfully? " + result); if (!result) { - Log.e(LOG_TAG, "Error adding account!"); + Log.e(LOG_TAG, "Failed to add account!"); } // Set components to sync (default: all). diff --git a/mobile/android/base/sync/stage/AndroidBrowserBookmarksServerSyncStage.java b/mobile/android/base/sync/stage/AndroidBrowserBookmarksServerSyncStage.java index 4ab79d634c73..be0697f01fc1 100644 --- a/mobile/android/base/sync/stage/AndroidBrowserBookmarksServerSyncStage.java +++ b/mobile/android/base/sync/stage/AndroidBrowserBookmarksServerSyncStage.java @@ -52,11 +52,6 @@ public class AndroidBrowserBookmarksServerSyncStage extends ServerSyncStage { private static final String BOOKMARKS_SORT = "index"; private static final long BOOKMARKS_REQUEST_LIMIT = 5000; // Sanity limit. - @Override - public void execute(org.mozilla.gecko.sync.GlobalSession session) throws NoSuchStageException { - super.execute(session); - } - @Override protected String getCollection() { return "bookmarks"; diff --git a/mobile/android/base/sync/stage/AndroidBrowserHistoryServerSyncStage.java b/mobile/android/base/sync/stage/AndroidBrowserHistoryServerSyncStage.java index ab52ff13060a..13bdc81dde62 100644 --- a/mobile/android/base/sync/stage/AndroidBrowserHistoryServerSyncStage.java +++ b/mobile/android/base/sync/stage/AndroidBrowserHistoryServerSyncStage.java @@ -52,11 +52,6 @@ public class AndroidBrowserHistoryServerSyncStage extends ServerSyncStage { private static final String HISTORY_SORT = "index"; private static final long HISTORY_REQUEST_LIMIT = 250; - @Override - public void execute(org.mozilla.gecko.sync.GlobalSession session) throws NoSuchStageException { - super.execute(session); - } - @Override protected String getCollection() { return "history"; diff --git a/mobile/android/base/sync/stage/ServerSyncStage.java b/mobile/android/base/sync/stage/ServerSyncStage.java index 6679ed088ae3..1f04c35f3598 100644 --- a/mobile/android/base/sync/stage/ServerSyncStage.java +++ b/mobile/android/base/sync/stage/ServerSyncStage.java @@ -95,10 +95,6 @@ public abstract class ServerSyncStage implements /** * Return a Crypto5Middleware-wrapped Server11Repository. * - * @param clusterURI - * @param data.username - * @param collection - * @return * @throws NoCollectionKeysSetException * @throws URISyntaxException */ diff --git a/security/manager/ssl/src/nsCrypto.cpp b/security/manager/ssl/src/nsCrypto.cpp index 1f532dc77f9c..3a5a7898864e 100644 --- a/security/manager/ssl/src/nsCrypto.cpp +++ b/security/manager/ssl/src/nsCrypto.cpp @@ -2164,7 +2164,6 @@ NS_IMETHODIMP nsCryptoRunnable::Run() { nsNSSShutDownPreventionLock locker; - JSPrincipals *principals; JSContext *cx = m_args->m_cx; JSAutoRequest ar(cx); @@ -2174,29 +2173,20 @@ nsCryptoRunnable::Run() return NS_ERROR_FAILURE; } - nsresult rv = m_args->m_principals->GetJSPrincipals(cx, &principals); - if (NS_FAILED(rv)) - return NS_ERROR_FAILURE; - // make sure the right context is on the stack. must not return w/out popping nsCOMPtr stack(do_GetService("@mozilla.org/js/xpc/ContextStack;1")); if (!stack || NS_FAILED(stack->Push(cx))) { - JSPRINCIPALS_DROP(cx, principals); return NS_ERROR_FAILURE; } - jsval retval; - if (JS_EvaluateScriptForPrincipals(cx, m_args->m_scope, principals, - m_args->m_jsCallback, - strlen(m_args->m_jsCallback), - nsnull, 0, - &retval) != JS_TRUE) { - rv = NS_ERROR_FAILURE; - } - + JSBool ok = + JS_EvaluateScriptForPrincipals(cx, m_args->m_scope, + nsJSPrincipals::get(m_args->m_principals), + m_args->m_jsCallback, + strlen(m_args->m_jsCallback), + nsnull, 0, nsnull); stack->Pop(nsnull); - JSPRINCIPALS_DROP(cx, principals); - return rv; + return ok ? NS_OK : NS_ERROR_FAILURE; } //Quick helper function to check if a newly issued cert diff --git a/storage/src/mozStorageService.cpp b/storage/src/mozStorageService.cpp index 4988ede95de8..0999d7faa033 100644 --- a/storage/src/mozStorageService.cpp +++ b/storage/src/mozStorageService.cpp @@ -194,9 +194,10 @@ public: // main thread! But at the time of writing this function is only called when // about:memory is loaded (not, for example, when telemetry pings occur) and // any delays in that case aren't so bad. - NS_IMETHOD CollectReports(nsIMemoryMultiReporterCallback *aCallback, + NS_IMETHOD CollectReports(nsIMemoryMultiReporterCallback *aCb, nsISupports *aClosure) { + nsresult rv; size_t totalConnSize = 0; { nsTArray > connections; @@ -218,29 +219,32 @@ public: SQLiteMutexAutoLock lockedScope(conn->sharedDBMutex); - totalConnSize += - doConnMeasurement(aCallback, aClosure, *conn.get(), pathHead, - NS_LITERAL_CSTRING("stmt"), mStmtDesc, - SQLITE_DBSTATUS_STMT_USED); - totalConnSize += - doConnMeasurement(aCallback, aClosure, *conn.get(), pathHead, - NS_LITERAL_CSTRING("cache"), mCacheDesc, - SQLITE_DBSTATUS_CACHE_USED); - totalConnSize += - doConnMeasurement(aCallback, aClosure, *conn.get(), pathHead, - NS_LITERAL_CSTRING("schema"), mSchemaDesc, - SQLITE_DBSTATUS_SCHEMA_USED); + rv = reportConn(aCb, aClosure, *conn.get(), pathHead, + NS_LITERAL_CSTRING("stmt"), mStmtDesc, + SQLITE_DBSTATUS_STMT_USED, &totalConnSize); + NS_ENSURE_SUCCESS(rv, rv); + + rv = reportConn(aCb, aClosure, *conn.get(), pathHead, + NS_LITERAL_CSTRING("cache"), mCacheDesc, + SQLITE_DBSTATUS_CACHE_USED, &totalConnSize); + NS_ENSURE_SUCCESS(rv, rv); + + rv = reportConn(aCb, aClosure, *conn.get(), pathHead, + NS_LITERAL_CSTRING("schema"), mSchemaDesc, + SQLITE_DBSTATUS_SCHEMA_USED, &totalConnSize); + NS_ENSURE_SUCCESS(rv, rv); } } PRInt64 other = ::sqlite3_memory_used() - totalConnSize; - aCallback->Callback(NS_LITERAL_CSTRING(""), - NS_LITERAL_CSTRING("explicit/storage/sqlite/other"), - nsIMemoryReporter::KIND_HEAP, - nsIMemoryReporter::UNITS_BYTES, other, - NS_LITERAL_CSTRING("All unclassified sqlite memory."), - aClosure); + rv = aCb->Callback(NS_LITERAL_CSTRING(""), + NS_LITERAL_CSTRING("explicit/storage/sqlite/other"), + nsIMemoryReporter::KIND_HEAP, + nsIMemoryReporter::UNITS_BYTES, other, + NS_LITERAL_CSTRING("All unclassified sqlite memory."), + aClosure); + NS_ENSURE_SUCCESS(rv, rv); return NS_OK; } @@ -272,14 +276,17 @@ private: * The memory report description. * @param aOption * The SQLite constant for getting the measurement. + * @param aTotal + * The accumulator for the measurement. */ - size_t doConnMeasurement(nsIMemoryMultiReporterCallback *aCallback, - nsISupports *aClosure, - sqlite3 *aConn, - const nsACString &aPathHead, - const nsACString &aKind, - const nsACString &aDesc, - int aOption) + nsresult reportConn(nsIMemoryMultiReporterCallback *aCb, + nsISupports *aClosure, + sqlite3 *aConn, + const nsACString &aPathHead, + const nsACString &aKind, + const nsACString &aDesc, + int aOption, + size_t *aTotal) { nsCString path(aPathHead); path.Append(aKind); @@ -290,11 +297,14 @@ private: nsresult rv = convertResultCode(rc); NS_ENSURE_SUCCESS(rv, rv); - aCallback->Callback(NS_LITERAL_CSTRING(""), path, - nsIMemoryReporter::KIND_HEAP, - nsIMemoryReporter::UNITS_BYTES, PRInt64(curr), - aDesc, aClosure); - return curr; + rv = aCb->Callback(NS_LITERAL_CSTRING(""), path, + nsIMemoryReporter::KIND_HEAP, + nsIMemoryReporter::UNITS_BYTES, PRInt64(curr), + aDesc, aClosure); + NS_ENSURE_SUCCESS(rv, rv); + *aTotal += curr; + + return NS_OK; } }; diff --git a/testing/xpcshell/xpcshell.ini b/testing/xpcshell/xpcshell.ini index 0221cd8e02db..2af59639ded9 100644 --- a/testing/xpcshell/xpcshell.ini +++ b/testing/xpcshell/xpcshell.ini @@ -72,6 +72,7 @@ skip-if = os == "android" skip-if = os == "android" [include:browser/components/dirprovider/tests/unit/xpcshell.ini] [include:browser/components/feeds/test/unit/xpcshell.ini] +[include:browser/components/migration/tests/unit/xpcshell.ini] [include:browser/components/places/tests/unit/xpcshell.ini] [include:browser/components/privatebrowsing/test/unit/xpcshell.ini] [include:browser/components/shell/test/unit/xpcshell.ini] diff --git a/toolkit/components/places/nsLivemarkService.js b/toolkit/components/places/nsLivemarkService.js index 6fed537352f2..da44f4f5a519 100644 --- a/toolkit/components/places/nsLivemarkService.js +++ b/toolkit/components/places/nsLivemarkService.js @@ -877,7 +877,7 @@ Livemark.prototype = { QueryInterface(Ci.nsIHttpChannel); channel.loadGroup = loadgroup; channel.loadFlags |= Ci.nsIRequest.LOAD_BACKGROUND | - Ci.nsIRequest.VALIDATE_ALWAYS; + Ci.nsIRequest.LOAD_BYPASS_CACHE; channel.requestMethod = "GET"; channel.setRequestHeader("X-Moz", "livebookmarks", false); diff --git a/toolkit/components/places/tests/chrome/test_reloadLivemarks.xul b/toolkit/components/places/tests/chrome/test_reloadLivemarks.xul index ab36f1ed7482..8b0a66261bd9 100644 --- a/toolkit/components/places/tests/chrome/test_reloadLivemarks.xul +++ b/toolkit/components/places/tests/chrome/test_reloadLivemarks.xul @@ -5,7 +5,7 @@ + onload="runTest()" onunload="cleanup()"> @@ -42,12 +42,6 @@ let gLivemarks = [ function runTest() { - if (navigator.platform.indexOf("Lin") != -1) { - ok(true, "Bug 734044: This test is disabled on Linux for random timeouts."); - SimpleTest.finish(); - return; - } - addLivemarks(function () { reloadLivemarks(false, function () { reloadLivemarks(true, function () { @@ -132,11 +126,23 @@ resultObserver.prototype = { if (this._livemark.status == Ci.mozILivemark.STATUS_LOADING) return; - this._livemark.unregisterForUpdates(this._node); + this._terminate(); this._callback(); + }, + _terminate: function () { + if (!this._terminated) { + this._livemark.unregisterForUpdates(this._node); + this._terminated = true; + } } }; +function cleanup() { + gLivemarks.forEach(function(aLivemarkData) { + if (aLivemarkData._observer) + aLivemarkData._observer._terminate(); + }); +} ]]> diff --git a/toolkit/content/Makefile.in b/toolkit/content/Makefile.in index 11c1ab5d00eb..50d633c9b5fe 100644 --- a/toolkit/content/Makefile.in +++ b/toolkit/content/Makefile.in @@ -55,6 +55,8 @@ DEFINES += \ -DCXX_VERSION="$(CXX_VERSION)" \ -DCXXFLAGS="$(CXXFLAGS)" \ -DCPPFLAGS="$(CPPFLAGS)" \ + -DMOZ_APP_NAME=$(MOZ_APP_NAME) \ + -DMOZ_BUILD_APP=$(MOZ_BUILD_APP) \ $(NULL) MOZ_SOURCE_STAMP ?= $(shell hg -R $(topsrcdir) parent --template="{node|short}\n" 2>/dev/null) diff --git a/toolkit/content/aboutSupport.js b/toolkit/content/aboutSupport.js index 1e648dad65da..8fbb2eb198a3 100644 --- a/toolkit/content/aboutSupport.js +++ b/toolkit/content/aboutSupport.js @@ -38,6 +38,7 @@ const Cc = Components.classes; const Ci = Components.interfaces; +const Cu = Components.utils; Components.utils.import("resource://gre/modules/AddonManager.jsm"); Components.utils.import("resource://gre/modules/Services.jsm"); @@ -113,6 +114,7 @@ window.onload = function () { document.getElementById("version-box").textContent = version; // Update the other sections. + populateResetBox(); populatePreferencesSection(); populateExtensionsSection(); populateGraphicsSection(); @@ -561,3 +563,51 @@ function openProfileDirectory() { "nsILocalFile", "initWithPath"); new nsLocalFile(profileDir).reveal(); } + +/** + * Profile reset is only supported for the default profile if the appropriate migrator exists. + */ +function populateResetBox() { + let profileService = Cc["@mozilla.org/toolkit/profile-service;1"] + .getService(Ci.nsIToolkitProfileService); + let currentProfileDir = Services.dirsvc.get("ProfD", Ci.nsIFile); + +#expand const MOZ_APP_NAME = "__MOZ_APP_NAME__"; +#expand const MOZ_BUILD_APP = "__MOZ_BUILD_APP__"; + + // Only show the reset box for the default profile if the self-migrator used for reset exists. + try { + if (!currentProfileDir.equals(profileService.selectedProfile.rootDir) || + !("@mozilla.org/profile/migrator;1?app=" + MOZ_BUILD_APP + "&type=" + MOZ_APP_NAME in Cc)) + return; + document.getElementById("reset-box").style.visibility = "visible"; + } catch (e) { + // Catch exception when there is no selected profile. + Cu.reportError(e); + } +} + +/** + * Restart the application to reset the profile. + */ +function resetProfileAndRestart() { + let branding = Services.strings.createBundle("chrome://branding/locale/brand.properties"); + let brandShortName = branding.GetStringFromName("brandShortName"); + + // Prompt the user to confirm. + let retVals = { + reset: false, + }; + window.openDialog("chrome://global/content/resetProfile.xul", null, + "chrome,modal,centerscreen,titlebar,dialog=yes", retVals); + if (!retVals.reset) + return; + + // Set the reset profile environment variable. + let env = Cc["@mozilla.org/process/environment;1"] + .getService(Ci.nsIEnvironment); + env.set("MOZ_RESET_PROFILE_RESTART", "1"); + + let appStartup = Cc["@mozilla.org/toolkit/app-startup;1"].getService(Ci.nsIAppStartup); + appStartup.quit(Ci.nsIAppStartup.eForceQuit | Ci.nsIAppStartup.eRestart); +} diff --git a/toolkit/content/aboutSupport.xhtml b/toolkit/content/aboutSupport.xhtml index e92194bdcc63..a392b9a14240 100644 --- a/toolkit/content/aboutSupport.xhtml +++ b/toolkit/content/aboutSupport.xhtml @@ -42,6 +42,7 @@ %globalDTD; %brandDTD; %aboutSupportDTD; + %resetProfileDTD; ]> @@ -57,6 +58,14 @@ +

+

&aboutSupport.pageTitle;

diff --git a/toolkit/content/jar.mn b/toolkit/content/jar.mn index afc8549acd06..6f0d2d6367ff 100644 --- a/toolkit/content/jar.mn +++ b/toolkit/content/jar.mn @@ -37,6 +37,9 @@ toolkit.jar: *+ content/global/globalOverlay.js (globalOverlay.js) + content/global/mozilla.xhtml (mozilla.xhtml) *+ content/global/nsDragAndDrop.js (nsDragAndDrop.js) + content/global/resetProfile.css (resetProfile.css) +* content/global/resetProfile.js (resetProfile.js) +* content/global/resetProfile.xul (resetProfile.xul) * content/global/treeUtils.js (treeUtils.js) *+ content/global/viewZoomOverlay.js (viewZoomOverlay.js) *+ content/global/bindings/autocomplete.xml (widgets/autocomplete.xml) diff --git a/toolkit/content/resetProfile.css b/toolkit/content/resetProfile.css new file mode 100644 index 000000000000..2a8114801a67 --- /dev/null +++ b/toolkit/content/resetProfile.css @@ -0,0 +1,11 @@ +/* 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/. */ + +#migratedItems { + -moz-margin-start: 1.5em; +} + +#resetProfileFooter { + font-weight: bold; +} diff --git a/toolkit/content/resetProfile.js b/toolkit/content/resetProfile.js new file mode 100644 index 000000000000..975a9edcb64e --- /dev/null +++ b/toolkit/content/resetProfile.js @@ -0,0 +1,35 @@ +/* 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/. */ + +Components.utils.import("resource://gre/modules/Services.jsm"); + +// based on onImportItemsPageShow from migration.js +function onResetProfileLoad() { +#expand const MOZ_BUILD_APP = "__MOZ_BUILD_APP__"; +#expand const MOZ_APP_NAME = "__MOZ_APP_NAME__"; + const MAX_MIGRATED_TYPES = 16; + + var migratedItems = document.getElementById("migratedItems"); + var bundle = Services.strings.createBundle("chrome://" + MOZ_BUILD_APP + + "/locale/migration/migration.properties"); + + // Loop over possible data to migrate to give the user a list of what will be preserved. This + // assumes that if the string for the data exists then it will be migrated since calling + // getMigrateData now won't give the correct result. + for (var i = 1; i < MAX_MIGRATED_TYPES; ++i) { + var itemID = Math.pow(2, i); + try { + var checkbox = document.createElement("label"); + checkbox.setAttribute("value", bundle.GetStringFromName(itemID + "_" + MOZ_APP_NAME)); + migratedItems.appendChild(checkbox); + } catch (x) { + // Catch exceptions when the string for a data type doesn't exist because it's not migrated + } + } +} + +function onResetProfileAccepted() { + var retVals = window.arguments[0]; + retVals.reset = true; +} diff --git a/toolkit/content/resetProfile.xul b/toolkit/content/resetProfile.xul new file mode 100644 index 000000000000..bd2ee2627b13 --- /dev/null +++ b/toolkit/content/resetProfile.xul @@ -0,0 +1,36 @@ + + +# 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/. + + +%brandDTD; + +%resetProfileDTD; +]> + + + + + + +