From 74f28e30ee9f97a7140db26f881e932125b006b4 Mon Sep 17 00:00:00 2001 From: Mike Hommey Date: Tue, 26 Mar 2013 11:07:02 +0100 Subject: [PATCH 001/129] Bug 854085 - Fix unused-but-set-variable from ASSERT_ON_THREAD macro in media/mtransport/runnable_utils.h. r=jesup --- media/mtransport/runnable_utils.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/media/mtransport/runnable_utils.h b/media/mtransport/runnable_utils.h index a1c79dce5e93..b63f6f32fb74 100644 --- a/media/mtransport/runnable_utils.h +++ b/media/mtransport/runnable_utils.h @@ -54,6 +54,7 @@ static inline nsresult RUN_ON_THREAD(nsIEventTarget *thread, nsIRunnable *runnab return runnable_ref->Run(); } +#ifdef MOZ_DEBUG #define ASSERT_ON_THREAD(t) do { \ if (t) { \ bool on; \ @@ -63,7 +64,10 @@ static inline nsresult RUN_ON_THREAD(nsIEventTarget *thread, nsIRunnable *runnab MOZ_ASSERT(on); \ } \ } while(0) -} - +#else +#define ASSERT_ON_THREAD(t) #endif +} /* namespace mozilla */ + +#endif From 34ede8281f9a77c6a205448e245104245a74cbac Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 26 Mar 2013 21:40:00 +1100 Subject: [PATCH 002/129] Bug 854807 - Fix thinko in CloneFunctionObjectIfNotSingleton(). r=smaug. --- js/src/jsfuninlines.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/js/src/jsfuninlines.h b/js/src/jsfuninlines.h index 8a3f3f36e697..10bad1727d11 100644 --- a/js/src/jsfuninlines.h +++ b/js/src/jsfuninlines.h @@ -191,11 +191,11 @@ CloneFunctionObjectIfNotSingleton(JSContext *cx, HandleFunction fun, HandleObjec // These intermediate variables are needed to avoid link errors on some // platforms. Sigh. - gc::AllocKind finalizeKind = JSFunction::ExtendedFinalizeKind; + gc::AllocKind finalizeKind = JSFunction::FinalizeKind; gc::AllocKind extendedFinalizeKind = JSFunction::ExtendedFinalizeKind; gc::AllocKind kind = fun->isExtended() - ? finalizeKind - : extendedFinalizeKind; + ? extendedFinalizeKind + : finalizeKind; return CloneFunctionObject(cx, fun, parent, kind); } From 02b67b001f6a917b7a9cf7f81bb0cae2a790f1ea Mon Sep 17 00:00:00 2001 From: Jon Coppeard Date: Tue, 19 Mar 2013 18:50:57 +0000 Subject: [PATCH 003/129] Bug 853498 - GC: Make sure wrapped things are not marked gray r=billm --HG-- extra : rebase_source : 252c8f915af6852f1df09caec0775920b0483003 --- js/src/jsapi.cpp | 11 +++++++++++ js/src/jscompartment.cpp | 2 -- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 9aef641a521a..c6c8f8ded888 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -1518,6 +1518,8 @@ JS_WrapObject(JSContext *cx, JSObject **objp) { AssertHeapIsIdle(cx); CHECK_REQUEST(cx); + if (*objp) + JS::ExposeGCThingToActiveJS(*objp, JSTRACE_OBJECT); return cx->compartment->wrap(cx, objp); } @@ -1526,6 +1528,8 @@ JS_WrapValue(JSContext *cx, jsval *vp) { AssertHeapIsIdle(cx); CHECK_REQUEST(cx); + if (vp) + JS::ExposeValueToActiveJS(*vp); RootedValue value(cx, *vp); bool ok = cx->compartment->wrap(cx, &value); *vp = value.get(); @@ -1537,6 +1541,13 @@ JS_WrapId(JSContext *cx, jsid *idp) { AssertHeapIsIdle(cx); CHECK_REQUEST(cx); + if (idp) { + jsid id = *idp; + if (JSID_IS_STRING(id)) + JS::ExposeGCThingToActiveJS(JSID_TO_STRING(id), JSTRACE_STRING); + else if (JSID_IS_OBJECT(id)) + JS::ExposeGCThingToActiveJS(JSID_TO_OBJECT(id), JSTRACE_OBJECT); + } return cx->compartment->wrapId(cx, idp); } diff --git a/js/src/jscompartment.cpp b/js/src/jscompartment.cpp index 94ac437b7a2f..d6da1b9a6617 100644 --- a/js/src/jscompartment.cpp +++ b/js/src/jscompartment.cpp @@ -199,8 +199,6 @@ JSCompartment::putWrapper(const CrossCompartmentKey &wrapped, const js::Value &w JS_ASSERT(!IsPoisonedPtr(wrapper.toGCThing())); JS_ASSERT_IF(wrapped.kind == CrossCompartmentKey::StringWrapper, wrapper.isString()); JS_ASSERT_IF(wrapped.kind != CrossCompartmentKey::StringWrapper, wrapper.isObject()); - // todo: uncomment when bug 815999 is fixed: - // JS_ASSERT(!wrapped.wrapped->isMarked(gc::GRAY)); return crossCompartmentWrappers.put(wrapped, wrapper); } From 6c16193bd3179155342a05dc026708a7b93fc20b Mon Sep 17 00:00:00 2001 From: Marco Bonardo Date: Tue, 26 Mar 2013 12:07:23 +0100 Subject: [PATCH 004/129] Bug 848935 - Add debug spew for browser_aboutHome.js intermittent failure. --- .../base/content/test/browser_aboutHome.js | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/browser/base/content/test/browser_aboutHome.js b/browser/base/content/test/browser_aboutHome.js index 98c1cb8e0dc4..1020c1e8a5aa 100644 --- a/browser/base/content/test/browser_aboutHome.js +++ b/browser/base/content/test/browser_aboutHome.js @@ -31,7 +31,8 @@ let gTests = [ }, run: function (aSnippetsMap) { - isnot(aSnippetsMap.get("snippets-last-update"), null); + isnot(aSnippetsMap.get("snippets-last-update"), null, + "snippets-last-update should have a value"); } }, @@ -116,7 +117,7 @@ let gTests = [ cm.getCategoryEntry("healthreport-js-provider", "SearchesProvider"); } catch (ex) { // Health Report disabled, or no SearchesProvider. - return; + return Promise.resolve(); } let deferred = Promise.defer(); @@ -220,9 +221,9 @@ function test() let snippetsMap = yield promiseSetupSnippetsMap(tab, test.setup); // Ensure browser has set attributes already, or wait for them. yield promise; - + info("Running test"); yield test.run(snippetsMap); - + info("Cleanup"); gBrowser.removeCurrentTab(); } @@ -243,8 +244,10 @@ function promiseNewTabLoadEvent(aUrl, aEventType="load") { let deferred = Promise.defer(); let tab = gBrowser.selectedTab = gBrowser.addTab(aUrl); + info("Wait tab event: " + aEventType); tab.linkedBrowser.addEventListener(aEventType, function load(event) { tab.linkedBrowser.removeEventListener(aEventType, load, true); + info("Tab event received: " + aEventType); deferred.resolve(tab); }, true); return deferred.promise; @@ -264,7 +267,12 @@ function promiseSetupSnippetsMap(aTab, aSetupFn) { let deferred = Promise.defer(); let cw = aTab.linkedBrowser.contentWindow.wrappedJSObject; + info("Waiting for snippets map"); cw.ensureSnippetsMapThen(function (aSnippetsMap) { + info("Got snippets map: " + + "{ last-update: " + aSnippetsMap.get("snippets-last-update") + + ", cached-version: " + aSnippetsMap.get("snippets-cached-version") + + " }"); // Don't try to update. aSnippetsMap.set("snippets-last-update", Date.now()); aSnippetsMap.set("snippets-cached-version", AboutHomeUtils.snippetsVersion); @@ -293,6 +301,8 @@ function promiseBrowserAttributes(aTab) //docElt.setAttribute("snippetsURL", "nonexistent://test"); let observer = new MutationObserver(function (mutations) { for (let mutation of mutations) { + info("Got attribute mutation: " + mutation.attributeName + + " from " + mutation.oldValue); if (mutation.attributeName == "snippetsURL" && docElt.getAttribute("snippetsURL") != "nonexistent://test") { docElt.setAttribute("snippetsURL", "nonexistent://test"); @@ -300,6 +310,7 @@ function promiseBrowserAttributes(aTab) // Now we just have to wait for the last attribute. if (mutation.attributeName == "searchEngineURL") { + info("Remove attributes observer"); observer.disconnect(); // Must be sure to continue after the page mutation observer. executeSoon(function() deferred.resolve()); @@ -307,6 +318,7 @@ function promiseBrowserAttributes(aTab) } } }); + info("Add attributes observer"); observer.observe(docElt, { attributes: true }); return deferred.promise; From 4fe36b6a32d340ad99d7f678d0fe52adea9217b3 Mon Sep 17 00:00:00 2001 From: Ed Morley Date: Tue, 26 Mar 2013 11:10:14 +0000 Subject: [PATCH 005/129] Bug 854407 - Give the 'child process NNNN still alive after shutdown' failure a unique test name; r=jmaher --- build/automation.py.in | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build/automation.py.in b/build/automation.py.in index 8aed3403418d..486b48f13d41 100644 --- a/build/automation.py.in +++ b/build/automation.py.in @@ -1139,7 +1139,7 @@ user_pref("camino.use_system_proxy_settings", false); // Camino-only, harmless t return True foundZombie = False - self.log.info('INFO | automation.py | Reading PID log: %s', processLog) + self.log.info('INFO | zombiecheck | Reading PID log: %s', processLog) processList = [] pidRE = re.compile(r'launched child process (\d+)$') processLogFD = open(processLog) @@ -1151,10 +1151,10 @@ user_pref("camino.use_system_proxy_settings", false); // Camino-only, harmless t processLogFD.close() for processPID in processList: - self.log.info("INFO | automation.py | Checking for orphan process with PID: %d", processPID) + self.log.info("INFO | zombiecheck | Checking for orphan process with PID: %d", processPID) if self.isPidAlive(processPID): foundZombie = True - self.log.info("TEST-UNEXPECTED-FAIL | automation.py | child process %d still alive after shutdown", processPID) + self.log.info("TEST-UNEXPECTED-FAIL | zombiecheck | child process %d still alive after shutdown", processPID) self.killPid(processPID) return foundZombie From 8b28e5b8f13bdd1d5182c190deb1c60bc76c8324 Mon Sep 17 00:00:00 2001 From: Jan Varga Date: Tue, 26 Mar 2013 12:13:17 +0100 Subject: [PATCH 006/129] Bug 767944 - Implement a manager for centralized quota and storage handling. r=bent --- b2g/installer/package-manifest.in | 1 + browser/base/content/pageinfo/permissions.js | 24 +- browser/installer/package-manifest.in | 1 + content/base/src/nsDocument.cpp | 12 +- content/media/webrtc/MediaEngineWebRTC.h | 1 + dom/base/nsDOMWindowUtils.cpp | 4 +- dom/base/nsGlobalWindow.cpp | 11 +- dom/file/FileHandle.cpp | 2 +- dom/file/FileService.cpp | 25 +- dom/file/FileService.h | 10 +- dom/file/LockedFile.cpp | 6 +- dom/file/nsIFileStorage.h | 46 +- dom/indexedDB/CheckPermissionsHelper.cpp | 9 +- dom/indexedDB/Client.cpp | 338 +++ dom/indexedDB/Client.h | 87 + dom/indexedDB/FileInfo.cpp | 4 +- dom/indexedDB/FileManager.cpp | 6 +- dom/indexedDB/FileManager.h | 14 +- dom/indexedDB/IDBDatabase.cpp | 105 +- dom/indexedDB/IDBDatabase.h | 46 +- dom/indexedDB/IDBFactory.cpp | 24 +- dom/indexedDB/IDBFileHandle.cpp | 5 +- dom/indexedDB/IDBTransaction.h | 1 + dom/indexedDB/IndexedDatabase.h | 43 - dom/indexedDB/IndexedDatabaseInlines.h | 13 - dom/indexedDB/IndexedDatabaseManager.cpp | 1843 +--------------- dom/indexedDB/IndexedDatabaseManager.h | 403 +--- dom/indexedDB/Makefile.in | 6 +- dom/indexedDB/OpenDatabaseHelper.cpp | 146 +- dom/indexedDB/OpenDatabaseHelper.h | 8 +- dom/indexedDB/TransactionThreadPool.cpp | 25 +- dom/indexedDB/TransactionThreadPool.h | 10 +- dom/indexedDB/ipc/IndexedDBChild.cpp | 6 +- dom/indexedDB/nsIIndexedDatabaseManager.idl | 56 +- dom/indexedDB/test/bug839193.js | 13 +- dom/indexedDB/test/file.js | 6 +- dom/indexedDB/test/helpers.js | 12 +- dom/quota/AcquireListener.h | 29 + dom/quota/ArrayCluster.h | 106 + dom/quota/CheckQuotaHelper.cpp | 5 +- dom/quota/CheckQuotaHelper.h | 2 +- dom/quota/Client.h | 110 + dom/quota/FileStreams.cpp | 2 + dom/quota/FileStreams.h | 2 +- dom/quota/Makefile.in | 20 + dom/quota/OriginOrPatternString.h | 54 + dom/quota/QuotaManager.cpp | 2067 ++++++++++++++++-- dom/quota/QuotaManager.h | 301 ++- dom/quota/QuotaObject.cpp | 159 ++ dom/quota/QuotaObject.h | 90 + dom/quota/StorageMatcher.h | 191 ++ dom/quota/StoragePrivilege.h | 21 + dom/quota/UsageRunnable.h | 81 + dom/quota/Utilities.h | 36 + dom/quota/moz.build | 6 + dom/quota/nsIOfflineStorage.h | 92 + dom/quota/nsIQuotaManager.idl | 44 + dom/quota/nsIQuotaRequest.idl | 14 + dom/quota/nsIUsageCallback.idl | 20 + js/xpconnect/src/dom_quickstubs.qsconf | 6 +- layout/build/nsLayoutCID.h | 4 + layout/build/nsLayoutModule.cpp | 9 +- mobile/android/installer/package-manifest.in | 1 + storage/src/TelemetryVFS.cpp | 1 + toolkit/forgetaboutsite/ForgetAboutSite.jsm | 10 +- 65 files changed, 4100 insertions(+), 2755 deletions(-) create mode 100644 dom/indexedDB/Client.cpp create mode 100644 dom/indexedDB/Client.h create mode 100644 dom/quota/AcquireListener.h create mode 100644 dom/quota/ArrayCluster.h create mode 100644 dom/quota/Client.h create mode 100644 dom/quota/OriginOrPatternString.h create mode 100644 dom/quota/QuotaObject.cpp create mode 100644 dom/quota/QuotaObject.h create mode 100644 dom/quota/StorageMatcher.h create mode 100644 dom/quota/StoragePrivilege.h create mode 100644 dom/quota/UsageRunnable.h create mode 100644 dom/quota/Utilities.h create mode 100644 dom/quota/nsIOfflineStorage.h create mode 100644 dom/quota/nsIQuotaManager.idl create mode 100644 dom/quota/nsIQuotaRequest.idl create mode 100644 dom/quota/nsIUsageCallback.idl diff --git a/b2g/installer/package-manifest.in b/b2g/installer/package-manifest.in index 9c7d18e973c8..dd46c7a9cfd0 100644 --- a/b2g/installer/package-manifest.in +++ b/b2g/installer/package-manifest.in @@ -202,6 +202,7 @@ @BINPATH@/components/dom_browserelement.xpt @BINPATH@/components/dom_messages.xpt @BINPATH@/components/dom_power.xpt +@BINPATH@/components/dom_quota.xpt @BINPATH@/components/dom_range.xpt @BINPATH@/components/dom_settings.xpt @BINPATH@/components/dom_permissionsettings.xpt diff --git a/browser/base/content/pageinfo/permissions.js b/browser/base/content/pageinfo/permissions.js index bfdae9dcc256..ddf201800d2e 100644 --- a/browser/base/content/pageinfo/permissions.js +++ b/browser/base/content/pageinfo/permissions.js @@ -7,11 +7,11 @@ const ALLOW = nsIPermissionManager.ALLOW_ACTION; // 1 const BLOCK = nsIPermissionManager.DENY_ACTION; // 2 const SESSION = nsICookiePermission.ACCESS_SESSION; // 8 -const nsIIndexedDatabaseManager = - Components.interfaces.nsIIndexedDatabaseManager; +const nsIQuotaManager = Components.interfaces.nsIQuotaManager; var gPermURI; var gPrefs; +var gUsageRequest; var gPermObj = { image: function getImageDefaultPermission() @@ -116,9 +116,10 @@ function onUnloadPermission() .getService(Components.interfaces.nsIObserverService); os.removeObserver(permissionObserver, "perm-changed"); - var dbManager = Components.classes["@mozilla.org/dom/indexeddb/manager;1"] - .getService(nsIIndexedDatabaseManager); - dbManager.cancelGetUsageForURI(gPermURI, onIndexedDBUsageCallback); + if (gUsageRequest) { + gUsageRequest.cancel(); + gUsageRequest = null; + } } function initRow(aPartId) @@ -205,9 +206,10 @@ function setRadioState(aPartId, aValue) function initIndexedDBRow() { - var dbManager = Components.classes["@mozilla.org/dom/indexeddb/manager;1"] - .getService(nsIIndexedDatabaseManager); - dbManager.getUsageForURI(gPermURI, onIndexedDBUsageCallback); + var quotaManager = Components.classes["@mozilla.org/dom/quota/manager;1"] + .getService(nsIQuotaManager); + gUsageRequest = + quotaManager.getUsageForURI(gPermURI, onIndexedDBUsageCallback); var status = document.getElementById("indexedDBStatus"); var button = document.getElementById("indexedDBClear"); @@ -219,9 +221,9 @@ function initIndexedDBRow() function onIndexedDBClear() { - Components.classes["@mozilla.org/dom/indexeddb/manager;1"] - .getService(nsIIndexedDatabaseManager) - .clearDatabasesForURI(gPermURI); + Components.classes["@mozilla.org/dom/quota/manager;1"] + .getService(nsIQuotaManager) + .clearStoragesForURI(gPermURI); var permissionManager = Components.classes[PERMISSION_CONTRACTID] .getService(nsIPermissionManager); diff --git a/browser/installer/package-manifest.in b/browser/installer/package-manifest.in index 193bf24b97b7..22524369ede9 100644 --- a/browser/installer/package-manifest.in +++ b/browser/installer/package-manifest.in @@ -203,6 +203,7 @@ #endif @BINPATH@/components/dom_browserelement.xpt @BINPATH@/components/dom_power.xpt +@BINPATH@/components/dom_quota.xpt @BINPATH@/components/dom_range.xpt @BINPATH@/components/dom_settings.xpt @BINPATH@/components/dom_permissionsettings.xpt diff --git a/content/base/src/nsDocument.cpp b/content/base/src/nsDocument.cpp index 15c99627e177..5ae71c66d49e 100644 --- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -156,7 +156,7 @@ #include "mozAutoDocUpdate.h" #include "nsGlobalWindow.h" #include "mozilla/dom/EncodingUtils.h" -#include "mozilla/dom/indexedDB/IndexedDatabaseManager.h" +#include "mozilla/dom/quota/QuotaManager.h" #include "nsDOMNavigationTiming.h" #include "nsEventStateManager.h" @@ -7638,11 +7638,11 @@ nsDocument::CanSavePresentation(nsIRequest *aNewRequest) } } - // Check if we have running IndexedDB transactions - indexedDB::IndexedDatabaseManager* idbManager = - win ? indexedDB::IndexedDatabaseManager::Get() : nullptr; - if (idbManager && idbManager->HasOpenTransactions(win)) { - return false; + // Check if we have running offline storage transactions + quota::QuotaManager* quotaManager = + win ? quota::QuotaManager::Get() : nullptr; + if (quotaManager && quotaManager->HasOpenTransactions(win)) { + return false; } #ifdef MOZ_WEBRTC diff --git a/content/media/webrtc/MediaEngineWebRTC.h b/content/media/webrtc/MediaEngineWebRTC.h index 72703e56c3df..213b20c26a3b 100644 --- a/content/media/webrtc/MediaEngineWebRTC.h +++ b/content/media/webrtc/MediaEngineWebRTC.h @@ -18,6 +18,7 @@ #include "DOMMediaStream.h" #include "nsDirectoryServiceDefs.h" #include "nsComponentManagerUtils.h" +#include "nsRefPtrHashtable.h" #include "VideoUtils.h" #include "MediaEngine.h" diff --git a/dom/base/nsDOMWindowUtils.cpp b/dom/base/nsDOMWindowUtils.cpp index 6db7a7bf05d1..ed4ceddd64dc 100644 --- a/dom/base/nsDOMWindowUtils.cpp +++ b/dom/base/nsDOMWindowUtils.cpp @@ -63,6 +63,7 @@ #include "mozilla/dom/Element.h" #include "mozilla/dom/indexedDB/FileInfo.h" #include "mozilla/dom/indexedDB/IndexedDatabaseManager.h" +#include "mozilla/dom/quota/QuotaManager.h" #include "GeckoProfiler.h" #include "nsDOMBlobBuilder.h" #include "nsIDOMFileHandle.h" @@ -2756,8 +2757,7 @@ nsDOMWindowUtils::GetFileReferences(const nsAString& aDatabaseName, NS_ENSURE_TRUE(window, NS_ERROR_FAILURE); nsCString origin; - nsresult rv = indexedDB::IndexedDatabaseManager::GetASCIIOriginFromWindow( - window, origin); + nsresult rv = quota::QuotaManager::GetASCIIOriginFromWindow(window, origin); NS_ENSURE_SUCCESS(rv, rv); nsRefPtr mgr = diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index b481323162bf..faba920f3359 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -207,7 +207,7 @@ #include "prenv.h" #include "mozilla/dom/indexedDB/IDBFactory.h" -#include "mozilla/dom/indexedDB/IndexedDatabaseManager.h" +#include "mozilla/dom/quota/QuotaManager.h" #include "mozilla/dom/StructuredCloneTags.h" @@ -1390,11 +1390,10 @@ nsGlobalWindow::FreeInnerObjects() AutoPushJSContext cx(scx ? scx->GetNativeContext() : nullptr); mozilla::dom::workers::CancelWorkersForWindow(cx, this); - // Close all IndexedDB databases for this window. - indexedDB::IndexedDatabaseManager* idbManager = - indexedDB::IndexedDatabaseManager::Get(); - if (idbManager) { - idbManager->AbortCloseDatabasesForWindow(this); + // Close all offline storages for this window. + quota::QuotaManager* quotaManager = quota::QuotaManager::Get(); + if (quotaManager) { + quotaManager->AbortCloseStoragesForWindow(this); } ClearAllTimeouts(); diff --git a/dom/file/FileHandle.cpp b/dom/file/FileHandle.cpp index 9a9271c8374c..82d31ffad5d2 100644 --- a/dom/file/FileHandle.cpp +++ b/dom/file/FileHandle.cpp @@ -107,7 +107,7 @@ FileHandle::Open(FileMode aMode, ErrorResult& aError) { MOZ_ASSERT(NS_IsMainThread()); - if (FileService::IsShuttingDown() || mFileStorage->IsStorageShuttingDown()) { + if (FileService::IsShuttingDown() || mFileStorage->IsShuttingDown()) { aError.Throw(NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR); return nullptr; } diff --git a/dom/file/FileService.cpp b/dom/file/FileService.cpp index 2cf1702fe7c1..b8288b074cb9 100644 --- a/dom/file/FileService.cpp +++ b/dom/file/FileService.cpp @@ -152,11 +152,11 @@ FileService::Enqueue(LockedFile* aLockedFile, FileHelper* aFileHelper) FileHandle* fileHandle = aLockedFile->mFileHandle; - if (fileHandle->mFileStorage->IsStorageInvalidated()) { + if (fileHandle->mFileStorage->IsInvalidated()) { return NS_ERROR_NOT_AVAILABLE; } - nsISupports* storageId = fileHandle->mFileStorage->StorageId(); + nsIAtom* storageId = fileHandle->mFileStorage->Id(); const nsAString& fileName = fileHandle->mFileName; bool modeIsWrite = aLockedFile->mMode == LockedFile::READ_WRITE; @@ -226,7 +226,7 @@ FileService::NotifyLockedFileCompleted(LockedFile* aLockedFile) NS_ASSERTION(aLockedFile, "Null pointer!"); FileHandle* fileHandle = aLockedFile->mFileHandle; - nsISupports* storageId = fileHandle->mFileStorage->StorageId(); + nsIAtom* storageId = fileHandle->mFileStorage->Id(); FileStorageInfo* fileStorageInfo; if (!mFileStorageInfos.Get(storageId, &fileStorageInfo)) { @@ -256,10 +256,10 @@ FileService::NotifyLockedFileCompleted(LockedFile* aLockedFile) } } -bool -FileService::WaitForAllStoragesToComplete( - nsTArray >& aStorages, - nsIRunnable* aCallback) +void +FileService::WaitForStoragesToComplete( + nsTArray >& aStorages, + nsIRunnable* aCallback) { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); NS_ASSERTION(!aStorages.IsEmpty(), "No databases to wait on!"); @@ -272,8 +272,6 @@ FileService::WaitForAllStoragesToComplete( if (MaybeFireCallback(*callback)) { mCompleteCallbacks.RemoveElementAt(mCompleteCallbacks.Length() - 1); } - - return true; } void @@ -283,7 +281,7 @@ FileService::AbortLockedFilesForStorage(nsIFileStorage* aFileStorage) NS_ASSERTION(aFileStorage, "Null pointer!"); FileStorageInfo* fileStorageInfo; - if (!mFileStorageInfos.Get(aFileStorage->StorageId(), &fileStorageInfo)) { + if (!mFileStorageInfos.Get(aFileStorage->Id(), &fileStorageInfo)) { return; } @@ -303,7 +301,7 @@ FileService::HasLockedFilesForStorage(nsIFileStorage* aFileStorage) NS_ASSERTION(aFileStorage, "Null pointer!"); FileStorageInfo* fileStorageInfo; - if (!mFileStorageInfos.Get(aFileStorage->StorageId(), &fileStorageInfo)) { + if (!mFileStorageInfos.Get(aFileStorage->Id(), &fileStorageInfo)) { return false; } @@ -330,8 +328,7 @@ FileService::MaybeFireCallback(StoragesCompleteCallback& aCallback) NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); for (uint32_t index = 0; index < aCallback.mStorages.Length(); index++) { - if (mFileStorageInfos.Get(aCallback.mStorages[index]->StorageId(), - nullptr)) { + if (mFileStorageInfos.Get(aCallback.mStorages[index]->Id(), nullptr)) { return false; } } @@ -488,7 +485,7 @@ FileService::FileStorageInfo::RemoveLockedFileQueue(LockedFile* aLockedFile) bool FileService::FileStorageInfo::HasRunningLockedFiles( - nsIFileStorage* aFileStorage) + nsIFileStorage* aFileStorage) { for (uint32_t index = 0; index < mLockedFileQueues.Length(); index++) { LockedFile* lockedFile = mLockedFileQueues[index]->mLockedFile; diff --git a/dom/file/FileService.h b/dom/file/FileService.h index e3f94af6033c..97f5933dc170 100644 --- a/dom/file/FileService.h +++ b/dom/file/FileService.h @@ -46,9 +46,9 @@ public: void NotifyLockedFileCompleted(LockedFile* aLockedFile); - bool - WaitForAllStoragesToComplete(nsTArray >& aStorages, - nsIRunnable* aCallback); + void + WaitForStoragesToComplete(nsTArray >& aStorages, + nsIRunnable* aCallback); void AbortLockedFilesForStorage(nsIFileStorage* aFileStorage); @@ -129,8 +129,8 @@ private: inline void CollectRunningAndDelayedLockedFiles( - nsIFileStorage* aFileStorage, - nsTArray >& aLockedFiles); + nsIFileStorage* aFileStorage, + nsTArray >& aLockedFiles); void LockFileForReading(const nsAString& aFileName) diff --git a/dom/file/LockedFile.cpp b/dom/file/LockedFile.cpp index 83b20723becb..e09ef700cd11 100644 --- a/dom/file/LockedFile.cpp +++ b/dom/file/LockedFile.cpp @@ -384,7 +384,7 @@ LockedFile::CreateParallelStream(nsISupports** aStream) NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); nsIFileStorage* fileStorage = mFileHandle->mFileStorage; - if (fileStorage->IsStorageInvalidated()) { + if (fileStorage->IsInvalidated()) { return NS_ERROR_NOT_AVAILABLE; } @@ -404,7 +404,7 @@ LockedFile::GetOrCreateStream(nsISupports** aStream) NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); nsIFileStorage* fileStorage = mFileHandle->mFileStorage; - if (fileStorage->IsStorageInvalidated()) { + if (fileStorage->IsInvalidated()) { return NS_ERROR_NOT_AVAILABLE; } @@ -957,7 +957,7 @@ FinishHelper::Run() } nsIFileStorage* fileStorage = mLockedFile->mFileHandle->mFileStorage; - if (fileStorage->IsStorageInvalidated()) { + if (fileStorage->IsInvalidated()) { mAborted = true; } diff --git a/dom/file/nsIFileStorage.h b/dom/file/nsIFileStorage.h index e985f0a3ac3b..22a916b311d6 100644 --- a/dom/file/nsIFileStorage.h +++ b/dom/file/nsIFileStorage.h @@ -10,52 +10,50 @@ #include "nsISupports.h" #define NS_FILESTORAGE_IID \ - {0xa0801944, 0x2f1c, 0x4203, \ - { 0x9c, 0xaa, 0xaa, 0x47, 0xe0, 0x0c, 0x67, 0x92 } } + {0x6278f453, 0xd557, 0x4a55, \ + { 0x99, 0x3e, 0xf4, 0x69, 0xe2, 0xa5, 0xe1, 0xd0 } } + +class nsIAtom; class nsIFileStorage : public nsISupports { public: NS_DECLARE_STATIC_IID_ACCESSOR(NS_FILESTORAGE_IID) - virtual const nsACString& - StorageOrigin() = 0; + NS_IMETHOD_(nsIAtom*) + Id() = 0; - virtual nsISupports* - StorageId() = 0; + // Whether or not the storage has been invalidated. If it has then no further + // operations for this storage will be allowed to run. + NS_IMETHOD_(bool) + IsInvalidated() = 0; - virtual bool - IsStorageInvalidated() = 0; + NS_IMETHOD_(bool) + IsShuttingDown() = 0; - virtual bool - IsStorageShuttingDown() = 0; - - virtual void + NS_IMETHOD_(void) SetThreadLocals() = 0; - virtual void + NS_IMETHOD_(void) UnsetThreadLocals() = 0; }; NS_DEFINE_STATIC_IID_ACCESSOR(nsIFileStorage, NS_FILESTORAGE_IID) #define NS_DECL_NSIFILESTORAGE \ - virtual const nsACString& \ - StorageOrigin() MOZ_OVERRIDE; \ + NS_IMETHOD_(nsIAtom*) \ + Id() MOZ_OVERRIDE; \ \ - virtual nsISupports* \ - StorageId() MOZ_OVERRIDE; \ + NS_IMETHOD_(bool) \ + IsInvalidated() MOZ_OVERRIDE; \ \ - virtual bool \ - IsStorageInvalidated() MOZ_OVERRIDE; \ + NS_IMETHOD_(bool) \ + IsShuttingDown() MOZ_OVERRIDE; \ \ - virtual bool \ - IsStorageShuttingDown() MOZ_OVERRIDE; \ - \ - virtual void \ + NS_IMETHOD_(void) \ SetThreadLocals() MOZ_OVERRIDE; \ \ - virtual void \ + NS_IMETHOD_(void) \ UnsetThreadLocals() MOZ_OVERRIDE; #endif // nsIFileStorage_h__ diff --git a/dom/indexedDB/CheckPermissionsHelper.cpp b/dom/indexedDB/CheckPermissionsHelper.cpp index ada2c2e277f1..fd7f5d152a59 100644 --- a/dom/indexedDB/CheckPermissionsHelper.cpp +++ b/dom/indexedDB/CheckPermissionsHelper.cpp @@ -19,8 +19,9 @@ #include "nsDOMStorage.h" #include "nsNetUtil.h" #include "nsThreadUtils.h" -#include "mozilla/Services.h" +#include "mozilla/dom/quota/QuotaManager.h" #include "mozilla/Preferences.h" +#include "mozilla/Services.h" #include "IndexedDatabaseManager.h" @@ -140,10 +141,10 @@ CheckPermissionsHelper::Run() window.swap(mWindow); if (permission == PERMISSION_ALLOWED) { - IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get(); - NS_ASSERTION(mgr, "This should never be null!"); + quota::QuotaManager* quotaManager = quota::QuotaManager::Get(); + NS_ASSERTION(quotaManager, "This should never be null!"); - return helper->Dispatch(mgr->IOThread()); + return helper->Dispatch(quotaManager->IOThread()); } NS_ASSERTION(permission == PERMISSION_PROMPT || diff --git a/dom/indexedDB/Client.cpp b/dom/indexedDB/Client.cpp new file mode 100644 index 000000000000..9884996c43bd --- /dev/null +++ b/dom/indexedDB/Client.cpp @@ -0,0 +1,338 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "Client.h" + +#include "mozilla/dom/quota/QuotaManager.h" +#include "mozilla/dom/quota/UsageRunnable.h" +#include "mozilla/dom/quota/Utilities.h" + +#include "IDBDatabase.h" +#include "IndexedDatabaseManager.h" +#include "TransactionThreadPool.h" + +USING_INDEXEDDB_NAMESPACE +using mozilla::dom::quota::QuotaManager; + +namespace { + +bool +GetDatabaseBaseFilename(const nsAString& aFilename, + nsAString& aDatabaseBaseFilename) +{ + NS_ASSERTION(!aFilename.IsEmpty(), "Bad argument!"); + + NS_NAMED_LITERAL_STRING(sqlite, ".sqlite"); + + if (!StringEndsWith(aFilename, sqlite)) { + return false; + } + + aDatabaseBaseFilename = + Substring(aFilename, 0, aFilename.Length() - sqlite.Length()); + + return true; +} + +} // anonymous namespace + +// This needs to be fully qualified to not confuse trace refcnt assertions. +NS_IMPL_ADDREF(mozilla::dom::indexedDB::Client) +NS_IMPL_RELEASE(mozilla::dom::indexedDB::Client) + +nsresult +Client::InitOrigin(const nsACString& aOrigin, UsageRunnable* aUsageRunnable) +{ + nsCOMPtr directory; + nsresult rv = GetDirectory(aOrigin, getter_AddRefs(directory)); + NS_ENSURE_SUCCESS(rv, rv); + + // We need to see if there are any files in the directory already. If they + // are database files then we need to cleanup stored files (if it's needed) + // and also get the usage. + + nsAutoTArray subdirsToProcess; + nsAutoTArray , 20> unknownFiles; + nsTHashtable validSubdirs; + validSubdirs.Init(20); + + nsCOMPtr entries; + rv = directory->GetDirectoryEntries(getter_AddRefs(entries)); + NS_ENSURE_SUCCESS(rv, rv); + + bool hasMore; + while (NS_SUCCEEDED((rv = entries->HasMoreElements(&hasMore))) && + hasMore && (!aUsageRunnable || !aUsageRunnable->Canceled())) { + nsCOMPtr entry; + rv = entries->GetNext(getter_AddRefs(entry)); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr file = do_QueryInterface(entry); + NS_ENSURE_TRUE(file, NS_NOINTERFACE); + + nsString leafName; + rv = file->GetLeafName(leafName); + NS_ENSURE_SUCCESS(rv, rv); + + if (StringEndsWith(leafName, NS_LITERAL_STRING(".sqlite-journal"))) { + continue; + } + + bool isDirectory; + rv = file->IsDirectory(&isDirectory); + NS_ENSURE_SUCCESS(rv, rv); + + if (isDirectory) { + if (!validSubdirs.GetEntry(leafName)) { + subdirsToProcess.AppendElement(leafName); + } + continue; + } + + nsString dbBaseFilename; + if (!GetDatabaseBaseFilename(leafName, dbBaseFilename)) { + unknownFiles.AppendElement(file); + continue; + } + + nsCOMPtr fmDirectory; + rv = directory->Clone(getter_AddRefs(fmDirectory)); + NS_ENSURE_SUCCESS(rv, rv); + + rv = fmDirectory->Append(dbBaseFilename); + NS_ENSURE_SUCCESS(rv, rv); + + rv = FileManager::InitDirectory(fmDirectory, file, aOrigin); + NS_ENSURE_SUCCESS(rv, rv); + + if (aUsageRunnable) { + int64_t fileSize; + rv = file->GetFileSize(&fileSize); + NS_ENSURE_SUCCESS(rv, rv); + + aUsageRunnable->AppendToDatabaseUsage(uint64_t(fileSize)); + + uint64_t usage; + rv = FileManager::GetUsage(fmDirectory, &usage); + NS_ENSURE_SUCCESS(rv, rv); + + aUsageRunnable->AppendToFileUsage(usage); + } + + validSubdirs.PutEntry(dbBaseFilename); + } + NS_ENSURE_SUCCESS(rv, rv); + + for (uint32_t i = 0; i < subdirsToProcess.Length(); i++) { + const nsString& subdir = subdirsToProcess[i]; + if (!validSubdirs.GetEntry(subdir)) { + NS_WARNING("Unknown subdirectory found!"); + return NS_ERROR_UNEXPECTED; + } + } + + for (uint32_t i = 0; i < unknownFiles.Length(); i++) { + nsCOMPtr& unknownFile = unknownFiles[i]; + + // Some temporary SQLite files could disappear, so we have to check if the + // unknown file still exists. + bool exists; + rv = unknownFile->Exists(&exists); + NS_ENSURE_SUCCESS(rv, rv); + + if (exists) { + nsString leafName; + unknownFile->GetLeafName(leafName); + + // The journal file may exists even after db has been correctly opened. + if (!StringEndsWith(leafName, NS_LITERAL_STRING(".sqlite-journal"))) { + NS_WARNING("Unknown file found!"); + return NS_ERROR_UNEXPECTED; + } + } + } + + return NS_OK; +} + +nsresult +Client::GetUsageForOrigin(const nsACString& aOrigin, + UsageRunnable* aUsageRunnable) +{ + NS_ASSERTION(aUsageRunnable, "Null pointer!"); + + nsCOMPtr directory; + nsresult rv = GetDirectory(aOrigin, getter_AddRefs(directory)); + NS_ENSURE_SUCCESS(rv, rv); + + rv = GetUsageForDirectoryInternal(directory, aUsageRunnable, true); + NS_ENSURE_SUCCESS(rv, rv); + + return NS_OK; +} + +bool +Client::IsTransactionServiceActivated() +{ + return !!TransactionThreadPool::Get(); +} + +void +Client::WaitForStoragesToComplete(nsTArray& aStorages, + nsIRunnable* aCallback) +{ + NS_ASSERTION(!aStorages.IsEmpty(), "No storages to wait on!"); + NS_ASSERTION(aCallback, "Passed null callback!"); + + TransactionThreadPool* pool = TransactionThreadPool::Get(); + NS_ASSERTION(pool, "Should have checked if transaction service is active!"); + + nsTArray databases(aStorages.Length()); + for (uint32_t index = 0; index < aStorages.Length(); index++) { + IDBDatabase* database = IDBDatabase::FromStorage(aStorages[index]); + NS_ASSERTION(database, "This shouldn't be null!"); + + databases.AppendElement(database); + } + + pool->WaitForDatabasesToComplete(databases, aCallback); +} + +void +Client::AbortTransactionsForStorage(nsIOfflineStorage* aStorage) +{ + NS_ASSERTION(aStorage, "Passed null storage!"); + + TransactionThreadPool* pool = TransactionThreadPool::Get(); + NS_ASSERTION(pool, "Should have checked if transaction service is active!"); + + IDBDatabase* database = IDBDatabase::FromStorage(aStorage); + NS_ASSERTION(database, "This shouldn't be null!"); + + pool->AbortTransactionsForDatabase(database); +} + +bool +Client::HasTransactionsForStorage(nsIOfflineStorage* aStorage) +{ + TransactionThreadPool* pool = TransactionThreadPool::Get(); + NS_ASSERTION(pool, "Should have checked if transaction service is active!"); + + IDBDatabase* database = IDBDatabase::FromStorage(aStorage); + NS_ASSERTION(database, "This shouldn't be null!"); + + return pool->HasTransactionsForDatabase(database); +} + +void +Client::OnOriginClearCompleted(const nsACString& aPattern) +{ + IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get(); + if (mgr) { + mgr->InvalidateFileManagersForPattern(aPattern); + } +} + +void +Client::ShutdownTransactionService() +{ + TransactionThreadPool::Shutdown(); +} + +void +Client::OnShutdownCompleted() +{ + IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get(); + if (mgr) { + mgr->InvalidateAllFileManagers(); + } +} + +nsresult +Client::GetDirectory(const nsACString& aOrigin, nsIFile** aDirectory) +{ + QuotaManager* quotaManager = QuotaManager::Get(); + NS_ASSERTION(quotaManager, "This should never fail!"); + + nsCOMPtr directory; + nsresult rv = + quotaManager->GetDirectoryForOrigin(aOrigin, getter_AddRefs(directory)); + NS_ENSURE_SUCCESS(rv, rv); + + NS_ASSERTION(directory, "What?"); + + rv = directory->Append(NS_LITERAL_STRING(IDB_DIRECTORY_NAME)); + NS_ENSURE_SUCCESS(rv, rv); + + directory.forget(aDirectory); + return NS_OK; +} + +nsresult +Client::GetUsageForDirectoryInternal(nsIFile* aDirectory, + UsageRunnable* aUsageRunnable, + bool aDatabaseFiles) +{ + NS_ASSERTION(aDirectory, "Null pointer!"); + NS_ASSERTION(aUsageRunnable, "Null pointer!"); + + nsCOMPtr entries; + nsresult rv = aDirectory->GetDirectoryEntries(getter_AddRefs(entries)); + NS_ENSURE_SUCCESS(rv, rv); + + if (!entries) { + return NS_OK; + } + + bool hasMore; + while (NS_SUCCEEDED((rv = entries->HasMoreElements(&hasMore))) && + hasMore && !aUsageRunnable->Canceled()) { + nsCOMPtr entry; + rv = entries->GetNext(getter_AddRefs(entry)); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr file(do_QueryInterface(entry)); + NS_ASSERTION(file, "Don't know what this is!"); + + bool isDirectory; + rv = file->IsDirectory(&isDirectory); + NS_ENSURE_SUCCESS(rv, rv); + + if (isDirectory) { + if (aDatabaseFiles) { + rv = GetUsageForDirectoryInternal(file, aUsageRunnable, false); + NS_ENSURE_SUCCESS(rv, rv); + } + else { + nsString leafName; + rv = file->GetLeafName(leafName); + NS_ENSURE_SUCCESS(rv, rv); + + if (!leafName.EqualsLiteral(JOURNAL_DIRECTORY_NAME)) { + NS_WARNING("Unknown directory found!"); + } + } + + continue; + } + + int64_t fileSize; + rv = file->GetFileSize(&fileSize); + NS_ENSURE_SUCCESS(rv, rv); + + NS_ASSERTION(fileSize >= 0, "Negative size?!"); + + if (aDatabaseFiles) { + aUsageRunnable->AppendToDatabaseUsage(uint64_t(fileSize)); + } + else { + aUsageRunnable->AppendToFileUsage(uint64_t(fileSize)); + } + } + NS_ENSURE_SUCCESS(rv, rv); + + return NS_OK; +} diff --git a/dom/indexedDB/Client.h b/dom/indexedDB/Client.h new file mode 100644 index 000000000000..39519bc21669 --- /dev/null +++ b/dom/indexedDB/Client.h @@ -0,0 +1,87 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_indexeddb_client_h__ +#define mozilla_dom_indexeddb_client_h__ + +#include "IndexedDatabase.h" + +#include "mozilla/dom/quota/Client.h" + +#define IDB_DIRECTORY_NAME "idb" +#define JOURNAL_DIRECTORY_NAME "journals" + +BEGIN_INDEXEDDB_NAMESPACE + +class Client : public mozilla::dom::quota::Client +{ + typedef mozilla::dom::quota::UsageRunnable UsageRunnable; + +public: + NS_IMETHOD_(nsrefcnt) + AddRef() MOZ_OVERRIDE; + + NS_IMETHOD_(nsrefcnt) + Release() MOZ_OVERRIDE; + + virtual Type + GetType() MOZ_OVERRIDE + { + return IDB; + } + + virtual nsresult + InitOrigin(const nsACString& aOrigin, + UsageRunnable* aUsageRunnable) MOZ_OVERRIDE; + + virtual nsresult + GetUsageForOrigin(const nsACString& aOrigin, + UsageRunnable* aUsageRunnable) MOZ_OVERRIDE; + + virtual bool + IsFileServiceUtilized() MOZ_OVERRIDE + { + return true; + } + + virtual bool + IsTransactionServiceActivated() MOZ_OVERRIDE; + + virtual void + WaitForStoragesToComplete(nsTArray& aStorages, + nsIRunnable* aCallback) MOZ_OVERRIDE; + + virtual void + AbortTransactionsForStorage(nsIOfflineStorage* aStorage) MOZ_OVERRIDE; + + virtual bool + HasTransactionsForStorage(nsIOfflineStorage* aStorage) MOZ_OVERRIDE; + + virtual void + OnOriginClearCompleted(const nsACString& aPattern) MOZ_OVERRIDE; + + virtual void + ShutdownTransactionService() MOZ_OVERRIDE; + + virtual void + OnShutdownCompleted() MOZ_OVERRIDE; + +private: + nsresult + GetDirectory(const nsACString& aOrigin, nsIFile** aDirectory); + + nsresult + GetUsageForDirectoryInternal(nsIFile* aDirectory, + UsageRunnable* aUsageRunnable, + bool aDatabaseFiles); + + nsAutoRefCnt mRefCnt; + NS_DECL_OWNINGTHREAD +}; + +END_INDEXEDDB_NAMESPACE + +#endif // mozilla_dom_indexeddb_client_h__ diff --git a/dom/indexedDB/FileInfo.cpp b/dom/indexedDB/FileInfo.cpp index 77d8830fd1a7..235099df8e6f 100644 --- a/dom/indexedDB/FileInfo.cpp +++ b/dom/indexedDB/FileInfo.cpp @@ -6,6 +6,8 @@ #include "FileInfo.h" +#include "mozilla/dom/quota/QuotaManager.h" + USING_INDEXEDDB_NAMESPACE // static @@ -91,7 +93,7 @@ FileInfo::UpdateReferences(nsAutoRefCnt& aRefCount, int32_t aDelta, void FileInfo::Cleanup() { - if (IndexedDatabaseManager::IsShuttingDown() || + if (quota::QuotaManager::IsShuttingDown() || mFileManager->Invalidated()) { return; } diff --git a/dom/indexedDB/FileManager.cpp b/dom/indexedDB/FileManager.cpp index e837b7b8c0b5..98a313b6b5ae 100644 --- a/dom/indexedDB/FileManager.cpp +++ b/dom/indexedDB/FileManager.cpp @@ -11,9 +11,11 @@ #include "nsIInputStream.h" #include "nsISimpleEnumerator.h" +#include "mozilla/dom/quota/Utilities.h" #include "mozStorageCID.h" #include "mozStorageHelper.h" +#include "Client.h" #include "FileInfo.h" #include "IndexedDatabaseManager.h" #include "OpenDatabaseHelper.h" @@ -21,8 +23,6 @@ #include "IndexedDatabaseInlines.h" #include -#define JOURNAL_DIRECTORY_NAME "journals" - USING_INDEXEDDB_NAMESPACE namespace { @@ -412,7 +412,7 @@ FileManager::GetUsage(nsIFile* aDirectory, uint64_t* aUsage) rv = file->GetFileSize(&fileSize); NS_ENSURE_SUCCESS(rv, rv); - IncrementUsage(&usage, uint64_t(fileSize)); + quota::IncrementUsage(&usage, uint64_t(fileSize)); } *aUsage = usage; diff --git a/dom/indexedDB/FileManager.h b/dom/indexedDB/FileManager.h index 370d4a8e70ca..8bea76f3c9f2 100644 --- a/dom/indexedDB/FileManager.h +++ b/dom/indexedDB/FileManager.h @@ -8,12 +8,14 @@ #define mozilla_dom_indexeddb_filemanager_h__ #include "IndexedDatabase.h" -#include "nsIFile.h" + #include "nsIDOMFile.h" +#include "nsIFile.h" + +#include "mozilla/dom/quota/StoragePrivilege.h" #include "nsDataHashtable.h" class mozIStorageConnection; -class mozIStorageServiceQuotaManagement; BEGIN_INDEXEDDB_NAMESPACE @@ -23,8 +25,10 @@ class FileManager { friend class FileInfo; + typedef mozilla::dom::quota::StoragePrivilege StoragePrivilege; + public: - FileManager(const nsACString& aOrigin, FactoryPrivilege aPrivilege, + FileManager(const nsACString& aOrigin, StoragePrivilege aPrivilege, const nsAString& aDatabaseName) : mOrigin(aOrigin), mPrivilege(aPrivilege), mDatabaseName(aDatabaseName), mLastFileId(0), mInvalidated(false) @@ -40,7 +44,7 @@ public: return mOrigin; } - const FactoryPrivilege& Privilege() const + const StoragePrivilege& Privilege() const { return mPrivilege; } @@ -81,7 +85,7 @@ public: private: nsCString mOrigin; - FactoryPrivilege mPrivilege; + StoragePrivilege mPrivilege; nsString mDatabaseName; nsString mDirectoryPath; diff --git a/dom/indexedDB/IDBDatabase.cpp b/dom/indexedDB/IDBDatabase.cpp index 4b994d4058aa..c20717620e0a 100644 --- a/dom/indexedDB/IDBDatabase.cpp +++ b/dom/indexedDB/IDBDatabase.cpp @@ -11,6 +11,7 @@ #include "mozilla/Mutex.h" #include "mozilla/storage.h" #include "mozilla/dom/ContentParent.h" +#include "mozilla/dom/quota/Client.h" #include "mozilla/dom/quota/QuotaManager.h" #include "nsDOMClassInfo.h" #include "nsDOMLists.h" @@ -27,7 +28,6 @@ #include "IDBObjectStore.h" #include "IDBTransaction.h" #include "IDBFactory.h" -#include "IndexedDatabaseManager.h" #include "TransactionThreadPool.h" #include "DictionaryHelpers.h" #include "nsContentUtils.h" @@ -37,6 +37,7 @@ USING_INDEXEDDB_NAMESPACE using mozilla::dom::ContentParent; +using mozilla::dom::quota::Client; using mozilla::dom::quota::QuotaManager; namespace { @@ -199,17 +200,30 @@ IDBDatabase::Create(IDBWrapperCache* aOwnerCache, db->mFileManager = aFileManager; db->mContentParent = aContentParent; - IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get(); - NS_ASSERTION(mgr, "This should never be null!"); + QuotaManager* quotaManager = QuotaManager::Get(); + NS_ASSERTION(quotaManager, "This should never be null!"); - if (!mgr->RegisterDatabase(db)) { + db->mQuotaClient = quotaManager->GetClient(Client::IDB); + NS_ASSERTION(db->mQuotaClient, "This shouldn't fail!"); + + if (!quotaManager->RegisterStorage(db)) { // Either out of memory or shutting down. return nullptr; } + db->mRegistered = true; + return db.forget(); } +// static +IDBDatabase* +IDBDatabase::FromStorage(nsIOfflineStorage* aStorage) +{ + return aStorage->GetClient()->GetType() == Client::IDB ? + static_cast(aStorage) : nullptr; +} + IDBDatabase::IDBDatabase() : mDatabaseId(0), mActorChild(nullptr), @@ -237,14 +251,14 @@ IDBDatabase::~IDBDatabase() if (mRegistered) { CloseInternal(true); - IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get(); - if (mgr) { - mgr->UnregisterDatabase(this); + QuotaManager* quotaManager = QuotaManager::Get(); + if (quotaManager) { + quotaManager->UnregisterStorage(this); } } } -void +NS_IMETHODIMP_(void) IDBDatabase::Invalidate() { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); @@ -311,9 +325,9 @@ IDBDatabase::CloseInternal(bool aIsDead) } } - IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get(); - if (mgr) { - mgr->OnDatabaseClosed(this); + QuotaManager* quotaManager = QuotaManager::Get(); + if (quotaManager) { + quotaManager->OnStorageClosed(this); } // And let the parent process know as well. @@ -324,8 +338,8 @@ IDBDatabase::CloseInternal(bool aIsDead) } } -bool -IDBDatabase::IsClosed() const +NS_IMETHODIMP_(bool) +IDBDatabase::IsClosed() { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); return mClosed; @@ -367,10 +381,10 @@ IDBDatabase::OnUnlink() // transactions from starting and unblock any other SetVersion callers. CloseInternal(true); - // No reason for the IndexedDatabaseManager to track us any longer. - IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get(); - if (mgr) { - mgr->UnregisterDatabase(this); + // No reason for the QuotaManager to track us any longer. + QuotaManager* quotaManager = QuotaManager::Get(); + if (quotaManager) { + quotaManager->UnregisterStorage(this); // Don't try to unregister again in the destructor. mRegistered = false; @@ -433,6 +447,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(IDBDatabase) NS_INTERFACE_MAP_ENTRY(nsIIDBDatabase) NS_INTERFACE_MAP_ENTRY(nsIFileStorage) + NS_INTERFACE_MAP_ENTRY(nsIOfflineStorage) NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(IDBDatabase) NS_INTERFACE_MAP_END_INHERITING(IDBWrapperCache) @@ -602,7 +617,7 @@ IDBDatabase::Transaction(const jsval& aStoreNames, { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); - if (IndexedDatabaseManager::IsShuttingDown()) { + if (QuotaManager::IsShuttingDown()) { return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; } @@ -744,7 +759,7 @@ IDBDatabase::MozCreateFileHandle(const nsAString& aName, return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; } - if (IndexedDatabaseManager::IsShuttingDown()) { + if (QuotaManager::IsShuttingDown()) { return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; } @@ -757,10 +772,10 @@ IDBDatabase::MozCreateFileHandle(const nsAString& aName, nsRefPtr helper = new CreateFileHelper(this, request, aName, aType); - IndexedDatabaseManager* manager = IndexedDatabaseManager::Get(); - NS_ASSERTION(manager, "We should definitely have a manager here"); + QuotaManager* quotaManager = QuotaManager::Get(); + NS_ASSERTION(quotaManager, "We should definitely have a manager here"); - nsresult rv = helper->Dispatch(manager->IOThread()); + nsresult rv = helper->Dispatch(quotaManager->IOThread()); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); request.forget(_retval); @@ -778,43 +793,55 @@ IDBDatabase::Close() return NS_OK; } -const nsACString& -IDBDatabase::StorageOrigin() +NS_IMETHODIMP_(nsIAtom*) +IDBDatabase::Id() { - return Origin(); + return mDatabaseId; } -nsISupports* -IDBDatabase::StorageId() +NS_IMETHODIMP_(bool) +IDBDatabase::IsInvalidated() { - return Id(); + return mInvalidated; } -bool -IDBDatabase::IsStorageInvalidated() +NS_IMETHODIMP_(bool) +IDBDatabase::IsShuttingDown() { - return IsInvalidated(); + return QuotaManager::IsShuttingDown(); } -bool -IDBDatabase::IsStorageShuttingDown() -{ - return IndexedDatabaseManager::IsShuttingDown(); -} - -void +NS_IMETHODIMP_(void) IDBDatabase::SetThreadLocals() { NS_ASSERTION(GetOwner(), "Should have owner!"); QuotaManager::SetCurrentWindow(GetOwner()); } -void +NS_IMETHODIMP_(void) IDBDatabase::UnsetThreadLocals() { QuotaManager::SetCurrentWindow(nullptr); } +NS_IMETHODIMP_(mozilla::dom::quota::Client*) +IDBDatabase::GetClient() +{ + return mQuotaClient; +} + +NS_IMETHODIMP_(bool) +IDBDatabase::IsOwned(nsPIDOMWindow* aOwner) +{ + return GetOwner() == aOwner; +} + +NS_IMETHODIMP_(const nsACString&) +IDBDatabase::Origin() +{ + return mASCIIOrigin; +} + nsresult IDBDatabase::PostHandleEvent(nsEventChainPostVisitor& aVisitor) { diff --git a/dom/indexedDB/IDBDatabase.h b/dom/indexedDB/IDBDatabase.h index 5df1fb2a5647..016508fb7387 100644 --- a/dom/indexedDB/IDBDatabase.h +++ b/dom/indexedDB/IDBDatabase.h @@ -12,9 +12,12 @@ #include "nsIDocument.h" #include "nsIFileStorage.h" #include "nsIIDBDatabase.h" +#include "nsIOfflineStorage.h" + #include "nsDOMEventTargetHelper.h" -#include "mozilla/dom/indexedDB/IDBWrapperCache.h" + #include "mozilla/dom/indexedDB/FileManager.h" +#include "mozilla/dom/indexedDB/IDBWrapperCache.h" class nsIScriptContext; class nsPIDOMWindow; @@ -22,6 +25,9 @@ class nsPIDOMWindow; namespace mozilla { namespace dom { class ContentParent; +namespace quota { +class Client; +} } } @@ -40,7 +46,7 @@ struct ObjectStoreInfoGuts; class IDBDatabase : public IDBWrapperCache, public nsIIDBDatabase, - public nsIFileStorage + public nsIOfflineStorage { friend class AsyncConnectionHelper; friend class IndexedDatabaseManager; @@ -50,6 +56,7 @@ public: NS_DECL_ISUPPORTS_INHERITED NS_DECL_NSIIDBDATABASE NS_DECL_NSIFILESTORAGE + NS_DECL_NSIOFFLINESTORAGE_NOCLOSE NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(IDBDatabase, IDBWrapperCache) @@ -61,14 +68,19 @@ public: FileManager* aFileManager, mozilla::dom::ContentParent* aContentParent); + static IDBDatabase* + FromStorage(nsIOfflineStorage* aStorage); + + static IDBDatabase* + FromStorage(nsIFileStorage* aStorage) + { + nsCOMPtr storage = do_QueryInterface(aStorage); + return storage ? FromStorage(storage) : nullptr; + } + // nsIDOMEventTarget virtual nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor); - nsIAtom* Id() const - { - return mDatabaseId; - } - DatabaseInfo* Info() const { return mDatabaseInfo; @@ -95,28 +107,10 @@ public: return doc.forget(); } - const nsCString& Origin() const - { - return mASCIIOrigin; - } - - void Invalidate(); - - // Whether or not the database has been invalidated. If it has then no further - // transactions for this database will be allowed to run. This function may be - // called on any thread. - bool IsInvalidated() const - { - return mInvalidated; - } - void DisconnectFromActorParent(); void CloseInternal(bool aIsDead); - // Whether or not the database has had Close called on it. - bool IsClosed() const; - void EnterSetVersionTransaction(); void ExitSetVersionTransaction(); @@ -195,6 +189,8 @@ private: mozilla::dom::ContentParent* mContentParent; + nsRefPtr mQuotaClient; + bool mInvalidated; bool mRegistered; bool mClosed; diff --git a/dom/indexedDB/IDBFactory.cpp b/dom/indexedDB/IDBFactory.cpp index fefff8732e3a..5322eb5ffb91 100644 --- a/dom/indexedDB/IDBFactory.cpp +++ b/dom/indexedDB/IDBFactory.cpp @@ -18,6 +18,8 @@ #include "mozilla/dom/ContentParent.h" #include "mozilla/dom/ContentChild.h" #include "mozilla/dom/PBrowserChild.h" +#include "mozilla/dom/quota/OriginOrPatternString.h" +#include "mozilla/dom/quota/QuotaManager.h" #include "mozilla/dom/TabChild.h" #include "mozilla/storage.h" #include "nsComponentManagerUtils.h" @@ -45,6 +47,7 @@ #include USING_INDEXEDDB_NAMESPACE +USING_QUOTA_NAMESPACE using mozilla::dom::ContentChild; using mozilla::dom::ContentParent; @@ -103,7 +106,7 @@ IDBFactory::Create(nsPIDOMWindow* aWindow, // Make sure that the manager is up before we do anything here since lots of // decisions depend on which process we're running in. - nsRefPtr mgr = + indexedDB::IndexedDatabaseManager* mgr = indexedDB::IndexedDatabaseManager::GetOrCreate(); NS_ENSURE_TRUE(mgr, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); @@ -111,7 +114,7 @@ IDBFactory::Create(nsPIDOMWindow* aWindow, nsCString origin(aASCIIOrigin); if (origin.IsEmpty()) { - rv = IndexedDatabaseManager::GetASCIIOriginFromWindow(aWindow, origin); + rv = QuotaManager::GetASCIIOriginFromWindow(aWindow, origin); if (NS_FAILED(rv)) { // Not allowed. *aFactory = nullptr; @@ -161,8 +164,7 @@ IDBFactory::Create(JSContext* aCx, NS_ASSERTION(nsContentUtils::IsCallerChrome(), "Only for chrome!"); nsCString origin; - nsresult rv = - IndexedDatabaseManager::GetASCIIOriginFromWindow(nullptr, origin); + nsresult rv = QuotaManager::GetASCIIOriginFromWindow(nullptr, origin); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); nsRefPtr factory = new IDBFactory(); @@ -521,7 +523,7 @@ IDBFactory::OpenCommon(const nsAString& aName, nsCOMPtr window; JSObject* scriptOwner = nullptr; - FactoryPrivilege privilege; + StoragePrivilege privilege; if (mWindow) { window = mWindow; @@ -551,17 +553,17 @@ IDBFactory::OpenCommon(const nsAString& aName, nsRefPtr permissionHelper = new CheckPermissionsHelper(openHelper, window, aDeleting); - IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get(); - NS_ASSERTION(mgr, "This should never be null!"); + QuotaManager* quotaManager = QuotaManager::Get(); + NS_ASSERTION(quotaManager, "This should never be null!"); - rv = - mgr->WaitForOpenAllowed(OriginOrPatternString::FromOrigin(aASCIIOrigin), - openHelper->Id(), permissionHelper); + rv = quotaManager->WaitForOpenAllowed(OriginOrPatternString::FromOrigin( + aASCIIOrigin), openHelper->Id(), + permissionHelper); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); } else if (aDeleting) { nsCOMPtr databaseId = - IndexedDatabaseManager::GetDatabaseId(aASCIIOrigin, aName); + QuotaManager::GetStorageId(aASCIIOrigin, aName); NS_ENSURE_TRUE(databaseId, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); IndexedDBDeleteDatabaseRequestChild* actor = diff --git a/dom/indexedDB/IDBFileHandle.cpp b/dom/indexedDB/IDBFileHandle.cpp index f71fd56a917a..3f866441cb9d 100644 --- a/dom/indexedDB/IDBFileHandle.cpp +++ b/dom/indexedDB/IDBFileHandle.cpp @@ -67,7 +67,10 @@ IDBFileHandle::Create(IDBDatabase* aDatabase, already_AddRefed IDBFileHandle::CreateStream(nsIFile* aFile, bool aReadOnly) { - const nsACString& origin = mFileStorage->StorageOrigin(); + nsCOMPtr storage = do_QueryInterface(mFileStorage); + NS_ASSERTION(storage, "This should always succeed!"); + + const nsACString& origin = storage->Origin(); nsCOMPtr result; diff --git a/dom/indexedDB/IDBTransaction.h b/dom/indexedDB/IDBTransaction.h index 147f597303d1..fbbc2c410fc1 100644 --- a/dom/indexedDB/IDBTransaction.h +++ b/dom/indexedDB/IDBTransaction.h @@ -20,6 +20,7 @@ #include "nsClassHashtable.h" #include "nsHashKeys.h" #include "nsInterfaceHashtable.h" +#include "nsRefPtrHashtable.h" #include "mozilla/dom/indexedDB/IDBDatabase.h" #include "mozilla/dom/indexedDB/IDBWrapperCache.h" diff --git a/dom/indexedDB/IndexedDatabase.h b/dom/indexedDB/IndexedDatabase.h index c9ff94e05334..b0ea8965f6c9 100644 --- a/dom/indexedDB/IndexedDatabase.h +++ b/dom/indexedDB/IndexedDatabase.h @@ -36,11 +36,6 @@ class FileInfo; class IDBDatabase; class IDBTransaction; -enum FactoryPrivilege { - Content, - Chrome -}; - template void SwapData(T& aData1, T& aData2) { @@ -175,44 +170,6 @@ struct SerializedStructuredCloneWriteInfo uint64_t offsetToKeyProp; }; -class OriginOrPatternString : public nsCString -{ -public: - static OriginOrPatternString - FromOrigin(const nsACString& aOrigin) - { - return OriginOrPatternString(aOrigin, true); - } - - static OriginOrPatternString - FromPattern(const nsACString& aPattern) - { - return OriginOrPatternString(aPattern, false); - } - - bool - IsOrigin() const - { - return mIsOrigin; - } - - bool - IsPattern() const - { - return !mIsOrigin; - } - -private: - OriginOrPatternString(const nsACString& aOriginOrPattern, bool aIsOrigin) - : nsCString(aOriginOrPattern), mIsOrigin(aIsOrigin) - { } - - bool - operator==(const OriginOrPatternString& aOther) MOZ_DELETE; - - bool mIsOrigin; -}; - END_INDEXEDDB_NAMESPACE #endif // mozilla_dom_indexeddb_indexeddatabase_h__ diff --git a/dom/indexedDB/IndexedDatabaseInlines.h b/dom/indexedDB/IndexedDatabaseInlines.h index f27d60c3479b..62e65d6c5a90 100644 --- a/dom/indexedDB/IndexedDatabaseInlines.h +++ b/dom/indexedDB/IndexedDatabaseInlines.h @@ -79,17 +79,4 @@ AppendConditionClause(const nsACString& aColumnName, aResult += NS_LITERAL_CSTRING(" :") + aArgName; } -inline void -IncrementUsage(uint64_t* aUsage, uint64_t aDelta) -{ - // Watch for overflow! - if ((UINT64_MAX - *aUsage) < aDelta) { - NS_WARNING("Usage exceeds the maximum!"); - *aUsage = UINT64_MAX; - } - else { - *aUsage += aDelta; - } -} - END_INDEXEDDB_NAMESPACE diff --git a/dom/indexedDB/IndexedDatabaseManager.cpp b/dom/indexedDB/IndexedDatabaseManager.cpp index 3f92a4b12530..7142480aa5ac 100644 --- a/dom/indexedDB/IndexedDatabaseManager.cpp +++ b/dom/indexedDB/IndexedDatabaseManager.cpp @@ -6,245 +6,52 @@ #include "IndexedDatabaseManager.h" -#include "mozIApplicationClearPrivateDataParams.h" -#include "nsIAtom.h" #include "nsIConsoleService.h" #include "nsIDOMScriptObjectFactory.h" #include "nsIFile.h" #include "nsIFileStorage.h" -#include "nsIObserverService.h" -#include "nsIPrincipal.h" #include "nsIScriptError.h" -#include "nsIScriptObjectPrincipal.h" -#include "nsIScriptSecurityManager.h" -#include "nsISHEntry.h" -#include "nsISimpleEnumerator.h" -#include "nsITimer.h" -#include "mozilla/dom/file/FileService.h" +#include "mozilla/ClearOnShutdown.h" #include "mozilla/dom/quota/QuotaManager.h" +#include "mozilla/dom/quota/Utilities.h" #include "mozilla/dom/TabContext.h" -#include "mozilla/LazyIdleThread.h" -#include "mozilla/Preferences.h" -#include "mozilla/Services.h" #include "mozilla/storage.h" -#include "nsAppDirectoryServiceDefs.h" #include "nsContentUtils.h" -#include "nsCRTGlue.h" -#include "nsDirectoryServiceUtils.h" #include "nsEventDispatcher.h" -#include "nsScriptSecurityManager.h" #include "nsThreadUtils.h" -#include "nsXPCOM.h" -#include "nsXPCOMPrivate.h" -#include "AsyncConnectionHelper.h" -#include "IDBDatabase.h" #include "IDBEvents.h" #include "IDBFactory.h" #include "IDBKeyRange.h" -#include "OpenDatabaseHelper.h" -#include "TransactionThreadPool.h" - -#include "IndexedDatabaseInlines.h" -#include - -// The amount of time, in milliseconds, that our IO thread will stay alive -// after the last event it processes. -#define DEFAULT_THREAD_TIMEOUT_MS 30000 - -// The amount of time, in milliseconds, that we will wait for active database -// transactions on shutdown before aborting them. -#define DEFAULT_SHUTDOWN_TIMER_MS 30000 - -// Amount of space that IndexedDB databases may use by default in megabytes. -#define DEFAULT_QUOTA_MB 50 - -// Preference that users can set to override DEFAULT_QUOTA_MB -#define PREF_INDEXEDDB_QUOTA "dom.indexedDB.warningQuota" - -// profile-before-change, when we need to shut down IDB -#define PROFILE_BEFORE_CHANGE_OBSERVER_ID "profile-before-change" +#include "IDBRequest.h" USING_INDEXEDDB_NAMESPACE -using namespace mozilla::services; using namespace mozilla::dom; -using mozilla::Preferences; -using mozilla::dom::file::FileService; -using mozilla::dom::quota::QuotaManager; +USING_QUOTA_NAMESPACE static NS_DEFINE_CID(kDOMSOF_CID, NS_DOM_SCRIPT_OBJECT_FACTORY_CID); namespace { -int32_t gShutdown = 0; +mozilla::StaticRefPtr gInstance; + +int32_t gInitialized = 0; int32_t gClosed = 0; -// Does not hold a reference. -IndexedDatabaseManager* gInstance = nullptr; - -int32_t gIndexedDBQuotaMB = DEFAULT_QUOTA_MB; - -bool -GetDatabaseBaseFilename(const nsAString& aFilename, - nsAString& aDatabaseBaseFilename) +class AsyncDeleteFileRunnable MOZ_FINAL : public nsIRunnable { - NS_ASSERTION(!aFilename.IsEmpty(), "Bad argument!"); - - NS_NAMED_LITERAL_STRING(sqlite, ".sqlite"); - nsAString::size_type filenameLen = aFilename.Length(); - nsAString::size_type sqliteLen = sqlite.Length(); - - if (sqliteLen > filenameLen || - Substring(aFilename, filenameLen - sqliteLen, sqliteLen) != sqlite) { - return false; - } - - aDatabaseBaseFilename = Substring(aFilename, 0, filenameLen - sqliteLen); - - return true; -} - -// Adds all databases in the hash to the given array. -template -PLDHashOperator -EnumerateToTArray(const nsACString& aKey, - nsTArray* aValue, - void* aUserArg) -{ - NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); - NS_ASSERTION(!aKey.IsEmpty(), "Empty key!"); - NS_ASSERTION(aValue, "Null pointer!"); - NS_ASSERTION(aUserArg, "Null pointer!"); - - static_cast*>(aUserArg)->AppendElements(*aValue); - return PL_DHASH_NEXT; -} - -bool -PatternMatchesOrigin(const nsACString& aPatternString, const nsACString& aOrigin) -{ - // Aren't we smart! - return StringBeginsWith(aOrigin, aPatternString); -} - -enum MozBrowserPatternFlag -{ - MozBrowser = 0, - NotMozBrowser, - IgnoreMozBrowser -}; - -// Use one of the friendly overloads below. -void -GetOriginPatternString(uint32_t aAppId, MozBrowserPatternFlag aBrowserFlag, - const nsACString& aOrigin, nsAutoCString& _retval) -{ - NS_ASSERTION(aAppId != nsIScriptSecurityManager::UNKNOWN_APP_ID, - "Bad appId!"); - NS_ASSERTION(aOrigin.IsEmpty() || aBrowserFlag != IgnoreMozBrowser, - "Bad args!"); - - if (aOrigin.IsEmpty()) { - _retval.Truncate(); - - _retval.AppendInt(aAppId); - _retval.Append('+'); - - if (aBrowserFlag != IgnoreMozBrowser) { - if (aBrowserFlag == MozBrowser) { - _retval.Append('t'); - } - else { - _retval.Append('f'); - } - _retval.Append('+'); - } - - return; - } - -#ifdef DEBUG - if (aAppId != nsIScriptSecurityManager::NO_APP_ID || - aBrowserFlag == MozBrowser) { - nsAutoCString pattern; - GetOriginPatternString(aAppId, aBrowserFlag, EmptyCString(), pattern); - NS_ASSERTION(PatternMatchesOrigin(pattern, aOrigin), - "Origin doesn't match parameters!"); - } -#endif - - _retval = aOrigin; -} - -void -GetOriginPatternString(uint32_t aAppId, bool aBrowserOnly, - const nsACString& aOrigin, nsAutoCString& _retval) -{ - return GetOriginPatternString(aAppId, - aBrowserOnly ? MozBrowser : NotMozBrowser, - aOrigin, _retval); -} - -void -GetOriginPatternStringMaybeIgnoreBrowser(uint32_t aAppId, bool aBrowserOnly, - nsAutoCString& _retval) -{ - return GetOriginPatternString(aAppId, - aBrowserOnly ? MozBrowser : IgnoreMozBrowser, - EmptyCString(), _retval); -} - -template -class PatternMatchArray : public nsAutoTArray -{ - typedef PatternMatchArray SelfType; - - struct Closure - { - Closure(SelfType& aSelf, const nsACString& aPattern) - : mSelf(aSelf), mPattern(aPattern) - { } - - SelfType& mSelf; - const nsACString& mPattern; - }; - public: - template - void - Find(const T& aHashtable, - const nsACString& aPattern) - { - SelfType::Clear(); + NS_DECL_ISUPPORTS + NS_DECL_NSIRUNNABLE - Closure closure(*this, aPattern); - aHashtable.EnumerateRead(SelfType::Enumerate, &closure); - } + AsyncDeleteFileRunnable(FileManager* aFileManager, int64_t aFileId); private: - static PLDHashOperator - Enumerate(const nsACString& aKey, - nsTArray* aValue, - void* aUserArg) - { - NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); - NS_ASSERTION(!aKey.IsEmpty(), "Empty key!"); - NS_ASSERTION(aValue, "Null pointer!"); - NS_ASSERTION(aUserArg, "Null pointer!"); - - Closure* closure = static_cast(aUserArg); - - if (PatternMatchesOrigin(closure->mPattern, aKey)) { - closure->mSelf.AppendElements(*aValue); - } - - return PL_DHASH_NEXT; - } + nsRefPtr mFileManager; + int64_t mFileId; }; -typedef PatternMatchArray DatabasePatternMatchArray; - PLDHashOperator InvalidateAndRemoveFileManagers( const nsACString& aKey, @@ -269,176 +76,52 @@ InvalidateAndRemoveFileManagers( return PL_DHASH_NEXT; } -void -SanitizeOriginString(nsCString& aOrigin) -{ - // We want profiles to be platform-independent so we always need to replace - // the same characters on every platform. Windows has the most extensive set - // of illegal characters so we use its FILE_ILLEGAL_CHARACTERS and - // FILE_PATH_SEPARATOR. - static const char kReplaceChars[] = CONTROL_CHARACTERS "/:*?\"<>|\\"; - -#ifdef XP_WIN - NS_ASSERTION(!strcmp(kReplaceChars, - FILE_ILLEGAL_CHARACTERS FILE_PATH_SEPARATOR), - "Illegal file characters have changed!"); -#endif - - aOrigin.ReplaceChar(kReplaceChars, '+'); -} - -nsresult -GetASCIIOriginFromURI(nsIURI* aURI, - uint32_t aAppId, - bool aInMozBrowser, - nsACString& aOrigin) -{ - NS_ASSERTION(aURI, "Null uri!"); - - nsCString origin; - mozilla::GetExtendedOrigin(aURI, aAppId, aInMozBrowser, origin); - - if (origin.IsEmpty()) { - NS_WARNING("GetExtendedOrigin returned empty string!"); - return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; - } - - aOrigin.Assign(origin); - return NS_OK; -} - -nsresult -GetASCIIOriginFromPrincipal(nsIPrincipal* aPrincipal, - nsACString& aOrigin) -{ - NS_ASSERTION(aPrincipal, "Don't hand me a null principal!"); - - static const char kChromeOrigin[] = "chrome"; - - nsCString origin; - if (nsContentUtils::IsSystemPrincipal(aPrincipal)) { - origin.AssignLiteral(kChromeOrigin); - } - else { - bool isNullPrincipal; - nsresult rv = aPrincipal->GetIsNullPrincipal(&isNullPrincipal); - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - - if (isNullPrincipal) { - NS_WARNING("IndexedDB not supported from this principal!"); - return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; - } - - rv = aPrincipal->GetExtendedOrigin(origin); - NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - - if (origin.EqualsLiteral(kChromeOrigin)) { - NS_WARNING("Non-chrome principal can't use chrome origin!"); - return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; - } - } - - aOrigin.Assign(origin); - return NS_OK; -} - } // anonymous namespace IndexedDatabaseManager::IndexedDatabaseManager() : mFileMutex("IndexedDatabaseManager.mFileMutex") { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); - NS_ASSERTION(!gInstance, "More than one instance!"); + + mFileManagers.Init(); } IndexedDatabaseManager::~IndexedDatabaseManager() { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); - NS_ASSERTION(!gInstance || gInstance == this, "Different instances!"); - gInstance = nullptr; } bool IndexedDatabaseManager::sIsMainProcess = false; // static -already_AddRefed +IndexedDatabaseManager* IndexedDatabaseManager::GetOrCreate() { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); - if (IsShuttingDown()) { - NS_ERROR("Calling GetOrCreateInstance() after shutdown!"); + if (IsClosed()) { + NS_ERROR("Calling GetOrCreate() after shutdown!"); return nullptr; } - nsRefPtr instance(gInstance); - - if (!instance) { + if (!gInstance) { sIsMainProcess = XRE_GetProcessType() == GeckoProcessType_Default; - instance = new IndexedDatabaseManager(); + nsRefPtr instance(new IndexedDatabaseManager()); - instance->mLiveDatabases.Init(); - instance->mFileManagers.Init(); - - nsresult rv; - - if (sIsMainProcess) { - nsCOMPtr dbBaseDirectory; - rv = NS_GetSpecialDirectory(NS_APP_INDEXEDDB_PARENT_DIR, - getter_AddRefs(dbBaseDirectory)); - if (NS_FAILED(rv)) { - rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, - getter_AddRefs(dbBaseDirectory)); - } - NS_ENSURE_SUCCESS(rv, nullptr); - - rv = dbBaseDirectory->Append(NS_LITERAL_STRING("indexedDB")); - NS_ENSURE_SUCCESS(rv, nullptr); - - rv = dbBaseDirectory->GetPath(instance->mDatabaseBasePath); - NS_ENSURE_SUCCESS(rv, nullptr); - - // Make a lazy thread for any IO we need (like clearing or enumerating the - // contents of indexedDB database directories). - instance->mIOThread = - new LazyIdleThread(DEFAULT_THREAD_TIMEOUT_MS, - NS_LITERAL_CSTRING("IndexedDB I/O"), - LazyIdleThread::ManualShutdown); - - // Make a timer here to avoid potential failures later. We don't actually - // initialize the timer until shutdown. - instance->mShutdownTimer = do_CreateInstance(NS_TIMER_CONTRACTID); - NS_ENSURE_TRUE(instance->mShutdownTimer, nullptr); - } - - // Make sure that the quota manager is up. - NS_ENSURE_TRUE(QuotaManager::GetOrCreate(), nullptr); - - nsCOMPtr obs = GetObserverService(); - NS_ENSURE_TRUE(obs, nullptr); - - // Must initialize the storage service on the main thread. - nsCOMPtr ss = - do_GetService(MOZ_STORAGE_SERVICE_CONTRACTID); - NS_ENSURE_TRUE(ss, nullptr); - - // We need this callback to know when to shut down all our threads. - rv = obs->AddObserver(instance, PROFILE_BEFORE_CHANGE_OBSERVER_ID, false); + nsresult rv = instance->Init(); NS_ENSURE_SUCCESS(rv, nullptr); - if (NS_FAILED(Preferences::AddIntVarCache(&gIndexedDBQuotaMB, - PREF_INDEXEDDB_QUOTA, - DEFAULT_QUOTA_MB))) { - NS_WARNING("Unable to respond to quota pref changes!"); - gIndexedDBQuotaMB = DEFAULT_QUOTA_MB; + if (PR_ATOMIC_SET(&gInitialized, 1)) { + NS_ERROR("Initialized more than once?!"); } - // The observer service will hold our last reference, don't AddRef here. gInstance = instance; + + ClearOnShutdown(&gInstance); } - return instance.forget(); + return gInstance; } // static @@ -455,44 +138,35 @@ IndexedDatabaseManager::FactoryCreate() { // Returns a raw pointer that carries an owning reference! Lame, but the // singleton factory macros force this. - return GetOrCreate().get(); + IndexedDatabaseManager* mgr = GetOrCreate(); + NS_IF_ADDREF(mgr); + return mgr; } nsresult -IndexedDatabaseManager::GetDirectoryForOrigin(const nsACString& aASCIIOrigin, - nsIFile** aDirectory) const +IndexedDatabaseManager::Init() { - nsresult rv; - nsCOMPtr directory = - do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv); - NS_ENSURE_SUCCESS(rv, rv); + // Make sure that the quota manager is up. + NS_ENSURE_TRUE(QuotaManager::GetOrCreate(), NS_ERROR_FAILURE); - rv = directory->InitWithPath(GetBaseDirectory()); - NS_ENSURE_SUCCESS(rv, rv); + // Must initialize the storage service on the main thread. + nsCOMPtr ss = + do_GetService(MOZ_STORAGE_SERVICE_CONTRACTID); + NS_ENSURE_TRUE(ss, NS_ERROR_FAILURE); - nsAutoCString originSanitized(aASCIIOrigin); - SanitizeOriginString(originSanitized); - - rv = directory->Append(NS_ConvertASCIItoUTF16(originSanitized)); - NS_ENSURE_SUCCESS(rv, rv); - - directory.forget(aDirectory); return NS_OK; } -// static -already_AddRefed -IndexedDatabaseManager::GetDatabaseId(const nsACString& aOrigin, - const nsAString& aName) +void +IndexedDatabaseManager::Destroy() { - nsCString str(aOrigin); - str.Append("*"); - str.Append(NS_ConvertUTF16toUTF8(aName)); + // Setting the closed flag prevents the service from being recreated. + // Don't set it though if there's no real instance created. + if (!!gInitialized && PR_ATOMIC_SET(&gClosed, 1)) { + NS_ERROR("Shutdown more than once?!"); + } - nsCOMPtr atom = do_GetAtom(str); - NS_ENSURE_TRUE(atom, nullptr); - - return atom.forget(); + delete this; } // static @@ -590,223 +264,14 @@ IndexedDatabaseManager::TabContextMayAccessOrigin(const TabContext& aContext, // browser elements. But if aContext is not for a browser element, it may // access both browser and non-browser elements. nsAutoCString pattern; - GetOriginPatternStringMaybeIgnoreBrowser(aContext.OwnOrContainingAppId(), - aContext.IsBrowserElement(), - pattern); + QuotaManager::GetOriginPatternStringMaybeIgnoreBrowser( + aContext.OwnOrContainingAppId(), + aContext.IsBrowserElement(), + pattern); return PatternMatchesOrigin(pattern, aOrigin); } -bool -IndexedDatabaseManager::RegisterDatabase(IDBDatabase* aDatabase) -{ - NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); - NS_ASSERTION(aDatabase, "Null pointer!"); - - // Don't allow any new databases to be created after shutdown. - if (IsShuttingDown()) { - return false; - } - - // Add this database to its origin array if it exists, create it otherwise. - nsTArray* array; - if (!mLiveDatabases.Get(aDatabase->Origin(), &array)) { - nsAutoPtr > newArray(new nsTArray()); - mLiveDatabases.Put(aDatabase->Origin(), newArray); - array = newArray.forget(); - } - if (!array->AppendElement(aDatabase)) { - NS_WARNING("Out of memory?"); - return false; - } - - aDatabase->mRegistered = true; - return true; -} - -void -IndexedDatabaseManager::UnregisterDatabase(IDBDatabase* aDatabase) -{ - NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); - NS_ASSERTION(aDatabase, "Null pointer!"); - - // Remove this database from its origin array, maybe remove the array if it - // is then empty. - nsTArray* array; - if (mLiveDatabases.Get(aDatabase->Origin(), &array) && - array->RemoveElement(aDatabase)) { - if (array->IsEmpty()) { - mLiveDatabases.Remove(aDatabase->Origin()); - } - return; - } - NS_ERROR("Didn't know anything about this database!"); -} - -void -IndexedDatabaseManager::OnUsageCheckComplete(AsyncUsageRunnable* aRunnable) -{ - NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); - NS_ASSERTION(aRunnable, "Null pointer!"); - NS_ASSERTION(!aRunnable->mURI, "Should have been cleared!"); - NS_ASSERTION(!aRunnable->mCallback, "Should have been cleared!"); - - if (!mUsageRunnables.RemoveElement(aRunnable)) { - NS_ERROR("Don't know anything about this runnable!"); - } -} - -nsresult -IndexedDatabaseManager::WaitForOpenAllowed( - const OriginOrPatternString& aOriginOrPattern, - nsIAtom* aId, - nsIRunnable* aRunnable) -{ - NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); - NS_ASSERTION(!aOriginOrPattern.IsEmpty(), "Empty pattern!"); - NS_ASSERTION(aRunnable, "Null pointer!"); - - nsAutoPtr op(new SynchronizedOp(aOriginOrPattern, aId)); - - // See if this runnable needs to wait. - bool delayed = false; - for (uint32_t index = mSynchronizedOps.Length(); index > 0; index--) { - nsAutoPtr& existingOp = mSynchronizedOps[index - 1]; - if (op->MustWaitFor(*existingOp)) { - existingOp->DelayRunnable(aRunnable); - delayed = true; - break; - } - } - - // Otherwise, dispatch it immediately. - if (!delayed) { - nsresult rv = NS_DispatchToCurrentThread(aRunnable); - NS_ENSURE_SUCCESS(rv, rv); - } - - // Adding this to the synchronized ops list will block any additional - // ops from proceeding until this one is done. - mSynchronizedOps.AppendElement(op.forget()); - - return NS_OK; -} - -void -IndexedDatabaseManager::AllowNextSynchronizedOp( - const OriginOrPatternString& aOriginOrPattern, - nsIAtom* aId) -{ - NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); - NS_ASSERTION(!aOriginOrPattern.IsEmpty(), "Empty origin/pattern!"); - - uint32_t count = mSynchronizedOps.Length(); - for (uint32_t index = 0; index < count; index++) { - nsAutoPtr& op = mSynchronizedOps[index]; - if (op->mOriginOrPattern.IsOrigin() == aOriginOrPattern.IsOrigin() && - op->mOriginOrPattern == aOriginOrPattern) { - if (op->mId == aId) { - NS_ASSERTION(op->mDatabases.IsEmpty(), "How did this happen?"); - - op->DispatchDelayedRunnables(); - - mSynchronizedOps.RemoveElementAt(index); - return; - } - - // If one or the other is for an origin clear, we should have matched - // solely on origin. - NS_ASSERTION(op->mId && aId, "Why didn't we match earlier?"); - } - } - - NS_NOTREACHED("Why didn't we find a SynchronizedOp?"); -} - -nsresult -IndexedDatabaseManager::AcquireExclusiveAccess( - const nsACString& aPattern, - IDBDatabase* aDatabase, - AsyncConnectionHelper* aHelper, - nsIRunnable* aRunnable, - WaitingOnDatabasesCallback aCallback, - void* aClosure) -{ - NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); - NS_ASSERTION(!aDatabase || aHelper, "Need a helper with a database!"); - NS_ASSERTION(aDatabase || aRunnable, "Need a runnable without a database!"); - - // Find the right SynchronizedOp. - SynchronizedOp* op = - FindSynchronizedOp(aPattern, aDatabase ? aDatabase->Id() : nullptr); - - NS_ASSERTION(op, "We didn't find a SynchronizedOp?"); - NS_ASSERTION(!op->mHelper, "SynchronizedOp already has a helper?!?"); - NS_ASSERTION(!op->mRunnable, "SynchronizedOp already has a runnable?!?"); - - DatabasePatternMatchArray matches; - matches.Find(mLiveDatabases, aPattern); - - // We need to wait for the databases to go away. - // Hold on to all database objects that represent the same database file - // (except the one that is requesting this version change). - nsTArray > liveDatabases; - - if (!matches.IsEmpty()) { - if (aDatabase) { - // Grab all databases that are not yet closed but whose database id match - // the one we're looking for. - for (uint32_t index = 0; index < matches.Length(); index++) { - IDBDatabase*& database = matches[index]; - if (!database->IsClosed() && - database != aDatabase && - database->Id() == aDatabase->Id()) { - liveDatabases.AppendElement(database); - } - } - } - else { - // We want *all* databases, even those that are closed, if we're going to - // clear the origin. - liveDatabases.AppendElements(matches); - } - } - - op->mHelper = aHelper; - op->mRunnable = aRunnable; - - if (!liveDatabases.IsEmpty()) { - NS_ASSERTION(op->mDatabases.IsEmpty(), - "How do we already have databases here?"); - op->mDatabases.AppendElements(liveDatabases); - - // Give our callback the databases so it can decide what to do with them. - aCallback(liveDatabases, aClosure); - - NS_ASSERTION(liveDatabases.IsEmpty(), - "Should have done something with the array!"); - - if (aDatabase) { - // Wait for those databases to close. - return NS_OK; - } - } - - // If we're trying to open a database and nothing blocks it, or if we're - // clearing an origin, then go ahead and schedule the op. - nsresult rv = RunSynchronizedOp(aDatabase, op); - NS_ENSURE_SUCCESS(rv, rv); - - return NS_OK; -} - -// static -bool -IndexedDatabaseManager::IsShuttingDown() -{ - return !!gShutdown; -} - // static bool IndexedDatabaseManager::IsClosed() @@ -814,307 +279,6 @@ IndexedDatabaseManager::IsClosed() return !!gClosed; } -void -IndexedDatabaseManager::AbortCloseDatabasesForWindow(nsPIDOMWindow* aWindow) -{ - NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); - NS_ASSERTION(aWindow, "Null pointer!"); - - nsAutoTArray liveDatabases; - mLiveDatabases.EnumerateRead(EnumerateToTArray, - &liveDatabases); - - FileService* service = FileService::Get(); - TransactionThreadPool* pool = TransactionThreadPool::Get(); - - for (uint32_t index = 0; index < liveDatabases.Length(); index++) { - IDBDatabase*& database = liveDatabases[index]; - if (database->GetOwner() == aWindow) { - if (NS_FAILED(database->Close())) { - NS_WARNING("Failed to close database for dying window!"); - } - - if (service) { - service->AbortLockedFilesForStorage(database); - } - - if (pool) { - pool->AbortTransactionsForDatabase(database); - } - } - } -} - -bool -IndexedDatabaseManager::HasOpenTransactions(nsPIDOMWindow* aWindow) -{ - NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); - NS_ASSERTION(aWindow, "Null pointer!"); - - nsAutoTArray liveDatabases; - mLiveDatabases.EnumerateRead(EnumerateToTArray, - &liveDatabases); - - FileService* service = FileService::Get(); - TransactionThreadPool* pool = TransactionThreadPool::Get(); - if (!service && !pool) { - return false; - } - - for (uint32_t index = 0; index < liveDatabases.Length(); index++) { - IDBDatabase*& database = liveDatabases[index]; - if (database->GetOwner() == aWindow && - ((service && service->HasLockedFilesForStorage(database)) || - (pool && pool->HasTransactionsForDatabase(database)))) { - return true; - } - } - - return false; -} - -void -IndexedDatabaseManager::OnDatabaseClosed(IDBDatabase* aDatabase) -{ - NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); - NS_ASSERTION(aDatabase, "Null pointer!"); - - // Check through the list of SynchronizedOps to see if any are waiting for - // this database to close before proceeding. - SynchronizedOp* op = FindSynchronizedOp(aDatabase->Origin(), aDatabase->Id()); - if (op) { - // This database is in the scope of this SynchronizedOp. Remove it - // from the list if necessary. - if (op->mDatabases.RemoveElement(aDatabase)) { - // Now set up the helper if there are no more live databases. - NS_ASSERTION(op->mHelper || op->mRunnable, - "How did we get rid of the helper/runnable before " - "removing the last database?"); - if (op->mDatabases.IsEmpty()) { - // At this point, all databases are closed, so no new transactions - // can be started. There may, however, still be outstanding - // transactions that have not completed. We need to wait for those - // before we dispatch the helper. - if (NS_FAILED(RunSynchronizedOp(aDatabase, op))) { - NS_WARNING("Failed to run synchronized op!"); - } - } - } - } -} - -// static -uint32_t -IndexedDatabaseManager::GetIndexedDBQuotaMB() -{ - return uint32_t(std::max(gIndexedDBQuotaMB, 0)); -} - -nsresult -IndexedDatabaseManager::EnsureOriginIsInitialized(const nsACString& aOrigin, - FactoryPrivilege aPrivilege, - nsIFile** aDirectory) -{ -#ifdef DEBUG - { - bool correctThread; - NS_ASSERTION(NS_SUCCEEDED(mIOThread->IsOnCurrentThread(&correctThread)) && - correctThread, - "Running on the wrong thread!"); - } -#endif - - nsCOMPtr directory; - nsresult rv = GetDirectoryForOrigin(aOrigin, getter_AddRefs(directory)); - NS_ENSURE_SUCCESS(rv, rv); - - bool exists; - rv = directory->Exists(&exists); - NS_ENSURE_SUCCESS(rv, rv); - - if (exists) { - bool isDirectory; - rv = directory->IsDirectory(&isDirectory); - NS_ENSURE_SUCCESS(rv, rv); - NS_ENSURE_TRUE(isDirectory, NS_ERROR_UNEXPECTED); - } - else { - rv = directory->Create(nsIFile::DIRECTORY_TYPE, 0755); - NS_ENSURE_SUCCESS(rv, rv); - } - - if (mInitializedOrigins.Contains(aOrigin)) { - NS_ADDREF(*aDirectory = directory); - return NS_OK; - } - - // We need to see if there are any files in the directory already. If they - // are database files then we need to cleanup stored files (if it's needed) - // and also initialize the quota. - - nsAutoTArray subdirsToProcess; - nsAutoTArray , 20> unknownFiles; - - uint64_t usage = 0; - - nsTHashtable validSubdirs; - validSubdirs.Init(20); - - nsCOMPtr entries; - rv = directory->GetDirectoryEntries(getter_AddRefs(entries)); - NS_ENSURE_SUCCESS(rv, rv); - - bool hasMore; - while (NS_SUCCEEDED((rv = entries->HasMoreElements(&hasMore))) && hasMore) { - nsCOMPtr entry; - rv = entries->GetNext(getter_AddRefs(entry)); - NS_ENSURE_SUCCESS(rv, rv); - - nsCOMPtr file = do_QueryInterface(entry); - NS_ENSURE_TRUE(file, NS_NOINTERFACE); - - nsString leafName; - rv = file->GetLeafName(leafName); - NS_ENSURE_SUCCESS(rv, rv); - - if (StringEndsWith(leafName, NS_LITERAL_STRING(".sqlite-journal"))) { - continue; - } - - bool isDirectory; - rv = file->IsDirectory(&isDirectory); - NS_ENSURE_SUCCESS(rv, rv); - - if (isDirectory) { - if (!validSubdirs.GetEntry(leafName)) { - subdirsToProcess.AppendElement(leafName); - } - continue; - } - - nsString dbBaseFilename; - if (!GetDatabaseBaseFilename(leafName, dbBaseFilename)) { - unknownFiles.AppendElement(file); - continue; - } - - nsCOMPtr fmDirectory; - rv = directory->Clone(getter_AddRefs(fmDirectory)); - NS_ENSURE_SUCCESS(rv, rv); - - rv = fmDirectory->Append(dbBaseFilename); - NS_ENSURE_SUCCESS(rv, rv); - - rv = FileManager::InitDirectory(fmDirectory, file, aOrigin); - NS_ENSURE_SUCCESS(rv, rv); - - if (aPrivilege != Chrome) { - uint64_t fileUsage; - rv = FileManager::GetUsage(fmDirectory, &fileUsage); - NS_ENSURE_SUCCESS(rv, rv); - - IncrementUsage(&usage, fileUsage); - - int64_t fileSize; - rv = file->GetFileSize(&fileSize); - NS_ENSURE_SUCCESS(rv, rv); - - IncrementUsage(&usage, uint64_t(fileSize)); - } - - validSubdirs.PutEntry(dbBaseFilename); - } - NS_ENSURE_SUCCESS(rv, rv); - - for (uint32_t i = 0; i < subdirsToProcess.Length(); i++) { - const nsString& subdir = subdirsToProcess[i]; - if (!validSubdirs.GetEntry(subdir)) { - NS_WARNING("Unknown subdirectory found!"); - return NS_ERROR_UNEXPECTED; - } - } - - for (uint32_t i = 0; i < unknownFiles.Length(); i++) { - nsCOMPtr& unknownFile = unknownFiles[i]; - - // Some temporary SQLite files could disappear, so we have to check if the - // unknown file still exists. - bool exists; - rv = unknownFile->Exists(&exists); - NS_ENSURE_SUCCESS(rv, rv); - - if (exists) { - nsString leafName; - unknownFile->GetLeafName(leafName); - - // The journal file may exists even after db has been correctly opened. - if (!StringEndsWith(leafName, NS_LITERAL_STRING(".sqlite-journal"))) { - NS_WARNING("Unknown file found!"); - return NS_ERROR_UNEXPECTED; - } - } - } - - if (aPrivilege != Chrome) { - QuotaManager* quotaManager = QuotaManager::Get(); - NS_ASSERTION(quotaManager, "Shouldn't be null!"); - - quotaManager->InitQuotaForOrigin(aOrigin, GetIndexedDBQuotaMB(), usage); - } - - mInitializedOrigins.AppendElement(aOrigin); - - NS_ADDREF(*aDirectory = directory); - return NS_OK; -} - -void -IndexedDatabaseManager::UninitializeOriginsByPattern( - const nsACString& aPattern) -{ -#ifdef DEBUG - { - bool correctThread; - NS_ASSERTION(NS_SUCCEEDED(mIOThread->IsOnCurrentThread(&correctThread)) && - correctThread, - "Running on the wrong thread!"); - } -#endif - - for (int32_t i = mInitializedOrigins.Length() - 1; i >= 0; i--) { - if (PatternMatchesOrigin(aPattern, mInitializedOrigins[i])) { - mInitializedOrigins.RemoveElementAt(i); - } - } -} - -// static -nsresult -IndexedDatabaseManager::GetASCIIOriginFromWindow(nsPIDOMWindow* aWindow, - nsCString& aASCIIOrigin) -{ - NS_ASSERTION(NS_IsMainThread(), - "We're about to touch a window off the main thread!"); - - if (!aWindow) { - aASCIIOrigin.AssignLiteral("chrome"); - NS_ASSERTION(nsContentUtils::IsCallerChrome(), - "Null window but not chrome!"); - return NS_OK; - } - - nsCOMPtr sop = do_QueryInterface(aWindow); - NS_ENSURE_TRUE(sop, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - - nsCOMPtr principal = sop->GetPrincipal(); - NS_ENSURE_TRUE(principal, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); - - nsresult rv = GetASCIIOriginFromPrincipal(principal, aASCIIOrigin); - NS_ENSURE_SUCCESS(rv, rv); - - return NS_OK; -} - #ifdef DEBUG //static bool @@ -1145,7 +309,7 @@ IndexedDatabaseManager::GetFileManager(const nsACString& aOrigin, return result.forget(); } } - + return nullptr; } @@ -1163,6 +327,12 @@ IndexedDatabaseManager::AddFileManager(FileManager* aFileManager) array->AppendElement(aFileManager); } +void +IndexedDatabaseManager::InvalidateAllFileManagers() +{ + mFileManagers.Enumerate(InvalidateAndRemoveFileManagers, nullptr); +} + void IndexedDatabaseManager::InvalidateFileManagersForPattern( const nsACString& aPattern) @@ -1204,906 +374,28 @@ IndexedDatabaseManager::AsyncDeleteFile(FileManager* aFileManager, NS_ENSURE_ARG_POINTER(aFileManager); - // See if we're currently clearing the databases for this origin. If so then + QuotaManager* quotaManager = QuotaManager::Get(); + NS_ASSERTION(quotaManager, "Shouldn't be null!"); + + // See if we're currently clearing the storages for this origin. If so then // we pretend that we've already deleted everything. - if (IsClearOriginPending(aFileManager->Origin())) { + if (quotaManager->IsClearOriginPending(aFileManager->Origin())) { return NS_OK; } nsRefPtr runnable = new AsyncDeleteFileRunnable(aFileManager, aFileId); - nsresult rv = mIOThread->Dispatch(runnable, NS_DISPATCH_NORMAL); + nsresult rv = + quotaManager->IOThread()->Dispatch(runnable, NS_DISPATCH_NORMAL); NS_ENSURE_SUCCESS(rv, rv); return NS_OK; } -// static -nsresult -IndexedDatabaseManager::RunSynchronizedOp(IDBDatabase* aDatabase, - SynchronizedOp* aOp) -{ - NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); - NS_ASSERTION(aOp, "Null pointer!"); - NS_ASSERTION(!aDatabase || aOp->mHelper, "No helper on this op!"); - NS_ASSERTION(aDatabase || aOp->mRunnable, "No runnable on this op!"); - NS_ASSERTION(!aDatabase || aOp->mDatabases.IsEmpty(), - "This op isn't ready to run!"); - - FileService* service = FileService::Get(); - TransactionThreadPool* pool = TransactionThreadPool::Get(); - - nsTArray databases; - if (aDatabase) { - if (service || pool) { - databases.AppendElement(aDatabase); - } - } - else { - aOp->mDatabases.SwapElements(databases); - } - - uint32_t waitCount = service && pool && !databases.IsEmpty() ? 2 : 1; - - nsRefPtr runnable = - new WaitForTransactionsToFinishRunnable(aOp, waitCount); - - // There's no point in delaying if we don't yet have a transaction thread pool - // or a file service. Also, if we're not waiting on any databases then we can - // also run immediately. - if (!(service || pool) || databases.IsEmpty()) { - nsresult rv = runnable->Run(); - NS_ENSURE_SUCCESS(rv, rv); - - return NS_OK; - } - - // Ask each service to call us back when they're done with this database. - if (service) { - // Have to copy here in case the pool needs a list too. - nsTArray > array; - array.AppendElements(databases); - - if (!service->WaitForAllStoragesToComplete(array, runnable)) { - NS_WARNING("Failed to wait for storages to complete!"); - return NS_ERROR_FAILURE; - } - } - - if (pool && !pool->WaitForAllDatabasesToComplete(databases, runnable)) { - NS_WARNING("Failed to wait for databases to complete!"); - return NS_ERROR_FAILURE; - } - - return NS_OK; -} - -IndexedDatabaseManager::SynchronizedOp* -IndexedDatabaseManager::FindSynchronizedOp(const nsACString& aPattern, - nsIAtom* aId) -{ - for (uint32_t index = 0; index < mSynchronizedOps.Length(); index++) { - const nsAutoPtr& currentOp = mSynchronizedOps[index]; - if (PatternMatchesOrigin(aPattern, currentOp->mOriginOrPattern) && - (!currentOp->mId || currentOp->mId == aId)) { - return currentOp; - } - } - - return nullptr; -} - -nsresult -IndexedDatabaseManager::ClearDatabasesForApp(uint32_t aAppId, bool aBrowserOnly) -{ - NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); - NS_ASSERTION(aAppId != nsIScriptSecurityManager::UNKNOWN_APP_ID, - "Bad appId!"); - - // This only works from the main process. - NS_ENSURE_TRUE(IsMainProcess(), NS_ERROR_NOT_AVAILABLE); - - nsAutoCString pattern; - GetOriginPatternStringMaybeIgnoreBrowser(aAppId, aBrowserOnly, pattern); - - // If there is a pending or running clear operation for this app, return - // immediately. - if (IsClearOriginPending(pattern)) { - return NS_OK; - } - - OriginOrPatternString oops = OriginOrPatternString::FromPattern(pattern); - - // Queue up the origin clear runnable. - nsRefPtr runnable = new OriginClearRunnable(oops); - - nsresult rv = WaitForOpenAllowed(oops, nullptr, runnable); - NS_ENSURE_SUCCESS(rv, rv); - - runnable->AdvanceState(); - - // Give the runnable some help by invalidating any databases in the way. - DatabasePatternMatchArray matches; - matches.Find(mLiveDatabases, pattern); - - for (uint32_t index = 0; index < matches.Length(); index++) { - // We need to grab references here to prevent the database from dying while - // we invalidate it. - nsRefPtr database = matches[index]; - database->Invalidate(); - } - - return NS_OK; -} - -NS_IMPL_ISUPPORTS2(IndexedDatabaseManager, nsIIndexedDatabaseManager, - nsIObserver) - -NS_IMETHODIMP -IndexedDatabaseManager::GetUsageForURI( - nsIURI* aURI, - nsIIndexedDatabaseUsageCallback* aCallback, - uint32_t aAppId, - bool aInMozBrowserOnly, - uint8_t aOptionalArgCount) -{ - NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); - - NS_ENSURE_ARG_POINTER(aURI); - NS_ENSURE_ARG_POINTER(aCallback); - - // This only works from the main process. - NS_ENSURE_TRUE(IsMainProcess(), NS_ERROR_NOT_AVAILABLE); - - if (!aOptionalArgCount) { - aAppId = nsIScriptSecurityManager::NO_APP_ID; - } - - // Figure out which origin we're dealing with. - nsCString origin; - nsresult rv = GetASCIIOriginFromURI(aURI, aAppId, aInMozBrowserOnly, origin); - NS_ENSURE_SUCCESS(rv, rv); - - OriginOrPatternString oops = OriginOrPatternString::FromOrigin(origin); - - nsRefPtr runnable = - new AsyncUsageRunnable(aAppId, aInMozBrowserOnly, oops, aURI, aCallback); - - nsRefPtr* newRunnable = - mUsageRunnables.AppendElement(runnable); - NS_ENSURE_TRUE(newRunnable, NS_ERROR_OUT_OF_MEMORY); - - // Otherwise put the computation runnable in the queue. - rv = WaitForOpenAllowed(oops, nullptr, runnable); - NS_ENSURE_SUCCESS(rv, rv); - - runnable->AdvanceState(); - - return NS_OK; -} - -NS_IMETHODIMP -IndexedDatabaseManager::CancelGetUsageForURI( - nsIURI* aURI, - nsIIndexedDatabaseUsageCallback* aCallback, - uint32_t aAppId, - bool aInMozBrowserOnly, - uint8_t aOptionalArgCount) -{ - NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); - - NS_ENSURE_ARG_POINTER(aURI); - NS_ENSURE_ARG_POINTER(aCallback); - - // This only works from the main process. - NS_ENSURE_TRUE(IsMainProcess(), NS_ERROR_NOT_AVAILABLE); - - if (!aOptionalArgCount) { - aAppId = nsIScriptSecurityManager::NO_APP_ID; - } - - // See if one of our pending callbacks matches both the URI and the callback - // given. Cancel an remove it if so. - for (uint32_t index = 0; index < mUsageRunnables.Length(); index++) { - nsRefPtr& runnable = mUsageRunnables[index]; - - if (runnable->mAppId == aAppId && - runnable->mInMozBrowserOnly == aInMozBrowserOnly) { - bool equals; - nsresult rv = runnable->mURI->Equals(aURI, &equals); - NS_ENSURE_SUCCESS(rv, rv); - - if (equals && SameCOMIdentity(aCallback, runnable->mCallback)) { - runnable->Cancel(); - break; - } - } - } - return NS_OK; -} - -NS_IMETHODIMP -IndexedDatabaseManager::ClearDatabasesForURI(nsIURI* aURI, - uint32_t aAppId, - bool aInMozBrowserOnly, - uint8_t aOptionalArgCount) -{ - NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); - - NS_ENSURE_ARG_POINTER(aURI); - - // This only works from the main process. - NS_ENSURE_TRUE(IsMainProcess(), NS_ERROR_NOT_AVAILABLE); - - if (!aOptionalArgCount) { - aAppId = nsIScriptSecurityManager::NO_APP_ID; - } - - // Figure out which origin we're dealing with. - nsCString origin; - nsresult rv = GetASCIIOriginFromURI(aURI, aAppId, aInMozBrowserOnly, origin); - NS_ENSURE_SUCCESS(rv, rv); - - nsAutoCString pattern; - GetOriginPatternString(aAppId, aInMozBrowserOnly, origin, pattern); - - // If there is a pending or running clear operation for this origin, return - // immediately. - if (IsClearOriginPending(pattern)) { - return NS_OK; - } - - OriginOrPatternString oops = OriginOrPatternString::FromPattern(pattern); - - // Queue up the origin clear runnable. - nsRefPtr runnable = new OriginClearRunnable(oops); - - rv = WaitForOpenAllowed(oops, nullptr, runnable); - NS_ENSURE_SUCCESS(rv, rv); - - runnable->AdvanceState(); - - // Give the runnable some help by invalidating any databases in the way. - DatabasePatternMatchArray matches; - matches.Find(mLiveDatabases, pattern); - - for (uint32_t index = 0; index < matches.Length(); index++) { - // We need to grab references to any live databases here to prevent them - // from dying while we invalidate them. - nsRefPtr database = matches[index]; - database->Invalidate(); - } - - // After everything has been invalidated the helper should be dispatched to - // the end of the event queue. - return NS_OK; -} - -NS_IMETHODIMP -IndexedDatabaseManager::Observe(nsISupports* aSubject, - const char* aTopic, - const PRUnichar* aData) -{ - NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); - - if (!strcmp(aTopic, PROFILE_BEFORE_CHANGE_OBSERVER_ID)) { - // Setting this flag prevents the service from being recreated and prevents - // further databases from being created. - if (PR_ATOMIC_SET(&gShutdown, 1)) { - NS_ERROR("Shutdown more than once?!"); - } - - if (sIsMainProcess) { - FileService* service = FileService::Get(); - if (service) { - // This should only wait for IDB databases (file storages) to complete. - // Other file storages may still have running locked files. - // If the necko service (thread pool) gets the shutdown notification - // first then the sync loop won't be processed at all, otherwise it will - // lock the main thread until all IDB file storages are finished. - - nsTArray > - liveDatabases(mLiveDatabases.Count()); - mLiveDatabases.EnumerateRead( - EnumerateToTArray >, - &liveDatabases); - - if (!liveDatabases.IsEmpty()) { - nsRefPtr runnable = - new WaitForLockedFilesToFinishRunnable(); - - if (!service->WaitForAllStoragesToComplete(liveDatabases, - runnable)) { - NS_WARNING("Failed to wait for databases to complete!"); - } - - nsIThread* thread = NS_GetCurrentThread(); - while (runnable->IsBusy()) { - if (!NS_ProcessNextEvent(thread)) { - NS_ERROR("Failed to process next event!"); - break; - } - } - } - } - - // Make sure to join with our IO thread. - if (NS_FAILED(mIOThread->Shutdown())) { - NS_WARNING("Failed to shutdown IO thread!"); - } - - // Kick off the shutdown timer. - if (NS_FAILED(mShutdownTimer->Init(this, DEFAULT_SHUTDOWN_TIMER_MS, - nsITimer::TYPE_ONE_SHOT))) { - NS_WARNING("Failed to initialize shutdown timer!"); - } - - // This will spin the event loop while we wait on all the database threads - // to close. Our timer may fire during that loop. - TransactionThreadPool::Shutdown(); - - // Cancel the timer regardless of whether it actually fired. - if (NS_FAILED(mShutdownTimer->Cancel())) { - NS_WARNING("Failed to cancel shutdown timer!"); - } - } - - mFileManagers.Enumerate(InvalidateAndRemoveFileManagers, nullptr); - - if (PR_ATOMIC_SET(&gClosed, 1)) { - NS_ERROR("Close more than once?!"); - } - - return NS_OK; - } - - if (!strcmp(aTopic, NS_TIMER_CALLBACK_TOPIC)) { - NS_ASSERTION(sIsMainProcess, "Should only happen in the main process!"); - - NS_WARNING("Some database operations are taking longer than expected " - "during shutdown and will be aborted!"); - - // Grab all live databases, for all origins. - nsAutoTArray liveDatabases; - mLiveDatabases.EnumerateRead(EnumerateToTArray, - &liveDatabases); - - // Invalidate them all. - if (!liveDatabases.IsEmpty()) { - uint32_t count = liveDatabases.Length(); - for (uint32_t index = 0; index < count; index++) { - liveDatabases[index]->Invalidate(); - } - } - - return NS_OK; - } - - if (!strcmp(aTopic, TOPIC_WEB_APP_CLEAR_DATA)) { - nsCOMPtr params = - do_QueryInterface(aSubject); - NS_ENSURE_TRUE(params, NS_ERROR_UNEXPECTED); - - uint32_t appId; - nsresult rv = params->GetAppId(&appId); - NS_ENSURE_SUCCESS(rv, rv); - - bool browserOnly; - rv = params->GetBrowserOnly(&browserOnly); - NS_ENSURE_SUCCESS(rv, rv); - - rv = ClearDatabasesForApp(appId, browserOnly); - NS_ENSURE_SUCCESS(rv, rv); - - return NS_OK; - } - - NS_NOTREACHED("Unknown topic!"); - return NS_ERROR_UNEXPECTED; -} - -NS_IMPL_THREADSAFE_ISUPPORTS1(IndexedDatabaseManager::OriginClearRunnable, - nsIRunnable) - -// static -void -IndexedDatabaseManager:: -OriginClearRunnable::InvalidateOpenedDatabases( - nsTArray >& aDatabases, - void* aClosure) -{ - NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); - - nsTArray > databases; - databases.SwapElements(aDatabases); - - for (uint32_t index = 0; index < databases.Length(); index++) { - databases[index]->Invalidate(); - } -} - -void -IndexedDatabaseManager:: -OriginClearRunnable::DeleteFiles(IndexedDatabaseManager* aManager) -{ - NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!"); - NS_ASSERTION(aManager, "Don't pass me null!"); - - nsresult rv; - - nsCOMPtr directory = - do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv); - NS_ENSURE_SUCCESS_VOID(rv); - - rv = directory->InitWithPath(aManager->GetBaseDirectory()); - NS_ENSURE_SUCCESS_VOID(rv); - - nsCOMPtr entries; - if (NS_FAILED(directory->GetDirectoryEntries(getter_AddRefs(entries))) || - !entries) { - return; - } - - nsCString originSanitized(mOriginOrPattern); - SanitizeOriginString(originSanitized); - - bool hasMore; - while (NS_SUCCEEDED((rv = entries->HasMoreElements(&hasMore))) && hasMore) { - nsCOMPtr entry; - rv = entries->GetNext(getter_AddRefs(entry)); - NS_ENSURE_SUCCESS_VOID(rv); - - nsCOMPtr file = do_QueryInterface(entry); - NS_ASSERTION(file, "Don't know what this is!"); - - bool isDirectory; - rv = file->IsDirectory(&isDirectory); - NS_ENSURE_SUCCESS_VOID(rv); - - if (!isDirectory) { - NS_WARNING("Something in the IndexedDB directory that doesn't belong!"); - continue; - } - - nsString leafName; - rv = file->GetLeafName(leafName); - NS_ENSURE_SUCCESS_VOID(rv); - - // Skip databases for other apps. - if (!PatternMatchesOrigin(originSanitized, - NS_ConvertUTF16toUTF8(leafName))) { - continue; - } - - if (NS_FAILED(file->Remove(true))) { - // This should never fail if we've closed all database connections - // correctly... - NS_ERROR("Failed to remove directory!"); - } - - QuotaManager* quotaManager = QuotaManager::Get(); - NS_ASSERTION(quotaManager, "Shouldn't be null!"); - - quotaManager->RemoveQuotaForPattern(mOriginOrPattern); - - aManager->UninitializeOriginsByPattern(mOriginOrPattern); - } -} - -NS_IMETHODIMP -IndexedDatabaseManager::OriginClearRunnable::Run() -{ - IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get(); - NS_ASSERTION(mgr, "This should never fail!"); - - switch (mCallbackState) { - case Pending: { - NS_NOTREACHED("Should never get here without being dispatched!"); - return NS_ERROR_UNEXPECTED; - } - - case OpenAllowed: { - NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); - - AdvanceState(); - - // Now we have to wait until the thread pool is done with all of the - // databases we care about. - nsresult rv = mgr->AcquireExclusiveAccess(mOriginOrPattern, this, - InvalidateOpenedDatabases, - nullptr); - NS_ENSURE_SUCCESS(rv, rv); - - return NS_OK; - } - - case IO: { - NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!"); - - AdvanceState(); - - DeleteFiles(mgr); - - // Now dispatch back to the main thread. - if (NS_FAILED(NS_DispatchToMainThread(this, NS_DISPATCH_NORMAL))) { - NS_WARNING("Failed to dispatch to main thread!"); - return NS_ERROR_FAILURE; - } - - return NS_OK; - } - - case Complete: { - NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); - - mgr->InvalidateFileManagersForPattern(mOriginOrPattern); - - // Tell the IndexedDatabaseManager that we're done. - mgr->AllowNextSynchronizedOp(mOriginOrPattern, nullptr); - - return NS_OK; - } - - default: - NS_ERROR("Unknown state value!"); - return NS_ERROR_UNEXPECTED; - } - - NS_NOTREACHED("Should never get here!"); - return NS_ERROR_UNEXPECTED; -} - -IndexedDatabaseManager::AsyncUsageRunnable::AsyncUsageRunnable( - uint32_t aAppId, - bool aInMozBrowserOnly, - const OriginOrPatternString& aOrigin, - nsIURI* aURI, - nsIIndexedDatabaseUsageCallback* aCallback) -: mURI(aURI), - mCallback(aCallback), - mUsage(0), - mFileUsage(0), - mAppId(aAppId), - mCanceled(0), - mOrigin(aOrigin), - mCallbackState(Pending), - mInMozBrowserOnly(aInMozBrowserOnly) -{ - NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); - NS_ASSERTION(aURI, "Null pointer!"); - NS_ASSERTION(aOrigin.IsOrigin(), "Expect origin only here!"); - NS_ASSERTION(!aOrigin.IsEmpty(), "Empty origin!"); - NS_ASSERTION(aCallback, "Null pointer!"); -} - -void -IndexedDatabaseManager::AsyncUsageRunnable::Cancel() -{ - if (PR_ATOMIC_SET(&mCanceled, 1)) { - NS_ERROR("Canceled more than once?!"); - } -} - -nsresult -IndexedDatabaseManager::AsyncUsageRunnable::TakeShortcut() -{ - NS_ASSERTION(mCallbackState == Pending, "Huh?"); - - nsresult rv = NS_DispatchToCurrentThread(this); - NS_ENSURE_SUCCESS(rv, rv); - - mCallbackState = Shortcut; - return NS_OK; -} - -nsresult -IndexedDatabaseManager::AsyncUsageRunnable::RunInternal() -{ - IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get(); - NS_ASSERTION(mgr, "This should never fail!"); - - switch (mCallbackState) { - case Pending: { - NS_NOTREACHED("Should never get here without being dispatched!"); - return NS_ERROR_UNEXPECTED; - } - - case OpenAllowed: { - NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); - - AdvanceState(); - - if (NS_FAILED(mgr->IOThread()->Dispatch(this, NS_DISPATCH_NORMAL))) { - NS_WARNING("Failed to dispatch to the IO thread!"); - } - - return NS_OK; - } - - case IO: { - NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!"); - - AdvanceState(); - - // Get the directory that contains all the database files we care about. - nsCOMPtr directory; - nsresult rv = mgr->GetDirectoryForOrigin(mOrigin, getter_AddRefs(directory)); - NS_ENSURE_SUCCESS(rv, rv); - - bool exists; - rv = directory->Exists(&exists); - NS_ENSURE_SUCCESS(rv, rv); - - // If the directory exists then enumerate all the files inside, adding up the - // sizes to get the final usage statistic. - if (exists && !mCanceled) { - rv = GetUsageForDirectory(directory, &mUsage); - NS_ENSURE_SUCCESS(rv, rv); - } - - // Run dispatches us back to the main thread. - return NS_OK; - } - - case Complete: // Fall through - case Shortcut: { - NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); - - // Call the callback unless we were canceled. - if (!mCanceled) { - uint64_t usage = mUsage; - IncrementUsage(&usage, mFileUsage); - mCallback->OnUsageResult(mURI, usage, mFileUsage, mAppId, - mInMozBrowserOnly); - } - - // Clean up. - mURI = nullptr; - mCallback = nullptr; - - // And tell the IndexedDatabaseManager that we're done. - mgr->OnUsageCheckComplete(this); - if (mCallbackState == Complete) { - mgr->AllowNextSynchronizedOp(mOrigin, nullptr); - } - - return NS_OK; - } - - default: - NS_ERROR("Unknown state value!"); - return NS_ERROR_UNEXPECTED; - } - - NS_NOTREACHED("Should never get here!"); - return NS_ERROR_UNEXPECTED; -} - -nsresult -IndexedDatabaseManager::AsyncUsageRunnable::GetUsageForDirectory( - nsIFile* aDirectory, - uint64_t* aUsage) -{ - NS_ASSERTION(aDirectory, "Null pointer!"); - NS_ASSERTION(aUsage, "Null pointer!"); - - nsCOMPtr entries; - nsresult rv = aDirectory->GetDirectoryEntries(getter_AddRefs(entries)); - NS_ENSURE_SUCCESS(rv, rv); - - if (!entries) { - return NS_OK; - } - - bool hasMore; - while (NS_SUCCEEDED((rv = entries->HasMoreElements(&hasMore))) && - hasMore && !mCanceled) { - nsCOMPtr entry; - rv = entries->GetNext(getter_AddRefs(entry)); - NS_ENSURE_SUCCESS(rv, rv); - - nsCOMPtr file(do_QueryInterface(entry)); - NS_ASSERTION(file, "Don't know what this is!"); - - bool isDirectory; - rv = file->IsDirectory(&isDirectory); - NS_ENSURE_SUCCESS(rv, rv); - - if (isDirectory) { - if (aUsage == &mFileUsage) { - NS_WARNING("Unknown directory found!"); - } - else { - rv = GetUsageForDirectory(file, &mFileUsage); - NS_ENSURE_SUCCESS(rv, rv); - } - - continue; - } - - int64_t fileSize; - rv = file->GetFileSize(&fileSize); - NS_ENSURE_SUCCESS(rv, rv); - - NS_ASSERTION(fileSize >= 0, "Negative size?!"); - - IncrementUsage(aUsage, uint64_t(fileSize)); - } - NS_ENSURE_SUCCESS(rv, rv); - - return NS_OK; -} - -NS_IMPL_THREADSAFE_ISUPPORTS1(IndexedDatabaseManager::AsyncUsageRunnable, - nsIRunnable) - -NS_IMETHODIMP -IndexedDatabaseManager::AsyncUsageRunnable::Run() -{ - nsresult rv = RunInternal(); - - if (!NS_IsMainThread()) { - if (NS_FAILED(rv)) { - mUsage = 0; - } - - if (NS_FAILED(NS_DispatchToMainThread(this, NS_DISPATCH_NORMAL))) { - NS_WARNING("Failed to dispatch to main thread!"); - } - } - - return NS_OK; -} - -NS_IMPL_THREADSAFE_ISUPPORTS1( - IndexedDatabaseManager::WaitForTransactionsToFinishRunnable, - nsIRunnable) - -NS_IMETHODIMP -IndexedDatabaseManager::WaitForTransactionsToFinishRunnable::Run() -{ - NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); - NS_ASSERTION(mOp, "Null op!"); - NS_ASSERTION(mOp->mHelper || mOp->mRunnable, "Nothing to run!"); - NS_ASSERTION(mCountdown, "Wrong countdown!"); - - if (--mCountdown) { - return NS_OK; - } - - // Don't hold the callback alive longer than necessary. - nsRefPtr helper; - helper.swap(mOp->mHelper); - - nsCOMPtr runnable; - runnable.swap(mOp->mRunnable); - - mOp = nullptr; - - nsresult rv; - - if (helper && helper->HasTransaction()) { - // If the helper has a transaction, dispatch it to the transaction - // threadpool. - rv = helper->DispatchToTransactionPool(); - NS_ENSURE_SUCCESS(rv, rv); - } - else { - // Otherwise, dispatch it to the IO thread. - IndexedDatabaseManager* manager = IndexedDatabaseManager::Get(); - NS_ASSERTION(manager, "We should definitely have a manager here"); - - nsIEventTarget* target = manager->IOThread(); - - rv = helper ? - helper->Dispatch(target) : - target->Dispatch(runnable, NS_DISPATCH_NORMAL); - NS_ENSURE_SUCCESS(rv, rv); - } - - // The helper or runnable is responsible for calling - // IndexedDatabaseManager::AllowNextSynchronizedOp. - return NS_OK; -} - -NS_IMPL_THREADSAFE_ISUPPORTS1( - IndexedDatabaseManager::WaitForLockedFilesToFinishRunnable, - nsIRunnable) - -NS_IMETHODIMP -IndexedDatabaseManager::WaitForLockedFilesToFinishRunnable::Run() -{ - NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); - - mBusy = false; - - return NS_OK; -} - -IndexedDatabaseManager:: -SynchronizedOp::SynchronizedOp(const OriginOrPatternString& aOriginOrPattern, - nsIAtom* aId) -: mOriginOrPattern(aOriginOrPattern), mId(aId) -{ - NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); - MOZ_COUNT_CTOR(IndexedDatabaseManager::SynchronizedOp); -} - -IndexedDatabaseManager::SynchronizedOp::~SynchronizedOp() -{ - NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); - MOZ_COUNT_DTOR(IndexedDatabaseManager::SynchronizedOp); -} - -bool -IndexedDatabaseManager:: -SynchronizedOp::MustWaitFor(const SynchronizedOp& aExistingOp) -{ - NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); - - bool match; - - if (aExistingOp.mOriginOrPattern.IsOrigin()) { - if (mOriginOrPattern.IsOrigin()) { - match = aExistingOp.mOriginOrPattern.Equals(mOriginOrPattern); - } - else { - match = PatternMatchesOrigin(mOriginOrPattern, aExistingOp.mOriginOrPattern); - } - } - else if (mOriginOrPattern.IsOrigin()) { - match = PatternMatchesOrigin(aExistingOp.mOriginOrPattern, mOriginOrPattern); - } - else { - match = PatternMatchesOrigin(mOriginOrPattern, aExistingOp.mOriginOrPattern) || - PatternMatchesOrigin(aExistingOp.mOriginOrPattern, mOriginOrPattern); - } - - // If the origins don't match, the second can proceed. - if (!match) { - return false; - } - - // If the origins and the ids match, the second must wait. - if (aExistingOp.mId == mId) { - return true; - } - - // Waiting is required if either one corresponds to an origin clearing - // (a null Id). - if (!aExistingOp.mId || !mId) { - return true; - } - - // Otherwise, things for the same origin but different databases can proceed - // independently. - return false; -} - -void -IndexedDatabaseManager::SynchronizedOp::DelayRunnable(nsIRunnable* aRunnable) -{ - NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); - NS_ASSERTION(mDelayedRunnables.IsEmpty() || !mId, - "Only ClearOrigin operations can delay multiple runnables!"); - - mDelayedRunnables.AppendElement(aRunnable); -} - -void -IndexedDatabaseManager::SynchronizedOp::DispatchDelayedRunnables() -{ - NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); - NS_ASSERTION(!mHelper, "Any helper should be gone by now!"); - - uint32_t count = mDelayedRunnables.Length(); - for (uint32_t index = 0; index < count; index++) { - NS_DispatchToCurrentThread(mDelayedRunnables[index]); - } - - mDelayedRunnables.Clear(); -} +NS_IMPL_ADDREF(IndexedDatabaseManager) +NS_IMPL_RELEASE_WITH_DESTROY(IndexedDatabaseManager, Destroy()) +NS_IMPL_QUERY_INTERFACE1(IndexedDatabaseManager, nsIIndexedDatabaseManager) NS_IMETHODIMP IndexedDatabaseManager::InitWindowless(const jsval& aObj, JSContext* aCx) @@ -2162,18 +454,17 @@ IndexedDatabaseManager::InitWindowless(const jsval& aObj, JSContext* aCx) return NS_OK; } -IndexedDatabaseManager:: AsyncDeleteFileRunnable::AsyncDeleteFileRunnable(FileManager* aFileManager, int64_t aFileId) : mFileManager(aFileManager), mFileId(aFileId) { } -NS_IMPL_THREADSAFE_ISUPPORTS1(IndexedDatabaseManager::AsyncDeleteFileRunnable, +NS_IMPL_THREADSAFE_ISUPPORTS1(AsyncDeleteFileRunnable, nsIRunnable) NS_IMETHODIMP -IndexedDatabaseManager::AsyncDeleteFileRunnable::Run() +AsyncDeleteFileRunnable::Run() { NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!"); diff --git a/dom/indexedDB/IndexedDatabaseManager.h b/dom/indexedDB/IndexedDatabaseManager.h index 57311e52f6f8..966cd44e3721 100644 --- a/dom/indexedDB/IndexedDatabaseManager.h +++ b/dom/indexedDB/IndexedDatabaseManager.h @@ -9,23 +9,15 @@ #include "mozilla/dom/indexedDB/IndexedDatabase.h" -#include "mozilla/Mutex.h" - #include "nsIIndexedDatabaseManager.h" -#include "nsIObserver.h" -#include "nsIRunnable.h" -#include "nsIThread.h" -#include "nsIURI.h" +#include "mozilla/Mutex.h" #include "nsClassHashtable.h" -#include "nsRefPtrHashtable.h" #include "nsHashKeys.h" #define INDEXEDDB_MANAGER_CONTRACTID "@mozilla.org/dom/indexeddb/manager;1" class nsIAtom; -class nsIFile; -class nsITimer; class nsPIDOMWindow; class nsEventChainPostVisitor; @@ -35,96 +27,30 @@ class TabContext; } } - BEGIN_INDEXEDDB_NAMESPACE -class AsyncConnectionHelper; class FileManager; -class IDBDatabase; -class IndexedDatabaseManager MOZ_FINAL : public nsIIndexedDatabaseManager, - public nsIObserver +class IndexedDatabaseManager MOZ_FINAL : public nsIIndexedDatabaseManager { - friend class IDBDatabase; - public: - static already_AddRefed GetOrCreate(); - - // Returns a non-owning reference. - static IndexedDatabaseManager* Get(); - - // Returns an owning reference! No one should call this but the factory. - static IndexedDatabaseManager* FactoryCreate(); - NS_DECL_ISUPPORTS NS_DECL_NSIINDEXEDDATABASEMANAGER - NS_DECL_NSIOBSERVER - // Waits for databases to be cleared and for version change transactions to - // complete before dispatching the given runnable. - nsresult WaitForOpenAllowed(const OriginOrPatternString& aOriginOrPattern, - nsIAtom* aId, - nsIRunnable* aRunnable); + // Returns a non-owning reference. + static IndexedDatabaseManager* + GetOrCreate(); - void AllowNextSynchronizedOp(const OriginOrPatternString& aOriginOrPattern, - nsIAtom* aId); + // Returns a non-owning reference. + static IndexedDatabaseManager* + Get(); - nsIThread* IOThread() - { - NS_ASSERTION(mIOThread, "This should never be null!"); - return mIOThread; - } + // Returns an owning reference! No one should call this but the factory. + static IndexedDatabaseManager* + FactoryCreate(); - // Returns true if we've begun the shutdown process. - static bool IsShuttingDown(); - - static bool IsClosed(); - - typedef void - (*WaitingOnDatabasesCallback)(nsTArray >&, void*); - - // Acquire exclusive access to the database given (waits for all others to - // close). If databases need to close first, the callback will be invoked - // with an array of said databases. - nsresult AcquireExclusiveAccess(IDBDatabase* aDatabase, - const nsACString& aOrigin, - AsyncConnectionHelper* aHelper, - WaitingOnDatabasesCallback aCallback, - void* aClosure) - { - NS_ASSERTION(aDatabase, "Need a DB here!"); - return AcquireExclusiveAccess(aOrigin, aDatabase, aHelper, nullptr, - aCallback, aClosure); - } - - nsresult AcquireExclusiveAccess(const nsACString& aOrigin, - nsIRunnable* aRunnable, - WaitingOnDatabasesCallback aCallback, - void* aClosure) - { - return AcquireExclusiveAccess(aOrigin, nullptr, nullptr, aRunnable, aCallback, - aClosure); - } - - // Called when a window is being purged from the bfcache or the user leaves - // a page which isn't going into the bfcache. Forces any live database - // objects to close themselves and aborts any running transactions. - void AbortCloseDatabasesForWindow(nsPIDOMWindow* aWindow); - - // Used to check if there are running transactions in a given window. - bool HasOpenTransactions(nsPIDOMWindow* aWindow); - - static uint32_t - GetIndexedDBQuotaMB(); - - nsresult EnsureOriginIsInitialized(const nsACString& aOrigin, - FactoryPrivilege aPrivilege, - nsIFile** aDirectory); - - void UninitializeOriginsByPattern(const nsACString& aPattern); - - static nsresult - GetASCIIOriginFromWindow(nsPIDOMWindow* aWindow, nsCString& aASCIIOrigin); + static bool + IsClosed(); static bool IsMainProcess() @@ -143,25 +69,22 @@ public: void AddFileManager(FileManager* aFileManager); - void InvalidateFileManagersForPattern(const nsACString& aPattern); + void + InvalidateAllFileManagers(); - void InvalidateFileManager(const nsACString& aOrigin, - const nsAString& aDatabaseName); + void + InvalidateFileManagersForPattern(const nsACString& aPattern); - nsresult AsyncDeleteFile(FileManager* aFileManager, - int64_t aFileId); - - const nsString& - GetBaseDirectory() const - { - return mDatabaseBasePath; - } + void + InvalidateFileManager(const nsACString& aOrigin, + const nsAString& aDatabaseName); nsresult - GetDirectoryForOrigin(const nsACString& aASCIIOrigin, - nsIFile** aDirectory) const; + AsyncDeleteFile(FileManager* aFileManager, + int64_t aFileId); - static mozilla::Mutex& FileMutex() + static mozilla::Mutex& + FileMutex() { IndexedDatabaseManager* mgr = Get(); NS_ASSERTION(mgr, "Must have a manager here!"); @@ -169,10 +92,6 @@ public: return mgr->mFileMutex; } - static already_AddRefed - GetDatabaseId(const nsACString& aOrigin, - const nsAString& aName); - static nsresult FireWindowOnError(nsPIDOMWindow* aOwner, nsEventChainPostVisitor& aVisitor); @@ -185,288 +104,22 @@ private: IndexedDatabaseManager(); ~IndexedDatabaseManager(); - nsresult AcquireExclusiveAccess(const nsACString& aOrigin, - IDBDatabase* aDatabase, - AsyncConnectionHelper* aHelper, - nsIRunnable* aRunnable, - WaitingOnDatabasesCallback aCallback, - void* aClosure); + nsresult + Init(); - // Called when a database is created. - bool RegisterDatabase(IDBDatabase* aDatabase); - - // Called when a database is being unlinked or destroyed. - void UnregisterDatabase(IDBDatabase* aDatabase); - - // Called when a database has been closed. - void OnDatabaseClosed(IDBDatabase* aDatabase); - - nsresult ClearDatabasesForApp(uint32_t aAppId, bool aBrowserOnly); - - // Responsible for clearing the database files for a particular origin on the - // IO thread. Created when nsIIDBIndexedDatabaseManager::ClearDatabasesForURI - // is called. Runs three times, first on the main thread, next on the IO - // thread, and then finally again on the main thread. While on the IO thread - // the runnable will actually remove the origin's database files and the - // directory that contains them before dispatching itself back to the main - // thread. When back on the main thread the runnable will notify the - // IndexedDatabaseManager that the job has been completed. - class OriginClearRunnable MOZ_FINAL : public nsIRunnable - { - enum CallbackState { - // Not yet run. - Pending = 0, - - // Running on the main thread in the callback for OpenAllowed. - OpenAllowed, - - // Running on the IO thread. - IO, - - // Running on the main thread after all work is done. - Complete - }; - - public: - NS_DECL_ISUPPORTS - NS_DECL_NSIRUNNABLE - - OriginClearRunnable(const OriginOrPatternString& aOriginOrPattern) - : mOriginOrPattern(aOriginOrPattern), - mCallbackState(Pending) - { } - - void AdvanceState() - { - switch (mCallbackState) { - case Pending: - mCallbackState = OpenAllowed; - return; - case OpenAllowed: - mCallbackState = IO; - return; - case IO: - mCallbackState = Complete; - return; - default: - NS_NOTREACHED("Can't advance past Complete!"); - } - } - - static void InvalidateOpenedDatabases( - nsTArray >& aDatabases, - void* aClosure); - - void DeleteFiles(IndexedDatabaseManager* aManager); - - private: - OriginOrPatternString mOriginOrPattern; - CallbackState mCallbackState; - }; - - // Responsible for calculating the amount of space taken up by databases of a - // certain origin. Created when nsIIDBIndexedDatabaseManager::GetUsageForURI - // is called. May be canceled with - // nsIIDBIndexedDatabaseManager::CancelGetUsageForURI. Runs twice, first on - // the IO thread, then again on the main thread. While on the IO thread the - // runnable will calculate the size of all files in the origin's directory - // before dispatching itself back to the main thread. When on the main thread - // the runnable will call the callback and then notify the - // IndexedDatabaseManager that the job has been completed. - class AsyncUsageRunnable MOZ_FINAL : public nsIRunnable - { - enum CallbackState { - // Not yet run. - Pending = 0, - - // Running on the main thread in the callback for OpenAllowed. - OpenAllowed, - - // Running on the IO thread. - IO, - - // Running on the main thread after all work is done. - Complete, - - // Running on the main thread after skipping the work - Shortcut - }; - - public: - NS_DECL_ISUPPORTS - NS_DECL_NSIRUNNABLE - - AsyncUsageRunnable(uint32_t aAppId, - bool aInMozBrowserOnly, - const OriginOrPatternString& aOrigin, - nsIURI* aURI, - nsIIndexedDatabaseUsageCallback* aCallback); - - // Sets the canceled flag so that the callback is never called. - void Cancel(); - - void AdvanceState() - { - switch (mCallbackState) { - case Pending: - mCallbackState = OpenAllowed; - return; - case OpenAllowed: - mCallbackState = IO; - return; - case IO: - mCallbackState = Complete; - return; - default: - NS_NOTREACHED("Can't advance past Complete!"); - } - } - - nsresult TakeShortcut(); - - // Run calls the RunInternal method and makes sure that we always dispatch - // to the main thread in case of an error. - inline nsresult RunInternal(); - - nsresult GetUsageForDirectory(nsIFile* aDirectory, - uint64_t* aUsage); - - nsCOMPtr mURI; - nsCOMPtr mCallback; - uint64_t mUsage; - uint64_t mFileUsage; - uint32_t mAppId; - int32_t mCanceled; - OriginOrPatternString mOrigin; - CallbackState mCallbackState; - bool mInMozBrowserOnly; - }; - - // Called when AsyncUsageRunnable has finished its Run() method. - inline void OnUsageCheckComplete(AsyncUsageRunnable* aRunnable); - - // A struct that contains the information corresponding to a pending or - // running operation that requires synchronization (e.g. opening a db, - // clearing dbs for an origin, etc). - struct SynchronizedOp - { - SynchronizedOp(const OriginOrPatternString& aOriginOrPattern, - nsIAtom* aId); - ~SynchronizedOp(); - - // Test whether this SynchronizedOp needs to wait for the given op. - bool MustWaitFor(const SynchronizedOp& aOp); - - void DelayRunnable(nsIRunnable* aRunnable); - void DispatchDelayedRunnables(); - - const OriginOrPatternString mOriginOrPattern; - nsCOMPtr mId; - nsRefPtr mHelper; - nsCOMPtr mRunnable; - nsTArray > mDelayedRunnables; - nsTArray mDatabases; - }; - - // A callback runnable used by the TransactionPool when it's safe to proceed - // with a SetVersion/DeleteDatabase/etc. - class WaitForTransactionsToFinishRunnable MOZ_FINAL : public nsIRunnable - { - public: - WaitForTransactionsToFinishRunnable(SynchronizedOp* aOp, - uint32_t aCountdown) - : mOp(aOp), mCountdown(aCountdown) - { - NS_ASSERTION(mOp, "Why don't we have a runnable?"); - NS_ASSERTION(mOp->mDatabases.IsEmpty(), "We're here too early!"); - NS_ASSERTION(mOp->mHelper || mOp->mRunnable, - "What are we supposed to do when we're done?"); - NS_ASSERTION(mCountdown, "Wrong countdown!"); - } - - NS_DECL_ISUPPORTS - NS_DECL_NSIRUNNABLE - - private: - // The IndexedDatabaseManager holds this alive. - SynchronizedOp* mOp; - uint32_t mCountdown; - }; - - class WaitForLockedFilesToFinishRunnable MOZ_FINAL : public nsIRunnable - { - public: - WaitForLockedFilesToFinishRunnable() - : mBusy(true) - { } - - NS_DECL_ISUPPORTS - NS_DECL_NSIRUNNABLE - - bool IsBusy() const - { - return mBusy; - } - - private: - bool mBusy; - }; - - class AsyncDeleteFileRunnable MOZ_FINAL : public nsIRunnable - { - public: - NS_DECL_ISUPPORTS - NS_DECL_NSIRUNNABLE - AsyncDeleteFileRunnable(FileManager* aFileManager, int64_t aFileId); - - private: - nsRefPtr mFileManager; - int64_t mFileId; - }; - - static nsresult RunSynchronizedOp(IDBDatabase* aDatabase, - SynchronizedOp* aOp); - - SynchronizedOp* FindSynchronizedOp(const nsACString& aPattern, - nsIAtom* aId); - - bool IsClearOriginPending(const nsACString& aPattern) - { - return !!FindSynchronizedOp(aPattern, nullptr); - } - - // Maintains a list of live databases per origin. - nsClassHashtable > mLiveDatabases; + void + Destroy(); // Maintains a list of all file managers per origin. This list isn't // protected by any mutex but it is only ever touched on the IO thread. nsClassHashtable > > mFileManagers; - // Maintains a list of origins that we're currently enumerating to gather - // usage statistics. - nsAutoTArray, 1> mUsageRunnables; - - // Maintains a list of synchronized operatons that are in progress or queued. - nsAutoTArray, 5> mSynchronizedOps; - - // Thread on which IO is performed. - nsCOMPtr mIOThread; - - // A timer that gets activated at shutdown to ensure we close all databases. - nsCOMPtr mShutdownTimer; - - // A list of all successfully initialized origins. This list isn't protected - // by any mutex but it is only ever touched on the IO thread. - nsTArray mInitializedOrigins; - // Lock protecting FileManager.mFileInfos and nsDOMFileBase.mFileInfos // It's s also used to atomically update FileInfo.mRefCnt, FileInfo.mDBRefCnt // and FileInfo.mSliceRefCnt mozilla::Mutex mFileMutex; - nsString mDatabaseBasePath; - static bool sIsMainProcess; }; diff --git a/dom/indexedDB/Makefile.in b/dom/indexedDB/Makefile.in index 2b8d8cb8d04d..e0ee95d4c358 100644 --- a/dom/indexedDB/Makefile.in +++ b/dom/indexedDB/Makefile.in @@ -21,6 +21,7 @@ EXPORTS_NAMESPACES = mozilla/dom/indexedDB CPPSRCS = \ AsyncConnectionHelper.cpp \ CheckPermissionsHelper.cpp \ + Client.cpp \ DatabaseInfo.cpp \ FileInfo.cpp \ FileManager.cpp \ @@ -43,7 +44,10 @@ CPPSRCS = \ $(NULL) EXPORTS_mozilla/dom/indexedDB = \ + Client.h \ DatabaseInfo.h \ + FileManager.h \ + FileInfo.h \ IDBCursor.h \ IDBDatabase.h \ IDBEvents.h \ @@ -59,8 +63,6 @@ EXPORTS_mozilla/dom/indexedDB = \ IndexedDatabaseManager.h \ Key.h \ KeyPath.h \ - FileManager.h \ - FileInfo.h \ $(NULL) LOCAL_INCLUDES = \ diff --git a/dom/indexedDB/OpenDatabaseHelper.cpp b/dom/indexedDB/OpenDatabaseHelper.cpp index 5462f16c3aea..3684f1c55083 100644 --- a/dom/indexedDB/OpenDatabaseHelper.cpp +++ b/dom/indexedDB/OpenDatabaseHelper.cpp @@ -8,6 +8,8 @@ #include "nsIFile.h" +#include "mozilla/dom/quota/AcquireListener.h" +#include "mozilla/dom/quota/OriginOrPatternString.h" #include "mozilla/dom/quota/QuotaManager.h" #include "mozilla/storage.h" #include "nsEscape.h" @@ -15,6 +17,7 @@ #include "nsThreadUtils.h" #include "snappy/snappy.h" +#include "Client.h" #include "nsIBFCacheEntry.h" #include "IDBEvents.h" #include "IDBFactory.h" @@ -1323,7 +1326,8 @@ UpgradeSchemaFrom11_0To12_0(mozIStorageConnection* aConnection) class VersionChangeEventsRunnable; class SetVersionHelper : public AsyncConnectionHelper, - public IDBTransactionListener + public IDBTransactionListener, + public AcquireListener { friend class VersionChangeEventsRunnable; @@ -1346,6 +1350,9 @@ public: virtual nsresult GetSuccessResult(JSContext* aCx, jsval* aVal) MOZ_OVERRIDE; + virtual nsresult + OnExclusiveAccessAcquired() MOZ_OVERRIDE; + protected: virtual nsresult Init() MOZ_OVERRIDE; @@ -1393,7 +1400,8 @@ private: uint64_t mCurrentVersion; }; -class DeleteDatabaseHelper : public AsyncConnectionHelper +class DeleteDatabaseHelper : public AsyncConnectionHelper, + public AcquireListener { friend class VersionChangeEventsRunnable; public: @@ -1408,6 +1416,8 @@ public: mASCIIOrigin(aASCIIOrigin) { } + NS_DECL_ISUPPORTS_INHERITED + nsresult GetSuccessResult(JSContext* aCx, jsval* aVal); @@ -1419,6 +1429,9 @@ public: AsyncConnectionHelper::ReleaseMainThreadObjects(); } + virtual nsresult + OnExclusiveAccessAcquired() MOZ_OVERRIDE; + protected: nsresult DoDatabaseWork(mozIStorageConnection* aConnection); nsresult Init(); @@ -1470,11 +1483,11 @@ class VersionChangeEventsRunnable : public nsRunnable { public: VersionChangeEventsRunnable( - IDBDatabase* aRequestingDatabase, - IDBOpenDBRequest* aRequest, - nsTArray >& aWaitingDatabases, - int64_t aOldVersion, - int64_t aNewVersion) + IDBDatabase* aRequestingDatabase, + IDBOpenDBRequest* aRequest, + nsTArray >& aWaitingDatabases, + int64_t aOldVersion, + int64_t aNewVersion) : mRequestingDatabase(aRequestingDatabase), mRequest(aRequest), mOldVersion(aOldVersion), @@ -1497,7 +1510,9 @@ public: // closed. Also kick bfcached documents out of bfcache. uint32_t count = mWaitingDatabases.Length(); for (uint32_t index = 0; index < count; index++) { - nsRefPtr& database = mWaitingDatabases[index]; + IDBDatabase* database = + IDBDatabase::FromStorage(mWaitingDatabases[index]); + NS_ASSERTION(database, "This shouldn't be null!"); if (database->IsClosed()) { continue; @@ -1519,12 +1534,12 @@ public: // We can't kick the document out of the bfcache because it's not yet // fully in the bfcache. Instead we'll abort everything for the window // and mark it as not-bfcacheable. - IndexedDatabaseManager* manager = IndexedDatabaseManager::Get(); - NS_ASSERTION(manager, "Huh?"); - manager->AbortCloseDatabasesForWindow(owner); + QuotaManager* quotaManager = QuotaManager::Get(); + NS_ASSERTION(quotaManager, "Huh?"); + quotaManager->AbortCloseStoragesForWindow(owner); NS_ASSERTION(database->IsClosed(), - "AbortCloseDatabasesForWindow should have closed database"); + "AbortCloseStoragesForWindow should have closed database"); ownerDoc->DisallowBFCaching(); continue; } @@ -1559,12 +1574,12 @@ public: template static - void QueueVersionChange(nsTArray >& aDatabases, + void QueueVersionChange(nsTArray >& aDatabases, void* aClosure); private: nsRefPtr mRequestingDatabase; nsRefPtr mRequest; - nsTArray > mWaitingDatabases; + nsTArray > mWaitingDatabases; int64_t mOldVersion; int64_t mNewVersion; }; @@ -1576,7 +1591,7 @@ NS_IMPL_THREADSAFE_ISUPPORTS1(OpenDatabaseHelper, nsIRunnable) nsresult OpenDatabaseHelper::Init() { - mDatabaseId = IndexedDatabaseManager::GetDatabaseId(mASCIIOrigin, mName); + mDatabaseId = QuotaManager::GetStorageId(mASCIIOrigin, mName); NS_ENSURE_TRUE(mDatabaseId, NS_ERROR_FAILURE); return NS_OK; @@ -1609,7 +1624,7 @@ OpenDatabaseHelper::DoDatabaseWork() #ifdef DEBUG { bool correctThread; - NS_ASSERTION(NS_SUCCEEDED(IndexedDatabaseManager::Get()->IOThread()-> + NS_ASSERTION(NS_SUCCEEDED(QuotaManager::Get()->IOThread()-> IsOnCurrentThread(&correctThread)) && correctThread, "Running on the wrong thread!"); @@ -1618,7 +1633,7 @@ OpenDatabaseHelper::DoDatabaseWork() mState = eFiringEvents; // In case we fail somewhere along the line. - if (IndexedDatabaseManager::IsShuttingDown()) { + if (QuotaManager::IsShuttingDown()) { return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; } @@ -1631,14 +1646,34 @@ OpenDatabaseHelper::DoDatabaseWork() nsCOMPtr dbDirectory; - IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get(); - NS_ASSERTION(mgr, "This should never be null!"); + QuotaManager* quotaManager = QuotaManager::Get(); + NS_ASSERTION(quotaManager, "This should never be null!"); - nsresult rv = mgr->EnsureOriginIsInitialized(mASCIIOrigin, - mPrivilege, - getter_AddRefs(dbDirectory)); + nsresult rv = + quotaManager->EnsureOriginIsInitialized(mASCIIOrigin, + mPrivilege, + getter_AddRefs(dbDirectory)); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); + rv = dbDirectory->Append(NS_LITERAL_STRING(IDB_DIRECTORY_NAME)); + NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); + + bool exists; + rv = dbDirectory->Exists(&exists); + NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); + + if (!exists) { + rv = dbDirectory->Create(nsIFile::DIRECTORY_TYPE, 0755); + NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); + } +#ifdef DEBUG + else { + bool isDirectory; + NS_ASSERTION(NS_SUCCEEDED(dbDirectory->IsDirectory(&isDirectory)) && + isDirectory, "Should have caught this earlier!"); + } +#endif + nsAutoString filename; rv = GetDatabaseFilename(mName, filename); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); @@ -1710,6 +1745,9 @@ OpenDatabaseHelper::DoDatabaseWork() mState = eSetVersionPending; } + IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get(); + NS_ASSERTION(mgr, "This should never be null!"); + nsRefPtr fileManager = mgr->GetFileManager(mASCIIOrigin, mName); if (!fileManager) { fileManager = new FileManager(mASCIIOrigin, mPrivilege, mName); @@ -1917,12 +1955,13 @@ OpenDatabaseHelper::StartSetVersion() new SetVersionHelper(transaction, mOpenDBRequest, this, mRequestedVersion, mCurrentVersion); - IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get(); - NS_ASSERTION(mgr, "This should never be null!"); + QuotaManager* quotaManager = QuotaManager::Get(); + NS_ASSERTION(quotaManager, "This should never be null!"); - rv = mgr->AcquireExclusiveAccess(mDatabase, mDatabase->Origin(), helper, + rv = quotaManager->AcquireExclusiveAccess( + mDatabase, mDatabase->Origin(), helper, &VersionChangeEventsRunnable::QueueVersionChange, - helper); + helper); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); // The SetVersionHelper is responsible for dispatching us back to the @@ -1946,12 +1985,13 @@ OpenDatabaseHelper::StartDelete() new DeleteDatabaseHelper(mOpenDBRequest, this, mCurrentVersion, mName, mASCIIOrigin); - IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get(); - NS_ASSERTION(mgr, "This should never be null!"); + QuotaManager* quotaManager = QuotaManager::Get(); + NS_ASSERTION(quotaManager, "This should never be null!"); - rv = mgr->AcquireExclusiveAccess(mDatabase, mDatabase->Origin(), helper, + rv = quotaManager->AcquireExclusiveAccess( + mDatabase, mDatabase->Origin(), helper, &VersionChangeEventsRunnable::QueueVersionChange, - helper); + helper); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); // The DeleteDatabaseHelper is responsible for dispatching us back to the @@ -2040,10 +2080,10 @@ OpenDatabaseHelper::Run() DispatchSuccessEvent(); } - IndexedDatabaseManager* manager = IndexedDatabaseManager::Get(); - NS_ASSERTION(manager, "This should never be null!"); + QuotaManager* quotaManager = QuotaManager::Get(); + NS_ASSERTION(quotaManager, "This should never be null!"); - manager->AllowNextSynchronizedOp( + quotaManager->AllowNextSynchronizedOp( OriginOrPatternString::FromOrigin(mASCIIOrigin), mDatabaseId); @@ -2298,12 +2338,21 @@ SetVersionHelper::GetSuccessResult(JSContext* aCx, aVal); } +nsresult +SetVersionHelper::OnExclusiveAccessAcquired() +{ + nsresult rv = DispatchToTransactionPool(); + NS_ENSURE_SUCCESS(rv, rv); + + return NS_OK; +} + // static template void VersionChangeEventsRunnable::QueueVersionChange( - nsTArray >& aDatabases, - void* aClosure) + nsTArray >& aDatabases, + void* aClosure) { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); NS_ASSERTION(!aDatabases.IsEmpty(), "Why are we here?"); @@ -2366,23 +2415,28 @@ SetVersionHelper::NotifyTransactionPostComplete(IDBTransaction* aTransaction) return rv; } +NS_IMPL_ISUPPORTS_INHERITED0(DeleteDatabaseHelper, AsyncConnectionHelper); + nsresult DeleteDatabaseHelper::DoDatabaseWork(mozIStorageConnection* aConnection) { NS_ASSERTION(!aConnection, "How did we get a connection here?"); - const FactoryPrivilege& privilege = mOpenHelper->Privilege(); + const StoragePrivilege& privilege = mOpenHelper->Privilege(); - IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get(); - NS_ASSERTION(mgr, "This should never fail!"); + QuotaManager* quotaManager = QuotaManager::Get(); + NS_ASSERTION(quotaManager, "This should never fail!"); nsCOMPtr directory; - nsresult rv = mgr->GetDirectoryForOrigin(mASCIIOrigin, - getter_AddRefs(directory)); + nsresult rv = quotaManager->GetDirectoryForOrigin(mASCIIOrigin, + getter_AddRefs(directory)); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); NS_ASSERTION(directory, "What?"); + rv = directory->Append(NS_LITERAL_STRING(IDB_DIRECTORY_NAME)); + NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); + nsAutoString filename; rv = GetDatabaseFilename(mName, filename); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); @@ -2460,6 +2514,18 @@ DeleteDatabaseHelper::GetSuccessResult(JSContext* aCx, jsval* aVal) return NS_OK; } +nsresult +DeleteDatabaseHelper::OnExclusiveAccessAcquired() +{ + QuotaManager* quotaManager = QuotaManager::Get(); + NS_ASSERTION(quotaManager, "We should definitely have a manager here"); + + nsresult rv = Dispatch(quotaManager->IOThread()); + NS_ENSURE_SUCCESS(rv, rv); + + return NS_OK; +} + nsresult DeleteDatabaseHelper::Init() { diff --git a/dom/indexedDB/OpenDatabaseHelper.h b/dom/indexedDB/OpenDatabaseHelper.h index 5a3d987c3d05..bea3624364a0 100644 --- a/dom/indexedDB/OpenDatabaseHelper.h +++ b/dom/indexedDB/OpenDatabaseHelper.h @@ -24,6 +24,8 @@ BEGIN_INDEXEDDB_NAMESPACE class OpenDatabaseHelper : public HelperBase { + typedef mozilla::dom::quota::StoragePrivilege StoragePrivilege; + public: OpenDatabaseHelper(IDBOpenDBRequest* aRequest, const nsAString& aName, @@ -31,7 +33,7 @@ public: uint64_t aRequestedVersion, bool aForDeletion, mozilla::dom::ContentParent* aContentParent, - FactoryPrivilege aPrivilege) + StoragePrivilege aPrivilege) : HelperBase(aRequest), mOpenDBRequest(aRequest), mName(aName), mASCIIOrigin(aASCIIOrigin), mRequestedVersion(aRequestedVersion), mForDeletion(aForDeletion), mPrivilege(aPrivilege), mDatabaseId(nullptr), @@ -77,7 +79,7 @@ public: return mDatabase; } - const FactoryPrivilege& Privilege() const + const StoragePrivilege& Privilege() const { return mPrivilege; } @@ -109,7 +111,7 @@ protected: nsCString mASCIIOrigin; uint64_t mRequestedVersion; bool mForDeletion; - FactoryPrivilege mPrivilege; + StoragePrivilege mPrivilege; nsCOMPtr mDatabaseId; mozilla::dom::ContentParent* mContentParent; diff --git a/dom/indexedDB/TransactionThreadPool.cpp b/dom/indexedDB/TransactionThreadPool.cpp index 450b3d2e29d3..6420623a6fcc 100644 --- a/dom/indexedDB/TransactionThreadPool.cpp +++ b/dom/indexedDB/TransactionThreadPool.cpp @@ -279,8 +279,7 @@ TransactionThreadPool::GetQueueForTransaction(IDBTransaction* aTransaction) return *info->queue; } - TransactionInfo* transactionInfo = new TransactionInfo(aTransaction, - objectStoreNames); + TransactionInfo* transactionInfo = new TransactionInfo(aTransaction); dbTransactionInfo->transactions.Put(aTransaction, transactionInfo);; @@ -352,31 +351,23 @@ TransactionThreadPool::Dispatch(IDBTransaction* aTransaction, return NS_OK; } -bool -TransactionThreadPool::WaitForAllDatabasesToComplete( - nsTArray& aDatabases, - nsIRunnable* aCallback) +void +TransactionThreadPool::WaitForDatabasesToComplete( + nsTArray& aDatabases, + nsIRunnable* aCallback) { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); NS_ASSERTION(!aDatabases.IsEmpty(), "No databases to wait on!"); NS_ASSERTION(aCallback, "Null pointer!"); DatabasesCompleteCallback* callback = mCompleteCallbacks.AppendElement(); - if (!callback) { - NS_WARNING("Out of memory!"); - return false; - } callback->mCallback = aCallback; - if (!callback->mDatabases.SwapElements(aDatabases)) { - NS_ERROR("This should never fail!"); - } + callback->mDatabases.SwapElements(aDatabases); if (MaybeFireCallback(*callback)) { mCompleteCallbacks.RemoveElementAt(mCompleteCallbacks.Length() - 1); } - - return true; } // static @@ -430,12 +421,12 @@ TransactionThreadPool::AbortTransactionsForDatabase(IDBDatabase* aDatabase) struct NS_STACK_CLASS TransactionSearchInfo { - TransactionSearchInfo(IDBDatabase* aDatabase) + TransactionSearchInfo(nsIOfflineStorage* aDatabase) : db(aDatabase), found(false) { } - IDBDatabase* db; + nsIOfflineStorage* db; bool found; }; diff --git a/dom/indexedDB/TransactionThreadPool.h b/dom/indexedDB/TransactionThreadPool.h index 62768016b390..82d1ad3ca90b 100644 --- a/dom/indexedDB/TransactionThreadPool.h +++ b/dom/indexedDB/TransactionThreadPool.h @@ -16,7 +16,6 @@ #include "mozilla/Monitor.h" #include "nsClassHashtable.h" #include "nsHashKeys.h" -#include "nsRefPtrHashtable.h" #include "IDBTransaction.h" @@ -46,8 +45,8 @@ public: bool aFinish, nsIRunnable* aFinishRunnable); - bool WaitForAllDatabasesToComplete(nsTArray& aDatabases, - nsIRunnable* aCallback); + void WaitForDatabasesToComplete(nsTArray& aDatabases, + nsIRunnable* aCallback); // Abort all transactions, unless they are already in the process of being // committed, for aDatabase. @@ -83,8 +82,7 @@ protected: struct TransactionInfo { - TransactionInfo(IDBTransaction* aTransaction, - const nsTArray& aObjectStoreNames) + TransactionInfo(IDBTransaction* aTransaction) { MOZ_COUNT_CTOR(TransactionInfo); @@ -93,7 +91,6 @@ protected: transaction = aTransaction; queue = new TransactionQueue(aTransaction); - objectStoreNames.AppendElements(aObjectStoreNames); } ~TransactionInfo() @@ -103,7 +100,6 @@ protected: nsRefPtr transaction; nsRefPtr queue; - nsTArray objectStoreNames; nsTHashtable > blockedOn; nsTHashtable > blocking; }; diff --git a/dom/indexedDB/ipc/IndexedDBChild.cpp b/dom/indexedDB/ipc/IndexedDBChild.cpp index 0bd14d8817a3..8d48b987d0f4 100644 --- a/dom/indexedDB/ipc/IndexedDBChild.cpp +++ b/dom/indexedDB/ipc/IndexedDBChild.cpp @@ -11,6 +11,7 @@ #include "mozilla/Assertions.h" #include "mozilla/dom/ContentChild.h" +#include "mozilla/dom/quota/QuotaManager.h" #include "AsyncConnectionHelper.h" #include "DatabaseInfo.h" @@ -19,11 +20,11 @@ #include "IDBIndex.h" #include "IDBObjectStore.h" #include "IDBTransaction.h" -#include "IndexedDatabaseManager.h" USING_INDEXEDDB_NAMESPACE using namespace mozilla::dom; +using mozilla::dom::quota::QuotaManager; namespace { @@ -285,8 +286,7 @@ IndexedDBDatabaseChild::EnsureDatabase( databaseId = mDatabase->Id(); } else { - databaseId = - IndexedDatabaseManager::GetDatabaseId(aDBInfo.origin, aDBInfo.name); + databaseId = QuotaManager::GetStorageId(aDBInfo.origin, aDBInfo.name); } NS_ENSURE_TRUE(databaseId, false); diff --git a/dom/indexedDB/nsIIndexedDatabaseManager.idl b/dom/indexedDB/nsIIndexedDatabaseManager.idl index fef40c7eb992..da1be243d994 100644 --- a/dom/indexedDB/nsIIndexedDatabaseManager.idl +++ b/dom/indexedDB/nsIIndexedDatabaseManager.idl @@ -6,63 +6,9 @@ #include "nsISupports.idl" -interface nsIURI; - -[scriptable, function, uuid(38f15cc7-2df0-4a90-8b7f-1606b2243522)] -interface nsIIndexedDatabaseUsageCallback : nsISupports -{ - void onUsageResult(in nsIURI aURI, - in unsigned long long aUsage, - in unsigned long long aFileUsage, - in unsigned long aAppId, - in boolean aInMozBrowserOnly); -}; - -[scriptable, builtinclass, uuid(e5168115-baff-4559-887e-7c0405cc9e63)] +[scriptable, builtinclass, uuid(538d1085-517e-405a-a0f0-eb575cb0b8e5)] interface nsIIndexedDatabaseManager : nsISupports { - /** - * Schedules an asynchronous callback that will return the total amount of - * disk space being used by databases for the given origin. - * - * @param aURI - * The URI whose usage is being queried. - * @param aCallback - * The callback that will be called when the usage is available. - */ - [optional_argc] - void getUsageForURI(in nsIURI aURI, - in nsIIndexedDatabaseUsageCallback aCallback, - [optional] in unsigned long aAppId, - [optional] in boolean aInMozBrowserOnly); - - /** - * Cancels an asynchronous usage check initiated by a previous call to - * getUsageForURI(). - * - * @param aURI - * The URI whose usage is being queried. - * @param aCallback - * The callback that will be called when the usage is available. - */ - [optional_argc] - void cancelGetUsageForURI(in nsIURI aURI, - in nsIIndexedDatabaseUsageCallback aCallback, - [optional] in unsigned long aAppId, - [optional] in boolean aInMozBrowserOnly); - - /** - * Removes all databases stored for the given URI. The files may not be - * deleted immediately depending on prohibitive concurrent operations. - * - * @param aURI - * The URI whose databases are to be cleared. - */ - [optional_argc] - void clearDatabasesForURI(in nsIURI aURI, - [optional] in unsigned long aAppId, - [optional] in boolean aInMozBrowserOnly); - /** * Defines indexedDB and IDBKeyrange with its static functions on * aObject and initializes DOM exception providers if needed. diff --git a/dom/indexedDB/test/bug839193.js b/dom/indexedDB/test/bug839193.js index 343607483f76..293696802e7e 100644 --- a/dom/indexedDB/test/bug839193.js +++ b/dom/indexedDB/test/bug839193.js @@ -2,19 +2,18 @@ * 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 nsIIndexedDatabaseManager = - Components.interfaces.nsIIndexedDatabaseManager; +const nsIQuotaManager = Components.interfaces.nsIQuotaManager; let gURI = Components.classes["@mozilla.org/network/io-service;1"].getService(Components.interfaces.nsIIOService).newURI("http://localhost", null, null); -function onIndexedDBUsageCallback(uri, usage, fileUsage) {} +function onUsageCallback(uri, usage, fileUsage) {} function onLoad() { - var dbManager = Components.classes["@mozilla.org/dom/indexeddb/manager;1"] - .getService(nsIIndexedDatabaseManager); - dbManager.getUsageForURI(gURI, onIndexedDBUsageCallback); - dbManager.cancelGetUsageForURI(gURI, onIndexedDBUsageCallback); + var quotaManager = Components.classes["@mozilla.org/dom/quota/manager;1"] + .getService(nsIQuotaManager); + var quotaRequest = quotaManager.getUsageForURI(gURI, onUsageCallback); + quotaRequest.cancel(); Components.classes["@mozilla.org/observer-service;1"] .getService(Components.interfaces.nsIObserverService) .notifyObservers(window, "bug839193-loaded", null); diff --git a/dom/indexedDB/test/file.js b/dom/indexedDB/test/file.js index e254a3cbd035..e268c847ea41 100644 --- a/dom/indexedDB/test/file.js +++ b/dom/indexedDB/test/file.js @@ -173,8 +173,8 @@ function grabFileUsageAndContinueHandler(usage, fileUsage) function getUsage(usageHandler) { let comp = SpecialPowers.wrap(Components); - let idbManager = comp.classes["@mozilla.org/dom/indexeddb/manager;1"] - .getService(comp.interfaces.nsIIndexedDatabaseManager); + let quotaManager = comp.classes["@mozilla.org/dom/quota/manager;1"] + .getService(comp.interfaces.nsIQuotaManager); let uri = SpecialPowers.getDocumentURIObject(window.document); let callback = { @@ -183,7 +183,7 @@ function getUsage(usageHandler) } }; - idbManager.getUsageForURI(uri, callback); + quotaManager.getUsageForURI(uri, callback); } function scheduleGC() diff --git a/dom/indexedDB/test/helpers.js b/dom/indexedDB/test/helpers.js index fa514b3d9051..3e8b73b78c89 100644 --- a/dom/indexedDB/test/helpers.js +++ b/dom/indexedDB/test/helpers.js @@ -40,18 +40,18 @@ function clearAllDatabases(callback) { let comp = SpecialPowers.wrap(Components); - let idbManager = - comp.classes["@mozilla.org/dom/indexeddb/manager;1"] - .getService(comp.interfaces.nsIIndexedDatabaseManager); + let quotaManager = + comp.classes["@mozilla.org/dom/quota/manager;1"] + .getService(comp.interfaces.nsIQuotaManager); let uri = SpecialPowers.getDocumentURIObject(document); - idbManager.clearDatabasesForURI(uri); - idbManager.getUsageForURI(uri, function(uri, usage, fileUsage) { + quotaManager.clearStoragesForURI(uri); + quotaManager.getUsageForURI(uri, function(uri, usage, fileUsage) { if (usage) { ok(false, "getUsageForURI returned non-zero usage after clearing all " + - "databases!"); + "storages!"); } runCallback(); }); diff --git a/dom/quota/AcquireListener.h b/dom/quota/AcquireListener.h new file mode 100644 index 000000000000..cb02f3e4f9f0 --- /dev/null +++ b/dom/quota/AcquireListener.h @@ -0,0 +1,29 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_quota_acquirelistener_h__ +#define mozilla_dom_quota_acquirelistener_h__ + +#include "mozilla/dom/quota/QuotaCommon.h" + +BEGIN_QUOTA_NAMESPACE + +class AcquireListener +{ +public: + NS_IMETHOD_(nsrefcnt) + AddRef() = 0; + + NS_IMETHOD_(nsrefcnt) + Release() = 0; + + virtual nsresult + OnExclusiveAccessAcquired() = 0; +}; + +END_QUOTA_NAMESPACE + +#endif // mozilla_dom_quota_acquirelistener_h__ diff --git a/dom/quota/ArrayCluster.h b/dom/quota/ArrayCluster.h new file mode 100644 index 000000000000..7c72fb5dc1db --- /dev/null +++ b/dom/quota/ArrayCluster.h @@ -0,0 +1,106 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_quota_arraycluster_h__ +#define mozilla_dom_quota_arraycluster_h__ + +#include "mozilla/dom/quota/QuotaCommon.h" + +#include "Client.h" + +BEGIN_QUOTA_NAMESPACE + +template +class ArrayCluster +{ +public: + ArrayCluster() + { + mArrays.AppendElements(Length); + } + + nsTArray& + ArrayAt(uint32_t aIndex) + { + MOZ_ASSERT(aIndex < Length, "Bad index!"); + return mArrays[aIndex]; + } + + nsTArray& + operator[](uint32_t aIndex) + { + return ArrayAt(aIndex); + } + + bool + IsEmpty() + { + for (uint32_t index = 0; index < Length; index++) { + if (!mArrays[index].IsEmpty()) { + return false; + } + } + return true; + } + + template + void + AppendElementsTo(uint32_t aIndex, nsTArray& aArray) + { + NS_ASSERTION(aIndex < Length, "Bad index!"); + aArray.AppendElements(mArrays[aIndex]); + } + + template + void + AppendElementsTo(uint32_t aIndex, ArrayCluster& aArrayCluster) + { + NS_ASSERTION(aIndex < Length, "Bad index!"); + aArrayCluster[aIndex].AppendElements(mArrays[aIndex]); + } + + template + void + AppendElementsTo(nsTArray& aArray) + { + for (uint32_t index = 0; index < Length; index++) { + aArray.AppendElements(mArrays[index]); + } + } + + template + void + AppendElementsTo(ArrayCluster& aArrayCluster) + { + for (uint32_t index = 0; index < Length; index++) { + aArrayCluster[index].AppendElements(mArrays[index]); + } + } + + template + void + SwapElements(ArrayCluster& aArrayCluster) + { + for (uint32_t index = 0; index < Length; index++) { + mArrays[index].SwapElements(aArrayCluster.mArrays[index]); + } + } + + void + Clear() + { + for (uint32_t index = 0; index < Length; index++) { + mArrays[index].Clear(); + } + } + +private: + nsAutoTArray, Length> mArrays; +}; + +END_QUOTA_NAMESPACE + +#endif // mozilla_dom_quota_arraycluster_h__ diff --git a/dom/quota/CheckQuotaHelper.cpp b/dom/quota/CheckQuotaHelper.cpp index 266d63e68556..af5168855901 100644 --- a/dom/quota/CheckQuotaHelper.cpp +++ b/dom/quota/CheckQuotaHelper.cpp @@ -14,7 +14,7 @@ #include "nsIURI.h" #include "nsPIDOMWindow.h" -#include "mozilla/dom/indexedDB/IndexedDatabaseManager.h" +#include "mozilla/dom/quota/QuotaManager.h" #include "mozilla/Services.h" #include "nsContentUtils.h" #include "nsNetUtil.h" @@ -29,7 +29,6 @@ USING_QUOTA_NAMESPACE using namespace mozilla::services; -using mozilla::dom::indexedDB::IndexedDatabaseManager; using mozilla::MutexAutoLock; namespace { @@ -167,7 +166,7 @@ CheckQuotaHelper::Run() } } else if (mPromptResult == nsIPermissionManager::UNKNOWN_ACTION) { - uint32_t quota = IndexedDatabaseManager::GetIndexedDBQuotaMB(); + uint32_t quota = QuotaManager::GetStorageQuotaMB(); nsString quotaString; quotaString.AppendInt(quota); diff --git a/dom/quota/CheckQuotaHelper.h b/dom/quota/CheckQuotaHelper.h index 948b8e02832b..16d914105e7f 100644 --- a/dom/quota/CheckQuotaHelper.h +++ b/dom/quota/CheckQuotaHelper.h @@ -49,4 +49,4 @@ private: END_QUOTA_NAMESPACE -#endif // mozilla_dom_indexeddb_checkquotahelper_h__ +#endif // mozilla_dom_quota_checkquotahelper_h__ diff --git a/dom/quota/Client.h b/dom/quota/Client.h new file mode 100644 index 000000000000..e04f7a691bd2 --- /dev/null +++ b/dom/quota/Client.h @@ -0,0 +1,110 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_quota_client_h__ +#define mozilla_dom_quota_client_h__ + +#include "mozilla/dom/quota/QuotaCommon.h" + +class nsIOfflineStorage; +class nsIRunnable; + +BEGIN_QUOTA_NAMESPACE + +class UsageRunnable; + +// An abstract interface for quota manager clients. +// Each storage API must provide an implementation of this interface in order +// to participate in centralized quota and storage handling. +class Client +{ +public: + NS_IMETHOD_(nsrefcnt) + AddRef() = 0; + + NS_IMETHOD_(nsrefcnt) + Release() = 0; + + enum Type { + IDB = 0, + //LS, + //APPCACHE, + TYPE_MAX + }; + + virtual Type + GetType() = 0; + + static nsresult + TypeToText(Type aType, nsAString& aText) + { + switch (aType) { + case IDB: + aText.AssignLiteral("idb"); + break; + + case TYPE_MAX: + default: + NS_NOTREACHED("Bad id value!"); + return NS_ERROR_UNEXPECTED; + } + + return NS_OK; + } + + static nsresult + TypeFromText(const nsAString& aText, Type& aType) + { + if (aText.EqualsLiteral("idb")) { + aType = IDB; + } + else { + return NS_ERROR_FAILURE; + } + + return NS_OK; + } + + virtual nsresult + InitOrigin(const nsACString& aOrigin, UsageRunnable* aUsageRunnable) = 0; + + virtual nsresult + GetUsageForOrigin(const nsACString& aOrigin, + UsageRunnable* aUsageRunnable) = 0; + + virtual bool + IsFileServiceUtilized() = 0; + + virtual bool + IsTransactionServiceActivated() = 0; + + virtual void + WaitForStoragesToComplete(nsTArray& aStorages, + nsIRunnable* aCallback) = 0; + + virtual void + AbortTransactionsForStorage(nsIOfflineStorage* aStorage) = 0; + + virtual bool + HasTransactionsForStorage(nsIOfflineStorage* aStorage) = 0; + + virtual void + OnOriginClearCompleted(const nsACString& aPattern) = 0; + + virtual void + ShutdownTransactionService() = 0; + + virtual void + OnShutdownCompleted() = 0; + +protected: + virtual ~Client() + { } +}; + +END_QUOTA_NAMESPACE + +#endif // mozilla_dom_quota_client_h__ diff --git a/dom/quota/FileStreams.cpp b/dom/quota/FileStreams.cpp index 9de244f7792c..cf4d9731e17e 100644 --- a/dom/quota/FileStreams.cpp +++ b/dom/quota/FileStreams.cpp @@ -6,6 +6,8 @@ #include "FileStreams.h" +#include "QuotaManager.h" + USING_QUOTA_NAMESPACE template diff --git a/dom/quota/FileStreams.h b/dom/quota/FileStreams.h index 77bfad47121e..ba56cdbbc76d 100644 --- a/dom/quota/FileStreams.h +++ b/dom/quota/FileStreams.h @@ -11,7 +11,7 @@ #include "nsFileStreams.h" -#include "QuotaManager.h" +#include "QuotaObject.h" BEGIN_QUOTA_NAMESPACE diff --git a/dom/quota/Makefile.in b/dom/quota/Makefile.in index fcba5264eb76..41cf0e4e5de3 100644 --- a/dom/quota/Makefile.in +++ b/dom/quota/Makefile.in @@ -12,6 +12,7 @@ include $(DEPTH)/config/autoconf.mk LIBRARY_NAME = domquota_s LIBXUL_LIBRARY = 1 FORCE_STATIC_LIB = 1 +FAIL_ON_WARNINGS := 1 include $(topsrcdir)/dom/dom-config.mk @@ -21,12 +22,31 @@ CPPSRCS = \ CheckQuotaHelper.cpp \ FileStreams.cpp \ QuotaManager.cpp \ + QuotaObject.cpp \ + $(NULL) + +EXPORTS = \ + nsIOfflineStorage.h \ $(NULL) EXPORTS_mozilla/dom/quota = \ + AcquireListener.h \ + ArrayCluster.h \ + Client.h \ FileStreams.h \ + OriginOrPatternString.h \ QuotaCommon.h \ QuotaManager.h \ + QuotaObject.h \ + StoragePrivilege.h \ + UsageRunnable.h \ + Utilities.h \ $(NULL) +LOCAL_INCLUDES = \ + -I$(topsrcdir)/caps/include \ + $(NULL) + +include $(topsrcdir)/config/config.mk +include $(topsrcdir)/ipc/chromium/chromium-config.mk include $(topsrcdir)/config/rules.mk diff --git a/dom/quota/OriginOrPatternString.h b/dom/quota/OriginOrPatternString.h new file mode 100644 index 000000000000..a26e30d140e9 --- /dev/null +++ b/dom/quota/OriginOrPatternString.h @@ -0,0 +1,54 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_quota_originorpatternstring_h__ +#define mozilla_dom_quota_originorpatternstring_h__ + +#include "mozilla/dom/quota/QuotaCommon.h" + +BEGIN_QUOTA_NAMESPACE + +class OriginOrPatternString : public nsCString +{ +public: + static OriginOrPatternString + FromOrigin(const nsACString& aOrigin) + { + return OriginOrPatternString(aOrigin, true); + } + + static OriginOrPatternString + FromPattern(const nsACString& aPattern) + { + return OriginOrPatternString(aPattern, false); + } + + bool + IsOrigin() const + { + return mIsOrigin; + } + + bool + IsPattern() const + { + return !mIsOrigin; + } + +private: + OriginOrPatternString(const nsACString& aOriginOrPattern, bool aIsOrigin) + : nsCString(aOriginOrPattern), mIsOrigin(aIsOrigin) + { } + + bool + operator==(const OriginOrPatternString& aOther) MOZ_DELETE; + + bool mIsOrigin; +}; + +END_QUOTA_NAMESPACE + +#endif // mozilla_dom_quota_originorpatternstring_h__ diff --git a/dom/quota/QuotaManager.cpp b/dom/quota/QuotaManager.cpp index 42da545f5b87..13a4db72623f 100644 --- a/dom/quota/QuotaManager.cpp +++ b/dom/quota/QuotaManager.cpp @@ -6,19 +6,321 @@ #include "QuotaManager.h" +#include "mozIApplicationClearPrivateDataParams.h" +#include "nsIAtom.h" #include "nsIFile.h" +#include "nsIObserverService.h" +#include "nsIOfflineStorage.h" +#include "nsIPrincipal.h" +#include "nsIQuotaRequest.h" +#include "nsIRunnable.h" +#include "nsISimpleEnumerator.h" +#include "nsIScriptObjectPrincipal.h" +#include "nsIScriptSecurityManager.h" +#include "nsITimer.h" +#include "nsIURI.h" +#include "nsIUsageCallback.h" -#include "mozilla/ClearOnShutdown.h" +#include +#include "mozilla/dom/file/FileService.h" +#include "mozilla/dom/indexedDB/Client.h" +#include "mozilla/LazyIdleThread.h" +#include "mozilla/Preferences.h" +#include "mozilla/Services.h" +#include "nsAppDirectoryServiceDefs.h" #include "nsComponentManagerUtils.h" +#include "nsContentUtils.h" +#include "nsCRTGlue.h" +#include "nsDirectoryServiceUtils.h" +#include "nsScriptSecurityManager.h" +#include "nsThreadUtils.h" +#include "nsXULAppAPI.h" #include "xpcpublic.h" +#include "AcquireListener.h" #include "CheckQuotaHelper.h" +#include "OriginOrPatternString.h" +#include "QuotaObject.h" +#include "StorageMatcher.h" +#include "UsageRunnable.h" +#include "Utilities.h" + +// The amount of time, in milliseconds, that our IO thread will stay alive +// after the last event it processes. +#define DEFAULT_THREAD_TIMEOUT_MS 30000 + +// The amount of time, in milliseconds, that we will wait for active storage +// transactions on shutdown before aborting them. +#define DEFAULT_SHUTDOWN_TIMER_MS 30000 + +// Amount of space that storages may use by default in megabytes. +#define DEFAULT_QUOTA_MB 50 + +// Preference that users can set to override DEFAULT_QUOTA_MB +#define PREF_STORAGE_QUOTA "dom.indexedDB.warningQuota" + +// profile-before-change, when we need to shut down quota manager +#define PROFILE_BEFORE_CHANGE_OBSERVER_ID "profile-before-change" + +#define METADATA_FILE_NAME ".metadata" USING_QUOTA_NAMESPACE +using namespace mozilla::dom; +using mozilla::dom::file::FileService; + +BEGIN_QUOTA_NAMESPACE + +// A struct that contains the information corresponding to a pending or +// running operation that requires synchronization (e.g. opening a db, +// clearing dbs for an origin, etc). +struct SynchronizedOp +{ + SynchronizedOp(const OriginOrPatternString& aOriginOrPattern, + nsISupports* aId); + + ~SynchronizedOp(); + + // Test whether this SynchronizedOp needs to wait for the given op. + bool + MustWaitFor(const SynchronizedOp& aOp); + + void + DelayRunnable(nsIRunnable* aRunnable); + + void + DispatchDelayedRunnables(); + + const OriginOrPatternString mOriginOrPattern; + nsCOMPtr mId; + nsRefPtr mListener; + nsTArray > mDelayedRunnables; + ArrayCluster mStorages; +}; + +// Responsible for clearing the storage files for a particular origin on the +// IO thread. Created when nsIQuotaManager::ClearStoragesForURI is called. +// Runs three times, first on the main thread, next on the IO thread, and then +// finally again on the main thread. While on the IO thread the runnable will +// actually remove the origin's storage files and the directory that contains +// them before dispatching itself back to the main thread. When back on the main +// thread the runnable will notify the QuotaManager that the job has been +// completed. +class OriginClearRunnable MOZ_FINAL : public nsIRunnable, + public AcquireListener +{ + enum CallbackState { + // Not yet run. + Pending = 0, + + // Running on the main thread in the callback for OpenAllowed. + OpenAllowed, + + // Running on the IO thread. + IO, + + // Running on the main thread after all work is done. + Complete + }; + +public: + NS_DECL_ISUPPORTS + NS_DECL_NSIRUNNABLE + + // AcquireListener override + virtual nsresult + OnExclusiveAccessAcquired() MOZ_OVERRIDE; + + OriginClearRunnable(const OriginOrPatternString& aOriginOrPattern) + : mOriginOrPattern(aOriginOrPattern), + mCallbackState(Pending) + { } + + void + AdvanceState() + { + switch (mCallbackState) { + case Pending: + mCallbackState = OpenAllowed; + return; + case OpenAllowed: + mCallbackState = IO; + return; + case IO: + mCallbackState = Complete; + return; + default: + NS_NOTREACHED("Can't advance past Complete!"); + } + } + + static void + InvalidateOpenedStorages(nsTArray >& aStorages, + void* aClosure); + + void + DeleteFiles(QuotaManager* aQuotaManager); + +private: + OriginOrPatternString mOriginOrPattern; + CallbackState mCallbackState; +}; + +// Responsible for calculating the amount of space taken up by storages of a +// certain origin. Created when nsIQuotaManager::GetUsageForURI is called. +// May be canceled with nsIQuotaRequest::Cancel. Runs three times, first +// on the main thread, next on the IO thread, and then finally again on the main +// thread. While on the IO thread the runnable will calculate the size of all +// files in the origin's directory before dispatching itself back to the main +// thread. When on the main thread the runnable will call the callback and then +// notify the QuotaManager that the job has been completed. +class AsyncUsageRunnable MOZ_FINAL : public UsageRunnable, + public nsIRunnable, + public nsIQuotaRequest +{ + enum CallbackState { + // Not yet run. + Pending = 0, + + // Running on the main thread in the callback for OpenAllowed. + OpenAllowed, + + // Running on the IO thread. + IO, + + // Running on the main thread after all work is done. + Complete, + + // Running on the main thread after skipping the work + Shortcut + }; + +public: + NS_DECL_ISUPPORTS + NS_DECL_NSIRUNNABLE + NS_DECL_NSIQUOTAREQUEST + + AsyncUsageRunnable(uint32_t aAppId, + bool aInMozBrowserOnly, + const OriginOrPatternString& aOrigin, + nsIURI* aURI, + nsIUsageCallback* aCallback); + + void + AdvanceState() + { + switch (mCallbackState) { + case Pending: + mCallbackState = OpenAllowed; + return; + case OpenAllowed: + mCallbackState = IO; + return; + case IO: + mCallbackState = Complete; + return; + default: + NS_NOTREACHED("Can't advance past Complete!"); + } + } + + nsresult + TakeShortcut(); + + // Run calls the RunInternal method and makes sure that we always dispatch + // to the main thread in case of an error. + inline nsresult + RunInternal(); + + nsCOMPtr mURI; + nsCOMPtr mCallback; + uint32_t mAppId; + OriginOrPatternString mOrigin; + CallbackState mCallbackState; + bool mInMozBrowserOnly; +}; + +END_QUOTA_NAMESPACE namespace { -nsAutoPtr gInstance; +QuotaManager* gInstance = nullptr; +int32_t gShutdown = 0; + +int32_t gStorageQuotaMB = DEFAULT_QUOTA_MB; + +// A callback runnable used by the TransactionPool when it's safe to proceed +// with a SetVersion/DeleteDatabase/etc. +class WaitForTransactionsToFinishRunnable MOZ_FINAL : public nsIRunnable +{ +public: + WaitForTransactionsToFinishRunnable(SynchronizedOp* aOp) + : mOp(aOp), mCountdown(1) + { + NS_ASSERTION(mOp, "Why don't we have a runnable?"); + NS_ASSERTION(mOp->mStorages.IsEmpty(), "We're here too early!"); + NS_ASSERTION(mOp->mListener, + "What are we supposed to do when we're done?"); + NS_ASSERTION(mCountdown, "Wrong countdown!"); + } + + NS_DECL_ISUPPORTS + NS_DECL_NSIRUNNABLE + + void + AddRun() + { + mCountdown++; + } + +private: + // The QuotaManager holds this alive. + SynchronizedOp* mOp; + uint32_t mCountdown; +}; + +class WaitForLockedFilesToFinishRunnable MOZ_FINAL : public nsIRunnable +{ +public: + WaitForLockedFilesToFinishRunnable() + : mBusy(true) + { } + + NS_DECL_ISUPPORTS + NS_DECL_NSIRUNNABLE + + bool + IsBusy() const + { + return mBusy; + } + +private: + bool mBusy; +}; + +bool +IsMainProcess() +{ + return XRE_GetProcessType() == GeckoProcessType_Default; +} + +void +SanitizeOriginString(nsCString& aOrigin) +{ + // We want profiles to be platform-independent so we always need to replace + // the same characters on every platform. Windows has the most extensive set + // of illegal characters so we use its FILE_ILLEGAL_CHARACTERS and + // FILE_PATH_SEPARATOR. + static const char kReplaceChars[] = CONTROL_CHARACTERS "/:*?\"<>|\\"; + +#ifdef XP_WIN + NS_ASSERTION(!strcmp(kReplaceChars, + FILE_ILLEGAL_CHARACTERS FILE_PATH_SEPARATOR), + "Illegal file characters have changed!"); +#endif + + aOrigin.ReplaceChar(kReplaceChars, '+'); +} PLDHashOperator RemoveQuotaForPatternCallback(const nsACString& aKey, @@ -32,7 +334,7 @@ RemoveQuotaForPatternCallback(const nsACString& aKey, const nsACString* pattern = static_cast(aUserArg); - if (StringBeginsWith(aKey, *pattern)) { + if (PatternMatchesOrigin(*pattern, aKey)) { return PL_DHASH_REMOVE; } @@ -41,180 +343,47 @@ RemoveQuotaForPatternCallback(const nsACString& aKey, } // anonymous namespace -void -QuotaObject::AddRef() -{ - QuotaManager* quotaManager = QuotaManager::Get(); - if (!quotaManager) { - NS_ERROR("Null quota manager, this shouldn't happen, possible leak!"); - - NS_AtomicIncrementRefcnt(mRefCnt); - - return; - } - - MutexAutoLock lock(quotaManager->mQuotaMutex); - - ++mRefCnt; -} - -void -QuotaObject::Release() -{ - QuotaManager* quotaManager = QuotaManager::Get(); - if (!quotaManager) { - NS_ERROR("Null quota manager, this shouldn't happen, possible leak!"); - - nsrefcnt count = NS_AtomicDecrementRefcnt(mRefCnt); - if (count == 0) { - mRefCnt = 1; - delete this; - } - - return; - } - - { - MutexAutoLock lock(quotaManager->mQuotaMutex); - - --mRefCnt; - - if (mRefCnt > 0) { - return; - } - - if (mOriginInfo) { - mOriginInfo->mQuotaObjects.Remove(mPath); - } - } - - delete this; -} - -void -QuotaObject::UpdateSize(int64_t aSize) -{ - QuotaManager* quotaManager = QuotaManager::Get(); - NS_ASSERTION(quotaManager, "Shouldn't be null!"); - - MutexAutoLock lock(quotaManager->mQuotaMutex); - - if (mOriginInfo) { - mOriginInfo->mUsage -= mSize; - mSize = aSize; - mOriginInfo->mUsage += mSize; - } -} - -bool -QuotaObject::MaybeAllocateMoreSpace(int64_t aOffset, int32_t aCount) -{ - int64_t end = aOffset + aCount; - - QuotaManager* quotaManager = QuotaManager::Get(); - NS_ASSERTION(quotaManager, "Shouldn't be null!"); - - MutexAutoLock lock(quotaManager->mQuotaMutex); - - if (mSize >= end || !mOriginInfo) { - return true; - } - - int64_t newUsage = mOriginInfo->mUsage - mSize + end; - if (newUsage > mOriginInfo->mLimit) { - // This will block the thread, but it will also drop the mutex while - // waiting. The mutex will be reacquired again when the waiting is finished. - if (!quotaManager->LockedQuotaIsLifted()) { - return false; - } - - // Threads raced, the origin info removal has been done by some other - // thread. - if (!mOriginInfo) { - // The other thread could allocate more space. - if (end > mSize) { - mSize = end; - } - - return true; - } - - nsCString origin = mOriginInfo->mOrigin; - - mOriginInfo->LockedClearOriginInfos(); - NS_ASSERTION(!mOriginInfo, - "Should have cleared in LockedClearOriginInfos!"); - - quotaManager->mOriginInfos.Remove(origin); - - // Some other thread could increase the size without blocking (increasing - // the origin usage without hitting the limit), but no more than this one. - NS_ASSERTION(mSize < end, "This shouldn't happen!"); - - mSize = end; - - return true; - } - - mOriginInfo->mUsage = newUsage; - mSize = end; - - return true; -} - -#ifdef DEBUG -void -OriginInfo::LockedClearOriginInfos() -{ - QuotaManager* quotaManager = QuotaManager::Get(); - NS_ASSERTION(quotaManager, "Shouldn't be null!"); - - quotaManager->mQuotaMutex.AssertCurrentThreadOwns(); - - mQuotaObjects.EnumerateRead(ClearOriginInfoCallback, nullptr); -} -#endif - -// static -PLDHashOperator -OriginInfo::ClearOriginInfoCallback(const nsAString& aKey, - QuotaObject* aValue, - void* aUserArg) -{ - NS_ASSERTION(!aKey.IsEmpty(), "Empty key!"); - NS_ASSERTION(aValue, "Null pointer!"); - - aValue->mOriginInfo = nullptr; - - return PL_DHASH_NEXT; -} - QuotaManager::QuotaManager() : mCurrentWindowIndex(BAD_TLS_INDEX), mQuotaMutex("QuotaManager.mQuotaMutex") { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); + NS_ASSERTION(!gInstance, "More than one instance!"); } QuotaManager::~QuotaManager() { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); + NS_ASSERTION(!gInstance || gInstance == this, "Different instances!"); + gInstance = nullptr; } // static QuotaManager* QuotaManager::GetOrCreate() { + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); + + if (IsShuttingDown()) { + NS_ERROR("Calling GetOrCreate() after shutdown!"); + return nullptr; + } + if (!gInstance) { - NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); + nsRefPtr instance(new QuotaManager()); - nsAutoPtr instance(new QuotaManager()); + nsresult rv = instance->Init(); + NS_ENSURE_SUCCESS(rv, nullptr); - NS_ENSURE_TRUE(instance->Init(), nullptr); + nsCOMPtr obs = mozilla::services::GetObserverService(); + NS_ENSURE_TRUE(obs, nullptr); - gInstance = instance.forget(); + // We need this callback to know when to shut down all our threads. + rv = obs->AddObserver(instance, PROFILE_BEFORE_CHANGE_OBSERVER_ID, false); + NS_ENSURE_SUCCESS(rv, nullptr); - ClearOnShutdown(&gInstance); + // The observer service will hold our last reference, don't AddRef here. + gInstance = instance; } return gInstance; @@ -228,7 +397,25 @@ QuotaManager::Get() return gInstance; } +// static +QuotaManager* +QuotaManager::FactoryCreate() +{ + // Returns a raw pointer that carries an owning reference! Lame, but the + // singleton factory macros force this. + QuotaManager* quotaManager = GetOrCreate(); + NS_IF_ADDREF(quotaManager); + return quotaManager; +} + +// static bool +QuotaManager::IsShuttingDown() +{ + return !!gShutdown; +} + +nsresult QuotaManager::Init() { // We need a thread-local to hold the current window. @@ -237,13 +424,59 @@ QuotaManager::Init() if (PR_NewThreadPrivateIndex(&mCurrentWindowIndex, nullptr) != PR_SUCCESS) { NS_ERROR("PR_NewThreadPrivateIndex failed, QuotaManager disabled"); mCurrentWindowIndex = BAD_TLS_INDEX; - return false; + return NS_ERROR_FAILURE; + } + + nsresult rv; + if (IsMainProcess()) { + nsCOMPtr dbBaseDirectory; + rv = NS_GetSpecialDirectory(NS_APP_INDEXEDDB_PARENT_DIR, + getter_AddRefs(dbBaseDirectory)); + if (NS_FAILED(rv)) { + rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, + getter_AddRefs(dbBaseDirectory)); + } + NS_ENSURE_SUCCESS(rv, rv); + + rv = dbBaseDirectory->Append(NS_LITERAL_STRING("indexedDB")); + NS_ENSURE_SUCCESS(rv, rv); + + rv = dbBaseDirectory->GetPath(mStorageBasePath); + NS_ENSURE_SUCCESS(rv, rv); + + // Make a lazy thread for any IO we need (like clearing or enumerating the + // contents of storage directories). + mIOThread = new LazyIdleThread(DEFAULT_THREAD_TIMEOUT_MS, + NS_LITERAL_CSTRING("Storage I/O"), + LazyIdleThread::ManualShutdown); + + // Make a timer here to avoid potential failures later. We don't actually + // initialize the timer until shutdown. + mShutdownTimer = do_CreateInstance(NS_TIMER_CONTRACTID); + NS_ENSURE_TRUE(mShutdownTimer, NS_ERROR_FAILURE); + } + + if (NS_FAILED(Preferences::AddIntVarCache(&gStorageQuotaMB, + PREF_STORAGE_QUOTA, + DEFAULT_QUOTA_MB))) { + NS_WARNING("Unable to respond to quota pref changes!"); + gStorageQuotaMB = DEFAULT_QUOTA_MB; } mOriginInfos.Init(); mCheckQuotaHelpers.Init(); + mLiveStorages.Init(); - return true; + MOZ_STATIC_ASSERT(Client::IDB == 0 && Client::TYPE_MAX == 1, + "Fix the registration!"); + + NS_ASSERTION(mClients.Capacity() == Client::TYPE_MAX, + "Should be using an auto array with correct capacity!"); + + // Register IndexedDB + mClients.AppendElement(new indexedDB::Client()); + + return NS_OK; } void @@ -345,6 +578,712 @@ QuotaManager::GetQuotaObject(const nsACString& aOrigin, return GetQuotaObject(aOrigin, file); } +bool +QuotaManager::RegisterStorage(nsIOfflineStorage* aStorage) +{ + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); + NS_ASSERTION(aStorage, "Null pointer!"); + + // Don't allow any new storages to be created after shutdown. + if (IsShuttingDown()) { + return false; + } + + // Add this storage to its origin info if it exists, create it otherwise. + const nsACString& origin = aStorage->Origin(); + ArrayCluster* cluster; + if (!mLiveStorages.Get(origin, &cluster)) { + cluster = new ArrayCluster(); + mLiveStorages.Put(origin, cluster); + } + (*cluster)[aStorage->GetClient()->GetType()].AppendElement(aStorage); + + return true; +} + +void +QuotaManager::UnregisterStorage(nsIOfflineStorage* aStorage) +{ + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); + NS_ASSERTION(aStorage, "Null pointer!"); + + // Remove this storage from its origin array, maybe remove the array if it + // is then empty. + const nsACString& origin = aStorage->Origin(); + ArrayCluster* cluster; + if (mLiveStorages.Get(origin, &cluster) && + (*cluster)[aStorage->GetClient()->GetType()].RemoveElement(aStorage)) { + if (cluster->IsEmpty()) { + mLiveStorages.Remove(origin); + } + return; + } + NS_ERROR("Didn't know anything about this storage!"); +} + +void +QuotaManager::OnStorageClosed(nsIOfflineStorage* aStorage) +{ + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); + NS_ASSERTION(aStorage, "Null pointer!"); + + // Check through the list of SynchronizedOps to see if any are waiting for + // this storage to close before proceeding. + SynchronizedOp* op = + FindSynchronizedOp(aStorage->Origin(), aStorage->Id()); + if (op) { + Client::Type clientType = aStorage->GetClient()->GetType(); + + // This storage is in the scope of this SynchronizedOp. Remove it + // from the list if necessary. + if (op->mStorages[clientType].RemoveElement(aStorage)) { + // Now set up the helper if there are no more live storages. + NS_ASSERTION(op->mListener, + "How did we get rid of the listener before removing the " + "last storage?"); + if (op->mStorages[clientType].IsEmpty()) { + // At this point, all storages are closed, so no new transactions + // can be started. There may, however, still be outstanding + // transactions that have not completed. We need to wait for those + // before we dispatch the helper. + if (NS_FAILED(RunSynchronizedOp(aStorage, op))) { + NS_WARNING("Failed to run synchronized op!"); + } + } + } + } +} + +void +QuotaManager::AbortCloseStoragesForWindow(nsPIDOMWindow* aWindow) +{ + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); + NS_ASSERTION(aWindow, "Null pointer!"); + + FileService* service = FileService::Get(); + + StorageMatcher > liveStorages; + liveStorages.Find(mLiveStorages); + + for (uint32_t i = 0; i < Client::TYPE_MAX; i++) { + nsRefPtr& client = mClients[i]; + bool utilized = service && client->IsFileServiceUtilized(); + bool activated = client->IsTransactionServiceActivated(); + + nsTArray& array = liveStorages[i]; + for (uint32_t j = 0; j < array.Length(); j++) { + nsIOfflineStorage*& storage = array[j]; + + if (storage->IsOwned(aWindow)) { + if (NS_FAILED(storage->Close())) { + NS_WARNING("Failed to close storage for dying window!"); + } + + if (utilized) { + service->AbortLockedFilesForStorage(storage); + } + + if (activated) { + client->AbortTransactionsForStorage(storage); + } + } + } + } +} + +bool +QuotaManager::HasOpenTransactions(nsPIDOMWindow* aWindow) +{ + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); + NS_ASSERTION(aWindow, "Null pointer!"); + + FileService* service = FileService::Get(); + + nsAutoPtr > > liveStorages; + + for (uint32_t i = 0; i < Client::TYPE_MAX; i++) { + nsRefPtr& client = mClients[i]; + bool utilized = service && client->IsFileServiceUtilized(); + bool activated = client->IsTransactionServiceActivated(); + + if (utilized || activated) { + if (!liveStorages) { + liveStorages = new StorageMatcher >(); + liveStorages->Find(mLiveStorages); + } + + nsTArray& storages = liveStorages->ArrayAt(i); + for (uint32_t j = 0; j < storages.Length(); j++) { + nsIOfflineStorage*& storage = storages[j]; + + if (storage->IsOwned(aWindow) && + ((utilized && service->HasLockedFilesForStorage(storage)) || + (activated && client->HasTransactionsForStorage(storage)))) { + return true; + } + } + } + } + + return false; +} + +nsresult +QuotaManager::WaitForOpenAllowed(const OriginOrPatternString& aOriginOrPattern, + nsIAtom* aId, + nsIRunnable* aRunnable) +{ + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); + NS_ASSERTION(!aOriginOrPattern.IsEmpty(), "Empty pattern!"); + NS_ASSERTION(aRunnable, "Null pointer!"); + + nsAutoPtr op(new SynchronizedOp(aOriginOrPattern, aId)); + + // See if this runnable needs to wait. + bool delayed = false; + for (uint32_t index = mSynchronizedOps.Length(); index > 0; index--) { + nsAutoPtr& existingOp = mSynchronizedOps[index - 1]; + if (op->MustWaitFor(*existingOp)) { + existingOp->DelayRunnable(aRunnable); + delayed = true; + break; + } + } + + // Otherwise, dispatch it immediately. + if (!delayed) { + nsresult rv = NS_DispatchToCurrentThread(aRunnable); + NS_ENSURE_SUCCESS(rv, rv); + } + + // Adding this to the synchronized ops list will block any additional + // ops from proceeding until this one is done. + mSynchronizedOps.AppendElement(op.forget()); + + return NS_OK; +} + +void +QuotaManager::AllowNextSynchronizedOp( + const OriginOrPatternString& aOriginOrPattern, + nsIAtom* aId) +{ + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); + NS_ASSERTION(!aOriginOrPattern.IsEmpty(), "Empty origin/pattern!"); + + uint32_t count = mSynchronizedOps.Length(); + for (uint32_t index = 0; index < count; index++) { + nsAutoPtr& op = mSynchronizedOps[index]; + if (op->mOriginOrPattern.IsOrigin() == aOriginOrPattern.IsOrigin() && + op->mOriginOrPattern == aOriginOrPattern) { + if (op->mId == aId) { + NS_ASSERTION(op->mStorages.IsEmpty(), "How did this happen?"); + + op->DispatchDelayedRunnables(); + + mSynchronizedOps.RemoveElementAt(index); + return; + } + + // If one or the other is for an origin clear, we should have matched + // solely on origin. + NS_ASSERTION(op->mId && aId, "Why didn't we match earlier?"); + } + } + + NS_NOTREACHED("Why didn't we find a SynchronizedOp?"); +} + +nsresult +QuotaManager::GetDirectoryForOrigin(const nsACString& aASCIIOrigin, + nsIFile** aDirectory) const +{ + nsresult rv; + nsCOMPtr directory = + do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv); + NS_ENSURE_SUCCESS(rv, rv); + + rv = directory->InitWithPath(mStorageBasePath); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoCString originSanitized(aASCIIOrigin); + SanitizeOriginString(originSanitized); + + rv = directory->Append(NS_ConvertASCIItoUTF16(originSanitized)); + NS_ENSURE_SUCCESS(rv, rv); + + directory.forget(aDirectory); + return NS_OK; +} + +nsresult +QuotaManager::EnsureOriginIsInitialized(const nsACString& aOrigin, + StoragePrivilege aPrivilege, + nsIFile** aDirectory) +{ +#ifdef DEBUG + { + bool correctThread; + NS_ASSERTION(NS_SUCCEEDED(mIOThread->IsOnCurrentThread(&correctThread)) && + correctThread, + "Running on the wrong thread!"); + } +#endif + + nsCOMPtr directory; + nsresult rv = GetDirectoryForOrigin(aOrigin, getter_AddRefs(directory)); + NS_ENSURE_SUCCESS(rv, rv); + + bool exists; + rv = directory->Exists(&exists); + NS_ENSURE_SUCCESS(rv, rv); + + if (exists) { + bool isDirectory; + rv = directory->IsDirectory(&isDirectory); + NS_ENSURE_SUCCESS(rv, rv); + NS_ENSURE_TRUE(isDirectory, NS_ERROR_UNEXPECTED); + } + else { + rv = directory->Create(nsIFile::DIRECTORY_TYPE, 0755); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr metadataFile; + rv = directory->Clone(getter_AddRefs(metadataFile)); + NS_ENSURE_SUCCESS(rv, rv); + + rv = metadataFile->Append(NS_LITERAL_STRING(METADATA_FILE_NAME)); + NS_ENSURE_SUCCESS(rv, rv); + + rv = metadataFile->Create(nsIFile::NORMAL_FILE_TYPE, 0644); + NS_ENSURE_SUCCESS(rv, rv); + } + + if (mInitializedOrigins.Contains(aOrigin)) { + NS_ADDREF(*aDirectory = directory); + return NS_OK; + } + + rv = MaybeUpgradeOriginDirectory(directory); + NS_ENSURE_SUCCESS(rv, rv); + + // We need to initialize directories of all clients if they exists and also + // get the total usage to initialize the quota. + nsAutoPtr runnable; + if (aPrivilege != Chrome) { + runnable = new UsageRunnable(); + } + + nsCOMPtr entries; + rv = directory->GetDirectoryEntries(getter_AddRefs(entries)); + NS_ENSURE_SUCCESS(rv, rv); + + bool hasMore; + while (NS_SUCCEEDED((rv = entries->HasMoreElements(&hasMore))) && hasMore) { + nsCOMPtr entry; + rv = entries->GetNext(getter_AddRefs(entry)); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr file = do_QueryInterface(entry); + NS_ENSURE_TRUE(file, NS_NOINTERFACE); + + nsString leafName; + rv = file->GetLeafName(leafName); + NS_ENSURE_SUCCESS(rv, rv); + + if (leafName.EqualsLiteral(METADATA_FILE_NAME)) { + continue; + } + + bool isDirectory; + rv = file->IsDirectory(&isDirectory); + NS_ENSURE_SUCCESS(rv, rv); + + if (!isDirectory) { + NS_WARNING("Unknown file found!"); + return NS_ERROR_UNEXPECTED; + } + + Client::Type clientType; + rv = Client::TypeFromText(leafName, clientType); + if (NS_FAILED(rv)) { + NS_WARNING("Unknown directory found!"); + return NS_ERROR_UNEXPECTED; + } + + rv = mClients[clientType]->InitOrigin(aOrigin, runnable); + NS_ENSURE_SUCCESS(rv, rv); + } + + if (aPrivilege != Chrome) { + QuotaManager* quotaManager = QuotaManager::Get(); + NS_ASSERTION(quotaManager, "Shouldn't be null!"); + + quotaManager->InitQuotaForOrigin(aOrigin, GetStorageQuotaMB(), + runnable->TotalUsage()); + } + + mInitializedOrigins.AppendElement(aOrigin); + + NS_ADDREF(*aDirectory = directory); + return NS_OK; +} + +void +QuotaManager::UninitializeOriginsByPattern(const nsACString& aPattern) +{ +#ifdef DEBUG + { + bool correctThread; + NS_ASSERTION(NS_SUCCEEDED(mIOThread->IsOnCurrentThread(&correctThread)) && + correctThread, + "Running on the wrong thread!"); + } +#endif + + for (int32_t i = mInitializedOrigins.Length() - 1; i >= 0; i--) { + if (PatternMatchesOrigin(aPattern, mInitializedOrigins[i])) { + mInitializedOrigins.RemoveElementAt(i); + } + } +} + +already_AddRefed +QuotaManager::GetClient(Client::Type aClientType) +{ + nsRefPtr client = mClients.SafeElementAt(aClientType); + return client.forget(); +} + +// static +uint32_t +QuotaManager::GetStorageQuotaMB() +{ + return uint32_t(std::max(gStorageQuotaMB, 0)); +} + +// static +already_AddRefed +QuotaManager::GetStorageId(const nsACString& aOrigin, + const nsAString& aName) +{ + nsCString str(aOrigin); + str.Append("*"); + str.Append(NS_ConvertUTF16toUTF8(aName)); + + nsCOMPtr atom = do_GetAtom(str); + NS_ENSURE_TRUE(atom, nullptr); + + return atom.forget(); +} + +// static +nsresult +QuotaManager::GetASCIIOriginFromURI(nsIURI* aURI, + uint32_t aAppId, + bool aInMozBrowser, + nsACString& aASCIIOrigin) +{ + NS_ASSERTION(aURI, "Null uri!"); + + nsCString origin; + mozilla::GetExtendedOrigin(aURI, aAppId, aInMozBrowser, origin); + + if (origin.IsEmpty()) { + NS_WARNING("GetExtendedOrigin returned empty string!"); + return NS_ERROR_FAILURE; + } + + aASCIIOrigin.Assign(origin); + return NS_OK; +} + +// static +nsresult +QuotaManager::GetASCIIOriginFromPrincipal(nsIPrincipal* aPrincipal, + nsACString& aASCIIOrigin) +{ + NS_ASSERTION(aPrincipal, "Don't hand me a null principal!"); + + static const char kChromeOrigin[] = "chrome"; + + nsCString origin; + if (nsContentUtils::IsSystemPrincipal(aPrincipal)) { + origin.AssignLiteral(kChromeOrigin); + } + else { + bool isNullPrincipal; + nsresult rv = aPrincipal->GetIsNullPrincipal(&isNullPrincipal); + NS_ENSURE_SUCCESS(rv, rv); + + if (isNullPrincipal) { + NS_WARNING("IndexedDB not supported from this principal!"); + return NS_ERROR_FAILURE; + } + + rv = aPrincipal->GetExtendedOrigin(origin); + NS_ENSURE_SUCCESS(rv, rv); + + if (origin.EqualsLiteral(kChromeOrigin)) { + NS_WARNING("Non-chrome principal can't use chrome origin!"); + return NS_ERROR_FAILURE; + } + } + + aASCIIOrigin.Assign(origin); + return NS_OK; +} + +// static +nsresult +QuotaManager::GetASCIIOriginFromWindow(nsPIDOMWindow* aWindow, + nsACString& aASCIIOrigin) +{ + NS_ASSERTION(NS_IsMainThread(), + "We're about to touch a window off the main thread!"); + + if (!aWindow) { + aASCIIOrigin.AssignLiteral("chrome"); + NS_ASSERTION(nsContentUtils::IsCallerChrome(), + "Null window but not chrome!"); + return NS_OK; + } + + nsCOMPtr sop = do_QueryInterface(aWindow); + NS_ENSURE_TRUE(sop, NS_ERROR_FAILURE); + + nsCOMPtr principal = sop->GetPrincipal(); + NS_ENSURE_TRUE(principal, NS_ERROR_FAILURE); + + nsresult rv = GetASCIIOriginFromPrincipal(principal, aASCIIOrigin); + NS_ENSURE_SUCCESS(rv, rv); + + return NS_OK; +} + +NS_IMPL_ISUPPORTS2(QuotaManager, nsIQuotaManager, nsIObserver) + +NS_IMETHODIMP +QuotaManager::GetUsageForURI(nsIURI* aURI, + nsIUsageCallback* aCallback, + uint32_t aAppId, + bool aInMozBrowserOnly, + uint8_t aOptionalArgCount, + nsIQuotaRequest** _retval) +{ + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); + + NS_ENSURE_ARG_POINTER(aURI); + NS_ENSURE_ARG_POINTER(aCallback); + + // This only works from the main process. + NS_ENSURE_TRUE(IsMainProcess(), NS_ERROR_NOT_AVAILABLE); + + if (!aOptionalArgCount) { + aAppId = nsIScriptSecurityManager::NO_APP_ID; + } + + // Figure out which origin we're dealing with. + nsCString origin; + nsresult rv = GetASCIIOriginFromURI(aURI, aAppId, aInMozBrowserOnly, origin); + NS_ENSURE_SUCCESS(rv, rv); + + OriginOrPatternString oops = OriginOrPatternString::FromOrigin(origin); + + nsRefPtr runnable = + new AsyncUsageRunnable(aAppId, aInMozBrowserOnly, oops, aURI, aCallback); + + // Put the computation runnable in the queue. + rv = WaitForOpenAllowed(oops, nullptr, runnable); + NS_ENSURE_SUCCESS(rv, rv); + + runnable->AdvanceState(); + + runnable.forget(_retval); + return NS_OK; +} + +NS_IMETHODIMP +QuotaManager::ClearStoragesForURI(nsIURI* aURI, + uint32_t aAppId, + bool aInMozBrowserOnly, + uint8_t aOptionalArgCount) +{ + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); + + NS_ENSURE_ARG_POINTER(aURI); + + // This only works from the main process. + NS_ENSURE_TRUE(IsMainProcess(), NS_ERROR_NOT_AVAILABLE); + + if (!aOptionalArgCount) { + aAppId = nsIScriptSecurityManager::NO_APP_ID; + } + + // Figure out which origin we're dealing with. + nsCString origin; + nsresult rv = GetASCIIOriginFromURI(aURI, aAppId, aInMozBrowserOnly, origin); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoCString pattern; + GetOriginPatternString(aAppId, aInMozBrowserOnly, origin, pattern); + + // If there is a pending or running clear operation for this origin, return + // immediately. + if (IsClearOriginPending(pattern)) { + return NS_OK; + } + + OriginOrPatternString oops = OriginOrPatternString::FromPattern(pattern); + + // Queue up the origin clear runnable. + nsRefPtr runnable = new OriginClearRunnable(oops); + + rv = WaitForOpenAllowed(oops, nullptr, runnable); + NS_ENSURE_SUCCESS(rv, rv); + + runnable->AdvanceState(); + + // Give the runnable some help by invalidating any storages in the way. + StorageMatcher > matches; + matches.Find(mLiveStorages, pattern); + + for (uint32_t index = 0; index < matches.Length(); index++) { + // We need to grab references to any live storages here to prevent them + // from dying while we invalidate them. + nsCOMPtr storage = matches[index]; + storage->Invalidate(); + } + + // After everything has been invalidated the helper should be dispatched to + // the end of the event queue. + return NS_OK; +} + +NS_IMETHODIMP +QuotaManager::Observe(nsISupports* aSubject, + const char* aTopic, + const PRUnichar* aData) +{ + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); + + if (!strcmp(aTopic, PROFILE_BEFORE_CHANGE_OBSERVER_ID)) { + // Setting this flag prevents the service from being recreated and prevents + // further storagess from being created. + if (PR_ATOMIC_SET(&gShutdown, 1)) { + NS_ERROR("Shutdown more than once?!"); + } + + if (IsMainProcess()) { + FileService* service = FileService::Get(); + if (service) { + // This should only wait for storages registered in this manager + // to complete. Other storages may still have running locked files. + // If the necko service (thread pool) gets the shutdown notification + // first then the sync loop won't be processed at all, otherwise it will + // lock the main thread until all storages registered in this manager + // are finished. + + nsTArray indexes; + for (uint32_t index = 0; index < Client::TYPE_MAX; index++) { + if (mClients[index]->IsFileServiceUtilized()) { + indexes.AppendElement(index); + } + } + + StorageMatcher > > liveStorages; + liveStorages.Find(mLiveStorages, &indexes); + + if (!liveStorages.IsEmpty()) { + nsRefPtr runnable = + new WaitForLockedFilesToFinishRunnable(); + + service->WaitForStoragesToComplete(liveStorages, runnable); + + nsIThread* thread = NS_GetCurrentThread(); + while (runnable->IsBusy()) { + if (!NS_ProcessNextEvent(thread)) { + NS_ERROR("Failed to process next event!"); + break; + } + } + } + } + + // Make sure to join with our IO thread. + if (NS_FAILED(mIOThread->Shutdown())) { + NS_WARNING("Failed to shutdown IO thread!"); + } + + // Kick off the shutdown timer. + if (NS_FAILED(mShutdownTimer->Init(this, DEFAULT_SHUTDOWN_TIMER_MS, + nsITimer::TYPE_ONE_SHOT))) { + NS_WARNING("Failed to initialize shutdown timer!"); + } + + // Each client will spin the event loop while we wait on all the threads + // to close. Our timer may fire during that loop. + for (uint32_t index = 0; index < Client::TYPE_MAX; index++) { + mClients[index]->ShutdownTransactionService(); + } + + // Cancel the timer regardless of whether it actually fired. + if (NS_FAILED(mShutdownTimer->Cancel())) { + NS_WARNING("Failed to cancel shutdown timer!"); + } + } + + for (uint32_t index = 0; index < Client::TYPE_MAX; index++) { + mClients[index]->OnShutdownCompleted(); + } + + return NS_OK; + } + + if (!strcmp(aTopic, NS_TIMER_CALLBACK_TOPIC)) { + NS_ASSERTION(IsMainProcess(), "Should only happen in the main process!"); + + NS_WARNING("Some storage operations are taking longer than expected " + "during shutdown and will be aborted!"); + + // Grab all live storages, for all origins. + StorageMatcher > liveStorages; + liveStorages.Find(mLiveStorages); + + // Invalidate them all. + if (!liveStorages.IsEmpty()) { + uint32_t count = liveStorages.Length(); + for (uint32_t index = 0; index < count; index++) { + liveStorages[index]->Invalidate(); + } + } + + return NS_OK; + } + + if (!strcmp(aTopic, TOPIC_WEB_APP_CLEAR_DATA)) { + nsCOMPtr params = + do_QueryInterface(aSubject); + NS_ENSURE_TRUE(params, NS_ERROR_UNEXPECTED); + + uint32_t appId; + nsresult rv = params->GetAppId(&appId); + NS_ENSURE_SUCCESS(rv, rv); + + bool browserOnly; + rv = params->GetBrowserOnly(&browserOnly); + NS_ENSURE_SUCCESS(rv, rv); + + rv = ClearStoragesForApp(appId, browserOnly); + NS_ENSURE_SUCCESS(rv, rv); + + return NS_OK; + } + + NS_NOTREACHED("Unknown topic!"); + return NS_ERROR_UNEXPECTED; +} + void QuotaManager::SetCurrentWindowInternal(nsPIDOMWindow* aWindow) { @@ -424,3 +1363,815 @@ QuotaManager::LockedQuotaIsLifted() return result; } + +nsresult +QuotaManager::AcquireExclusiveAccess(const nsACString& aPattern, + nsIOfflineStorage* aStorage, + AcquireListener* aListener, + WaitingOnStoragesCallback aCallback, + void* aClosure) +{ + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); + NS_ASSERTION(aListener, "Need a listener!"); + + // Find the right SynchronizedOp. + SynchronizedOp* op = + FindSynchronizedOp(aPattern, aStorage ? aStorage->Id() : nullptr); + + NS_ASSERTION(op, "We didn't find a SynchronizedOp?"); + NS_ASSERTION(!op->mListener, "SynchronizedOp already has a listener?!?"); + + nsTArray > liveStorages; + + if (aStorage) { + // We need to wait for the storages to go away. + // Hold on to all storage objects that represent the same storage file + // (except the one that is requesting this version change). + + Client::Type clientType = aStorage->GetClient()->GetType(); + + StorageMatcher > matches; + matches.Find(mLiveStorages, aPattern, clientType); + + if (!matches.IsEmpty()) { + // Grab all storages that are not yet closed but whose storage id match + // the one we're looking for. + for (uint32_t index = 0; index < matches.Length(); index++) { + nsIOfflineStorage*& storage = matches[index]; + if (!storage->IsClosed() && + storage != aStorage && + storage->Id() == aStorage->Id()) { + liveStorages.AppendElement(storage); + } + } + } + + if (!liveStorages.IsEmpty()) { + NS_ASSERTION(op->mStorages[clientType].IsEmpty(), + "How do we already have storages here?"); + op->mStorages[clientType].AppendElements(liveStorages); + } + } + else { + StorageMatcher > matches; + matches.Find(mLiveStorages, aPattern); + + if (!matches.IsEmpty()) { + // We want *all* storages, even those that are closed, when we're going to + // clear the origin. + matches.AppendElementsTo(liveStorages); + + NS_ASSERTION(op->mStorages.IsEmpty(), + "How do we already have storages here?"); + matches.SwapElements(op->mStorages); + } + } + + op->mListener = aListener; + + if (!liveStorages.IsEmpty()) { + // Give our callback the storages so it can decide what to do with them. + aCallback(liveStorages, aClosure); + + NS_ASSERTION(liveStorages.IsEmpty(), + "Should have done something with the array!"); + + if (aStorage) { + // Wait for those storages to close. + return NS_OK; + } + } + + // If we're trying to open a storage and nothing blocks it, or if we're + // clearing an origin, then go ahead and schedule the op. + nsresult rv = RunSynchronizedOp(aStorage, op); + NS_ENSURE_SUCCESS(rv, rv); + + return NS_OK; +} + +nsresult +QuotaManager::RunSynchronizedOp(nsIOfflineStorage* aStorage, + SynchronizedOp* aOp) +{ + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); + NS_ASSERTION(aOp, "Null pointer!"); + NS_ASSERTION(aOp->mListener, "No listener on this op!"); + NS_ASSERTION(!aStorage || + aOp->mStorages[aStorage->GetClient()->GetType()].IsEmpty(), + "This op isn't ready to run!"); + + ArrayCluster storages; + + uint32_t startIndex; + uint32_t endIndex; + + if (aStorage) { + Client::Type clientType = aStorage->GetClient()->GetType(); + + storages[clientType].AppendElement(aStorage); + + startIndex = clientType; + endIndex = clientType + 1; + } + else { + aOp->mStorages.SwapElements(storages); + + startIndex = 0; + endIndex = Client::TYPE_MAX; + } + + nsRefPtr runnable = + new WaitForTransactionsToFinishRunnable(aOp); + + // Ask the file service to call us back when it's done with this storage. + FileService* service = FileService::Get(); + + if (service) { + // Have to copy here in case a transaction service needs a list too. + nsTArray > array; + + for (uint32_t index = startIndex; index < endIndex; index++) { + if (!storages[index].IsEmpty() && + mClients[index]->IsFileServiceUtilized()) { + array.AppendElements(storages[index]); + } + } + + if (!array.IsEmpty()) { + runnable->AddRun(); + + service->WaitForStoragesToComplete(array, runnable); + } + } + + // Ask each transaction service to call us back when they're done with this + // storage. + for (uint32_t index = startIndex; index < endIndex; index++) { + nsRefPtr& client = mClients[index]; + if (!storages[index].IsEmpty() && client->IsTransactionServiceActivated()) { + runnable->AddRun(); + + client->WaitForStoragesToComplete(storages[index], runnable); + } + } + + nsresult rv = runnable->Run(); + NS_ENSURE_SUCCESS(rv, rv); + + return NS_OK; +} + +SynchronizedOp* +QuotaManager::FindSynchronizedOp(const nsACString& aPattern, + nsISupports* aId) +{ + for (uint32_t index = 0; index < mSynchronizedOps.Length(); index++) { + const nsAutoPtr& currentOp = mSynchronizedOps[index]; + if (PatternMatchesOrigin(aPattern, currentOp->mOriginOrPattern) && + (!currentOp->mId || currentOp->mId == aId)) { + return currentOp; + } + } + + return nullptr; +} + +nsresult +QuotaManager::ClearStoragesForApp(uint32_t aAppId, bool aBrowserOnly) +{ + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); + NS_ASSERTION(aAppId != nsIScriptSecurityManager::UNKNOWN_APP_ID, + "Bad appId!"); + + // This only works from the main process. + NS_ENSURE_TRUE(IsMainProcess(), NS_ERROR_NOT_AVAILABLE); + + nsAutoCString pattern; + GetOriginPatternStringMaybeIgnoreBrowser(aAppId, aBrowserOnly, pattern); + + // If there is a pending or running clear operation for this app, return + // immediately. + if (IsClearOriginPending(pattern)) { + return NS_OK; + } + + OriginOrPatternString oops = OriginOrPatternString::FromPattern(pattern); + + // Queue up the origin clear runnable. + nsRefPtr runnable = new OriginClearRunnable(oops); + + nsresult rv = WaitForOpenAllowed(oops, nullptr, runnable); + NS_ENSURE_SUCCESS(rv, rv); + + runnable->AdvanceState(); + + // Give the runnable some help by invalidating any storages in the way. + StorageMatcher > matches; + matches.Find(mLiveStorages, pattern); + + for (uint32_t index = 0; index < matches.Length(); index++) { + // We need to grab references here to prevent the storage from dying while + // we invalidate it. + nsCOMPtr storage = matches[index]; + storage->Invalidate(); + } + + return NS_OK; +} + +nsresult +QuotaManager::MaybeUpgradeOriginDirectory(nsIFile* aDirectory) +{ + NS_ASSERTION(aDirectory, "Null pointer!"); + + nsCOMPtr metadataFile; + nsresult rv = aDirectory->Clone(getter_AddRefs(metadataFile)); + NS_ENSURE_SUCCESS(rv, rv); + + rv = metadataFile->Append(NS_LITERAL_STRING(METADATA_FILE_NAME)); + NS_ENSURE_SUCCESS(rv, rv); + + bool exists; + rv = metadataFile->Exists(&exists); + NS_ENSURE_SUCCESS(rv, rv); + + if (!exists) { + // Directory structure upgrade needed. + // Move all files to IDB specific directory. + + nsString idbDirectoryName; + rv = Client::TypeToText(Client::IDB, idbDirectoryName); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr idbDirectory; + rv = aDirectory->Clone(getter_AddRefs(idbDirectory)); + NS_ENSURE_SUCCESS(rv, rv); + + rv = idbDirectory->Append(idbDirectoryName); + NS_ENSURE_SUCCESS(rv, rv); + + rv = idbDirectory->Create(nsIFile::DIRECTORY_TYPE, 0755); + if (NS_FAILED(rv)) { + NS_WARNING("IDB directory already exists!"); + } + + nsCOMPtr entries; + rv = aDirectory->GetDirectoryEntries(getter_AddRefs(entries)); + NS_ENSURE_SUCCESS(rv, rv); + + bool hasMore; + while (NS_SUCCEEDED((rv = entries->HasMoreElements(&hasMore))) && hasMore) { + nsCOMPtr entry; + rv = entries->GetNext(getter_AddRefs(entry)); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr file = do_QueryInterface(entry); + NS_ENSURE_TRUE(file, NS_NOINTERFACE); + + nsString leafName; + rv = file->GetLeafName(leafName); + NS_ENSURE_SUCCESS(rv, rv); + + if (!leafName.Equals(idbDirectoryName)) { + rv = file->MoveTo(idbDirectory, EmptyString()); + NS_ENSURE_SUCCESS(rv, rv); + } + } + + rv = metadataFile->Create(nsIFile::NORMAL_FILE_TYPE, 0644); + NS_ENSURE_SUCCESS(rv, rv); + } + + return NS_OK; +} + +void +QuotaManager::GetOriginPatternString(uint32_t aAppId, + MozBrowserPatternFlag aBrowserFlag, + const nsACString& aOrigin, + nsAutoCString& _retval) +{ + NS_ASSERTION(aAppId != nsIScriptSecurityManager::UNKNOWN_APP_ID, + "Bad appId!"); + NS_ASSERTION(aOrigin.IsEmpty() || aBrowserFlag != IgnoreMozBrowser, + "Bad args!"); + + if (aOrigin.IsEmpty()) { + _retval.Truncate(); + + _retval.AppendInt(aAppId); + _retval.Append('+'); + + if (aBrowserFlag != IgnoreMozBrowser) { + if (aBrowserFlag == MozBrowser) { + _retval.Append('t'); + } + else { + _retval.Append('f'); + } + _retval.Append('+'); + } + + return; + } + +#ifdef DEBUG + if (aAppId != nsIScriptSecurityManager::NO_APP_ID || + aBrowserFlag == MozBrowser) { + nsAutoCString pattern; + GetOriginPatternString(aAppId, aBrowserFlag, EmptyCString(), pattern); + NS_ASSERTION(PatternMatchesOrigin(pattern, aOrigin), + "Origin doesn't match parameters!"); + } +#endif + + _retval = aOrigin; +} + +SynchronizedOp::SynchronizedOp(const OriginOrPatternString& aOriginOrPattern, + nsISupports* aId) +: mOriginOrPattern(aOriginOrPattern), mId(aId) +{ + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); + MOZ_COUNT_CTOR(SynchronizedOp); +} + +SynchronizedOp::~SynchronizedOp() +{ + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); + MOZ_COUNT_DTOR(SynchronizedOp); +} + +bool +SynchronizedOp::MustWaitFor(const SynchronizedOp& aExistingOp) +{ + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); + + bool match; + + if (aExistingOp.mOriginOrPattern.IsOrigin()) { + if (mOriginOrPattern.IsOrigin()) { + match = aExistingOp.mOriginOrPattern.Equals(mOriginOrPattern); + } + else { + match = PatternMatchesOrigin(mOriginOrPattern, aExistingOp.mOriginOrPattern); + } + } + else if (mOriginOrPattern.IsOrigin()) { + match = PatternMatchesOrigin(aExistingOp.mOriginOrPattern, mOriginOrPattern); + } + else { + match = PatternMatchesOrigin(mOriginOrPattern, aExistingOp.mOriginOrPattern) || + PatternMatchesOrigin(aExistingOp.mOriginOrPattern, mOriginOrPattern); + } + + // If the origins don't match, the second can proceed. + if (!match) { + return false; + } + + // If the origins and the ids match, the second must wait. + if (aExistingOp.mId == mId) { + return true; + } + + // Waiting is required if either one corresponds to an origin clearing + // (a null Id). + if (!aExistingOp.mId || !mId) { + return true; + } + + // Otherwise, things for the same origin but different storages can proceed + // independently. + return false; +} + +void +SynchronizedOp::DelayRunnable(nsIRunnable* aRunnable) +{ + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); + NS_ASSERTION(mDelayedRunnables.IsEmpty() || !mId, + "Only ClearOrigin operations can delay multiple runnables!"); + + mDelayedRunnables.AppendElement(aRunnable); +} + +void +SynchronizedOp::DispatchDelayedRunnables() +{ + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); + NS_ASSERTION(!mListener, "Any listener should be gone by now!"); + + uint32_t count = mDelayedRunnables.Length(); + for (uint32_t index = 0; index < count; index++) { + NS_DispatchToCurrentThread(mDelayedRunnables[index]); + } + + mDelayedRunnables.Clear(); +} + +nsresult +OriginClearRunnable::OnExclusiveAccessAcquired() +{ + QuotaManager* quotaManager = QuotaManager::Get(); + NS_ASSERTION(quotaManager, "This should never fail!"); + + nsresult rv = quotaManager->IOThread()->Dispatch(this, NS_DISPATCH_NORMAL); + NS_ENSURE_SUCCESS(rv, rv); + + return NS_OK; +} + +// static +void +OriginClearRunnable::InvalidateOpenedStorages( + nsTArray >& aStorages, + void* aClosure) +{ + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); + + nsTArray > storages; + storages.SwapElements(aStorages); + + for (uint32_t index = 0; index < storages.Length(); index++) { + storages[index]->Invalidate(); + } +} + +void +OriginClearRunnable::DeleteFiles(QuotaManager* aQuotaManager) +{ + NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!"); + NS_ASSERTION(aQuotaManager, "Don't pass me null!"); + + nsresult rv; + + nsCOMPtr directory = + do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv); + NS_ENSURE_SUCCESS_VOID(rv); + + rv = directory->InitWithPath(aQuotaManager->GetBaseDirectory()); + NS_ENSURE_SUCCESS_VOID(rv); + + nsCOMPtr entries; + if (NS_FAILED(directory->GetDirectoryEntries(getter_AddRefs(entries))) || + !entries) { + return; + } + + nsCString originSanitized(mOriginOrPattern); + SanitizeOriginString(originSanitized); + + bool hasMore; + while (NS_SUCCEEDED((rv = entries->HasMoreElements(&hasMore))) && hasMore) { + nsCOMPtr entry; + rv = entries->GetNext(getter_AddRefs(entry)); + NS_ENSURE_SUCCESS_VOID(rv); + + nsCOMPtr file = do_QueryInterface(entry); + NS_ASSERTION(file, "Don't know what this is!"); + + bool isDirectory; + rv = file->IsDirectory(&isDirectory); + NS_ENSURE_SUCCESS_VOID(rv); + + if (!isDirectory) { + NS_WARNING("Something in the IndexedDB directory that doesn't belong!"); + continue; + } + + nsString leafName; + rv = file->GetLeafName(leafName); + NS_ENSURE_SUCCESS_VOID(rv); + + // Skip storages for other apps. + if (!PatternMatchesOrigin(originSanitized, + NS_ConvertUTF16toUTF8(leafName))) { + continue; + } + + if (NS_FAILED(file->Remove(true))) { + // This should never fail if we've closed all storage connections + // correctly... + NS_ERROR("Failed to remove directory!"); + } + } + + aQuotaManager->RemoveQuotaForPattern(mOriginOrPattern); + + aQuotaManager->UninitializeOriginsByPattern(mOriginOrPattern); +} + +NS_IMPL_THREADSAFE_ISUPPORTS1(OriginClearRunnable, nsIRunnable) + +NS_IMETHODIMP +OriginClearRunnable::Run() +{ + QuotaManager* quotaManager = QuotaManager::Get(); + NS_ASSERTION(quotaManager, "This should never fail!"); + + switch (mCallbackState) { + case Pending: { + NS_NOTREACHED("Should never get here without being dispatched!"); + return NS_ERROR_UNEXPECTED; + } + + case OpenAllowed: { + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); + + AdvanceState(); + + // Now we have to wait until the thread pool is done with all of the + // storages we care about. + nsresult rv = + quotaManager->AcquireExclusiveAccess(mOriginOrPattern, this, + InvalidateOpenedStorages, nullptr); + NS_ENSURE_SUCCESS(rv, rv); + + return NS_OK; + } + + case IO: { + NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!"); + + AdvanceState(); + + DeleteFiles(quotaManager); + + // Now dispatch back to the main thread. + if (NS_FAILED(NS_DispatchToMainThread(this, NS_DISPATCH_NORMAL))) { + NS_WARNING("Failed to dispatch to main thread!"); + return NS_ERROR_FAILURE; + } + + return NS_OK; + } + + case Complete: { + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); + + for (uint32_t index = 0; index < Client::TYPE_MAX; index++) { + quotaManager->mClients[index]->OnOriginClearCompleted(mOriginOrPattern); + } + + // Tell the QuotaManager that we're done. + quotaManager->AllowNextSynchronizedOp(mOriginOrPattern, nullptr); + + return NS_OK; + } + + default: + NS_ERROR("Unknown state value!"); + return NS_ERROR_UNEXPECTED; + } + + NS_NOTREACHED("Should never get here!"); + return NS_ERROR_UNEXPECTED; +} + +AsyncUsageRunnable::AsyncUsageRunnable(uint32_t aAppId, + bool aInMozBrowserOnly, + const OriginOrPatternString& aOrigin, + nsIURI* aURI, + nsIUsageCallback* aCallback) +: mURI(aURI), + mCallback(aCallback), + mAppId(aAppId), + mOrigin(aOrigin), + mCallbackState(Pending), + mInMozBrowserOnly(aInMozBrowserOnly) +{ + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); + NS_ASSERTION(aURI, "Null pointer!"); + NS_ASSERTION(aOrigin.IsOrigin(), "Expect origin only here!"); + NS_ASSERTION(!aOrigin.IsEmpty(), "Empty origin!"); + NS_ASSERTION(aCallback, "Null pointer!"); +} + +nsresult +AsyncUsageRunnable::TakeShortcut() +{ + NS_ASSERTION(mCallbackState == Pending, "Huh?"); + + nsresult rv = NS_DispatchToCurrentThread(this); + NS_ENSURE_SUCCESS(rv, rv); + + mCallbackState = Shortcut; + return NS_OK; +} + +nsresult +AsyncUsageRunnable::RunInternal() +{ + QuotaManager* quotaManager = QuotaManager::Get(); + NS_ASSERTION(quotaManager, "This should never fail!"); + + nsresult rv; + + switch (mCallbackState) { + case Pending: { + NS_NOTREACHED("Should never get here without being dispatched!"); + return NS_ERROR_UNEXPECTED; + } + + case OpenAllowed: { + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); + + AdvanceState(); + + rv = quotaManager->IOThread()->Dispatch(this, NS_DISPATCH_NORMAL); + if (NS_FAILED(rv)) { + NS_WARNING("Failed to dispatch to the IO thread!"); + } + + return NS_OK; + } + + case IO: { + NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!"); + + AdvanceState(); + + // Get the directory that contains all the storage files we care about. + nsCOMPtr directory; + rv = quotaManager->GetDirectoryForOrigin(mOrigin, + getter_AddRefs(directory)); + NS_ENSURE_SUCCESS(rv, rv); + + bool exists; + rv = directory->Exists(&exists); + NS_ENSURE_SUCCESS(rv, rv); + + // If the directory exists then enumerate all the files inside, adding up + // the sizes to get the final usage statistic. + if (exists && !mCanceled) { + bool initialized = quotaManager->mInitializedOrigins.Contains(mOrigin); + + if (!initialized) { + rv = quotaManager->MaybeUpgradeOriginDirectory(directory); + NS_ENSURE_SUCCESS(rv, rv); + } + + nsCOMPtr entries; + rv = directory->GetDirectoryEntries(getter_AddRefs(entries)); + NS_ENSURE_SUCCESS(rv, rv); + + bool hasMore; + while (NS_SUCCEEDED((rv = entries->HasMoreElements(&hasMore))) && + hasMore && !mCanceled) { + nsCOMPtr entry; + rv = entries->GetNext(getter_AddRefs(entry)); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr file = do_QueryInterface(entry); + NS_ENSURE_TRUE(file, NS_NOINTERFACE); + + nsString leafName; + rv = file->GetLeafName(leafName); + NS_ENSURE_SUCCESS(rv, rv); + + if (leafName.EqualsLiteral(METADATA_FILE_NAME)) { + continue; + } + + if (!initialized) { + bool isDirectory; + rv = file->IsDirectory(&isDirectory); + NS_ENSURE_SUCCESS(rv, rv); + + if (!isDirectory) { + NS_WARNING("Unknown file found!"); + return NS_ERROR_UNEXPECTED; + } + } + + Client::Type clientType; + rv = Client::TypeFromText(leafName, clientType); + if (NS_FAILED(rv)) { + NS_WARNING("Unknown directory found!"); + if (!initialized) { + return NS_ERROR_UNEXPECTED; + } + continue; + } + + nsRefPtr& client = quotaManager->mClients[clientType]; + + if (!initialized) { + rv = client->InitOrigin(mOrigin, this); + } + else { + rv = client->GetUsageForOrigin(mOrigin, this); + } + NS_ENSURE_SUCCESS(rv, rv); + } + } + + // Run dispatches us back to the main thread. + return NS_OK; + } + + case Complete: // Fall through + case Shortcut: { + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); + + // Call the callback unless we were canceled. + if (!mCanceled) { + mCallback->OnUsageResult(mURI, TotalUsage(), FileUsage(), mAppId, + mInMozBrowserOnly); + } + + // Clean up. + mURI = nullptr; + mCallback = nullptr; + + // And tell the QuotaManager that we're done. + if (mCallbackState == Complete) { + quotaManager->AllowNextSynchronizedOp(mOrigin, nullptr); + } + + return NS_OK; + } + + default: + NS_ERROR("Unknown state value!"); + return NS_ERROR_UNEXPECTED; + } + + NS_NOTREACHED("Should never get here!"); + return NS_ERROR_UNEXPECTED; +} + +NS_IMPL_THREADSAFE_ISUPPORTS2(AsyncUsageRunnable, + nsIRunnable, + nsIQuotaRequest) + +NS_IMETHODIMP +AsyncUsageRunnable::Run() +{ + nsresult rv = RunInternal(); + + if (!NS_IsMainThread()) { + if (NS_FAILED(rv)) { + ResetUsage(); + } + + if (NS_FAILED(NS_DispatchToMainThread(this, NS_DISPATCH_NORMAL))) { + NS_WARNING("Failed to dispatch to main thread!"); + } + } + + return NS_OK; +} + +NS_IMETHODIMP +AsyncUsageRunnable::Cancel() +{ + if (PR_ATOMIC_SET(&mCanceled, 1)) { + NS_WARNING("Canceled more than once?!"); + return NS_ERROR_UNEXPECTED; + } + + return NS_OK; +} + +NS_IMPL_THREADSAFE_ISUPPORTS1(WaitForTransactionsToFinishRunnable, nsIRunnable) + +NS_IMETHODIMP +WaitForTransactionsToFinishRunnable::Run() +{ + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); + NS_ASSERTION(mOp, "Null op!"); + NS_ASSERTION(mOp->mListener, "Nothing to run!"); + NS_ASSERTION(mCountdown, "Wrong countdown!"); + + if (--mCountdown) { + return NS_OK; + } + + // Don't hold the listener alive longer than necessary. + nsRefPtr listener; + listener.swap(mOp->mListener); + + mOp = nullptr; + + nsresult rv = listener->OnExclusiveAccessAcquired(); + NS_ENSURE_SUCCESS(rv, rv); + + // The listener is responsible for calling + // QuotaManager::AllowNextSynchronizedOp. + return NS_OK; +} + +NS_IMPL_THREADSAFE_ISUPPORTS1(WaitForLockedFilesToFinishRunnable, nsIRunnable) + +NS_IMETHODIMP +WaitForLockedFilesToFinishRunnable::Run() +{ + NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); + + mBusy = false; + + return NS_OK; +} diff --git a/dom/quota/QuotaManager.h b/dom/quota/QuotaManager.h index 3a35f868aeb9..e22d2c1600cb 100644 --- a/dom/quota/QuotaManager.h +++ b/dom/quota/QuotaManager.h @@ -9,95 +9,62 @@ #include "QuotaCommon.h" +#include "nsIObserver.h" +#include "nsIQuotaManager.h" + #include "mozilla/Mutex.h" -#include "nsDataHashtable.h" +#include "nsClassHashtable.h" #include "nsRefPtrHashtable.h" #include "nsThreadUtils.h" +#include "ArrayCluster.h" +#include "Client.h" +#include "StoragePrivilege.h" + +#define QUOTA_MANAGER_CONTRACTID "@mozilla.org/dom/quota/manager;1" + +class nsIAtom; +class nsIOfflineStorage; +class nsIPrincipal; +class nsIThread; +class nsITimer; +class nsIURI; class nsPIDOMWindow; BEGIN_QUOTA_NAMESPACE +class AcquireListener; +class AsyncUsageRunnable; class CheckQuotaHelper; +class OriginClearRunnable; class OriginInfo; -class QuotaManager; +class OriginOrPatternString; +class QuotaObject; +struct SynchronizedOp; -class QuotaObject +class QuotaManager MOZ_FINAL : public nsIQuotaManager, + public nsIObserver { - friend class OriginInfo; - friend class QuotaManager; - -public: - void - AddRef(); - - void - Release(); - - void - UpdateSize(int64_t aSize); - - bool - MaybeAllocateMoreSpace(int64_t aOffset, int32_t aCount); - -private: - QuotaObject(OriginInfo* aOriginInfo, const nsAString& aPath, int64_t aSize) - : mOriginInfo(aOriginInfo), mPath(aPath), mSize(aSize) - { } - - virtual ~QuotaObject() - { } - - nsAutoRefCnt mRefCnt; - - OriginInfo* mOriginInfo; - nsString mPath; - int64_t mSize; -}; - -class OriginInfo -{ - friend class QuotaManager; - friend class QuotaObject; - -public: - OriginInfo(const nsACString& aOrigin, int64_t aLimit, int64_t aUsage) - : mOrigin(aOrigin), mLimit(aLimit), mUsage(aUsage) - { - mQuotaObjects.Init(); - } - - NS_INLINE_DECL_THREADSAFE_REFCOUNTING(OriginInfo) - -private: - void -#ifdef DEBUG - LockedClearOriginInfos(); -#else - LockedClearOriginInfos() - { - mQuotaObjects.EnumerateRead(ClearOriginInfoCallback, nullptr); - } -#endif - - static PLDHashOperator - ClearOriginInfoCallback(const nsAString& aKey, - QuotaObject* aValue, void* aUserArg); - - nsDataHashtable mQuotaObjects; - - nsCString mOrigin; - int64_t mLimit; - int64_t mUsage; -}; - -class QuotaManager -{ - friend class nsAutoPtr; + friend class AsyncUsageRunnable; + friend class OriginClearRunnable; friend class OriginInfo; friend class QuotaObject; + enum MozBrowserPatternFlag + { + MozBrowser = 0, + NotMozBrowser, + IgnoreMozBrowser + }; + + typedef void + (*WaitingOnStoragesCallback)(nsTArray >&, void*); + public: + NS_DECL_ISUPPORTS + NS_DECL_NSIQUOTAMANAGER + NS_DECL_NSIOBSERVER + // Returns a non-owning reference. static QuotaManager* GetOrCreate(); @@ -106,6 +73,13 @@ public: static QuotaManager* Get(); + // Returns an owning reference! No one should call this but the factory. + static QuotaManager* + FactoryCreate(); + + // Returns true if we've begun the shutdown process. + static bool IsShuttingDown(); + void InitQuotaForOrigin(const nsACString& aOrigin, int64_t aLimit, @@ -148,12 +122,143 @@ public: quotaManager->CancelPromptsForWindowInternal(aWindow); } + // Called when a storage is created. + bool + RegisterStorage(nsIOfflineStorage* aStorage); + + // Called when a storage is being unlinked or destroyed. + void + UnregisterStorage(nsIOfflineStorage* aStorage); + + // Called when a storage has been closed. + void + OnStorageClosed(nsIOfflineStorage* aStorage); + + // Called when a window is being purged from the bfcache or the user leaves + // a page which isn't going into the bfcache. Forces any live storage + // objects to close themselves and aborts any running transactions. + void + AbortCloseStoragesForWindow(nsPIDOMWindow* aWindow); + + // Used to check if there are running transactions in a given window. + bool + HasOpenTransactions(nsPIDOMWindow* aWindow); + + // Waits for storages to be cleared and for version change transactions to + // complete before dispatching the given runnable. + nsresult + WaitForOpenAllowed(const OriginOrPatternString& aOriginOrPattern, + nsIAtom* aId, + nsIRunnable* aRunnable); + + // Acquire exclusive access to the storage given (waits for all others to + // close). If storages need to close first, the callback will be invoked + // with an array of said storages. + nsresult + AcquireExclusiveAccess(nsIOfflineStorage* aStorage, + const nsACString& aOrigin, + AcquireListener* aListener, + WaitingOnStoragesCallback aCallback, + void* aClosure) + { + NS_ASSERTION(aStorage, "Need a storage here!"); + return AcquireExclusiveAccess(aOrigin, aStorage, aListener, aCallback, + aClosure); + } + + nsresult + AcquireExclusiveAccess(const nsACString& aOrigin, + AcquireListener* aListener, + WaitingOnStoragesCallback aCallback, + void* aClosure) + { + return AcquireExclusiveAccess(aOrigin, nullptr, aListener, aCallback, + aClosure); + } + + void + AllowNextSynchronizedOp(const OriginOrPatternString& aOriginOrPattern, + nsIAtom* aId); + + bool + IsClearOriginPending(const nsACString& aPattern) + { + return !!FindSynchronizedOp(aPattern, nullptr); + } + + nsresult + GetDirectoryForOrigin(const nsACString& aASCIIOrigin, + nsIFile** aDirectory) const; + + nsresult + EnsureOriginIsInitialized(const nsACString& aOrigin, + StoragePrivilege aPrivilege, + nsIFile** aDirectory); + + void + UninitializeOriginsByPattern(const nsACString& aPattern); + + nsIThread* + IOThread() + { + NS_ASSERTION(mIOThread, "This should never be null!"); + return mIOThread; + } + + already_AddRefed + GetClient(Client::Type aClientType); + + const nsString& + GetBaseDirectory() const + { + return mStorageBasePath; + } + + static uint32_t + GetStorageQuotaMB(); + + static already_AddRefed + GetStorageId(const nsACString& aOrigin, + const nsAString& aName); + + static nsresult + GetASCIIOriginFromURI(nsIURI* aURI, + uint32_t aAppId, + bool aInMozBrowser, + nsACString& aASCIIOrigin); + + static nsresult + GetASCIIOriginFromPrincipal(nsIPrincipal* aPrincipal, + nsACString& aASCIIOrigin); + + static nsresult + GetASCIIOriginFromWindow(nsPIDOMWindow* aWindow, + nsACString& aASCIIOrigin); + + static void + GetOriginPatternString(uint32_t aAppId, bool aBrowserOnly, + const nsACString& aOrigin, nsAutoCString& _retval) + { + return GetOriginPatternString(aAppId, + aBrowserOnly ? MozBrowser : NotMozBrowser, + aOrigin, _retval); + } + + static void + GetOriginPatternStringMaybeIgnoreBrowser(uint32_t aAppId, bool aBrowserOnly, + nsAutoCString& _retval) + { + return GetOriginPatternString(aAppId, + aBrowserOnly ? MozBrowser : IgnoreMozBrowser, + EmptyCString(), _retval); + } + private: QuotaManager(); virtual ~QuotaManager(); - bool + nsresult Init(); void @@ -167,6 +272,33 @@ private: bool LockedQuotaIsLifted(); + nsresult + AcquireExclusiveAccess(const nsACString& aOrigin, + nsIOfflineStorage* aStorage, + AcquireListener* aListener, + WaitingOnStoragesCallback aCallback, + void* aClosure); + + nsresult + RunSynchronizedOp(nsIOfflineStorage* aStorage, + SynchronizedOp* aOp); + + SynchronizedOp* + FindSynchronizedOp(const nsACString& aPattern, + nsISupports* aId); + + nsresult + ClearStoragesForApp(uint32_t aAppId, bool aBrowserOnly); + + nsresult + MaybeUpgradeOriginDirectory(nsIFile* aDirectory); + + static void + GetOriginPatternString(uint32_t aAppId, + MozBrowserPatternFlag aBrowserFlag, + const nsACString& aOrigin, + nsAutoCString& _retval); + // TLS storage index for the current thread's window. unsigned int mCurrentWindowIndex; @@ -177,6 +309,27 @@ private: // A map of Windows to the corresponding quota helper. nsRefPtrHashtable, CheckQuotaHelper> mCheckQuotaHelpers; + + // Maintains a list of live storages per origin. + nsClassHashtable > mLiveStorages; + + // Maintains a list of synchronized operatons that are in progress or queued. + nsAutoTArray, 5> mSynchronizedOps; + + // Thread on which IO is performed. + nsCOMPtr mIOThread; + + // A timer that gets activated at shutdown to ensure we close all storages. + nsCOMPtr mShutdownTimer; + + // A list of all successfully initialized origins. This list isn't protected + // by any mutex but it is only ever touched on the IO thread. + nsTArray mInitializedOrigins; + + nsAutoTArray, Client::TYPE_MAX> mClients; + + nsString mStorageBasePath; }; class AutoEnterWindow diff --git a/dom/quota/QuotaObject.cpp b/dom/quota/QuotaObject.cpp new file mode 100644 index 000000000000..410b557bdfc2 --- /dev/null +++ b/dom/quota/QuotaObject.cpp @@ -0,0 +1,159 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "QuotaObject.h" + +#include "QuotaManager.h" + +USING_QUOTA_NAMESPACE + +void +QuotaObject::AddRef() +{ + QuotaManager* quotaManager = QuotaManager::Get(); + if (!quotaManager) { + NS_ERROR("Null quota manager, this shouldn't happen, possible leak!"); + + NS_AtomicIncrementRefcnt(mRefCnt); + + return; + } + + MutexAutoLock lock(quotaManager->mQuotaMutex); + + ++mRefCnt; +} + +void +QuotaObject::Release() +{ + QuotaManager* quotaManager = QuotaManager::Get(); + if (!quotaManager) { + NS_ERROR("Null quota manager, this shouldn't happen, possible leak!"); + + nsrefcnt count = NS_AtomicDecrementRefcnt(mRefCnt); + if (count == 0) { + mRefCnt = 1; + delete this; + } + + return; + } + + { + MutexAutoLock lock(quotaManager->mQuotaMutex); + + --mRefCnt; + + if (mRefCnt > 0) { + return; + } + + if (mOriginInfo) { + mOriginInfo->mQuotaObjects.Remove(mPath); + } + } + + delete this; +} + +void +QuotaObject::UpdateSize(int64_t aSize) +{ + QuotaManager* quotaManager = QuotaManager::Get(); + NS_ASSERTION(quotaManager, "Shouldn't be null!"); + + MutexAutoLock lock(quotaManager->mQuotaMutex); + + if (mOriginInfo) { + mOriginInfo->mUsage -= mSize; + mSize = aSize; + mOriginInfo->mUsage += mSize; + } +} + +bool +QuotaObject::MaybeAllocateMoreSpace(int64_t aOffset, int32_t aCount) +{ + int64_t end = aOffset + aCount; + + QuotaManager* quotaManager = QuotaManager::Get(); + NS_ASSERTION(quotaManager, "Shouldn't be null!"); + + MutexAutoLock lock(quotaManager->mQuotaMutex); + + if (mSize >= end || !mOriginInfo) { + return true; + } + + int64_t newUsage = mOriginInfo->mUsage - mSize + end; + if (newUsage > mOriginInfo->mLimit) { + // This will block the thread, but it will also drop the mutex while + // waiting. The mutex will be reacquired again when the waiting is finished. + if (!quotaManager->LockedQuotaIsLifted()) { + return false; + } + + // Threads raced, the origin info removal has been done by some other + // thread. + if (!mOriginInfo) { + // The other thread could allocate more space. + if (end > mSize) { + mSize = end; + } + + return true; + } + + nsCString origin = mOriginInfo->mOrigin; + + mOriginInfo->LockedClearOriginInfos(); + NS_ASSERTION(!mOriginInfo, + "Should have cleared in LockedClearOriginInfos!"); + + quotaManager->mOriginInfos.Remove(origin); + + // Some other thread could increase the size without blocking (increasing + // the origin usage without hitting the limit), but no more than this one. + NS_ASSERTION(mSize < end, "This shouldn't happen!"); + + mSize = end; + + return true; + } + + mOriginInfo->mUsage = newUsage; + mSize = end; + + return true; +} + +#ifdef DEBUG +void +OriginInfo::LockedClearOriginInfos() +{ + QuotaManager* quotaManager = QuotaManager::Get(); + NS_ASSERTION(quotaManager, "Shouldn't be null!"); + + quotaManager->mQuotaMutex.AssertCurrentThreadOwns(); + + mQuotaObjects.EnumerateRead(ClearOriginInfoCallback, nullptr); +} +#endif + +// static +PLDHashOperator +OriginInfo::ClearOriginInfoCallback(const nsAString& aKey, + QuotaObject* aValue, + void* aUserArg) +{ + NS_ASSERTION(!aKey.IsEmpty(), "Empty key!"); + NS_ASSERTION(aValue, "Null pointer!"); + + aValue->mOriginInfo = nullptr; + + return PL_DHASH_NEXT; +} diff --git a/dom/quota/QuotaObject.h b/dom/quota/QuotaObject.h new file mode 100644 index 000000000000..0ec3447a605c --- /dev/null +++ b/dom/quota/QuotaObject.h @@ -0,0 +1,90 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_quota_quotaobject_h__ +#define mozilla_dom_quota_quotaobject_h__ + +#include "mozilla/dom/quota/QuotaCommon.h" + +#include "nsDataHashtable.h" + +BEGIN_QUOTA_NAMESPACE + +class OriginInfo; +class QuotaManager; + +class QuotaObject +{ + friend class OriginInfo; + friend class QuotaManager; + +public: + void + AddRef(); + + void + Release(); + + void + UpdateSize(int64_t aSize); + + bool + MaybeAllocateMoreSpace(int64_t aOffset, int32_t aCount); + +private: + QuotaObject(OriginInfo* aOriginInfo, const nsAString& aPath, int64_t aSize) + : mOriginInfo(aOriginInfo), mPath(aPath), mSize(aSize) + { } + + virtual ~QuotaObject() + { } + + nsAutoRefCnt mRefCnt; + + OriginInfo* mOriginInfo; + nsString mPath; + int64_t mSize; +}; + +class OriginInfo +{ + friend class QuotaManager; + friend class QuotaObject; + +public: + OriginInfo(const nsACString& aOrigin, int64_t aLimit, int64_t aUsage) + : mOrigin(aOrigin), mLimit(aLimit), mUsage(aUsage) + { + mQuotaObjects.Init(); + } + + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(OriginInfo) + +private: + void +#ifdef DEBUG + LockedClearOriginInfos(); +#else + LockedClearOriginInfos() + { + mQuotaObjects.EnumerateRead(ClearOriginInfoCallback, nullptr); + } +#endif + + static PLDHashOperator + ClearOriginInfoCallback(const nsAString& aKey, + QuotaObject* aValue, void* aUserArg); + + nsDataHashtable mQuotaObjects; + + nsCString mOrigin; + int64_t mLimit; + int64_t mUsage; +}; + +END_QUOTA_NAMESPACE + +#endif // mozilla_dom_quota_quotaobject_h__ diff --git a/dom/quota/StorageMatcher.h b/dom/quota/StorageMatcher.h new file mode 100644 index 000000000000..156f4c55add4 --- /dev/null +++ b/dom/quota/StorageMatcher.h @@ -0,0 +1,191 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_quota_patternmatcher_h__ +#define mozilla_dom_quota_patternmatcher_h__ + +#include "mozilla/dom/quota/QuotaCommon.h" + +#include "ArrayCluster.h" +#include "Utilities.h" + +BEGIN_QUOTA_NAMESPACE + +template > +class StorageMatcher : public ValueType +{ + typedef StorageMatcher SelfType; + + struct Closure + { + Closure(SelfType& aSelf) + : mSelf(aSelf), mPattern(EmptyCString()), mIndexes(nullptr) + { } + + Closure(SelfType& aSelf, const nsACString& aPattern) + : mSelf(aSelf), mPattern(aPattern), mIndexes(nullptr) + { } + + Closure(SelfType& aSelf, const nsTArray* aIndexes) + : mSelf(aSelf), mPattern(EmptyCString()), mIndexes(aIndexes) + { } + + Closure(SelfType& aSelf, const nsACString& aPattern, + const nsTArray* aIndexes) + : mSelf(aSelf), mPattern(aPattern), mIndexes(aIndexes) + { } + + SelfType& mSelf; + const nsACString& mPattern; + const nsTArray* mIndexes; + }; + +public: + template + void + Find(const nsBaseHashtable& aHashtable, + const nsACString& aPattern) + { + SelfType::Clear(); + + Closure closure(*this, aPattern); + aHashtable.EnumerateRead(SelfType::MatchPattern, &closure); + } + + template + void + Find(const nsBaseHashtable& aHashtable, + const nsTArray* aIndexes) + { + SelfType::Clear(); + + Closure closure(*this, aIndexes); + aHashtable.EnumerateRead(SelfType::MatchIndexes, &closure); + } + + template + void + Find(const nsBaseHashtable& aHashtable, + uint32_t aIndex) + { + nsAutoTArray indexes; + indexes.AppendElement(aIndex); + + Find(aHashtable, &indexes); + } + + template + void + Find(const nsBaseHashtable& aHashtable, + const nsACString& aPattern, + const nsTArray* aIndexes) + { + SelfType::Clear(); + + Closure closure(*this, aPattern, aIndexes); + aHashtable.EnumerateRead(SelfType::MatchPatternAndIndexes, &closure); + } + + template + void + Find(const nsBaseHashtable& aHashtable, + const nsACString& aPattern, + uint32_t aIndex) + { + nsAutoTArray indexes; + indexes.AppendElement(aIndex); + + Find(aHashtable, aPattern, &indexes); + } + + template + void + Find(const nsBaseHashtable& aHashtable) + { + SelfType::Clear(); + + Closure closure(*this); + aHashtable.EnumerateRead(SelfType::MatchAll, &closure); + } + +private: + static PLDHashOperator + MatchPattern(const nsACString& aKey, + BaseType* aValue, + void* aUserArg) + { + MOZ_ASSERT(!aKey.IsEmpty(), "Empty key!"); + MOZ_ASSERT(aValue, "Null pointer!"); + MOZ_ASSERT(aUserArg, "Null pointer!"); + + Closure* closure = static_cast(aUserArg); + + if (PatternMatchesOrigin(closure->mPattern, aKey)) { + aValue->AppendElementsTo(closure->mSelf); + } + + return PL_DHASH_NEXT; + } + + static PLDHashOperator + MatchIndexes(const nsACString& aKey, + BaseType* aValue, + void* aUserArg) + { + MOZ_ASSERT(!aKey.IsEmpty(), "Empty key!"); + MOZ_ASSERT(aValue, "Null pointer!"); + MOZ_ASSERT(aUserArg, "Null pointer!"); + + Closure* closure = static_cast(aUserArg); + + for (uint32_t index = 0; index < closure->mIndexes->Length(); index++) { + aValue->AppendElementsTo(closure->mIndexes->ElementAt(index), + closure->mSelf); + } + + return PL_DHASH_NEXT; + } + + static PLDHashOperator + MatchPatternAndIndexes(const nsACString& aKey, + BaseType* aValue, + void* aUserArg) + { + MOZ_ASSERT(!aKey.IsEmpty(), "Empty key!"); + MOZ_ASSERT(aValue, "Null pointer!"); + MOZ_ASSERT(aUserArg, "Null pointer!"); + + Closure* closure = static_cast(aUserArg); + + if (PatternMatchesOrigin(closure->mPattern, aKey)) { + for (uint32_t index = 0; index < closure->mIndexes->Length(); index++) { + aValue->AppendElementsTo(closure->mIndexes->ElementAt(index), + closure->mSelf); + } + } + + return PL_DHASH_NEXT; + } + + static PLDHashOperator + MatchAll(const nsACString& aKey, + BaseType* aValue, + void* aUserArg) + { + MOZ_ASSERT(!aKey.IsEmpty(), "Empty key!"); + MOZ_ASSERT(aValue, "Null pointer!"); + MOZ_ASSERT(aUserArg, "Null pointer!"); + + Closure* closure = static_cast(aUserArg); + aValue->AppendElementsTo(closure->mSelf); + + return PL_DHASH_NEXT; + } +}; + +END_QUOTA_NAMESPACE + +#endif // mozilla_dom_quota_patternmatcher_h__ diff --git a/dom/quota/StoragePrivilege.h b/dom/quota/StoragePrivilege.h new file mode 100644 index 000000000000..6cd9c7b75964 --- /dev/null +++ b/dom/quota/StoragePrivilege.h @@ -0,0 +1,21 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_quota_storageprivilege_h__ +#define mozilla_dom_quota_storageprivilege_h__ + +#include "mozilla/dom/quota/QuotaCommon.h" + +BEGIN_QUOTA_NAMESPACE + +enum StoragePrivilege { + Content, + Chrome +}; + +END_QUOTA_NAMESPACE + +#endif // mozilla_dom_quota_storageprivilege_h__ diff --git a/dom/quota/UsageRunnable.h b/dom/quota/UsageRunnable.h new file mode 100644 index 000000000000..3542d862d66d --- /dev/null +++ b/dom/quota/UsageRunnable.h @@ -0,0 +1,81 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_quota_usagerunnable_h__ +#define mozilla_dom_quota_usagerunnable_h__ + +#include "mozilla/dom/quota/QuotaCommon.h" + +#include "Utilities.h" + +BEGIN_QUOTA_NAMESPACE + +class UsageRunnable +{ +public: + UsageRunnable() + : mCanceled(0), mDatabaseUsage(0), mFileUsage(0) + { } + + virtual ~UsageRunnable() + { } + + bool + Canceled() + { + return mCanceled; + } + + void + AppendToDatabaseUsage(uint64_t aUsage) + { + IncrementUsage(&mDatabaseUsage, aUsage); + } + + void + AppendToFileUsage(uint64_t aUsage) + { + IncrementUsage(&mFileUsage, aUsage); + } + + uint64_t + DatabaseUsage() + { + return mDatabaseUsage; + } + + uint64_t + FileUsage() + { + return mFileUsage; + } + + uint64_t + TotalUsage() + { + uint64_t totalUsage = mDatabaseUsage; + IncrementUsage(&totalUsage, mFileUsage); + return totalUsage; + } + + void + ResetUsage() + { + mDatabaseUsage = 0; + mFileUsage = 0; + } + +protected: + int32_t mCanceled; + +private: + uint64_t mDatabaseUsage; + uint64_t mFileUsage; +}; + +END_QUOTA_NAMESPACE + +#endif // mozilla_dom_quota_usagerunnable_h__ diff --git a/dom/quota/Utilities.h b/dom/quota/Utilities.h new file mode 100644 index 000000000000..7b35f246ca92 --- /dev/null +++ b/dom/quota/Utilities.h @@ -0,0 +1,36 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_quota_utilities_h__ +#define mozilla_dom_quota_utilities_h__ + +#include "mozilla/dom/quota/QuotaCommon.h" + +BEGIN_QUOTA_NAMESPACE + +inline void +IncrementUsage(uint64_t* aUsage, uint64_t aDelta) +{ + // Watch for overflow! + if ((UINT64_MAX - *aUsage) < aDelta) { + NS_WARNING("Usage exceeds the maximum!"); + *aUsage = UINT64_MAX; + } + else { + *aUsage += aDelta; + } +} + +inline bool +PatternMatchesOrigin(const nsACString& aPatternString, const nsACString& aOrigin) +{ + // Aren't we smart! + return StringBeginsWith(aOrigin, aPatternString); +} + +END_QUOTA_NAMESPACE + +#endif // mozilla_dom_quota_utilities_h__ diff --git a/dom/quota/moz.build b/dom/quota/moz.build index 1c46131196ba..e9d12b779e2f 100644 --- a/dom/quota/moz.build +++ b/dom/quota/moz.build @@ -3,6 +3,12 @@ # 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/. +XPIDL_SOURCES += [ + 'nsIQuotaManager.idl', + 'nsIQuotaRequest.idl', + 'nsIUsageCallback.idl', +] + XPIDL_MODULE = 'dom_quota' MODULE = 'dom' diff --git a/dom/quota/nsIOfflineStorage.h b/dom/quota/nsIOfflineStorage.h new file mode 100644 index 000000000000..8155b52f85bc --- /dev/null +++ b/dom/quota/nsIOfflineStorage.h @@ -0,0 +1,92 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef nsIOfflineStorage_h__ +#define nsIOfflineStorage_h__ + +#include "nsIFileStorage.h" + +#define NS_OFFLINESTORAGE_IID \ + {0xe531b6e0, 0x55b8, 0x4f39, \ + { 0x95, 0xbb, 0x97, 0x21, 0x4c, 0xb0, 0xf6, 0x1a } } + +namespace mozilla { +namespace dom { +namespace quota { +class Client; +} +} +} + +class nsIOfflineStorage : public nsIFileStorage +{ +public: + typedef mozilla::dom::quota::Client Client; + + NS_DECLARE_STATIC_IID_ACCESSOR(NS_OFFLINESTORAGE_IID) + + NS_IMETHOD_(Client*) + GetClient() = 0; + + NS_IMETHOD_(bool) + IsOwned(nsPIDOMWindow* aOwner) = 0; + + NS_IMETHOD_(const nsACString&) + Origin() = 0; + + // Implementation of this method should close the storage (without aborting + // running operations nor discarding pending operations). + NS_IMETHOD_(nsresult) + Close() = 0; + + // Whether or not the storage has had Close called on it. + NS_IMETHOD_(bool) + IsClosed() = 0; + + // Implementation of this method should close the storage, all running + // operations should be aborted and pending operations should be discarded. + NS_IMETHOD_(void) + Invalidate() = 0; +}; + +NS_DEFINE_STATIC_IID_ACCESSOR(nsIOfflineStorage, NS_OFFLINESTORAGE_IID) + +#define NS_DECL_NSIOFFLINESTORAGE \ + NS_IMETHOD_(Client*) \ + GetClient() MOZ_OVERRIDE; \ + \ + NS_IMETHOD_(bool) \ + IsOwned(nsPIDOMWindow* aOwner) MOZ_OVERRIDE; \ + \ + NS_IMETHOD_(const nsACString&) \ + Origin() MOZ_OVERRIDE; \ + \ + NS_IMETHOD_(nsresult) \ + Close() MOZ_OVERRIDE; \ + \ + NS_IMETHOD_(bool) \ + IsClosed() MOZ_OVERRIDE; \ + \ + NS_IMETHOD_(void) \ + Invalidate() MOZ_OVERRIDE; + +#define NS_DECL_NSIOFFLINESTORAGE_NOCLOSE \ + NS_IMETHOD_(Client*) \ + GetClient() MOZ_OVERRIDE; \ + \ + NS_IMETHOD_(bool) \ + IsOwned(nsPIDOMWindow* aOwner) MOZ_OVERRIDE; \ + \ + NS_IMETHOD_(const nsACString&) \ + Origin() MOZ_OVERRIDE; \ + \ + NS_IMETHOD_(bool) \ + IsClosed() MOZ_OVERRIDE; \ + \ + NS_IMETHOD_(void) \ + Invalidate() MOZ_OVERRIDE; + +#endif // nsIOfflineStorage_h__ diff --git a/dom/quota/nsIQuotaManager.idl b/dom/quota/nsIQuotaManager.idl new file mode 100644 index 000000000000..0e9195badd3e --- /dev/null +++ b/dom/quota/nsIQuotaManager.idl @@ -0,0 +1,44 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nsISupports.idl" + +interface nsIQuotaRequest; +interface nsIURI; +interface nsIUsageCallback; + +[scriptable, builtinclass, uuid(8d74e6f8-81c3-4045-9bb7-70bdb7b11b25)] +interface nsIQuotaManager : nsISupports +{ + /** + * Schedules an asynchronous callback that will return the total amount of + * disk space being used by storages for the given origin. + * + * @param aURI + * The URI whose usage is being queried. + * @param aCallback + * The callback that will be called when the usage is available. + */ + [optional_argc] + nsIQuotaRequest + getUsageForURI(in nsIURI aURI, + in nsIUsageCallback aCallback, + [optional] in unsigned long aAppId, + [optional] in boolean aInMozBrowserOnly); + + /** + * Removes all storages stored for the given URI. The files may not be + * deleted immediately depending on prohibitive concurrent operations. + * + * @param aURI + * The URI whose storages are to be cleared. + */ + [optional_argc] + void + clearStoragesForURI(in nsIURI aURI, + [optional] in unsigned long aAppId, + [optional] in boolean aInMozBrowserOnly); +}; diff --git a/dom/quota/nsIQuotaRequest.idl b/dom/quota/nsIQuotaRequest.idl new file mode 100644 index 000000000000..8cf2fdc78adb --- /dev/null +++ b/dom/quota/nsIQuotaRequest.idl @@ -0,0 +1,14 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nsISupports.idl" + +[scriptable, function, uuid(d96769ed-63ac-4070-ac5a-4b0e1728618a)] +interface nsIQuotaRequest : nsISupports +{ + void + cancel(); +}; diff --git a/dom/quota/nsIUsageCallback.idl b/dom/quota/nsIUsageCallback.idl new file mode 100644 index 000000000000..eb365e428fa8 --- /dev/null +++ b/dom/quota/nsIUsageCallback.idl @@ -0,0 +1,20 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nsISupports.idl" + +interface nsIURI; + +[scriptable, function, uuid(7b0f9928-0ddc-42c7-b9f2-6b2308b90b18)] +interface nsIUsageCallback : nsISupports +{ + void + onUsageResult(in nsIURI aURI, + in unsigned long long aUsage, + in unsigned long long aFileUsage, + in unsigned long aAppId, + in boolean aInMozBrowserOnly); +}; diff --git a/js/xpconnect/src/dom_quickstubs.qsconf b/js/xpconnect/src/dom_quickstubs.qsconf index 9221c4c5ee0a..2e80c9f371d2 100644 --- a/js/xpconnect/src/dom_quickstubs.qsconf +++ b/js/xpconnect/src/dom_quickstubs.qsconf @@ -215,13 +215,17 @@ members = [ 'nsIIDBTransaction.*', 'nsIIDBOpenDBRequest.*', 'nsIIDBVersionChangeEvent.*', - 'nsIIndexedDatabaseUsageCallback.*', 'nsIIndexedDatabaseManager.*', 'nsIDOMDOMError.*', # dom/file 'nsIDOMLockedFile.*', + + # dom/quota + 'nsIQuotaManager.*', + 'nsIQuotaRequest.*', + 'nsIUsageCallback.*', ] # Most interfaces can be found by searching the includePath; to find diff --git a/layout/build/nsLayoutCID.h b/layout/build/nsLayoutCID.h index 3e24d438a6ea..b07f20cddee2 100644 --- a/layout/build/nsLayoutCID.h +++ b/layout/build/nsLayoutCID.h @@ -95,4 +95,8 @@ #define DOMREQUEST_SERVICE_CID \ { 0x3160e271, 0x138d, 0x4cc7, { 0x9d, 0x63, 0x64, 0x29, 0xf1, 0x69, 0x57, 0xc7 } } +// {5a75c25a-5e7e-4d90-8f7c-07eb15cc0aa8} +#define QUOTA_MANAGER_CID \ +{ 0x5a75c25a, 0x5e7e, 0x4d90, { 0x8f, 0x7c, 0x07, 0xeb, 0x15, 0xcc, 0x0a, 0xa8 } } + #endif /* nsLayoutCID_h__ */ diff --git a/layout/build/nsLayoutModule.cpp b/layout/build/nsLayoutModule.cpp index 8228e1838fb1..c557afc6ce62 100644 --- a/layout/build/nsLayoutModule.cpp +++ b/layout/build/nsLayoutModule.cpp @@ -90,6 +90,7 @@ #include "mozilla/dom/EventSource.h" #include "mozilla/dom/indexedDB/IndexedDatabaseManager.h" #include "mozilla/dom/network/TCPSocketChild.h" +#include "mozilla/dom/quota/QuotaManager.h" #include "mozilla/OSFileConstants.h" #include "mozilla/Services.h" @@ -248,6 +249,7 @@ using namespace mozilla::dom::mobilemessage; using mozilla::dom::alarm::AlarmHalService; using mozilla::dom::indexedDB::IndexedDatabaseManager; using mozilla::dom::power::PowerManagerService; +using mozilla::dom::quota::QuotaManager; using mozilla::dom::TCPSocketChild; using mozilla::dom::time::TimeService; @@ -280,6 +282,8 @@ NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(IndexedDatabaseManager, IndexedDatabaseManager::FactoryCreate) NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(DOMRequestService, DOMRequestService::FactoryCreate) +NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(QuotaManager, + QuotaManager::FactoryCreate) #ifdef MOZ_B2G_RIL NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(SystemWorkerManager, SystemWorkerManager::FactoryCreate) @@ -783,6 +787,7 @@ NS_DEFINE_NAMED_CID(NS_DOMJSON_CID); NS_DEFINE_NAMED_CID(NS_TEXTEDITOR_CID); NS_DEFINE_NAMED_CID(INDEXEDDB_MANAGER_CID); NS_DEFINE_NAMED_CID(DOMREQUEST_SERVICE_CID); +NS_DEFINE_NAMED_CID(QUOTA_MANAGER_CID); #ifdef MOZ_B2G_RIL NS_DEFINE_NAMED_CID(SYSTEMWORKERMANAGER_CID); #endif @@ -1069,6 +1074,7 @@ static const mozilla::Module::CIDEntry kLayoutCIDs[] = { { &kNS_TEXTEDITOR_CID, false, NULL, nsPlaintextEditorConstructor }, { &kINDEXEDDB_MANAGER_CID, false, NULL, IndexedDatabaseManagerConstructor }, { &kDOMREQUEST_SERVICE_CID, false, NULL, DOMRequestServiceConstructor }, + { &kQUOTA_MANAGER_CID, false, NULL, QuotaManagerConstructor }, #ifdef MOZ_B2G_RIL { &kSYSTEMWORKERMANAGER_CID, true, NULL, SystemWorkerManagerConstructor }, #endif @@ -1216,6 +1222,7 @@ static const mozilla::Module::ContractIDEntry kLayoutContracts[] = { { "@mozilla.org/editor/texteditor;1", &kNS_TEXTEDITOR_CID }, { INDEXEDDB_MANAGER_CONTRACTID, &kINDEXEDDB_MANAGER_CID }, { DOMREQUEST_SERVICE_CONTRACTID, &kDOMREQUEST_SERVICE_CID }, + { QUOTA_MANAGER_CONTRACTID, &kQUOTA_MANAGER_CID }, #ifdef MOZ_B2G_RIL { SYSTEMWORKERMANAGER_CONTRACTID, &kSYSTEMWORKERMANAGER_CID }, #endif @@ -1294,7 +1301,7 @@ static const mozilla::Module::CategoryEntry kLayoutCategories[] = { { "net-channel-event-sinks", "CSPService", CSPSERVICE_CONTRACTID }, { JAVASCRIPT_GLOBAL_STATIC_NAMESET_CATEGORY, "PrivilegeManager", NS_SECURITYNAMESET_CONTRACTID }, { "app-startup", "Script Security Manager", "service," NS_SCRIPTSECURITYMANAGER_CONTRACTID }, - { TOPIC_WEB_APP_CLEAR_DATA, "IndexedDatabaseManager", "service," INDEXEDDB_MANAGER_CONTRACTID }, + { TOPIC_WEB_APP_CLEAR_DATA, "QuotaManager", "service," QUOTA_MANAGER_CONTRACTID }, #ifdef MOZ_WIDGET_GONK { "app-startup", "Volume Service", "service," NS_VOLUMESERVICE_CONTRACTID }, #endif diff --git a/mobile/android/installer/package-manifest.in b/mobile/android/installer/package-manifest.in index 0d2efcd999fc..2068dde29680 100644 --- a/mobile/android/installer/package-manifest.in +++ b/mobile/android/installer/package-manifest.in @@ -131,6 +131,7 @@ @BINPATH@/components/dom_json.xpt @BINPATH@/components/dom_browserelement.xpt @BINPATH@/components/dom_power.xpt +@BINPATH@/components/dom_quota.xpt @BINPATH@/components/dom_range.xpt @BINPATH@/components/dom_settings.xpt @BINPATH@/components/dom_sidebar.xpt diff --git a/storage/src/TelemetryVFS.cpp b/storage/src/TelemetryVFS.cpp index e4fce091f725..fd4abe311f0e 100644 --- a/storage/src/TelemetryVFS.cpp +++ b/storage/src/TelemetryVFS.cpp @@ -11,6 +11,7 @@ #include "nsThreadUtils.h" #include "mozilla/Util.h" #include "mozilla/dom/quota/QuotaManager.h" +#include "mozilla/dom/quota/QuotaObject.h" /** * This preference is a workaround to allow users/sysadmins to identify diff --git a/toolkit/forgetaboutsite/ForgetAboutSite.jsm b/toolkit/forgetaboutsite/ForgetAboutSite.jsm index 66e27004a35e..5e4a180054dd 100644 --- a/toolkit/forgetaboutsite/ForgetAboutSite.jsm +++ b/toolkit/forgetaboutsite/ForgetAboutSite.jsm @@ -209,9 +209,9 @@ this.ForgetAboutSite = { } } - // Indexed DB - let (idbm = Cc["@mozilla.org/dom/indexeddb/manager;1"]. - getService(Ci.nsIIndexedDatabaseManager)) { + // Offline Storages + let (qm = Cc["@mozilla.org/dom/quota/manager;1"]. + getService(Ci.nsIQuotaManager)) { // delete data from both HTTP and HTTPS sites let caUtils = {}; let scriptLoader = Cc["@mozilla.org/moz/jssubscript-loader;1"]. @@ -220,8 +220,8 @@ this.ForgetAboutSite = { caUtils); let httpURI = caUtils.makeURI("http://" + aDomain); let httpsURI = caUtils.makeURI("https://" + aDomain); - idbm.clearDatabasesForURI(httpURI); - idbm.clearDatabasesForURI(httpsURI); + qm.clearStoragesForURI(httpURI); + qm.clearStoragesForURI(httpsURI); } // Everybody else (including extensions) From fa2ed308e5468e1d43cbb791edfa988338dcf706 Mon Sep 17 00:00:00 2001 From: Olli Pettay Date: Tue, 26 Mar 2013 13:45:39 +0200 Subject: [PATCH 007/129] Bug 847590 - Paris binding for BeforeUnloadEvent, r=peterv --HG-- extra : rebase_source : d249e7a7e61c39ccba52a10234e2260b048c941d --- content/events/src/nsDOMBeforeUnloadEvent.h | 11 ++++++++++- dom/bindings/Bindings.conf | 4 ++++ dom/webidl/BeforeUnloadEvent.webidl | 12 ++++++++++++ dom/webidl/WebIDL.mk | 1 + 4 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 dom/webidl/BeforeUnloadEvent.webidl diff --git a/content/events/src/nsDOMBeforeUnloadEvent.h b/content/events/src/nsDOMBeforeUnloadEvent.h index 878fbe424fd1..4fad8127eb07 100644 --- a/content/events/src/nsDOMBeforeUnloadEvent.h +++ b/content/events/src/nsDOMBeforeUnloadEvent.h @@ -8,6 +8,7 @@ #include "nsIDOMBeforeUnloadEvent.h" #include "nsDOMEvent.h" +#include "mozilla/dom/BeforeUnloadEventBinding.h" class nsDOMBeforeUnloadEvent : public nsDOMEvent, public nsIDOMBeforeUnloadEvent @@ -15,7 +16,15 @@ class nsDOMBeforeUnloadEvent : public nsDOMEvent, public: nsDOMBeforeUnloadEvent(mozilla::dom::EventTarget* aOwner, nsPresContext* aPresContext, nsEvent* aEvent) - : nsDOMEvent(aOwner, aPresContext, aEvent) {} + : nsDOMEvent(aOwner, aPresContext, aEvent) + { + SetIsDOMBinding(); + } + + virtual JSObject* WrapObject(JSContext* aCx, JSObject* aScope) + { + return mozilla::dom::BeforeUnloadEventBinding::Wrap(aCx, aScope, this); + } NS_DECL_ISUPPORTS_INHERITED diff --git a/dom/bindings/Bindings.conf b/dom/bindings/Bindings.conf index 5edbb629147d..9e1a50f181e6 100644 --- a/dom/bindings/Bindings.conf +++ b/dom/bindings/Bindings.conf @@ -126,6 +126,10 @@ DOMInterfaces = { 'concrete': False, }, +'BeforeUnloadEvent': { + 'nativeType': 'nsDOMBeforeUnloadEvent', +}, + 'BiquadFilterNode': { 'resultNotAddRefed': [ 'frequency', 'q', 'gain' ], 'wrapperCache': False diff --git a/dom/webidl/BeforeUnloadEvent.webidl b/dom/webidl/BeforeUnloadEvent.webidl new file mode 100644 index 000000000000..e64e1b2c2991 --- /dev/null +++ b/dom/webidl/BeforeUnloadEvent.webidl @@ -0,0 +1,12 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + * + * For more information on this interface, please see + * http://www.whatwg.org/specs/web-apps/current-work/#beforeunloadevent + */ + +interface BeforeUnloadEvent : Event { + attribute DOMString returnValue; +}; diff --git a/dom/webidl/WebIDL.mk b/dom/webidl/WebIDL.mk index f6f3fbbd6448..7f1de25fd4af 100644 --- a/dom/webidl/WebIDL.mk +++ b/dom/webidl/WebIDL.mk @@ -21,6 +21,7 @@ webidl_files = \ AudioParam.webidl \ AudioSourceNode.webidl \ BatteryManager.webidl \ + BeforeUnloadEvent.webidl \ BiquadFilterNode.webidl \ Blob.webidl \ CanvasRenderingContext2D.webidl \ From 567675450f419f9e0bb6d9f5a9dcd6ec5ffddc7e Mon Sep 17 00:00:00 2001 From: Olli Pettay Date: Tue, 26 Mar 2013 13:45:45 +0200 Subject: [PATCH 008/129] Bug 854573 - Paris binding for CompositionEvent, r=peterv --HG-- extra : rebase_source : 3e04e198a329649d7e1f306a31cf96485f0afc0d --- content/events/src/nsDOMCompositionEvent.cpp | 2 ++ content/events/src/nsDOMCompositionEvent.h | 19 +++++++++++++ dom/bindings/Bindings.conf | 4 +++ dom/webidl/CompositionEvent.webidl | 29 ++++++++++++++++++++ dom/webidl/WebIDL.mk | 1 + 5 files changed, 55 insertions(+) create mode 100644 dom/webidl/CompositionEvent.webidl diff --git a/content/events/src/nsDOMCompositionEvent.cpp b/content/events/src/nsDOMCompositionEvent.cpp index f4a7271609b2..c7a457ca2a4b 100644 --- a/content/events/src/nsDOMCompositionEvent.cpp +++ b/content/events/src/nsDOMCompositionEvent.cpp @@ -30,6 +30,8 @@ nsDOMCompositionEvent::nsDOMCompositionEvent(mozilla::dom::EventTarget* aOwner, mData = static_cast(mEvent)->data; // TODO: Native event should have locale information. + + SetIsDOMBinding(); } nsDOMCompositionEvent::~nsDOMCompositionEvent() diff --git a/content/events/src/nsDOMCompositionEvent.h b/content/events/src/nsDOMCompositionEvent.h index a00219c05fac..80c34e92e3c6 100644 --- a/content/events/src/nsDOMCompositionEvent.h +++ b/content/events/src/nsDOMCompositionEvent.h @@ -9,6 +9,7 @@ #include "nsDOMUIEvent.h" #include "nsIDOMCompositionEvent.h" +#include "mozilla/dom/CompositionEventBinding.h" class nsDOMCompositionEvent : public nsDOMUIEvent, public nsIDOMCompositionEvent @@ -23,6 +24,24 @@ public: NS_FORWARD_TO_NSDOMUIEVENT NS_DECL_NSIDOMCOMPOSITIONEVENT + virtual JSObject* WrapObject(JSContext* aCx, JSObject* aScope) + { + return mozilla::dom::CompositionEventBinding::Wrap(aCx, aScope, this); + } + + void + InitCompositionEvent(const nsAString& aType, + bool aCanBubble, + bool aCancelable, + nsIDOMWindow* aView, + const nsAString& aData, + const nsAString& aLocale, + mozilla::ErrorResult& aRv) + { + aRv = InitCompositionEvent(aType, aCanBubble, aCancelable, aView, + aData, aLocale); + } + protected: nsString mData; nsString mLocale; diff --git a/dom/bindings/Bindings.conf b/dom/bindings/Bindings.conf index 9e1a50f181e6..4d62e4636f48 100644 --- a/dom/bindings/Bindings.conf +++ b/dom/bindings/Bindings.conf @@ -183,6 +183,10 @@ DOMInterfaces = { 'nativeType': 'nsDOMCommandEvent', }, +'CompositionEvent': { + 'nativeType': 'nsDOMCompositionEvent', +}, + 'CSS': { 'concrete': False, }, diff --git a/dom/webidl/CompositionEvent.webidl b/dom/webidl/CompositionEvent.webidl new file mode 100644 index 000000000000..c1a85fcbb2e5 --- /dev/null +++ b/dom/webidl/CompositionEvent.webidl @@ -0,0 +1,29 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + * + * http://dev.w3.org/2006/webapi/DOM-Level-3-Events/html/DOM3-Events.html#events-CompositionEvent + * + * Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C + * liability, trademark and document use rules apply. + */ + +interface WindowProxy; + +interface CompositionEvent : UIEvent +{ + readonly attribute DOMString? data; + readonly attribute DOMString locale; +}; + +partial interface CompositionEvent +{ + [Throws] + void initCompositionEvent(DOMString typeArg, + boolean canBubbleArg, + boolean cancelableArg, + WindowProxy? viewArg, + DOMString? dataArg, + DOMString localeArg); +}; diff --git a/dom/webidl/WebIDL.mk b/dom/webidl/WebIDL.mk index 7f1de25fd4af..1f44c9f40c17 100644 --- a/dom/webidl/WebIDL.mk +++ b/dom/webidl/WebIDL.mk @@ -33,6 +33,7 @@ webidl_files = \ ClientRectList.webidl \ CommandEvent.webidl \ Comment.webidl \ + CompositionEvent.webidl \ CSS.webidl \ CSSPrimitiveValue.webidl \ CSSStyleDeclaration.webidl \ From ab1c8e33eafd7c52dd481c6656789a6bb7a015d8 Mon Sep 17 00:00:00 2001 From: Landry Breuil Date: Tue, 26 Mar 2013 13:00:31 +0100 Subject: [PATCH 009/129] Bug 851611 followup - fix platforms where MOZ_ENABLE_PROFILER_SPS is undef r=bgirard --- tools/profiler/GeckoProfiler.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/profiler/GeckoProfiler.h b/tools/profiler/GeckoProfiler.h index 3a15b273a0b4..4c8e2b5452c8 100644 --- a/tools/profiler/GeckoProfiler.h +++ b/tools/profiler/GeckoProfiler.h @@ -104,13 +104,13 @@ static inline void profiler_stop() {} static inline bool profiler_is_active() { return false; } // Internal-only. Used by the event tracer. -static inline void profiler_responsinveness(const TimeStamp& aTime) {} +static inline void profiler_responsiveness(const mozilla::TimeStamp& aTime) {} // Internal-only. Used by the event tracer. static inline double* profiler_get_responsiveness() { return nullptr; } // Internal-only. -static inline void profile_set_frame_number(int frameNumber) {} +static inline void profiler_set_frame_number(int frameNumber) {} // Get the profile encoded as a JSON string. static inline char* profiler_get_profile() { return nullptr; } From 1634b9330dd00f7ac39e45e32e4316a15356cc99 Mon Sep 17 00:00:00 2001 From: Jon Coppeard Date: Tue, 26 Mar 2013 11:51:03 +0000 Subject: [PATCH 010/129] Bug 854852 - GC: One root missed from debugger r=terrence --- js/src/vm/Debugger.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/src/vm/Debugger.cpp b/js/src/vm/Debugger.cpp index 3b0117ab9423..814ea5c59683 100644 --- a/js/src/vm/Debugger.cpp +++ b/js/src/vm/Debugger.cpp @@ -879,7 +879,7 @@ Debugger::parseResumptionValue(Maybe &ac, bool ok, const Value Rooted obj(cx); RootedShape shape(cx); RootedId returnId(cx, NameToId(cx->names().return_)); - jsid throwId = NameToId(cx->names().throw_); + RootedId throwId(cx, NameToId(cx->names().throw_)); bool okResumption = rv.isObject(); if (okResumption) { obj = &rv.toObject(); From feb84a19335d6038c0bda5659b3c557b87176c3f Mon Sep 17 00:00:00 2001 From: Andrew Halberstadt Date: Tue, 26 Mar 2013 09:50:00 -0400 Subject: [PATCH 011/129] Bug 843296 - check for crashes in b2g emulator unittests during failures in marionette start up, r=jgriffin --- build/mobile/b2gautomation.py | 4 ++ layout/tools/reftest/runreftestb2g.py | 2 + .../client/marionette/b2ginstance.py | 54 ++++++++++++++++++- .../marionette/client/marionette/emulator.py | 3 ++ .../client/marionette/marionette.py | 20 +++++-- testing/mochitest/runtestsb2g.py | 2 + testing/xpcshell/runtestsb2g.py | 2 + 7 files changed, 82 insertions(+), 5 deletions(-) diff --git a/build/mobile/b2gautomation.py b/build/mobile/b2gautomation.py index 450ec0e1b3e7..e5d45bfe795d 100644 --- a/build/mobile/b2gautomation.py +++ b/build/mobile/b2gautomation.py @@ -10,6 +10,7 @@ import re import shutil import tempfile import time +import traceback from automation import Automation from devicemanager import NetworkTools @@ -106,11 +107,14 @@ class B2GRemoteAutomation(Automation): def checkForCrashes(self, directory, symbolsPath): crashed = False remote_dump_dir = self._remoteProfile + '/minidumps' + print "checking for crashes in '%s'" % remote_dump_dir if self._devicemanager.dirExists(remote_dump_dir): local_dump_dir = tempfile.mkdtemp() self._devicemanager.getDirectory(remote_dump_dir, local_dump_dir) try: crashed = mozcrash.check_for_crashes(local_dump_dir, symbolsPath, test_name=self.lastTestSeen) + except: + traceback.print_exc() finally: shutil.rmtree(local_dump_dir) self._devicemanager.removeDir(remote_dump_dir) diff --git a/layout/tools/reftest/runreftestb2g.py b/layout/tools/reftest/runreftestb2g.py index e06e66b87c4b..817a69f129a8 100644 --- a/layout/tools/reftest/runreftestb2g.py +++ b/layout/tools/reftest/runreftestb2g.py @@ -480,6 +480,8 @@ def main(args=sys.argv[1:]): kwargs['logcat_dir'] = options.logcat_dir if options.busybox: kwargs['busybox'] = options.busybox + if options.symbolsPath: + kwargs['symbols_path'] = options.symbolsPath if options.emulator_res: kwargs['emulator_res'] = options.emulator_res if options.b2gPath: diff --git a/testing/marionette/client/marionette/b2ginstance.py b/testing/marionette/client/marionette/b2ginstance.py index 4442686554be..6fdace8dc678 100644 --- a/testing/marionette/client/marionette/b2ginstance.py +++ b/testing/marionette/client/marionette/b2ginstance.py @@ -2,10 +2,18 @@ # 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/. +from ConfigParser import ConfigParser import os import platform +import posixpath +import shutil import subprocess import sys +import tempfile +import traceback + +from mozdevice import DeviceManagerADB +import mozcrash class B2GInstance(object): @classmethod @@ -68,7 +76,7 @@ class B2GInstance(object): return option raise Exception('%s not found!' % binary) - def __init__(self, homedir=None): + def __init__(self, homedir=None, devicemanager=None): if not homedir: homedir = self.find_b2g_dir() else: @@ -81,6 +89,13 @@ class B2GInstance(object): self.adb_path = self.check_adb(self.homedir) self.fastboot_path = self.check_fastboot(self.homedir) self.update_tools = os.path.join(self.homedir, 'tools', 'update-tools') + self._dm = devicemanager + + @property + def dm(self): + if not self._dm: + self._dm = DeviceManagerADB(adbPath=self.adb_path) + return self._dm def check_file(self, filePath): if not os.access(filePath, os.F_OK): @@ -88,6 +103,43 @@ class B2GInstance(object): 'directory as the homedir parameter, or set ' 'B2G_HOME correctly?') % filePath) + def check_remote_profiles(self, remote_profiles_ini='/data/b2g/mozilla/profiles.ini'): + if not self.dm.fileExists(remote_profiles_ini): + raise Exception("Remote file '%s' not found" % remote_profiles_ini) + + local_profiles_ini = tempfile.NamedTemporaryFile() + self.dm.getFile(remote_profiles_ini, local_profiles_ini.name) + cfg = ConfigParser() + cfg.readfp(local_profiles_ini) + + remote_profiles = [] + for section in cfg.sections(): + if cfg.has_option(section, 'Path'): + is_relative = 0 + if cfg.has_option(section, 'IsRelative'): + is_relative = cfg.getint(section, 'IsRelative') + + remote_profiles.append(posixpath.join(remote_profiles_ini, cfg.get(section, 'Path')) + if is_relative else cfg.get(section, 'Path')) + return remote_profiles + + def check_for_crashes(self, symbols_path): + remote_dump_dirs = [posixpath.join(p, 'minidumps') for p in self.check_remote_profiles()] + crashed = False + for remote_dump_dir in remote_dump_dirs: + print "checking for crashes in '%s'" % remote_dump_dir + local_dump_dir = tempfile.mkdtemp() + self.dm.getDirectory(remote_dump_dir, local_dump_dir) + try: + if mozcrash.check_for_crashes(local_dump_dir, symbols_path): + crashed = True + except: + traceback.print_exc() + finally: + shutil.rmtree(local_dump_dir) + self.dm.removeDir(remote_dump_dir) + return crashed + def import_update_tools(self): """Import the update_tools package from B2G""" sys.path.append(self.update_tools) diff --git a/testing/marionette/client/marionette/emulator.py b/testing/marionette/client/marionette/emulator.py index 0a3f8c0aa761..3ca6f7c12606 100644 --- a/testing/marionette/client/marionette/emulator.py +++ b/testing/marionette/client/marionette/emulator.py @@ -162,6 +162,9 @@ class Emulator(object): return True return False + def check_for_minidumps(self, symbols_path): + return self.b2g.check_for_crashes(symbols_path) + def create_sdcard(self, sdcard): self._tmp_sdcard = tempfile.mktemp(prefix='sdcard') sdargs = [self.mksdcard, "-l", "mySdCard", sdcard, self._tmp_sdcard] diff --git a/testing/marionette/client/marionette/marionette.py b/testing/marionette/client/marionette/marionette.py index 8eb09cec23be..42ac4f3f4996 100644 --- a/testing/marionette/client/marionette/marionette.py +++ b/testing/marionette/client/marionette/marionette.py @@ -168,7 +168,7 @@ class Marionette(object): emulator=None, sdcard=None, emulatorBinary=None, emulatorImg=None, emulator_res=None, gecko_path=None, connectToRunningEmulator=False, homedir=None, baseurl=None, - noWindow=False, logcat_dir=None, busybox=None): + noWindow=False, logcat_dir=None, busybox=None, symbols_path=None): self.host = host self.port = self.local_port = port self.bin = bin @@ -183,6 +183,7 @@ class Marionette(object): self.noWindow = noWindow self.logcat_dir = logcat_dir self._test_name = None + self.symbols_path = symbols_path if bin: port = int(self.port) @@ -366,10 +367,15 @@ class Marionette(object): def check_for_crash(self): returncode = None name = None + crashed = False if self.emulator: if self.emulator.check_for_crash(): returncode = self.emulator.proc.returncode name = 'emulator' + crashed = True + + if self.symbols_path and self.emulator.check_for_minidumps(self.symbols_path): + crashed = True elif self.instance: # In the future, a check for crashed Firefox processes # should be here. @@ -377,7 +383,7 @@ class Marionette(object): if returncode is not None: print ('PROCESS-CRASH | %s | abnormal termination with exit code %d' % (name, returncode)) - return returncode is not None + return crashed def absolute_url(self, relative_url): return "%s%s" % (self.baseurl, relative_url) @@ -386,8 +392,14 @@ class Marionette(object): return self._send_message('getStatus', 'value') def start_session(self, desired_capabilities=None): - # We are ignoring desired_capabilities, at least for now. - self.session = self._send_message('newSession', 'value') + try: + # We are ignoring desired_capabilities, at least for now. + self.session = self._send_message('newSession', 'value') + except: + traceback.print_exc() + self.check_for_crash() + sys.exit() + self.b2g = 'b2g' in self.session return self.session diff --git a/testing/mochitest/runtestsb2g.py b/testing/mochitest/runtestsb2g.py index dd184f4ee79a..9dc0507d046d 100644 --- a/testing/mochitest/runtestsb2g.py +++ b/testing/mochitest/runtestsb2g.py @@ -566,6 +566,8 @@ def run_remote_mochitests(automation, parser, options): kwargs['logcat_dir'] = options.logcat_dir if options.busybox: kwargs['busybox'] = options.busybox + if options.symbolsPath: + kwargs['symbols_path'] = options.symbolsPath # needless to say sdcard is only valid if using an emulator if options.sdcard: kwargs['sdcard'] = options.sdcard diff --git a/testing/xpcshell/runtestsb2g.py b/testing/xpcshell/runtestsb2g.py index 60b12a9ac634..6809089819c4 100644 --- a/testing/xpcshell/runtestsb2g.py +++ b/testing/xpcshell/runtestsb2g.py @@ -167,6 +167,8 @@ def main(): kwargs['logcat_dir'] = options.logcat_dir if options.busybox: kwargs['busybox'] = options.busybox + if options.symbolsPath: + kwargs['symbols_path'] = options.symbolsPath if options.b2g_path: kwargs['homedir'] = options.emu_path or options.b2g_path if options.address: From 3e91baaeae14d498960fb92a978c55dd5f89c5f4 Mon Sep 17 00:00:00 2001 From: Jonathan Watt Date: Tue, 26 Mar 2013 13:54:05 +0000 Subject: [PATCH 012/129] Bug 840820 - Make display as a vertical slider if it has an orient="vertical" attribute. r=mounir --- layout/forms/nsRangeFrame.cpp | 50 ++++++++++++++++++++--------------- layout/style/forms.css | 22 ++++++++++++--- 2 files changed, 46 insertions(+), 26 deletions(-) diff --git a/layout/forms/nsRangeFrame.cpp b/layout/forms/nsRangeFrame.cpp index f8b7ee6929bd..c31a7bca88dd 100644 --- a/layout/forms/nsRangeFrame.cpp +++ b/layout/forms/nsRangeFrame.cpp @@ -457,27 +457,31 @@ nsRangeFrame::AttributeChanged(int32_t aNameSpaceID, NS_ASSERTION(mTrackDiv, "The track div must exist!"); NS_ASSERTION(mThumbDiv, "The thumb div must exist!"); - if (aNameSpaceID == kNameSpaceID_None && - (aAttribute == nsGkAtoms::value || - aAttribute == nsGkAtoms::min || - aAttribute == nsGkAtoms::max || - aAttribute == nsGkAtoms::step)) { - // We want to update the position of the thumb, except in one special case: - // If the value attribute is being set, it is possible that we are in the - // middle of a type change away from type=range, under the - // SetAttr(..., nsGkAtoms::value, ...) call in nsHTMLInputElement:: - // HandleTypeChange. In that case the nsHTMLInputElement's type will - // already have changed, and if we call UpdateThumbPositionForValueChange() - // we'll fail the asserts under that call that check the type of our - // nsHTMLInputElement. Given that we're changing away from being a range - // and this frame will shortly be destroyed, there's no point in calling - // UpdateThumbPositionForValueChange() anyway. - MOZ_ASSERT(mContent->IsHTML(nsGkAtoms::input), "bad cast"); - bool typeIsRange = static_cast(mContent)->GetType() == - NS_FORM_INPUT_RANGE; - MOZ_ASSERT(typeIsRange || aAttribute == nsGkAtoms::value, "why?"); - if (typeIsRange) { - UpdateThumbPositionForValueChange(); + if (aNameSpaceID == kNameSpaceID_None) { + if (aAttribute == nsGkAtoms::value || + aAttribute == nsGkAtoms::min || + aAttribute == nsGkAtoms::max || + aAttribute == nsGkAtoms::step) { + // We want to update the position of the thumb, except in one special + // case: If the value attribute is being set, it is possible that we are + // in the middle of a type change away from type=range, under the + // SetAttr(..., nsGkAtoms::value, ...) call in nsHTMLInputElement:: + // HandleTypeChange. In that case the nsHTMLInputElement's type will + // already have changed, and if we call UpdateThumbPositionForValueChange() + // we'll fail the asserts under that call that check the type of our + // nsHTMLInputElement. Given that we're changing away from being a range + // and this frame will shortly be destroyed, there's no point in calling + // UpdateThumbPositionForValueChange() anyway. + MOZ_ASSERT(mContent->IsHTML(nsGkAtoms::input), "bad cast"); + bool typeIsRange = static_cast(mContent)->GetType() == + NS_FORM_INPUT_RANGE; + MOZ_ASSERT(typeIsRange || aAttribute == nsGkAtoms::value, "why?"); + if (typeIsRange) { + UpdateThumbPositionForValueChange(); + } + } else if (aAttribute == nsGkAtoms::orient) { + PresContext()->PresShell()->FrameNeedsReflow(this, nsIPresShell::eResize, + NS_FRAME_IS_DIRTY); } } @@ -554,7 +558,9 @@ nsRangeFrame::GetPrefWidth(nsRenderingContext *aRenderingContext) bool nsRangeFrame::IsHorizontal(const nsSize *aFrameSizeOverride) const { - return true; // until we decide how to support vertical range (bug 840820) + nsHTMLInputElement* element = static_cast(mContent); + return !element->AttrValueIs(kNameSpaceID_None, nsGkAtoms::orient, + nsGkAtoms::vertical, eCaseMatters); } double diff --git a/layout/style/forms.css b/layout/style/forms.css index 070f343abf14..52cd53a29cf8 100644 --- a/layout/style/forms.css +++ b/layout/style/forms.css @@ -717,9 +717,9 @@ meter { background: -moz-linear-gradient(top, #f77, #f77, #fcc 20%, #d44 45%, #d44 55%); } -input[type="range"] { +input[type=range] { -moz-appearance: none; - display: inline-block !important; + display: inline-block; width: 12em; height: 1.3em; margin: 0 0.7em; @@ -732,6 +732,11 @@ input[type="range"] { -moz-user-select: none ! important; } +input[type=range][orient=vertical] { + width: 1.3em; + height: 12em; +} + /** * Layout handles positioning of this pseudo-element specially (so that content * authors can concentrate on styling the thumb without worrying about the @@ -741,7 +746,7 @@ input[type="range"] { * If content authors want to have a vertical range, they will also need to * set the width/height of this pseudo-element. */ -::-moz-range-track { +input[type=range]::-moz-range-track { /* Prevent styling that would change the type of frame we construct. */ display: inline-block !important; float: none !important; @@ -756,13 +761,22 @@ input[type="range"] { -moz-user-select: none ! important; } +input[type=range][orient=vertical]::-moz-range-track { + border-top: none; + border-bottom: none; + border-left: solid 0.1em lightgrey; + border-right: solid 0.1em lightgrey; + width: 0.2em; + height: 100%; +} + /** * Layout handles positioning of this pseudo-element specially (so that content * authors can concentrate on styling the thumb without worrying about the * logic to position it). Specifically the 'margin', 'top' and 'left' * properties are ignored. */ -::-moz-range-thumb { +input[type=range]::-moz-range-thumb { /* Prevent styling that would change the type of frame we construct. */ display: inline-block !important; float: none !important; From 98f3b4f04febd55532185eb36a4772602a097170 Mon Sep 17 00:00:00 2001 From: Zack Weinberg Date: Tue, 26 Mar 2013 10:21:34 -0400 Subject: [PATCH 013/129] Bug 849633: change entity names for messages changed in bug 847181. r=tchevalier,ehsan --- .../en-US/chrome/layout/printing.properties | 55 ++++++++++--------- layout/printing/nsPrintEngine.cpp | 34 ++++++------ 2 files changed, 48 insertions(+), 41 deletions(-) diff --git a/dom/locales/en-US/chrome/layout/printing.properties b/dom/locales/en-US/chrome/layout/printing.properties index eea1bf3151dd..e3b2d84146c3 100644 --- a/dom/locales/en-US/chrome/layout/printing.properties +++ b/dom/locales/en-US/chrome/layout/printing.properties @@ -26,31 +26,36 @@ fileConfirm.exists=%S already exists.\nDo you want to replace it? print_error_dialog_title=Printer Error printpreview_error_dialog_title=Print Preview Error -# Print error codes. -#LOCALIZATION NOTE: Some of these are generic error codes which you may have -# already translated a generic error message for. Please do not reuse that -# error message in this context; we want to be more specific when we know -# the error has to do with printing. +# Printing error messages. +#LOCALIZATION NOTE: Some of these messages come in pairs, one +# for printing and one for print previewing. You can remove that +# distinction in your language by removing the entity with the _PP +# suffix; then the entity without a suffix will be used for both. +# You can also add that distinction to any of the messages that don't +# already have it by adding a new entity with a _PP suffix. # -# Any of these messages can be made print-preview-specific by adding a -# _PP suffix to the label. -NS_ERROR_FAILURE=An error occurred while printing. +# For instance, if you delete PERR_GFX_PRINTER_DOC_IS_BUSY_PP, then +# the PERR_GFX_PRINTER_DOC_IS_BUSY message will be used for that error +# condition when print previewing as well as when printing. If you +# add PERR_FAILURE_PP, then PERR_FAILURE will only be used when +# printing, and PERR_FAILURE_PP will be used under the same conditions +# when print previewing. +# +PERR_FAILURE=An error occurred while printing. -NS_ERROR_ABORT=The print job was aborted, or canceled. -NS_ERROR_NOT_AVAILABLE=Some printing functionality is not currently available. -NS_ERROR_NOT_IMPLEMENTED=Some printing functionality is not implemented yet. -NS_ERROR_OUT_OF_MEMORY=There is not enough free memory to print. -NS_ERROR_UNEXPECTED=There was an unexpected problem while printing. +PERR_ABORT=The print job was aborted, or canceled. +PERR_NOT_AVAILABLE=Some printing functionality is not currently available. +PERR_NOT_IMPLEMENTED=Some printing functionality is not implemented yet. +PERR_OUT_OF_MEMORY=There is not enough free memory to print. +PERR_UNEXPECTED=There was an unexpected problem while printing. -NS_ERROR_GFX_PRINTER_NO_PRINTER_AVAILABLE=No printers available. -NS_ERROR_GFX_PRINTER_NO_PRINTER_AVAILABLE_PP=No printers available, cannot show print preview. -NS_ERROR_GFX_PRINTER_NAME_NOT_FOUND=The selected printer could not be found. -NS_ERROR_GFX_PRINTER_COULD_NOT_OPEN_FILE=Failed to open output file for print to file. -NS_ERROR_GFX_PRINTER_STARTDOC=Printing failed while starting the print job. -NS_ERROR_GFX_PRINTER_ENDDOC=Printing failed while completing the print job. -NS_ERROR_GFX_PRINTER_STARTPAGE=Printing failed while starting a new page. -NS_ERROR_GFX_PRINTER_DOC_IS_BUSY=Cannot print this document yet, it is still being loaded. -NS_ERROR_GFX_PRINTER_DOC_IS_BUSY_PP=Cannot print-preview this document yet, it is still being loaded. -NS_ERROR_GFX_PRINTER_NO_XUL=Printing XUL documents is not supported. - -# EOF. +PERR_GFX_PRINTER_NO_PRINTER_AVAILABLE=No printers available. +PERR_GFX_PRINTER_NO_PRINTER_AVAILABLE_PP=No printers available, cannot show print preview. +PERR_GFX_PRINTER_NAME_NOT_FOUND=The selected printer could not be found. +PERR_GFX_PRINTER_COULD_NOT_OPEN_FILE=Failed to open output file for print to file. +PERR_GFX_PRINTER_STARTDOC=Printing failed while starting the print job. +PERR_GFX_PRINTER_ENDDOC=Printing failed while completing the print job. +PERR_GFX_PRINTER_STARTPAGE=Printing failed while starting a new page. +PERR_GFX_PRINTER_DOC_IS_BUSY=Cannot print this document yet, it is still being loaded. +PERR_GFX_PRINTER_DOC_IS_BUSY_PP=Cannot print-preview this document yet, it is still being loaded. +PERR_GFX_PRINTER_NO_XUL=Printing XUL documents is not supported. diff --git a/layout/printing/nsPrintEngine.cpp b/layout/printing/nsPrintEngine.cpp index 11dea7e6d1a6..6e51444f63e5 100644 --- a/layout/printing/nsPrintEngine.cpp +++ b/layout/printing/nsPrintEngine.cpp @@ -1584,26 +1584,28 @@ nsPrintEngine::ShowPrintErrorDialog(nsresult aPrintError, bool aIsPrinting) switch(aPrintError) { -#define NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(nserr) case nserr: stringName.AssignLiteral(#nserr); break; +#define ENTITY_FOR_ERROR(label) \ + case NS_ERROR_##label: stringName.AssignLiteral("PERR_" #label); break - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_NO_PRINTER_AVAILABLE) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_NAME_NOT_FOUND) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_COULD_NOT_OPEN_FILE) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_STARTDOC) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_ENDDOC) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_STARTPAGE) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_DOC_IS_BUSY) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_GFX_PRINTER_NO_XUL) // bug 136185 / bug 240490 + ENTITY_FOR_ERROR(GFX_PRINTER_NO_PRINTER_AVAILABLE); + ENTITY_FOR_ERROR(GFX_PRINTER_NAME_NOT_FOUND); + ENTITY_FOR_ERROR(GFX_PRINTER_COULD_NOT_OPEN_FILE); + ENTITY_FOR_ERROR(GFX_PRINTER_STARTDOC); + ENTITY_FOR_ERROR(GFX_PRINTER_ENDDOC); + ENTITY_FOR_ERROR(GFX_PRINTER_STARTPAGE); + ENTITY_FOR_ERROR(GFX_PRINTER_DOC_IS_BUSY); + ENTITY_FOR_ERROR(GFX_PRINTER_NO_XUL); // bug 136185 / bug 240490 + + ENTITY_FOR_ERROR(ABORT); + ENTITY_FOR_ERROR(NOT_AVAILABLE); + ENTITY_FOR_ERROR(NOT_IMPLEMENTED); + ENTITY_FOR_ERROR(OUT_OF_MEMORY); + ENTITY_FOR_ERROR(UNEXPECTED); - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_ABORT) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_NOT_AVAILABLE) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_NOT_IMPLEMENTED) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_OUT_OF_MEMORY) - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_UNEXPECTED) default: - NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG(NS_ERROR_FAILURE) + ENTITY_FOR_ERROR(FAILURE); -#undef NS_ERROR_TO_LOCALIZED_PRINT_ERROR_MSG +#undef ENTITY_FOR_ERROR } if (!aIsPrinting) { From 5d4b614e82eec09aba90ea783d16e12c3885333d Mon Sep 17 00:00:00 2001 From: "Brian R. Bondy" Date: Tue, 26 Mar 2013 10:40:01 -0400 Subject: [PATCH 014/129] Bug 825153 - WMF support in WinVista. r=padenot --- content/media/wmf/WMFDecoder.cpp | 22 ++++-------------- content/media/wmf/WMFUtils.cpp | 40 ++++++++++++++++++++------------ 2 files changed, 30 insertions(+), 32 deletions(-) diff --git a/content/media/wmf/WMFDecoder.cpp b/content/media/wmf/WMFDecoder.cpp index 72a6544acb62..2cc08433e253 100644 --- a/content/media/wmf/WMFDecoder.cpp +++ b/content/media/wmf/WMFDecoder.cpp @@ -10,6 +10,9 @@ #include "WMFUtils.h" #include "MediaDecoderStateMachine.h" #include "mozilla/Preferences.h" +#include "WinUtils.h" + +using namespace mozilla::widget; namespace mozilla { @@ -86,27 +89,12 @@ WMFDecoder::UnloadDLLs() wmf::UnloadDLLs(); } -bool IsWindows7OrLater() -{ - OSVERSIONINFO versionInfo; - versionInfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFO); - if (!GetVersionEx(&versionInfo)) { - return false; - } - // Note: Win Vista = 6.0 - // Win 7 = 6.1 - // Win 8 = 6.2 - return versionInfo.dwMajorVersion > 6 || - (versionInfo.dwMajorVersion == 6 && versionInfo.dwMinorVersion >= 1); -} - /* static */ bool WMFDecoder::IsEnabled() { - // We only use WMF on Windows 7 and up, until we can properly test Vista - // and how it responds with and without the Platform Update installed. - return IsWindows7OrLater() && + // We only use WMF on Windows Vista and up + return WinUtils::GetWindowsVersion() >= WinUtils::VISTA_VERSION && Preferences::GetBool("media.windows-media-foundation.enabled"); } diff --git a/content/media/wmf/WMFUtils.cpp b/content/media/wmf/WMFUtils.cpp index 13bd8a502ffb..08319ef0681d 100644 --- a/content/media/wmf/WMFUtils.cpp +++ b/content/media/wmf/WMFUtils.cpp @@ -9,6 +9,10 @@ #include "mozilla/RefPtr.h" #include "prlog.h" #include "nsThreadUtils.h" +#include "WinUtils.h" +#include "nsWindowsHelpers.h" + +using namespace mozilla::widget; namespace mozilla { @@ -269,15 +273,15 @@ DisableBlockedDecoders() { RefPtr pluginControl; HRESULT hr = wmf::MFGetPluginControl(byRef(pluginControl)); - NS_ENSURE_TRUE(SUCCEEDED(hr), hr); + if (SUCCEEDED(hr) && pluginControl) { + hr = DisableBlockedDecoders(pluginControl, + MFT_CATEGORY_VIDEO_DECODER); + NS_ENSURE_TRUE(SUCCEEDED(hr), hr); - hr = DisableBlockedDecoders(pluginControl, - MFT_CATEGORY_VIDEO_DECODER); - NS_ENSURE_TRUE(SUCCEEDED(hr), hr); - - hr = DisableBlockedDecoders(pluginControl, - MFT_CATEGORY_AUDIO_DECODER); - NS_ENSURE_TRUE(SUCCEEDED(hr), hr); + hr = DisableBlockedDecoders(pluginControl, + MFT_CATEGORY_AUDIO_DECODER); + NS_ENSURE_TRUE(SUCCEEDED(hr), hr); + } return S_OK; } @@ -286,15 +290,15 @@ static bool sDLLsLoaded = false; static bool sFailedToLoadDlls = false; struct WMFModule { - const char* name; + const wchar_t* name; HMODULE handle; }; static WMFModule sDLLs[] = { - { "mfplat.dll", NULL }, - { "mfreadwrite.dll", NULL }, - { "propsys.dll", NULL }, - { "mf.dll", NULL } + { L"mfplat.dll", NULL }, + { L"mfreadwrite.dll", NULL }, + { L"propsys.dll", NULL }, + { L"mf.dll", NULL } }; HRESULT @@ -312,7 +316,7 @@ LoadDLLs() // Try to load all the required DLLs. uint32_t dllLength = NS_ARRAY_LENGTH(sDLLs); for (uint32_t i = 0; i < dllLength; i++) { - sDLLs[i].handle = LoadLibraryA(sDLLs[i].name); + sDLLs[i].handle = LoadLibrarySystem32(sDLLs[i].name); if (!sDLLs[i].handle) { sFailedToLoadDlls = true; NS_WARNING("Failed to load WMF DLLs"); @@ -367,9 +371,15 @@ UnloadDLLs() HRESULT MFStartup() { + const int MF_VISTA_VERSION = (0x0001 << 16 | MF_API_VERSION); + const int MF_WIN7_VERSION = (0x0002 << 16 | MF_API_VERSION); + DECL_FUNCTION_PTR(MFStartup, ULONG, DWORD); ENSURE_FUNCTION_PTR(MFStartup, Mfplat.dll) - return MFStartupPtr(MF_VERSION, MFSTARTUP_FULL); + if (WinUtils::GetWindowsVersion() == WinUtils::VISTA_VERSION) + return MFStartupPtr(MF_VISTA_VERSION, MFSTARTUP_FULL); + else + return MFStartupPtr(MF_WIN7_VERSION, MFSTARTUP_FULL); } HRESULT From 586ab0d43acccca95c6d52d95b74cc7bc514e92d Mon Sep 17 00:00:00 2001 From: Ryan VanderMeulen Date: Tue, 26 Mar 2013 10:59:53 -0400 Subject: [PATCH 015/129] Bug 851965 - Disable test on WinXP due to hangs. --- parser/htmlparser/tests/crashtests/crashtests.list | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parser/htmlparser/tests/crashtests/crashtests.list b/parser/htmlparser/tests/crashtests/crashtests.list index 09c0a101ea1b..50eb99f19bf9 100644 --- a/parser/htmlparser/tests/crashtests/crashtests.list +++ b/parser/htmlparser/tests/crashtests/crashtests.list @@ -34,7 +34,7 @@ asserts-if(Android,1) skip-if((OSX==10.7||OSX==10.8)&&browserIsRemote) load 3287 load 408939-1.html load 423373-1.html load 445171-1.html -load 460706-1.xhtml # Bug 479499 +skip-if(/^Windows\x20NT\x205\.1/.test(http.oscpu)) load 460706-1.xhtml # skip on WinXP - bug 851965 load 468538-1.xhtml load 515278-1.html load 515533-1.html From 4648337f9ea1ca4f1262bd028fe35503ef1849a2 Mon Sep 17 00:00:00 2001 From: EKR Date: Mon, 4 Mar 2013 08:51:48 -0800 Subject: [PATCH 016/129] Assert on WrapRunnableRet with NS_DISPATCH_NORMAL Bug 847439. Assert on WrapRunnableRet with NS_DISPATCH_NORMAL. r=derf,jesup --- media/mtransport/runnable_utils.h | 11 +++++++- media/mtransport/runnable_utils.py | 1 + media/mtransport/runnable_utils_generated.h | 30 +++++++++++++++++++++ 3 files changed, 41 insertions(+), 1 deletion(-) diff --git a/media/mtransport/runnable_utils.h b/media/mtransport/runnable_utils.h index b63f6f32fb74..dae107923d54 100644 --- a/media/mtransport/runnable_utils.h +++ b/media/mtransport/runnable_utils.h @@ -18,9 +18,9 @@ namespace mozilla { class runnable_args_base : public nsRunnable { public: NS_IMETHOD Run() = 0; + virtual bool returns_value() const { return false; } }; - // The generated file contains four major function templates // (in variants for arbitrary numbers of arguments up to 10, // which is why it is machine generated). The four templates @@ -54,6 +54,15 @@ static inline nsresult RUN_ON_THREAD(nsIEventTarget *thread, nsIRunnable *runnab return runnable_ref->Run(); } +static inline nsresult RUN_ON_THREAD(nsIEventTarget *thread, runnable_args_base *runnable, uint32_t flags) { + // Detect attempts to return a value when in async mode, since this + // most likely means someone is trying to assign to a heap variable + // which is now out of scope. + MOZ_ASSERT((!(runnable->returns_value()) || (flags != NS_DISPATCH_NORMAL))); + + return RUN_ON_THREAD(thread, static_cast(runnable), flags); +} + #ifdef MOZ_DEBUG #define ASSERT_ON_THREAD(t) do { \ if (t) { \ diff --git a/media/mtransport/runnable_utils.py b/media/mtransport/runnable_utils.py index 2934445bfd92..5680be453921 100644 --- a/media/mtransport/runnable_utils.py +++ b/media/mtransport/runnable_utils.py @@ -89,6 +89,7 @@ def generate_class_template(args, ret = False, member = True): else: print " runnable_args_%s_%d_ret("%(nm, args) + gen_args_type(args, member) + ", R *r) :" print " " + gen_init(args, True, member) + " {}" + print " virtual bool returns_value() const { return true; }" print print " NS_IMETHOD Run() {" if ret: diff --git a/media/mtransport/runnable_utils_generated.h b/media/mtransport/runnable_utils_generated.h index 195cf16c45b2..544ba4b03847 100644 --- a/media/mtransport/runnable_utils_generated.h +++ b/media/mtransport/runnable_utils_generated.h @@ -25,6 +25,7 @@ template class runnable_args_nm_0_ret : public runnable_ public: runnable_args_nm_0_ret(M m, R *r) : m_(m), r_(r) {} + virtual bool returns_value() const { return true; } NS_IMETHOD Run() { *r_ = m_(); @@ -61,6 +62,7 @@ template class runnable_args_m_0_ret : publi public: runnable_args_m_0_ret(C o, M m, R *r) : o_(o), m_(m), r_(r) {} + virtual bool returns_value() const { return true; } NS_IMETHOD Run() { *r_ = ((*o_).*m_)(); @@ -98,6 +100,7 @@ template class runnable_args_nm_1_ret : pub public: runnable_args_nm_1_ret(M m, A0 a0, R *r) : m_(m), r_(r), a0_(a0) {} + virtual bool returns_value() const { return true; } NS_IMETHOD Run() { *r_ = m_(a0_); @@ -136,6 +139,7 @@ template class runnable_args_m_ public: runnable_args_m_1_ret(C o, M m, A0 a0, R *r) : o_(o), m_(m), r_(r), a0_(a0) {} + virtual bool returns_value() const { return true; } NS_IMETHOD Run() { *r_ = ((*o_).*m_)(a0_); @@ -175,6 +179,7 @@ template class runnable_args_n public: runnable_args_nm_2_ret(M m, A0 a0, A1 a1, R *r) : m_(m), r_(r), a0_(a0), a1_(a1) {} + virtual bool returns_value() const { return true; } NS_IMETHOD Run() { *r_ = m_(a0_, a1_); @@ -215,6 +220,7 @@ template class run public: runnable_args_m_2_ret(C o, M m, A0 a0, A1 a1, R *r) : o_(o), m_(m), r_(r), a0_(a0), a1_(a1) {} + virtual bool returns_value() const { return true; } NS_IMETHOD Run() { *r_ = ((*o_).*m_)(a0_, a1_); @@ -256,6 +262,7 @@ template class ru public: runnable_args_nm_3_ret(M m, A0 a0, A1 a1, A2 a2, R *r) : m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2) {} + virtual bool returns_value() const { return true; } NS_IMETHOD Run() { *r_ = m_(a0_, a1_, a2_); @@ -298,6 +305,7 @@ template Date: Mon, 25 Mar 2013 16:38:18 -0400 Subject: [PATCH 017/129] Bug 825722 - Fix intermittent failure by removing SMS timestamp comparison; r=jgriffin --- .../tests/marionette/test_incoming.js | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/dom/mobilemessage/tests/marionette/test_incoming.js b/dom/mobilemessage/tests/marionette/test_incoming.js index 512d305df987..505c4718ec79 100644 --- a/dom/mobilemessage/tests/marionette/test_incoming.js +++ b/dom/mobilemessage/tests/marionette/test_incoming.js @@ -11,12 +11,11 @@ const RECEIVER = "15555215554"; // the emulator's number let sms = window.navigator.mozSms; let body = "Hello SMS world!"; -let now = Date.now(); let completed = false; runEmulatorCmd("sms send " + SENDER + " " + body, function(result) { log("Sent fake SMS: " + result); - is(result[0], "OK"); + is(result[0], "OK", "Emulator command result"); completed = true; }); @@ -24,17 +23,15 @@ sms.onreceived = function onreceived(event) { log("Received an SMS!"); let message = event.message; - ok(message instanceof MozSmsMessage); + ok(message instanceof MozSmsMessage, "Message is instanceof MozSmsMessage"); - is(message.delivery, "received"); - is(message.deliveryStatus, "success"); - is(message.sender, SENDER); - is(message.receiver, RECEIVER); - is(message.body, body); - is(message.messageClass, "normal"); - ok(message.timestamp instanceof Date); - // SMSC timestamp is in seconds. - ok(Math.floor(message.timestamp.getTime() / 1000) >= Math.floor(now / 1000)); + is(message.delivery, "received", "Message delivery"); + is(message.deliveryStatus, "success", "Delivery status"); + is(message.sender, SENDER, "Message sender"); + is(message.receiver, RECEIVER, "Message receiver"); + is(message.body, body, "Message body"); + is(message.messageClass, "normal", "Message class"); + ok(message.timestamp instanceof Date, "Message timestamp is a date"); cleanUp(); }; From 2b732795540fc40523c7415d00b3c1130e8815ce Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Tue, 26 Mar 2013 11:31:53 -0400 Subject: [PATCH 018/129] Bug 848796 part 1. Rename nsXULDocument to mozilla::dom::XULDocument. r=ms2ger --HG-- rename : content/xul/document/src/nsXULDocument.cpp => content/xul/document/src/XULDocument.cpp rename : content/xul/document/src/nsXULDocument.h => content/xul/document/src/XULDocument.h --- .gdbinit | 2 +- browser/components/nsBrowserGlue.js | 2 +- .../browser/browser_toolbar_migration.js | 2 +- caps/src/nsScriptSecurityManager.cpp | 2 +- content/base/src/nsCCUncollectableMarker.cpp | 4 +- content/base/src/nsDocument.cpp | 2 +- content/xul/content/src/nsXULElement.cpp | 11 +- content/xul/content/src/nsXULElement.h | 8 +- content/xul/document/src/Makefile.in | 2 +- .../{nsXULDocument.cpp => XULDocument.cpp} | 512 +++++++++--------- .../src/{nsXULDocument.h => XULDocument.h} | 76 +-- .../document/src/nsXULPrototypeDocument.cpp | 5 +- .../xul/document/src/nsXULPrototypeDocument.h | 15 +- xpcom/base/ErrorList.h | 2 +- 14 files changed, 335 insertions(+), 310 deletions(-) rename content/xul/document/src/{nsXULDocument.cpp => XULDocument.cpp} (90%) rename content/xul/document/src/{nsXULDocument.h => XULDocument.h} (92%) diff --git a/.gdbinit b/.gdbinit index 3f33205530b4..22190e3ce713 100644 --- a/.gdbinit +++ b/.gdbinit @@ -88,7 +88,7 @@ def pa end # define a "pxul" command to display the type of a XUL element from -# an nsXULDocument* pointer. +# an nsXULElement* pointer. def pxul set $p = $arg0 print $p->mNodeInfo.mRawPtr->mInner.mName->mStaticAtom->mString diff --git a/browser/components/nsBrowserGlue.js b/browser/components/nsBrowserGlue.js index 80b55fdd4ed1..e0331e8203b1 100644 --- a/browser/components/nsBrowserGlue.js +++ b/browser/components/nsBrowserGlue.js @@ -1398,7 +1398,7 @@ BrowserGlue.prototype = { } // Add the entry to the persisted set for this document if it's not there. - // This code is mostly borrowed from nsXULDocument::Persist. + // This code is mostly borrowed from XULDocument::Persist. let docURL = aSource.ValueUTF8.split("#")[0]; let docResource = this._rdf.GetResource(docURL); let persistResource = this._rdf.GetResource("http://home.netscape.com/NC-rdf#persist"); diff --git a/browser/components/places/tests/browser/browser_toolbar_migration.js b/browser/components/places/tests/browser/browser_toolbar_migration.js index d2b893eb631e..c344aa1c1941 100644 --- a/browser/components/places/tests/browser/browser_toolbar_migration.js +++ b/browser/components/places/tests/browser/browser_toolbar_migration.js @@ -19,7 +19,7 @@ let localStore = { delete this.toolbar; let toolbar = this.RDF.GetResource(BROWSER_URL + "#PersonalToolbar"); // Add the entry to the persisted set for this document if it's not there. - // See nsXULDocument::Persist. + // See XULDocument::Persist. let doc = this.RDF.GetResource(BROWSER_URL); let persist = this.RDF.GetResource("http://home.netscape.com/NC-rdf#persist"); if (!this.store.HasAssertion(doc, persist, toolbar, true)) { diff --git a/caps/src/nsScriptSecurityManager.cpp b/caps/src/nsScriptSecurityManager.cpp index b224030c453a..3cf6bbd527f2 100644 --- a/caps/src/nsScriptSecurityManager.cpp +++ b/caps/src/nsScriptSecurityManager.cpp @@ -330,7 +330,7 @@ nsScriptSecurityManager::GetChannelPrincipal(nsIChannel* aChannel, } // OK, get the principal from the URI. Make sure this does the same thing - // as nsDocument::Reset and nsXULDocument::StartDocumentLoad. + // as nsDocument::Reset and XULDocument::StartDocumentLoad. nsCOMPtr uri; nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri)); NS_ENSURE_SUCCESS(rv, rv); diff --git a/content/base/src/nsCCUncollectableMarker.cpp b/content/base/src/nsCCUncollectableMarker.cpp index 7666eae3e47e..9cd88eda11c8 100644 --- a/content/base/src/nsCCUncollectableMarker.cpp +++ b/content/base/src/nsCCUncollectableMarker.cpp @@ -9,7 +9,7 @@ #include "nsServiceManagerUtils.h" #include "nsIContentViewer.h" #include "nsIDocument.h" -#include "nsXULDocument.h" +#include "XULDocument.h" #include "nsIWindowMediator.h" #include "nsPIDOMWindow.h" #include "nsIWebNavigation.h" @@ -425,7 +425,7 @@ TraceActiveWindowGlobal(const uint64_t& aId, nsGlobalWindow*& aWindow, void* aCl #ifdef MOZ_XUL nsIDocument* doc = aWindow->GetExtantDoc(); if (doc && doc->IsXUL()) { - nsXULDocument* xulDoc = static_cast(doc); + XULDocument* xulDoc = static_cast(doc); xulDoc->TraceProtos(closure->mTrc, closure->mGCNumber); } #endif diff --git a/content/base/src/nsDocument.cpp b/content/base/src/nsDocument.cpp index 5ae71c66d49e..b671bb43b5eb 100644 --- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -1945,7 +1945,7 @@ nsDocument::Reset(nsIChannel* aChannel, nsILoadGroup* aLoadGroup) nsCOMPtr uri; nsCOMPtr principal; if (aChannel) { - // Note: this code is duplicated in nsXULDocument::StartDocumentLoad and + // Note: this code is duplicated in XULDocument::StartDocumentLoad and // nsScriptSecurityManager::GetChannelPrincipal. // Note: this should match nsDocShell::OnLoadingSite NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri)); diff --git a/content/xul/content/src/nsXULElement.cpp b/content/xul/content/src/nsXULElement.cpp index 6d907c483ab8..bbe428c07f4b 100644 --- a/content/xul/content/src/nsXULElement.cpp +++ b/content/xul/content/src/nsXULElement.cpp @@ -65,7 +65,7 @@ #include "nsXULControllers.h" #include "nsIBoxObject.h" #include "nsPIBoxObject.h" -#include "nsXULDocument.h" +#include "XULDocument.h" #include "nsXULPopupListener.h" #include "nsRuleWalker.h" #include "nsIDOMCSSStyleDeclaration.h" @@ -106,6 +106,7 @@ #include "mozilla/dom/XULElementBinding.h" using namespace mozilla; +using namespace mozilla::dom; //---------------------------------------------------------------------- @@ -436,7 +437,7 @@ nsXULElement::GetElementsByAttribute(const nsAString& aAttribute, void* attrValue = new nsString(aValue); nsRefPtr list = new nsContentList(this, - nsXULDocument::MatchAttribute, + XULDocument::MatchAttribute, nsContentUtils::DestroyMatchString, attrValue, true, @@ -478,7 +479,7 @@ nsXULElement::GetElementsByAttributeNS(const nsAString& aNamespaceURI, void* attrValue = new nsString(aValue); nsRefPtr list = new nsContentList(this, - nsXULDocument::MatchAttribute, + XULDocument::MatchAttribute, nsContentUtils::DestroyMatchString, attrValue, true, @@ -2492,7 +2493,7 @@ nsXULPrototypeScript::DeserializeOutOfLine(nsIObjectInputStream* aInput, if (mSrcURI) { // NB: we must check the XUL script cache early, to avoid // multiple deserialization attempts for a given script. - // Note that nsXULDocument::LoadScript + // Note that XULDocument::LoadScript // checks the XUL script cache too, in order to handle the // serialization case. // @@ -2600,7 +2601,7 @@ nsXULPrototypeScript::Compile(const PRUnichar* aText, // protodoc's? // If we start using the protodoc's, make sure // the DowngradePrincipalIfNeeded stuff in - // nsXULDocument::OnStreamComplete still works! + // XULDocument::OnStreamComplete still works! aDocument->NodePrincipal(), urlspec.get(), aLineNo, diff --git a/content/xul/content/src/nsXULElement.h b/content/xul/content/src/nsXULElement.h index 3f06e253e80e..b40353373d85 100644 --- a/content/xul/content/src/nsXULElement.h +++ b/content/xul/content/src/nsXULElement.h @@ -199,7 +199,11 @@ public: nsXULPrototypeAttribute* mAttributes; // [OWNER] }; -class nsXULDocument; +namespace mozilla { +namespace dom { +class XULDocument; +} // namespace dom +} // namespace mozilla class nsXULPrototypeScript : public nsXULPrototypeNode { @@ -242,7 +246,7 @@ public: uint32_t mLineNo; bool mSrcLoading; bool mOutOfLine; - nsXULDocument* mSrcLoadWaiters; // [OWNER] but not COMPtr + mozilla::dom::XULDocument* mSrcLoadWaiters; // [OWNER] but not COMPtr uint32_t mLangVersion; private: JSScript* mScriptObject; diff --git a/content/xul/document/src/Makefile.in b/content/xul/document/src/Makefile.in index 81d64493944c..bcb57186729c 100644 --- a/content/xul/document/src/Makefile.in +++ b/content/xul/document/src/Makefile.in @@ -20,7 +20,7 @@ ifdef MOZ_XUL CPPSRCS += \ nsXULCommandDispatcher.cpp \ nsXULContentSink.cpp \ - nsXULDocument.cpp \ + XULDocument.cpp \ nsXULPrototypeCache.cpp \ nsXULPrototypeDocument.cpp \ $(NULL) diff --git a/content/xul/document/src/nsXULDocument.cpp b/content/xul/document/src/XULDocument.cpp similarity index 90% rename from content/xul/document/src/nsXULDocument.cpp rename to content/xul/document/src/XULDocument.cpp index bfab46e7395f..57b86b070c38 100644 --- a/content/xul/document/src/nsXULDocument.cpp +++ b/content/xul/document/src/XULDocument.cpp @@ -24,7 +24,7 @@ #include "mozilla/Util.h" // Note the ALPHABETICAL ORDERING -#include "nsXULDocument.h" +#include "XULDocument.h" #include "nsError.h" #include "nsIBoxObject.h" @@ -101,7 +101,6 @@ static NS_DEFINE_CID(kParserCID, NS_PARSER_CID); static bool IsChromeURI(nsIURI* aURI) { - // why is this check a member function of nsXULDocument? -gagan bool isChrome = false; if (NS_SUCCEEDED(aURI->SchemeIs("chrome", &isChrome)) && isChrome) return true; @@ -137,14 +136,14 @@ const uint32_t kMaxAttributeLength = 4096; // Statics // -int32_t nsXULDocument::gRefCnt = 0; +int32_t XULDocument::gRefCnt = 0; -nsIRDFService* nsXULDocument::gRDFService; -nsIRDFResource* nsXULDocument::kNC_persist; -nsIRDFResource* nsXULDocument::kNC_attribute; -nsIRDFResource* nsXULDocument::kNC_value; +nsIRDFService* XULDocument::gRDFService; +nsIRDFResource* XULDocument::kNC_persist; +nsIRDFResource* XULDocument::kNC_attribute; +nsIRDFResource* XULDocument::kNC_value; -PRLogModuleInfo* nsXULDocument::gXULLog; +PRLogModuleInfo* XULDocument::gXULLog; //---------------------------------------------------------------------- @@ -192,10 +191,12 @@ nsRefMapEntry::RemoveElement(Element* aElement) // ctors & dtors // - // NOTE! nsDocument::operator new() zeroes out all members, so - // don't bother initializing members to 0. +DOMCI_NODE_DATA(XULDocument, XULDocument) -nsXULDocument::nsXULDocument(void) +namespace mozilla { +namespace dom { + +XULDocument::XULDocument(void) : XMLDocument("application/vnd.mozilla.xul+xml"), mDocLWTheme(Doc_Theme_Uninitialized), mState(eState_Master), @@ -216,7 +217,7 @@ nsXULDocument::nsXULDocument(void) mAllowXULXBL = eTriTrue; } -nsXULDocument::~nsXULDocument() +XULDocument::~XULDocument() { NS_ASSERTION(mNextSrcLoadWaiter == nullptr, "unreferenced document still waiting for script source to load?"); @@ -239,7 +240,7 @@ nsXULDocument::~nsXULDocument() delete mTemplateBuilderTable; - Preferences::UnregisterCallback(nsXULDocument::DirectionChanged, + Preferences::UnregisterCallback(XULDocument::DirectionChanged, "intl.uidirection.", this); if (--gRefCnt == 0) { @@ -251,6 +252,9 @@ nsXULDocument::~nsXULDocument() } } +} // namespace dom +} // namespace mozilla + nsresult NS_NewXULDocument(nsIXULDocument** result) { @@ -258,7 +262,7 @@ NS_NewXULDocument(nsIXULDocument** result) if (! result) return NS_ERROR_NULL_POINTER; - nsXULDocument* doc = new nsXULDocument(); + XULDocument* doc = new XULDocument(); if (! doc) return NS_ERROR_OUT_OF_MEMORY; @@ -275,6 +279,9 @@ NS_NewXULDocument(nsIXULDocument** result) } +namespace mozilla { +namespace dom { + //---------------------------------------------------------------------- // // nsISupports interface @@ -307,9 +314,9 @@ TraverseObservers(nsIURI* aKey, nsIObserver* aData, void* aContext) return PL_DHASH_NEXT; } -NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsXULDocument, XMLDocument) +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(XULDocument, XMLDocument) NS_ASSERTION(!nsCCUncollectableMarker::InGeneration(cb, tmp->GetMarkedCCGeneration()), - "Shouldn't traverse nsXULDocument!"); + "Shouldn't traverse XULDocument!"); // XXX tmp->mForwardReferences? // XXX tmp->mContextStack? @@ -336,7 +343,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsXULDocument, XMLDocument) tmp->mPendingOverlayLoadNotifications.EnumerateRead(TraverseObservers, &cb); NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END -NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsXULDocument, XMLDocument) +NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(XULDocument, XMLDocument) delete tmp->mTemplateBuilderTable; tmp->mTemplateBuilderTable = nullptr; @@ -344,19 +351,17 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsXULDocument, XMLDocument) //XXX We should probably unlink all the objects we traverse. NS_IMPL_CYCLE_COLLECTION_UNLINK_END -NS_IMPL_ADDREF_INHERITED(nsXULDocument, XMLDocument) -NS_IMPL_RELEASE_INHERITED(nsXULDocument, XMLDocument) +NS_IMPL_ADDREF_INHERITED(XULDocument, XMLDocument) +NS_IMPL_RELEASE_INHERITED(XULDocument, XMLDocument) -DOMCI_NODE_DATA(XULDocument, nsXULDocument) - -// QueryInterface implementation for nsXULDocument -NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(nsXULDocument) - NS_DOCUMENT_INTERFACE_TABLE_BEGIN(nsXULDocument) - NS_INTERFACE_TABLE_ENTRY(nsXULDocument, nsIXULDocument) - NS_INTERFACE_TABLE_ENTRY(nsXULDocument, nsIDOMXULDocument) - NS_INTERFACE_TABLE_ENTRY(nsXULDocument, nsIStreamLoaderObserver) - NS_INTERFACE_TABLE_ENTRY(nsXULDocument, nsICSSLoaderObserver) +// QueryInterface implementation for XULDocument +NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(XULDocument) + NS_DOCUMENT_INTERFACE_TABLE_BEGIN(XULDocument) + NS_INTERFACE_TABLE_ENTRY(XULDocument, nsIXULDocument) + NS_INTERFACE_TABLE_ENTRY(XULDocument, nsIDOMXULDocument) + NS_INTERFACE_TABLE_ENTRY(XULDocument, nsIStreamLoaderObserver) + NS_INTERFACE_TABLE_ENTRY(XULDocument, nsICSSLoaderObserver) NS_OFFSET_AND_INTERFACE_TABLE_END NS_OFFSET_AND_INTERFACE_TABLE_TO_MAP_SEGUE NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(XULDocument) @@ -369,20 +374,20 @@ NS_INTERFACE_MAP_END_INHERITING(XMLDocument) // void -nsXULDocument::Reset(nsIChannel* aChannel, nsILoadGroup* aLoadGroup) +XULDocument::Reset(nsIChannel* aChannel, nsILoadGroup* aLoadGroup) { NS_NOTREACHED("Reset"); } void -nsXULDocument::ResetToURI(nsIURI* aURI, nsILoadGroup* aLoadGroup, - nsIPrincipal* aPrincipal) +XULDocument::ResetToURI(nsIURI* aURI, nsILoadGroup* aLoadGroup, + nsIPrincipal* aPrincipal) { NS_NOTREACHED("ResetToURI"); } void -nsXULDocument::SetContentType(const nsAString& aContentType) +XULDocument::SetContentType(const nsAString& aContentType) { NS_ASSERTION(aContentType.EqualsLiteral("application/vnd.mozilla.xul+xml"), "xul-documents always has content-type application/vnd.mozilla.xul+xml"); @@ -393,11 +398,11 @@ nsXULDocument::SetContentType(const nsAString& aContentType) // This is called when the master document begins loading, whether it's // being cached or not. nsresult -nsXULDocument::StartDocumentLoad(const char* aCommand, nsIChannel* aChannel, - nsILoadGroup* aLoadGroup, - nsISupports* aContainer, - nsIStreamListener **aDocListener, - bool aReset, nsIContentSink* aSink) +XULDocument::StartDocumentLoad(const char* aCommand, nsIChannel* aChannel, + nsILoadGroup* aLoadGroup, + nsISupports* aContainer, + nsIStreamListener **aDocListener, + bool aReset, nsIContentSink* aSink) { #ifdef PR_LOGGING if (PR_LOG_TEST(gXULLog, PR_LOG_WARNING)) { @@ -441,7 +446,7 @@ nsXULDocument::StartDocumentLoad(const char* aCommand, nsIChannel* aChannel, nullptr; // Same comment as nsChromeProtocolHandler::NewChannel and - // nsXULDocument::ResumeWalk + // XULDocument::ResumeWalk // - Ben Goodger // // We don't abort on failure here because there are too many valid @@ -459,7 +464,7 @@ nsXULDocument::StartDocumentLoad(const char* aCommand, nsIChannel* aChannel, if (proto) { // If we're racing with another document to load proto, wait till the // load has finished loading before trying to add cloned style sheets. - // nsXULDocument::EndLoad will call proto->NotifyLoadDone, which will + // XULDocument::EndLoad will call proto->NotifyLoadDone, which will // find all racing documents and notify them via OnPrototypeLoadDone, // which will add style sheet clones to each document. bool loaded; @@ -473,7 +478,7 @@ nsXULDocument::StartDocumentLoad(const char* aCommand, nsIChannel* aChannel, // We need a listener, even if proto is not yet loaded, in which // event the listener's OnStopRequest method does nothing, and all - // the interesting work happens below nsXULDocument::EndLoad, from + // the interesting work happens below XULDocument::EndLoad, from // the call there to mCurrentPrototype->NotifyLoadDone(). *aDocListener = new CachedChromeStreamListener(this, loaded); if (! *aDocListener) @@ -521,7 +526,7 @@ nsXULDocument::StartDocumentLoad(const char* aCommand, nsIChannel* aChannel, // This gets invoked after a prototype for this document or one of // its overlays is fully built in the content sink. void -nsXULDocument::EndLoad() +XULDocument::EndLoad() { // This can happen if an overlay fails to load if (!mCurrentPrototype) @@ -541,7 +546,7 @@ nsXULDocument::EndLoad() // If the current prototype is an overlay document (non-master prototype) // and we're filling the FastLoad disk cache, tell the cache we're done // loading it, and write the prototype. The master prototype is put into - // the cache earlier in nsXULDocument::StartDocumentLoad. + // the cache earlier in XULDocument::StartDocumentLoad. if (useXULCache && mIsWritingFastLoad && isChrome && mMasterPrototype != mCurrentPrototype) { nsXULPrototypeCache::GetInstance()->WritePrototype(mCurrentPrototype); @@ -599,7 +604,7 @@ nsXULDocument::EndLoad() } NS_IMETHODIMP -nsXULDocument::OnPrototypeLoadDone(bool aResumeWalk) +XULDocument::OnPrototypeLoadDone(bool aResumeWalk) { nsresult rv; @@ -619,7 +624,7 @@ nsXULDocument::OnPrototypeLoadDone(bool aResumeWalk) // called when an error occurs parsing a document bool -nsXULDocument::OnDocumentParserError() +XULDocument::OnDocumentParserError() { // don't report errors that are from overlays if (mCurrentPrototype && mMasterPrototype != mCurrentPrototype) { @@ -682,9 +687,9 @@ struct nsAttrNameInfo }; void -nsXULDocument::SynchronizeBroadcastListener(nsIDOMElement *aBroadcaster, - nsIDOMElement *aListener, - const nsAString &aAttr) +XULDocument::SynchronizeBroadcastListener(nsIDOMElement *aBroadcaster, + nsIDOMElement *aListener, + const nsAString &aAttr) { if (!nsContentUtils::IsSafeToRunScript()) { nsDelayedBroadcastUpdate delayedUpdate(aBroadcaster, aListener, @@ -755,9 +760,9 @@ nsXULDocument::SynchronizeBroadcastListener(nsIDOMElement *aBroadcaster, } NS_IMETHODIMP -nsXULDocument::AddBroadcastListenerFor(nsIDOMElement* aBroadcaster, - nsIDOMElement* aListener, - const nsAString& aAttr) +XULDocument::AddBroadcastListenerFor(nsIDOMElement* aBroadcaster, + nsIDOMElement* aListener, + const nsAString& aAttr) { NS_ENSURE_ARG(aBroadcaster && aListener); @@ -842,9 +847,9 @@ nsXULDocument::AddBroadcastListenerFor(nsIDOMElement* aBroadcaster, } NS_IMETHODIMP -nsXULDocument::RemoveBroadcastListenerFor(nsIDOMElement* aBroadcaster, - nsIDOMElement* aListener, - const nsAString& aAttr) +XULDocument::RemoveBroadcastListenerFor(nsIDOMElement* aBroadcaster, + nsIDOMElement* aListener, + const nsAString& aAttr) { // If we haven't added any broadcast listeners, then there sure // aren't any to remove. @@ -881,9 +886,9 @@ nsXULDocument::RemoveBroadcastListenerFor(nsIDOMElement* aBroadcaster, } nsresult -nsXULDocument::ExecuteOnBroadcastHandlerFor(nsIContent* aBroadcaster, - nsIDOMElement* aListener, - nsIAtom* aAttr) +XULDocument::ExecuteOnBroadcastHandlerFor(nsIContent* aBroadcaster, + nsIDOMElement* aListener, + nsIAtom* aAttr) { // Now we execute the onchange handler in the context of the // observer. We need to find the observer in order to @@ -941,9 +946,9 @@ nsXULDocument::ExecuteOnBroadcastHandlerFor(nsIContent* aBroadcaster, } void -nsXULDocument::AttributeWillChange(nsIDocument* aDocument, - Element* aElement, int32_t aNameSpaceID, - nsIAtom* aAttribute, int32_t aModType) +XULDocument::AttributeWillChange(nsIDocument* aDocument, + Element* aElement, int32_t aNameSpaceID, + nsIAtom* aAttribute, int32_t aModType) { NS_ABORT_IF_FALSE(aElement, "Null content!"); NS_PRECONDITION(aAttribute, "Must have an attribute that's changing!"); @@ -959,9 +964,9 @@ nsXULDocument::AttributeWillChange(nsIDocument* aDocument, } void -nsXULDocument::AttributeChanged(nsIDocument* aDocument, - Element* aElement, int32_t aNameSpaceID, - nsIAtom* aAttribute, int32_t aModType) +XULDocument::AttributeChanged(nsIDocument* aDocument, + Element* aElement, int32_t aNameSpaceID, + nsIAtom* aAttribute, int32_t aModType) { NS_ASSERTION(aDocument == this, "unexpected doc"); @@ -1056,10 +1061,10 @@ nsXULDocument::AttributeChanged(nsIDocument* aDocument, } void -nsXULDocument::ContentAppended(nsIDocument* aDocument, - nsIContent* aContainer, - nsIContent* aFirstNewContent, - int32_t aNewIndexInContainer) +XULDocument::ContentAppended(nsIDocument* aDocument, + nsIContent* aContainer, + nsIContent* aFirstNewContent, + int32_t aNewIndexInContainer) { NS_ASSERTION(aDocument == this, "unexpected doc"); @@ -1075,10 +1080,10 @@ nsXULDocument::ContentAppended(nsIDocument* aDocument, } void -nsXULDocument::ContentInserted(nsIDocument* aDocument, - nsIContent* aContainer, - nsIContent* aChild, - int32_t aIndexInContainer) +XULDocument::ContentInserted(nsIDocument* aDocument, + nsIContent* aContainer, + nsIContent* aChild, + int32_t aIndexInContainer) { NS_ASSERTION(aDocument == this, "unexpected doc"); @@ -1089,11 +1094,11 @@ nsXULDocument::ContentInserted(nsIDocument* aDocument, } void -nsXULDocument::ContentRemoved(nsIDocument* aDocument, - nsIContent* aContainer, - nsIContent* aChild, - int32_t aIndexInContainer, - nsIContent* aPreviousSibling) +XULDocument::ContentRemoved(nsIDocument* aDocument, + nsIContent* aContainer, + nsIContent* aChild, + int32_t aIndexInContainer, + nsIContent* aPreviousSibling) { NS_ASSERTION(aDocument == this, "unexpected doc"); @@ -1109,8 +1114,8 @@ nsXULDocument::ContentRemoved(nsIDocument* aDocument, // void -nsXULDocument::GetElementsForID(const nsAString& aID, - nsCOMArray& aElements) +XULDocument::GetElementsForID(const nsAString& aID, + nsCOMArray& aElements) { aElements.Clear(); @@ -1125,7 +1130,7 @@ nsXULDocument::GetElementsForID(const nsAString& aID, } nsresult -nsXULDocument::AddForwardReference(nsForwardReference* aRef) +XULDocument::AddForwardReference(nsForwardReference* aRef) { if (mResolutionPhase < aRef->GetPhase()) { if (!mForwardReferences.AppendElement(aRef)) { @@ -1142,7 +1147,7 @@ nsXULDocument::AddForwardReference(nsForwardReference* aRef) } nsresult -nsXULDocument::ResolveForwardReferences() +XULDocument::ResolveForwardReferences() { if (mResolutionPhase == nsForwardReference::eDone) return NS_OK; @@ -1185,7 +1190,7 @@ nsXULDocument::ResolveForwardReferences() if (mResolutionPhase == nsForwardReference::eStart) { // Resolve() loaded a dynamic overlay, - // (see nsXULDocument::LoadOverlayInternal()). + // (see XULDocument::LoadOverlayInternal()). // Return for now, we will be called again. return NS_OK; } @@ -1201,7 +1206,7 @@ nsXULDocument::ResolveForwardReferences() } NS_IMETHODIMP -nsXULDocument::GetScriptGlobalObjectOwner(nsIScriptGlobalObjectOwner** aGlobalOwner) +XULDocument::GetScriptGlobalObjectOwner(nsIScriptGlobalObjectOwner** aGlobalOwner) { NS_IF_ADDREF(*aGlobalOwner = mMasterPrototype); return NS_OK; @@ -1213,9 +1218,9 @@ nsXULDocument::GetScriptGlobalObjectOwner(nsIScriptGlobalObjectOwner** aGlobalOw // NS_IMETHODIMP -nsXULDocument::GetElementsByAttribute(const nsAString& aAttribute, - const nsAString& aValue, - nsIDOMNodeList** aReturn) +XULDocument::GetElementsByAttribute(const nsAString& aAttribute, + const nsAString& aValue, + nsIDOMNodeList** aReturn) { nsCOMPtr attrAtom(do_GetAtom(aAttribute)); NS_ENSURE_TRUE(attrAtom, NS_ERROR_OUT_OF_MEMORY); @@ -1235,10 +1240,10 @@ nsXULDocument::GetElementsByAttribute(const nsAString& aAttribute, } NS_IMETHODIMP -nsXULDocument::GetElementsByAttributeNS(const nsAString& aNamespaceURI, - const nsAString& aAttribute, - const nsAString& aValue, - nsIDOMNodeList** aReturn) +XULDocument::GetElementsByAttributeNS(const nsAString& aNamespaceURI, + const nsAString& aAttribute, + const nsAString& aValue, + nsIDOMNodeList** aReturn) { nsCOMPtr attrAtom(do_GetAtom(aAttribute)); NS_ENSURE_TRUE(attrAtom, NS_ERROR_OUT_OF_MEMORY); @@ -1267,8 +1272,8 @@ nsXULDocument::GetElementsByAttributeNS(const nsAString& aNamespaceURI, } NS_IMETHODIMP -nsXULDocument::Persist(const nsAString& aID, - const nsAString& aAttr) +XULDocument::Persist(const nsAString& aID, + const nsAString& aAttr) { // If we're currently reading persisted attributes out of the // localstore, _don't_ re-enter and try to set them again! @@ -1317,8 +1322,8 @@ nsXULDocument::Persist(const nsAString& aID, } nsresult -nsXULDocument::Persist(nsIContent* aElement, int32_t aNameSpaceID, - nsIAtom* aAttribute) +XULDocument::Persist(nsIContent* aElement, int32_t aNameSpaceID, + nsIAtom* aAttribute) { // For non-chrome documents, persistance is simply broken if (!nsContentUtils::IsSystemPrincipal(NodePrincipal())) @@ -1424,8 +1429,8 @@ nsXULDocument::Persist(nsIContent* aElement, int32_t aNameSpaceID, nsresult -nsXULDocument::GetViewportSize(int32_t* aWidth, - int32_t* aHeight) +XULDocument::GetViewportSize(int32_t* aWidth, + int32_t* aHeight) { *aWidth = *aHeight = 0; @@ -1446,7 +1451,7 @@ nsXULDocument::GetViewportSize(int32_t* aWidth, } NS_IMETHODIMP -nsXULDocument::GetWidth(int32_t* aWidth) +XULDocument::GetWidth(int32_t* aWidth) { NS_ENSURE_ARG_POINTER(aWidth); @@ -1455,7 +1460,7 @@ nsXULDocument::GetWidth(int32_t* aWidth) } NS_IMETHODIMP -nsXULDocument::GetHeight(int32_t* aHeight) +XULDocument::GetHeight(int32_t* aHeight) { NS_ENSURE_ARG_POINTER(aHeight); @@ -1469,7 +1474,7 @@ nsXULDocument::GetHeight(int32_t* aHeight) // NS_IMETHODIMP -nsXULDocument::GetPopupNode(nsIDOMNode** aNode) +XULDocument::GetPopupNode(nsIDOMNode** aNode) { *aNode = nullptr; @@ -1492,7 +1497,7 @@ nsXULDocument::GetPopupNode(nsIDOMNode** aNode) } NS_IMETHODIMP -nsXULDocument::SetPopupNode(nsIDOMNode* aNode) +XULDocument::SetPopupNode(nsIDOMNode* aNode) { if (aNode) { // only allow real node objects @@ -1510,7 +1515,7 @@ nsXULDocument::SetPopupNode(nsIDOMNode* aNode) // Returns the rangeOffset element from the XUL Popup Manager. This is for // chrome callers only. NS_IMETHODIMP -nsXULDocument::GetPopupRangeParent(nsIDOMNode** aRangeParent) +XULDocument::GetPopupRangeParent(nsIDOMNode** aRangeParent) { NS_ENSURE_ARG_POINTER(aRangeParent); *aRangeParent = nullptr; @@ -1533,7 +1538,7 @@ nsXULDocument::GetPopupRangeParent(nsIDOMNode** aRangeParent) // Returns the rangeOffset element from the XUL Popup Manager. We check the // rangeParent to determine if the caller has rights to access to the data. NS_IMETHODIMP -nsXULDocument::GetPopupRangeOffset(int32_t* aRangeOffset) +XULDocument::GetPopupRangeOffset(int32_t* aRangeOffset) { NS_ENSURE_ARG_POINTER(aRangeOffset); @@ -1553,7 +1558,7 @@ nsXULDocument::GetPopupRangeOffset(int32_t* aRangeOffset) } NS_IMETHODIMP -nsXULDocument::GetTooltipNode(nsIDOMNode** aNode) +XULDocument::GetTooltipNode(nsIDOMNode** aNode) { *aNode = nullptr; @@ -1568,7 +1573,7 @@ nsXULDocument::GetTooltipNode(nsIDOMNode** aNode) } NS_IMETHODIMP -nsXULDocument::SetTooltipNode(nsIDOMNode* aNode) +XULDocument::SetTooltipNode(nsIDOMNode* aNode) { // do nothing return NS_OK; @@ -1576,7 +1581,7 @@ nsXULDocument::SetTooltipNode(nsIDOMNode* aNode) NS_IMETHODIMP -nsXULDocument::GetCommandDispatcher(nsIDOMXULCommandDispatcher** aTracker) +XULDocument::GetCommandDispatcher(nsIDOMXULCommandDispatcher** aTracker) { *aTracker = mCommandDispatcher; NS_IF_ADDREF(*aTracker); @@ -1584,7 +1589,7 @@ nsXULDocument::GetCommandDispatcher(nsIDOMXULCommandDispatcher** aTracker) } Element* -nsXULDocument::GetElementById(const nsAString& aId) +XULDocument::GetElementById(const nsAString& aId) { if (!CheckGetElementByIdArg(aId)) return nullptr; @@ -1606,7 +1611,7 @@ nsXULDocument::GetElementById(const nsAString& aId) } nsresult -nsXULDocument::AddElementToDocumentPre(Element* aElement) +XULDocument::AddElementToDocumentPre(Element* aElement) { // Do a bunch of work that's necessary when an element gets added // to the XUL Document. @@ -1653,7 +1658,7 @@ nsXULDocument::AddElementToDocumentPre(Element* aElement) } nsresult -nsXULDocument::AddElementToDocumentPost(Element* aElement) +XULDocument::AddElementToDocumentPost(Element* aElement) { // We need to pay special attention to the keyset tag to set up a listener if (aElement->NodeInfo()->Equals(nsGkAtoms::keyset, kNameSpaceID_XUL)) { @@ -1688,7 +1693,7 @@ nsXULDocument::AddElementToDocumentPost(Element* aElement) } NS_IMETHODIMP -nsXULDocument::AddSubtreeToDocument(nsIContent* aContent) +XULDocument::AddSubtreeToDocument(nsIContent* aContent) { NS_ASSERTION(aContent->GetCurrentDoc() == this, "Element not in doc!"); // From here on we only care about elements. @@ -1717,7 +1722,7 @@ nsXULDocument::AddSubtreeToDocument(nsIContent* aContent) } NS_IMETHODIMP -nsXULDocument::RemoveSubtreeFromDocument(nsIContent* aContent) +XULDocument::RemoveSubtreeFromDocument(nsIContent* aContent) { // From here on we only care about elements. if (!aContent->IsElement()) { @@ -1781,8 +1786,8 @@ nsXULDocument::RemoveSubtreeFromDocument(nsIContent* aContent) } NS_IMETHODIMP -nsXULDocument::SetTemplateBuilderFor(nsIContent* aContent, - nsIXULTemplateBuilder* aBuilder) +XULDocument::SetTemplateBuilderFor(nsIContent* aContent, + nsIXULTemplateBuilder* aBuilder) { if (! mTemplateBuilderTable) { if (!aBuilder) { @@ -1803,8 +1808,8 @@ nsXULDocument::SetTemplateBuilderFor(nsIContent* aContent, } NS_IMETHODIMP -nsXULDocument::GetTemplateBuilderFor(nsIContent* aContent, - nsIXULTemplateBuilder** aResult) +XULDocument::GetTemplateBuilderFor(nsIContent* aContent, + nsIXULTemplateBuilder** aResult) { if (mTemplateBuilderTable) { mTemplateBuilderTable->Get(aContent, aResult); @@ -1825,7 +1830,7 @@ GetRefMapAttribute(Element* aElement, nsAutoString* aValue) } nsresult -nsXULDocument::AddElementToRefMap(Element* aElement) +XULDocument::AddElementToRefMap(Element* aElement) { // Look at the element's 'ref' attribute, and if set, // add an entry in the resource-to-element map to the element. @@ -1843,7 +1848,7 @@ nsXULDocument::AddElementToRefMap(Element* aElement) } void -nsXULDocument::RemoveElementFromRefMap(Element* aElement) +XULDocument::RemoveElementFromRefMap(Element* aElement) { // Remove the element from the resource-to-element map. nsAutoString value; @@ -1864,7 +1869,7 @@ nsXULDocument::RemoveElementFromRefMap(Element* aElement) // nsresult -nsXULDocument::Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const +XULDocument::Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const { // We don't allow cloning of a XUL document *aResult = nullptr; @@ -1878,7 +1883,7 @@ nsXULDocument::Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const // nsresult -nsXULDocument::Init() +XULDocument::Init() { mRefMap.Init(); @@ -1918,12 +1923,12 @@ nsXULDocument::Init() } } - Preferences::RegisterCallback(nsXULDocument::DirectionChanged, + Preferences::RegisterCallback(XULDocument::DirectionChanged, "intl.uidirection.", this); #ifdef PR_LOGGING if (! gXULLog) - gXULLog = PR_NewLogModule("nsXULDocument"); + gXULLog = PR_NewLogModule("XULDocument"); #endif return NS_OK; @@ -1931,7 +1936,7 @@ nsXULDocument::Init() nsresult -nsXULDocument::StartLayout(void) +XULDocument::StartLayout(void) { mMayStartLayout = true; nsCOMPtr shell = GetShell(); @@ -1963,10 +1968,10 @@ nsXULDocument::StartLayout(void) /* static */ bool -nsXULDocument::MatchAttribute(nsIContent* aContent, - int32_t aNamespaceID, - nsIAtom* aAttrName, - void* aData) +XULDocument::MatchAttribute(nsIContent* aContent, + int32_t aNamespaceID, + nsIAtom* aAttrName, + void* aData) { NS_PRECONDITION(aContent, "Must have content node to work with!"); nsString* attrValue = static_cast(aData); @@ -2003,11 +2008,11 @@ nsXULDocument::MatchAttribute(nsIContent* aContent, } nsresult -nsXULDocument::PrepareToLoad(nsISupports* aContainer, - const char* aCommand, - nsIChannel* aChannel, - nsILoadGroup* aLoadGroup, - nsIParser** aResult) +XULDocument::PrepareToLoad(nsISupports* aContainer, + const char* aCommand, + nsIChannel* aChannel, + nsILoadGroup* aLoadGroup, + nsIParser** aResult) { // Get the document's principal nsCOMPtr principal; @@ -2018,9 +2023,9 @@ nsXULDocument::PrepareToLoad(nsISupports* aContainer, nsresult -nsXULDocument::PrepareToLoadPrototype(nsIURI* aURI, const char* aCommand, - nsIPrincipal* aDocumentPrincipal, - nsIParser** aResult) +XULDocument::PrepareToLoadPrototype(nsIURI* aURI, const char* aCommand, + nsIPrincipal* aDocumentPrincipal, + nsIParser** aResult) { nsresult rv; @@ -2068,7 +2073,7 @@ nsXULDocument::PrepareToLoadPrototype(nsIURI* aURI, const char* aCommand, nsresult -nsXULDocument::ApplyPersistentAttributes() +XULDocument::ApplyPersistentAttributes() { // For non-chrome documents, persistance is simply broken if (!nsContentUtils::IsSystemPrincipal(NodePrincipal())) @@ -2088,7 +2093,7 @@ nsXULDocument::ApplyPersistentAttributes() nsresult -nsXULDocument::ApplyPersistentAttributesInternal() +XULDocument::ApplyPersistentAttributesInternal() { nsCOMArray elements; @@ -2141,8 +2146,8 @@ nsXULDocument::ApplyPersistentAttributesInternal() nsresult -nsXULDocument::ApplyPersistentAttributesToElements(nsIRDFResource* aResource, - nsCOMArray& aElements) +XULDocument::ApplyPersistentAttributesToElements(nsIRDFResource* aResource, + nsCOMArray& aElements) { nsresult rv; @@ -2213,7 +2218,7 @@ nsXULDocument::ApplyPersistentAttributesToElements(nsIRDFResource* aResource, } void -nsXULDocument::TraceProtos(JSTracer* aTrc, uint32_t aGCNumber) +XULDocument::TraceProtos(JSTracer* aTrc, uint32_t aGCNumber) { uint32_t i, count = mPrototypes.Length(); for (i = 0; i < count; ++i) { @@ -2223,15 +2228,15 @@ nsXULDocument::TraceProtos(JSTracer* aTrc, uint32_t aGCNumber) //---------------------------------------------------------------------- // -// nsXULDocument::ContextStack +// XULDocument::ContextStack // -nsXULDocument::ContextStack::ContextStack() +XULDocument::ContextStack::ContextStack() : mTop(nullptr), mDepth(0) { } -nsXULDocument::ContextStack::~ContextStack() +XULDocument::ContextStack::~ContextStack() { while (mTop) { Entry* doomed = mTop; @@ -2242,8 +2247,8 @@ nsXULDocument::ContextStack::~ContextStack() } nsresult -nsXULDocument::ContextStack::Push(nsXULPrototypeElement* aPrototype, - nsIContent* aElement) +XULDocument::ContextStack::Push(nsXULPrototypeElement* aPrototype, + nsIContent* aElement) { Entry* entry = new Entry; if (! entry) @@ -2262,7 +2267,7 @@ nsXULDocument::ContextStack::Push(nsXULPrototypeElement* aPrototype, } nsresult -nsXULDocument::ContextStack::Pop() +XULDocument::ContextStack::Pop() { if (mDepth == 0) return NS_ERROR_UNEXPECTED; @@ -2277,9 +2282,9 @@ nsXULDocument::ContextStack::Pop() } nsresult -nsXULDocument::ContextStack::Peek(nsXULPrototypeElement** aPrototype, - nsIContent** aElement, - int32_t* aIndex) +XULDocument::ContextStack::Peek(nsXULPrototypeElement** aPrototype, + nsIContent** aElement, + int32_t* aIndex) { if (mDepth == 0) return NS_ERROR_UNEXPECTED; @@ -2294,7 +2299,7 @@ nsXULDocument::ContextStack::Peek(nsXULPrototypeElement** aPrototype, nsresult -nsXULDocument::ContextStack::SetTopIndex(int32_t aIndex) +XULDocument::ContextStack::SetTopIndex(int32_t aIndex) { if (mDepth == 0) return NS_ERROR_UNEXPECTED; @@ -2310,7 +2315,7 @@ nsXULDocument::ContextStack::SetTopIndex(int32_t aIndex) // nsresult -nsXULDocument::PrepareToWalk() +XULDocument::PrepareToWalk() { // Prepare to walk the mCurrentPrototype nsresult rv; @@ -2400,8 +2405,8 @@ nsXULDocument::PrepareToWalk() } nsresult -nsXULDocument::CreateAndInsertPI(const nsXULPrototypePI* aProtoPI, - nsINode* aParent, uint32_t aIndex) +XULDocument::CreateAndInsertPI(const nsXULPrototypePI* aProtoPI, + nsINode* aParent, uint32_t aIndex) { NS_PRECONDITION(aProtoPI, "null ptr"); NS_PRECONDITION(aParent, "null ptr"); @@ -2428,10 +2433,10 @@ nsXULDocument::CreateAndInsertPI(const nsXULPrototypePI* aProtoPI, } nsresult -nsXULDocument::InsertXMLStylesheetPI(const nsXULPrototypePI* aProtoPI, - nsINode* aParent, - uint32_t aIndex, - nsIContent* aPINode) +XULDocument::InsertXMLStylesheetPI(const nsXULPrototypePI* aProtoPI, + nsINode* aParent, + uint32_t aIndex, + nsIContent* aPINode) { nsCOMPtr ssle(do_QueryInterface(aPINode)); NS_ASSERTION(ssle, "passed XML Stylesheet node does not " @@ -2470,10 +2475,10 @@ nsXULDocument::InsertXMLStylesheetPI(const nsXULPrototypePI* aProtoPI, } nsresult -nsXULDocument::InsertXULOverlayPI(const nsXULPrototypePI* aProtoPI, - nsINode* aParent, - uint32_t aIndex, - nsIContent* aPINode) +XULDocument::InsertXULOverlayPI(const nsXULPrototypePI* aProtoPI, + nsINode* aParent, + uint32_t aIndex, + nsIContent* aPINode) { nsresult rv; @@ -2519,7 +2524,7 @@ nsXULDocument::InsertXULOverlayPI(const nsXULPrototypePI* aProtoPI, } nsresult -nsXULDocument::AddChromeOverlays() +XULDocument::AddChromeOverlays() { nsresult rv; @@ -2554,7 +2559,7 @@ nsXULDocument::AddChromeOverlays() continue; } - // Same comment as in nsXULDocument::InsertXULOverlayPI + // Same comment as in XULDocument::InsertXULOverlayPI mUnloadedOverlays.InsertElementAt(0, uri); } @@ -2562,7 +2567,7 @@ nsXULDocument::AddChromeOverlays() } NS_IMETHODIMP -nsXULDocument::LoadOverlay(const nsAString& aURL, nsIObserver* aObserver) +XULDocument::LoadOverlay(const nsAString& aURL, nsIObserver* aObserver) { nsresult rv; @@ -2592,9 +2597,9 @@ nsXULDocument::LoadOverlay(const nsAString& aURL, nsIObserver* aObserver) } nsresult -nsXULDocument::LoadOverlayInternal(nsIURI* aURI, bool aIsDynamic, - bool* aShouldReturn, - bool* aFailureFromContent) +XULDocument::LoadOverlayInternal(nsIURI* aURI, bool aIsDynamic, + bool* aShouldReturn, + bool* aFailureFromContent) { nsresult rv; @@ -2644,7 +2649,7 @@ nsXULDocument::LoadOverlayInternal(nsIURI* aURI, bool aIsDynamic, nsXULPrototypeCache::GetInstance()->GetPrototype(aURI) : nullptr; // Same comment as nsChromeProtocolHandler::NewChannel and - // nsXULDocument::StartDocumentLoad + // XULDocument::StartDocumentLoad // - Ben Goodger // // We don't abort on failure here because there are too many valid @@ -2784,7 +2789,7 @@ FirePendingMergeNotification(nsIURI* aKey, nsCOMPtr& aObserver, voi } nsresult -nsXULDocument::ResumeWalk() +XULDocument::ResumeWalk() { // Walk the prototype and build the delegate content model. The // walk is performed in a top-down, left-to-right fashion. That @@ -3058,7 +3063,7 @@ nsXULDocument::ResumeWalk() } nsresult -nsXULDocument::DoneWalking() +XULDocument::DoneWalking() { NS_PRECONDITION(mPendingSheets == 0, "there are sheets to be loaded"); NS_PRECONDITION(!mStillWalking, "walk not done"); @@ -3177,9 +3182,9 @@ nsXULDocument::DoneWalking() } NS_IMETHODIMP -nsXULDocument::StyleSheetLoaded(nsCSSStyleSheet* aSheet, - bool aWasAlternate, - nsresult aStatus) +XULDocument::StyleSheetLoaded(nsCSSStyleSheet* aSheet, + bool aWasAlternate, + nsresult aStatus) { if (!aWasAlternate) { // Don't care about when alternate sheets finish loading @@ -3198,7 +3203,7 @@ nsXULDocument::StyleSheetLoaded(nsCSSStyleSheet* aSheet, } void -nsXULDocument::MaybeBroadcast() +XULDocument::MaybeBroadcast() { // Only broadcast when not in an update and when safe to run scripts. if (mUpdateNestLevel == 0 && @@ -3207,7 +3212,7 @@ nsXULDocument::MaybeBroadcast() if (!nsContentUtils::IsSafeToRunScript()) { if (!mInDestructor) { nsContentUtils::AddScriptRunner( - NS_NewRunnableMethod(this, &nsXULDocument::MaybeBroadcast)); + NS_NewRunnableMethod(this, &XULDocument::MaybeBroadcast)); } return; } @@ -3254,7 +3259,7 @@ nsXULDocument::MaybeBroadcast() } void -nsXULDocument::EndUpdate(nsUpdateType aUpdateType) +XULDocument::EndUpdate(nsUpdateType aUpdateType) { XMLDocument::EndUpdate(aUpdateType); @@ -3262,7 +3267,7 @@ nsXULDocument::EndUpdate(nsUpdateType aUpdateType) } void -nsXULDocument::ReportMissingOverlay(nsIURI* aURI) +XULDocument::ReportMissingOverlay(nsIURI* aURI) { NS_PRECONDITION(aURI, "Must have a URI"); @@ -3279,7 +3284,7 @@ nsXULDocument::ReportMissingOverlay(nsIURI* aURI) } nsresult -nsXULDocument::LoadScript(nsXULPrototypeScript* aScriptProto, bool* aBlock) +XULDocument::LoadScript(nsXULPrototypeScript* aScriptProto, bool* aBlock) { // Load a transcluded script nsresult rv; @@ -3368,11 +3373,11 @@ nsXULDocument::LoadScript(nsXULPrototypeScript* aScriptProto, bool* aBlock) NS_IMETHODIMP -nsXULDocument::OnStreamComplete(nsIStreamLoader* aLoader, - nsISupports* context, - nsresult aStatus, - uint32_t stringLen, - const uint8_t* string) +XULDocument::OnStreamComplete(nsIStreamLoader* aLoader, + nsISupports* context, + nsresult aStatus, + uint32_t stringLen, + const uint8_t* string) { nsCOMPtr request; aLoader->GetRequest(getter_AddRefs(request)); @@ -3458,7 +3463,7 @@ nsXULDocument::OnStreamComplete(nsIStreamLoader* aLoader, // containing a companion nsXULPrototypeScript node that owns a // GC root protecting the script object. Otherwise, the script // cache entry will dangle once the uncached prototype document - // is released when its owning nsXULDocument is unloaded. + // is released when its owning XULDocument is unloaded. // // (See http://bugzilla.mozilla.org/show_bug.cgi?id=98207 for // the true crime story.) @@ -3501,13 +3506,13 @@ nsXULDocument::OnStreamComplete(nsIStreamLoader* aLoader, rv = ResumeWalk(); - // Load a pointer to the prototype-script's list of nsXULDocuments who + // Load a pointer to the prototype-script's list of XULDocuments who // raced to load the same script - nsXULDocument** docp = &scriptProto->mSrcLoadWaiters; + XULDocument** docp = &scriptProto->mSrcLoadWaiters; // Resume walking other documents that waited for this one's load, first // executing the script we just compiled, in each doc's script context - nsXULDocument* doc; + XULDocument* doc; while ((doc = *docp) != nullptr) { NS_ASSERTION(doc->mCurrentScriptProto == scriptProto, "waiting for wrong script to load?"); @@ -3530,7 +3535,7 @@ nsXULDocument::OnStreamComplete(nsIStreamLoader* aLoader, nsresult -nsXULDocument::ExecuteScript(nsIScriptContext * aContext, JSScript* aScriptObject) +XULDocument::ExecuteScript(nsIScriptContext * aContext, JSScript* aScriptObject) { NS_PRECONDITION(aScriptObject != nullptr && aContext != nullptr, "null ptr"); if (! aScriptObject || ! aContext) @@ -3544,7 +3549,7 @@ nsXULDocument::ExecuteScript(nsIScriptContext * aContext, JSScript* aScriptObjec } nsresult -nsXULDocument::ExecuteScript(nsXULPrototypeScript *aScript) +XULDocument::ExecuteScript(nsXULPrototypeScript *aScript) { NS_PRECONDITION(aScript != nullptr, "null ptr"); NS_ENSURE_TRUE(aScript, NS_ERROR_NULL_POINTER); @@ -3568,9 +3573,9 @@ nsXULDocument::ExecuteScript(nsXULPrototypeScript *aScript) nsresult -nsXULDocument::CreateElementFromPrototype(nsXULPrototypeElement* aPrototype, - Element** aResult, - bool aIsRoot) +XULDocument::CreateElementFromPrototype(nsXULPrototypeElement* aPrototype, + Element** aResult, + bool aIsRoot) { // Create a content model element from a prototype element. NS_PRECONDITION(aPrototype != nullptr, "null ptr"); @@ -3626,8 +3631,8 @@ nsXULDocument::CreateElementFromPrototype(nsXULPrototypeElement* aPrototype, } nsresult -nsXULDocument::CreateOverlayElement(nsXULPrototypeElement* aPrototype, - Element** aResult) +XULDocument::CreateOverlayElement(nsXULPrototypeElement* aPrototype, + Element** aResult) { nsresult rv; @@ -3649,8 +3654,8 @@ nsXULDocument::CreateOverlayElement(nsXULPrototypeElement* aPrototype, } nsresult -nsXULDocument::AddAttributes(nsXULPrototypeElement* aPrototype, - nsIContent* aElement) +XULDocument::AddAttributes(nsXULPrototypeElement* aPrototype, + nsIContent* aElement) { nsresult rv; @@ -3672,8 +3677,8 @@ nsXULDocument::AddAttributes(nsXULPrototypeElement* aPrototype, nsresult -nsXULDocument::CheckTemplateBuilderHookup(nsIContent* aElement, - bool* aNeedsHookup) +XULDocument::CheckTemplateBuilderHookup(nsIContent* aElement, + bool* aNeedsHookup) { // See if the element already has a `database' attribute. If it // does, then the template builder has already been created. @@ -3700,7 +3705,7 @@ nsXULDocument::CheckTemplateBuilderHookup(nsIContent* aElement, } /* static */ nsresult -nsXULDocument::CreateTemplateBuilder(nsIContent* aElement) +XULDocument::CreateTemplateBuilder(nsIContent* aElement) { // Check if need to construct a tree builder or content builder. bool isTreeBuilder = false; @@ -3771,7 +3776,7 @@ nsXULDocument::CreateTemplateBuilder(nsIContent* aElement) nsresult -nsXULDocument::AddPrototypeSheets() +XULDocument::AddPrototypeSheets() { nsresult rv; @@ -3803,11 +3808,11 @@ nsXULDocument::AddPrototypeSheets() //---------------------------------------------------------------------- // -// nsXULDocument::OverlayForwardReference +// XULDocument::OverlayForwardReference // nsForwardReference::Result -nsXULDocument::OverlayForwardReference::Resolve() +XULDocument::OverlayForwardReference::Resolve() { // Resolve a forward reference from an overlay element; attempt to // hook it up into the main document. @@ -3872,9 +3877,9 @@ nsXULDocument::OverlayForwardReference::Resolve() nsresult -nsXULDocument::OverlayForwardReference::Merge(nsIContent* aTargetNode, - nsIContent* aOverlayNode, - bool aNotify) +XULDocument::OverlayForwardReference::Merge(nsIContent* aTargetNode, + nsIContent* aOverlayNode, + bool aNotify) { // This function is given: // aTargetNode: the node in the document whose 'id' attribute @@ -4021,7 +4026,7 @@ nsXULDocument::OverlayForwardReference::Merge(nsIContent* aTargetNode, -nsXULDocument::OverlayForwardReference::~OverlayForwardReference() +XULDocument::OverlayForwardReference::~OverlayForwardReference() { #ifdef PR_LOGGING if (PR_LOG_TEST(gXULLog, PR_LOG_WARNING) && !mResolved) { @@ -4050,11 +4055,11 @@ nsXULDocument::OverlayForwardReference::~OverlayForwardReference() //---------------------------------------------------------------------- // -// nsXULDocument::BroadcasterHookup +// XULDocument::BroadcasterHookup // nsForwardReference::Result -nsXULDocument::BroadcasterHookup::Resolve() +XULDocument::BroadcasterHookup::Resolve() { nsresult rv; @@ -4066,7 +4071,7 @@ nsXULDocument::BroadcasterHookup::Resolve() } -nsXULDocument::BroadcasterHookup::~BroadcasterHookup() +XULDocument::BroadcasterHookup::~BroadcasterHookup() { #ifdef PR_LOGGING if (PR_LOG_TEST(gXULLog, PR_LOG_WARNING) && !mResolved) { @@ -4100,11 +4105,11 @@ nsXULDocument::BroadcasterHookup::~BroadcasterHookup() //---------------------------------------------------------------------- // -// nsXULDocument::TemplateBuilderHookup +// XULDocument::TemplateBuilderHookup // nsForwardReference::Result -nsXULDocument::TemplateBuilderHookup::Resolve() +XULDocument::TemplateBuilderHookup::Resolve() { bool needsHookup; nsresult rv = CheckTemplateBuilderHookup(mElement, &needsHookup); @@ -4124,11 +4129,11 @@ nsXULDocument::TemplateBuilderHookup::Resolve() //---------------------------------------------------------------------- nsresult -nsXULDocument::BroadcastAttributeChangeFromOverlay(nsIContent* aNode, - int32_t aNameSpaceID, - nsIAtom* aAttribute, - nsIAtom* aPrefix, - const nsAString& aValue) +XULDocument::BroadcastAttributeChangeFromOverlay(nsIContent* aNode, + int32_t aNameSpaceID, + nsIAtom* aAttribute, + nsIAtom* aPrefix, + const nsAString& aValue) { nsresult rv = NS_OK; @@ -4165,11 +4170,11 @@ nsXULDocument::BroadcastAttributeChangeFromOverlay(nsIContent* aNode, } nsresult -nsXULDocument::FindBroadcaster(Element* aElement, - nsIDOMElement** aListener, - nsString& aBroadcasterID, - nsString& aAttribute, - nsIDOMElement** aBroadcaster) +XULDocument::FindBroadcaster(Element* aElement, + nsIDOMElement** aListener, + nsString& aBroadcasterID, + nsString& aAttribute, + nsIDOMElement** aBroadcaster) { nsresult rv; nsINodeInfo *ni = aElement->NodeInfo(); @@ -4254,9 +4259,9 @@ nsXULDocument::FindBroadcaster(Element* aElement, } nsresult -nsXULDocument::CheckBroadcasterHookup(Element* aElement, - bool* aNeedsHookup, - bool* aDidResolve) +XULDocument::CheckBroadcasterHookup(Element* aElement, + bool* aNeedsHookup, + bool* aDidResolve) { // Resolve a broadcaster hookup. Look at the element that we're // trying to resolve: it could be an '' element, or just @@ -4315,8 +4320,8 @@ nsXULDocument::CheckBroadcasterHookup(Element* aElement, } nsresult -nsXULDocument::InsertElement(nsIContent* aParent, nsIContent* aChild, - bool aNotify) +XULDocument::InsertElement(nsIContent* aParent, nsIContent* aChild, + bool aNotify) { // Insert aChild appropriately into aParent, accounting for a // 'pos' attribute set on aChild. @@ -4396,7 +4401,7 @@ nsXULDocument::InsertElement(nsIContent* aParent, nsIContent* aChild, } nsresult -nsXULDocument::RemoveElement(nsIContent* aParent, nsIContent* aChild) +XULDocument::RemoveElement(nsIContent* aParent, nsIContent* aChild) { int32_t nodeOffset = aParent->IndexOf(aChild); @@ -4409,7 +4414,7 @@ nsXULDocument::RemoveElement(nsIContent* aParent, nsIContent* aChild) // CachedChromeStreamListener // -nsXULDocument::CachedChromeStreamListener::CachedChromeStreamListener(nsXULDocument* aDocument, bool aProtoLoaded) +XULDocument::CachedChromeStreamListener::CachedChromeStreamListener(XULDocument* aDocument, bool aProtoLoaded) : mDocument(aDocument), mProtoLoaded(aProtoLoaded) { @@ -4417,27 +4422,27 @@ nsXULDocument::CachedChromeStreamListener::CachedChromeStreamListener(nsXULDocum } -nsXULDocument::CachedChromeStreamListener::~CachedChromeStreamListener() +XULDocument::CachedChromeStreamListener::~CachedChromeStreamListener() { NS_RELEASE(mDocument); } -NS_IMPL_ISUPPORTS2(nsXULDocument::CachedChromeStreamListener, +NS_IMPL_ISUPPORTS2(XULDocument::CachedChromeStreamListener, nsIRequestObserver, nsIStreamListener) NS_IMETHODIMP -nsXULDocument::CachedChromeStreamListener::OnStartRequest(nsIRequest *request, - nsISupports* acontext) +XULDocument::CachedChromeStreamListener::OnStartRequest(nsIRequest *request, + nsISupports* acontext) { return NS_ERROR_PARSED_DATA_CACHED; } NS_IMETHODIMP -nsXULDocument::CachedChromeStreamListener::OnStopRequest(nsIRequest *request, - nsISupports* aContext, - nsresult aStatus) +XULDocument::CachedChromeStreamListener::OnStopRequest(nsIRequest *request, + nsISupports* aContext, + nsresult aStatus) { if (! mProtoLoaded) return NS_OK; @@ -4447,11 +4452,11 @@ nsXULDocument::CachedChromeStreamListener::OnStopRequest(nsIRequest *request, NS_IMETHODIMP -nsXULDocument::CachedChromeStreamListener::OnDataAvailable(nsIRequest *request, - nsISupports* aContext, - nsIInputStream* aInStr, - uint64_t aSourceOffset, - uint32_t aCount) +XULDocument::CachedChromeStreamListener::OnDataAvailable(nsIRequest *request, + nsISupports* aContext, + nsIInputStream* aInStr, + uint64_t aSourceOffset, + uint32_t aCount) { NS_NOTREACHED("CachedChromeStream doesn't receive data"); return NS_ERROR_UNEXPECTED; @@ -4462,21 +4467,21 @@ nsXULDocument::CachedChromeStreamListener::OnDataAvailable(nsIRequest *request, // ParserObserver // -nsXULDocument::ParserObserver::ParserObserver(nsXULDocument* aDocument, - nsXULPrototypeDocument* aPrototype) +XULDocument::ParserObserver::ParserObserver(XULDocument* aDocument, + nsXULPrototypeDocument* aPrototype) : mDocument(aDocument), mPrototype(aPrototype) { } -nsXULDocument::ParserObserver::~ParserObserver() +XULDocument::ParserObserver::~ParserObserver() { } -NS_IMPL_ISUPPORTS1(nsXULDocument::ParserObserver, nsIRequestObserver) +NS_IMPL_ISUPPORTS1(XULDocument::ParserObserver, nsIRequestObserver) NS_IMETHODIMP -nsXULDocument::ParserObserver::OnStartRequest(nsIRequest *request, - nsISupports* aContext) +XULDocument::ParserObserver::OnStartRequest(nsIRequest *request, + nsISupports* aContext) { // Guard against buggy channels calling OnStartRequest multiple times. if (mPrototype) { @@ -4498,9 +4503,9 @@ nsXULDocument::ParserObserver::OnStartRequest(nsIRequest *request, } NS_IMETHODIMP -nsXULDocument::ParserObserver::OnStopRequest(nsIRequest *request, - nsISupports* aContext, - nsresult aStatus) +XULDocument::ParserObserver::OnStopRequest(nsIRequest *request, + nsISupports* aContext, + nsresult aStatus) { nsresult rv = NS_OK; @@ -4528,7 +4533,7 @@ nsXULDocument::ParserObserver::OnStopRequest(nsIRequest *request, } already_AddRefed -nsXULDocument::GetWindowRoot() +XULDocument::GetWindowRoot() { nsCOMPtr ir = do_QueryReferent(mDocumentContainer); nsCOMPtr window(do_GetInterface(ir)); @@ -4537,7 +4542,7 @@ nsXULDocument::GetWindowRoot() } bool -nsXULDocument::IsDocumentRightToLeft() +XULDocument::IsDocumentRightToLeft() { // setting the localedir attribute on the root element forces a // specific direction for the document. @@ -4589,16 +4594,16 @@ nsXULDocument::IsDocumentRightToLeft() } void -nsXULDocument::ResetDocumentDirection() +XULDocument::ResetDocumentDirection() { DocumentStatesChanged(NS_DOCUMENT_STATE_RTL_LOCALE); } int -nsXULDocument::DirectionChanged(const char* aPrefName, void* aData) +XULDocument::DirectionChanged(const char* aPrefName, void* aData) { // Reset the direction and restyle the document if necessary. - nsXULDocument* doc = (nsXULDocument *)aData; + XULDocument* doc = (XULDocument *)aData; if (doc) { doc->ResetDocumentDirection(); } @@ -4607,7 +4612,7 @@ nsXULDocument::DirectionChanged(const char* aPrefName, void* aData) } int -nsXULDocument::GetDocumentLWTheme() +XULDocument::GetDocumentLWTheme() { if (mDocLWTheme == Doc_Theme_Uninitialized) { mDocLWTheme = Doc_Theme_None; // No lightweight theme by default @@ -4633,7 +4638,10 @@ nsXULDocument::GetDocumentLWTheme() } NS_IMETHODIMP -nsXULDocument::GetBoxObjectFor(nsIDOMElement* aElement, nsIBoxObject** aResult) +XULDocument::GetBoxObjectFor(nsIDOMElement* aElement, nsIBoxObject** aResult) { return nsDocument::GetBoxObjectFor(aElement, aResult); } + +} // namespace dom +} // namespace mozilla diff --git a/content/xul/document/src/nsXULDocument.h b/content/xul/document/src/XULDocument.h similarity index 92% rename from content/xul/document/src/nsXULDocument.h rename to content/xul/document/src/XULDocument.h index fac4a58909a8..7d800fb38e5f 100644 --- a/content/xul/document/src/nsXULDocument.h +++ b/content/xul/document/src/XULDocument.h @@ -3,8 +3,8 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#ifndef nsXULDocument_h__ -#define nsXULDocument_h__ +#ifndef mozilla_dom_XULDocument_h +#define mozilla_dom_XULDocument_h #include "nsCOMPtr.h" #include "nsXULPrototypeDocument.h" @@ -81,15 +81,19 @@ private: /** * The XUL document class */ -class nsXULDocument : public mozilla::dom::XMLDocument, - public nsIXULDocument, - public nsIDOMXULDocument, - public nsIStreamLoaderObserver, - public nsICSSLoaderObserver + +namespace mozilla { +namespace dom { + +class XULDocument : public XMLDocument, + public nsIXULDocument, + public nsIDOMXULDocument, + public nsIStreamLoaderObserver, + public nsICSSLoaderObserver { public: - nsXULDocument(); - virtual ~nsXULDocument(); + XULDocument(); + virtual ~XULDocument(); // nsISupports interface NS_DECL_ISUPPORTS_INHERITED @@ -140,7 +144,7 @@ public: NS_FORWARD_NSIDOMNODE_TO_NSINODE // nsIDOMDocument interface - NS_FORWARD_NSIDOMDOCUMENT(mozilla::dom::XMLDocument::) + NS_FORWARD_NSIDOMDOCUMENT(XMLDocument::) // And explicitly import the things from nsDocument that we just shadowed using nsDocument::GetImplementation; using nsDocument::GetTitle; @@ -150,7 +154,7 @@ public: using nsDocument::GetMozFullScreenElement; // nsDocument interface overrides - virtual mozilla::dom::Element* GetElementById(const nsAString & elementId); + virtual Element* GetElementById(const nsAString & elementId); // nsIDOMXULDocument interface NS_DECL_NSIDOMXULDOCUMENT @@ -176,8 +180,7 @@ public: nsIAtom* aAttrName, void* aData); - NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsXULDocument, - mozilla::dom::XMLDocument) + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(XULDocument, XMLDocument) virtual nsXPCClassInfo* GetClassInfo(); @@ -186,15 +189,15 @@ public: protected: // Implementation methods friend nsresult - NS_NewXULDocument(nsIXULDocument** aResult); + (::NS_NewXULDocument(nsIXULDocument** aResult)); nsresult Init(void); nsresult StartLayout(void); nsresult - AddElementToRefMap(mozilla::dom::Element* aElement); + AddElementToRefMap(Element* aElement); void - RemoveElementFromRefMap(mozilla::dom::Element* aElement); + RemoveElementFromRefMap(Element* aElement); nsresult GetViewportSize(int32_t* aWidth, int32_t* aHeight); @@ -220,10 +223,10 @@ protected: nsCOMArray& aElements); nsresult - AddElementToDocumentPre(mozilla::dom::Element* aElement); + AddElementToDocumentPre(Element* aElement); nsresult - AddElementToDocumentPost(mozilla::dom::Element* aElement); + AddElementToDocumentPost(Element* aElement); nsresult ExecuteOnBroadcastHandlerFor(nsIContent* aBroadcaster, @@ -264,7 +267,7 @@ protected: // NOTE, THIS IS STILL IN PROGRESS, TALK TO PINK OR SCC BEFORE // CHANGING - nsXULDocument* mNextSrcLoadWaiter; // [OWNER] but not COMPtr + XULDocument* mNextSrcLoadWaiter; // [OWNER] but not COMPtr // Tracks elements with a 'ref' attribute, or an 'id' attribute where // the element's namespace has no registered ID attribute name. @@ -376,7 +379,7 @@ protected: * Note that the resulting content node is not bound to any tree */ nsresult CreateElementFromPrototype(nsXULPrototypeElement* aPrototype, - mozilla::dom::Element** aResult, + Element** aResult, bool aIsRoot); /** @@ -384,7 +387,7 @@ protected: * later resolution. */ nsresult CreateOverlayElement(nsXULPrototypeElement* aPrototype, - mozilla::dom::Element** aResult); + Element** aResult); /** * Add attributes from the prototype to the element. @@ -452,13 +455,13 @@ protected: class BroadcasterHookup : public nsForwardReference { protected: - nsXULDocument* mDocument; // [WEAK] - nsRefPtr mObservesElement; // [OWNER] + XULDocument* mDocument; // [WEAK] + nsRefPtr mObservesElement; // [OWNER] bool mResolved; public: - BroadcasterHookup(nsXULDocument* aDocument, - mozilla::dom::Element* aObservesElement) + BroadcasterHookup(XULDocument* aDocument, + Element* aObservesElement) : mDocument(aDocument), mObservesElement(aObservesElement), mResolved(false) @@ -480,14 +483,14 @@ protected: class OverlayForwardReference : public nsForwardReference { protected: - nsXULDocument* mDocument; // [WEAK] + XULDocument* mDocument; // [WEAK] nsCOMPtr mOverlay; // [OWNER] bool mResolved; nsresult Merge(nsIContent* aTargetNode, nsIContent* aOverlayNode, bool aNotify); public: - OverlayForwardReference(nsXULDocument* aDocument, nsIContent* aOverlay) + OverlayForwardReference(XULDocument* aDocument, nsIContent* aOverlay) : mDocument(aDocument), mOverlay(aOverlay), mResolved(false) {} virtual ~OverlayForwardReference(); @@ -518,14 +521,14 @@ protected: // values of the out params should not be relied on (though *aListener and // *aBroadcaster do need to be released if non-null, of course). nsresult - FindBroadcaster(mozilla::dom::Element* aElement, + FindBroadcaster(Element* aElement, nsIDOMElement** aListener, nsString& aBroadcasterID, nsString& aAttribute, nsIDOMElement** aBroadcaster); nsresult - CheckBroadcasterHookup(mozilla::dom::Element* aElement, + CheckBroadcasterHookup(Element* aElement, bool* aNeedsHookup, bool* aDidResolve); @@ -625,13 +628,13 @@ protected: class CachedChromeStreamListener : public nsIStreamListener { protected: - nsXULDocument* mDocument; - bool mProtoLoaded; + XULDocument* mDocument; + bool mProtoLoaded; virtual ~CachedChromeStreamListener(); public: - CachedChromeStreamListener(nsXULDocument* aDocument, + CachedChromeStreamListener(XULDocument* aDocument, bool aProtoLoaded); NS_DECL_ISUPPORTS @@ -644,12 +647,12 @@ protected: class ParserObserver : public nsIRequestObserver { protected: - nsRefPtr mDocument; + nsRefPtr mDocument; nsRefPtr mPrototype; virtual ~ParserObserver(); public: - ParserObserver(nsXULDocument* aDocument, + ParserObserver(XULDocument* aDocument, nsXULPrototypeDocument* aPrototype); NS_DECL_ISUPPORTS @@ -720,4 +723,7 @@ private: }; -#endif // nsXULDocument_h__ +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_XULDocument_h diff --git a/content/xul/document/src/nsXULPrototypeDocument.cpp b/content/xul/document/src/nsXULPrototypeDocument.cpp index 0fcb0ed1c378..0832252ebcbe 100644 --- a/content/xul/document/src/nsXULPrototypeDocument.cpp +++ b/content/xul/document/src/nsXULPrototypeDocument.cpp @@ -5,7 +5,7 @@ #include "nsXULPrototypeDocument.h" -#include "nsXULDocument.h" +#include "XULDocument.h" #include "nsAString.h" #include "nsIObjectInputStream.h" @@ -34,6 +34,7 @@ using mozilla::dom::DestroyProtoAndIfaceCache; using mozilla::AutoPushJSContext; +using mozilla::dom::XULDocument; static NS_DEFINE_CID(kDOMScriptObjectFactoryCID, NS_DOM_SCRIPT_OBJECT_FACTORY_CID); @@ -637,7 +638,7 @@ nsXULPrototypeDocument::GetNodeInfoManager() nsresult -nsXULPrototypeDocument::AwaitLoadDone(nsXULDocument* aDocument, bool* aResult) +nsXULPrototypeDocument::AwaitLoadDone(XULDocument* aDocument, bool* aResult) { nsresult rv = NS_OK; diff --git a/content/xul/document/src/nsXULPrototypeDocument.h b/content/xul/document/src/nsXULPrototypeDocument.h index cdb2114814f5..54f2a2700db2 100644 --- a/content/xul/document/src/nsXULPrototypeDocument.h +++ b/content/xul/document/src/nsXULPrototypeDocument.h @@ -18,18 +18,23 @@ class nsIAtom; class nsIPrincipal; class nsIURI; class nsNodeInfoManager; -class nsXULDocument; class nsXULPrototypeElement; class nsXULPrototypePI; class nsXULPDGlobalObject; struct JSTracer; +namespace mozilla { +namespace dom { +class XULDocument; +} // namespace dom +} // namespace mozilla + /** * A "prototype" document that stores shared document information * for the XUL cache. * Among other things, stores the tree of nsXULPrototype* * objects, from which the real DOM tree is built later in - * nsXULDocument::ResumeWalk. + * XULDocument::ResumeWalk. */ class nsXULPrototypeDocument : public nsIScriptGlobalObjectOwner, public nsISerializable @@ -93,10 +98,10 @@ public: /** * If current prototype document has not yet finished loading, * appends aDocument to the list of documents to notify (via - * nsXULDocument::OnPrototypeLoadDone()) and sets aLoaded to false. + * XULDocument::OnPrototypeLoadDone()) and sets aLoaded to false. * Otherwise sets aLoaded to true. */ - nsresult AwaitLoadDone(nsXULDocument* aDocument, bool* aResult); + nsresult AwaitLoadDone(mozilla::dom::XULDocument* aDocument, bool* aResult); /** * Notifies each document registered via AwaitLoadDone on this @@ -130,7 +135,7 @@ protected: nsRefPtr mGlobalObject; bool mLoaded; - nsTArray< nsRefPtr > mPrototypeWaiters; + nsTArray< nsRefPtr > mPrototypeWaiters; nsRefPtr mNodeInfoManager; diff --git a/xpcom/base/ErrorList.h b/xpcom/base/ErrorList.h index de8ade7928a7..16ebf38db78f 100644 --- a/xpcom/base/ErrorList.h +++ b/xpcom/base/ErrorList.h @@ -692,7 +692,7 @@ ERROR(NS_CONTENT_BLOCKED, SUCCESS(8)), ERROR(NS_CONTENT_BLOCKED_SHOW_ALT, SUCCESS(9)), ERROR(NS_PROPTABLE_PROP_OVERWRITTEN, SUCCESS(11)), - /* Error codes for FindBroadcaster in nsXULDocument.cpp */ + /* Error codes for FindBroadcaster in XULDocument.cpp */ ERROR(NS_FINDBROADCASTER_NOT_FOUND, SUCCESS(12)), ERROR(NS_FINDBROADCASTER_FOUND, SUCCESS(13)), ERROR(NS_FINDBROADCASTER_AWAIT_OVERLAYS, SUCCESS(14)), From 0790ddb12c89cca9f4c21e447e585c0039e4677f Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Tue, 26 Mar 2013 11:31:53 -0400 Subject: [PATCH 019/129] Bug 848796 part 2. Add WebIDL API for XULDocument. r=peterv --- content/base/public/nsIDocument.h | 8 +- content/base/src/nsDocument.cpp | 50 ++-- content/base/src/nsDocument.h | 3 +- content/xul/content/src/nsXULElement.cpp | 4 +- content/xul/document/src/XULDocument.cpp | 298 +++++++++++++------ content/xul/document/src/XULDocument.h | 61 +++- dom/webidl/XULDocument.webidl | 57 ++++ layout/xul/base/src/nsXULTooltipListener.cpp | 6 +- layout/xul/tree/nsTreeBodyFrame.cpp | 6 +- 9 files changed, 343 insertions(+), 150 deletions(-) create mode 100644 dom/webidl/XULDocument.webidl diff --git a/content/base/public/nsIDocument.h b/content/base/public/nsIDocument.h index c9f361739099..07c797788a05 100644 --- a/content/base/public/nsIDocument.h +++ b/content/base/public/nsIDocument.h @@ -110,8 +110,8 @@ typedef CallbackObjectHolder NodeFilterHolder; } // namespace mozilla #define NS_IDOCUMENT_IID \ -{ 0x45ce048f, 0x5970, 0x411e, \ - { 0xaa, 0x99, 0x12, 0xed, 0x3a, 0x55, 0xc9, 0xc3 } } +{ 0x699e0649, 0x55f2, 0x47f1, \ + { 0x93, 0x38, 0xcd, 0x67, 0xf3, 0x2b, 0x04, 0xe9 } } // Flag for AddStyleSheet(). #define NS_STYLESHEET_FROM_CATALOG (1 << 0) @@ -1306,7 +1306,9 @@ public: * Get the box object for an element. This is not exposed through a * scriptable interface except for XUL documents. */ - NS_IMETHOD GetBoxObjectFor(nsIDOMElement* aElement, nsIBoxObject** aResult) = 0; + virtual already_AddRefed + GetBoxObjectFor(mozilla::dom::Element* aElement, + mozilla::ErrorResult& aRv) = 0; /** * Get the compatibility mode for this document diff --git a/content/base/src/nsDocument.cpp b/content/base/src/nsDocument.cpp index b671bb43b5eb..d63578e9cda5 100644 --- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -5927,16 +5927,21 @@ nsDocument::DoNotifyPossibleTitleChange() true, true); } -NS_IMETHODIMP -nsDocument::GetBoxObjectFor(nsIDOMElement* aElement, nsIBoxObject** aResult) +already_AddRefed +nsDocument::GetBoxObjectFor(Element* aElement, ErrorResult& aRv) { - nsCOMPtr content(do_QueryInterface(aElement)); - NS_ENSURE_TRUE(content, NS_ERROR_UNEXPECTED); + if (!aElement) { + aRv.Throw(NS_ERROR_UNEXPECTED); + return nullptr; + } - nsIDocument* doc = content->OwnerDoc(); - NS_ENSURE_TRUE(doc == this, NS_ERROR_DOM_WRONG_DOCUMENT_ERR); + nsIDocument* doc = aElement->OwnerDoc(); + if (doc != this) { + aRv.Throw(NS_ERROR_DOM_WRONG_DOCUMENT_ERR); + return nullptr; + } - if (!mHasWarnedAboutBoxObjects && !content->IsXUL()) { + if (!mHasWarnedAboutBoxObjects && !aElement->IsXUL()) { mHasWarnedAboutBoxObjects = true; nsContentUtils::ReportToConsole(nsIScriptError::warningFlag, "BoxObjects", this, @@ -5944,22 +5949,18 @@ nsDocument::GetBoxObjectFor(nsIDOMElement* aElement, nsIBoxObject** aResult) "UseOfGetBoxObjectForWarning"); } - *aResult = nullptr; - if (!mBoxObjectTable) { mBoxObjectTable = new nsInterfaceHashtable, nsPIBoxObject>; mBoxObjectTable->Init(12); } else { - // Want to use Get(content, aResult); but it's the wrong type - *aResult = mBoxObjectTable->GetWeak(content); - if (*aResult) { - NS_ADDREF(*aResult); - return NS_OK; + nsCOMPtr boxObject = mBoxObjectTable->Get(aElement); + if (boxObject) { + return boxObject.forget(); } } int32_t namespaceID; - nsCOMPtr tag = BindingManager()->ResolveTag(content, &namespaceID); + nsCOMPtr tag = BindingManager()->ResolveTag(aElement, &namespaceID); nsAutoCString contractID("@mozilla.org/layout/xul-boxobject"); if (namespaceID == kNameSpaceID_XUL) { @@ -5984,19 +5985,18 @@ nsDocument::GetBoxObjectFor(nsIDOMElement* aElement, nsIBoxObject** aResult) contractID += ";1"; nsCOMPtr boxObject(do_CreateInstance(contractID.get())); - if (!boxObject) - return NS_ERROR_FAILURE; - - boxObject->Init(content); - - if (mBoxObjectTable) { - mBoxObjectTable->Put(content, boxObject.get()); + if (!boxObject) { + aRv.Throw(NS_ERROR_FAILURE); + return nullptr; } - *aResult = boxObject; - NS_ADDREF(*aResult); + boxObject->Init(aElement); - return NS_OK; + if (mBoxObjectTable) { + mBoxObjectTable->Put(aElement, boxObject.get()); + } + + return boxObject.forget(); } void diff --git a/content/base/src/nsDocument.h b/content/base/src/nsDocument.h index 0dcb94990286..b86f89acd236 100644 --- a/content/base/src/nsDocument.h +++ b/content/base/src/nsDocument.h @@ -812,7 +812,8 @@ public: virtual NS_HIDDEN_(void) ForgetLink(mozilla::dom::Link* aLink); NS_HIDDEN_(void) ClearBoxObjectFor(nsIContent* aContent); - NS_IMETHOD GetBoxObjectFor(nsIDOMElement* aElement, nsIBoxObject** aResult); + already_AddRefed GetBoxObjectFor(mozilla::dom::Element* aElement, + mozilla::ErrorResult& aRv); virtual NS_HIDDEN_(nsresult) GetXBLChildNodesFor(nsIContent* aContent, nsIDOMNodeList** aResult); diff --git a/content/xul/content/src/nsXULElement.cpp b/content/xul/content/src/nsXULElement.cpp index bbe428c07f4b..8453f881c0d5 100644 --- a/content/xul/content/src/nsXULElement.cpp +++ b/content/xul/content/src/nsXULElement.cpp @@ -1367,10 +1367,8 @@ nsXULElement::GetBoxObject(nsIBoxObject** aResult) already_AddRefed nsXULElement::GetBoxObject(ErrorResult& rv) { - nsCOMPtr boxObject; // XXX sXBL/XBL2 issue! Owner or current document? - rv = OwnerDoc()->GetBoxObjectFor(this, getter_AddRefs(boxObject)); - return boxObject.forget(); + return OwnerDoc()->GetBoxObjectFor(this, rv); } // Methods for setting/getting attributes from nsIDOMXULElement diff --git a/content/xul/document/src/XULDocument.cpp b/content/xul/document/src/XULDocument.cpp index 57b86b070c38..ee63965ce7e9 100644 --- a/content/xul/document/src/XULDocument.cpp +++ b/content/xul/document/src/XULDocument.cpp @@ -148,7 +148,7 @@ PRLogModuleInfo* XULDocument::gXULLog; //---------------------------------------------------------------------- struct BroadcasterMapEntry : public PLDHashEntryHdr { - nsIDOMElement* mBroadcaster; // [WEAK] + Element* mBroadcaster; // [WEAK] nsSmallVoidArray mListeners; // [OWNING] of BroadcastListener objects }; @@ -687,8 +687,8 @@ struct nsAttrNameInfo }; void -XULDocument::SynchronizeBroadcastListener(nsIDOMElement *aBroadcaster, - nsIDOMElement *aListener, +XULDocument::SynchronizeBroadcastListener(Element *aBroadcaster, + Element *aListener, const nsAString &aAttr) { if (!nsContentUtils::IsSafeToRunScript()) { @@ -698,15 +698,13 @@ XULDocument::SynchronizeBroadcastListener(nsIDOMElement *aBroadcaster, MaybeBroadcast(); return; } - nsCOMPtr broadcaster = do_QueryInterface(aBroadcaster); - nsCOMPtr listener = do_QueryInterface(aListener); bool notify = mDocumentLoaded || mHandlingDelayedBroadcasters; if (aAttr.EqualsLiteral("*")) { - uint32_t count = broadcaster->GetAttrCount(); + uint32_t count = aBroadcaster->GetAttrCount(); nsTArray attributes(count); for (uint32_t i = 0; i < count; ++i) { - const nsAttrName* attrName = broadcaster->GetAttrNameAt(i); + const nsAttrName* attrName = aBroadcaster->GetAttrNameAt(i); int32_t nameSpaceID = attrName->NamespaceID(); nsIAtom* name = attrName->LocalName(); @@ -723,9 +721,9 @@ XULDocument::SynchronizeBroadcastListener(nsIDOMElement *aBroadcaster, int32_t nameSpaceID = attributes[count].mNamespaceID; nsIAtom* name = attributes[count].mName; nsAutoString value; - if (broadcaster->GetAttr(nameSpaceID, name, value)) { - listener->SetAttr(nameSpaceID, name, attributes[count].mPrefix, - value, notify); + if (aBroadcaster->GetAttr(nameSpaceID, name, value)) { + aListener->SetAttr(nameSpaceID, name, attributes[count].mPrefix, + value, notify); } #if 0 @@ -734,7 +732,7 @@ XULDocument::SynchronizeBroadcastListener(nsIDOMElement *aBroadcaster, // |onbroadcast| handler before the |onload| handler, // which could define JS properties that mask XBL // properties, etc. - ExecuteOnBroadcastHandlerFor(broadcaster, aListener, name); + ExecuteOnBroadcastHandlerFor(aBroadcaster, aListener, name); #endif } } @@ -743,10 +741,10 @@ XULDocument::SynchronizeBroadcastListener(nsIDOMElement *aBroadcaster, nsCOMPtr name = do_GetAtom(aAttr); nsAutoString value; - if (broadcaster->GetAttr(kNameSpaceID_None, name, value)) { - listener->SetAttr(kNameSpaceID_None, name, value, notify); + if (aBroadcaster->GetAttr(kNameSpaceID_None, name, value)) { + aListener->SetAttr(kNameSpaceID_None, name, value, notify); } else { - listener->UnsetAttr(kNameSpaceID_None, name, notify); + aListener->UnsetAttr(kNameSpaceID_None, name, notify); } #if 0 @@ -754,7 +752,7 @@ XULDocument::SynchronizeBroadcastListener(nsIDOMElement *aBroadcaster, // hookup: doing so would potentially run the |onbroadcast| // handler before the |onload| handler, which could define JS // properties that mask XBL properties, etc. - ExecuteOnBroadcastHandlerFor(broadcaster, aListener, name); + ExecuteOnBroadcastHandlerFor(aBroadcaster, aListener, name); #endif } } @@ -764,19 +762,31 @@ XULDocument::AddBroadcastListenerFor(nsIDOMElement* aBroadcaster, nsIDOMElement* aListener, const nsAString& aAttr) { - NS_ENSURE_ARG(aBroadcaster && aListener); - + ErrorResult rv; + nsCOMPtr broadcaster = do_QueryInterface(aBroadcaster); + nsCOMPtr listener = do_QueryInterface(aListener); + NS_ENSURE_ARG(broadcaster && listener); + AddBroadcastListenerFor(*broadcaster, *listener, aAttr, rv); + return rv.ErrorCode(); +} + +void +XULDocument::AddBroadcastListenerFor(Element& aBroadcaster, Element& aListener, + const nsAString& aAttr, ErrorResult& aRv) +{ nsresult rv = - nsContentUtils::CheckSameOrigin(this, aBroadcaster); + nsContentUtils::CheckSameOrigin(this, &aBroadcaster); if (NS_FAILED(rv)) { - return rv; + aRv.Throw(rv); + return; } - rv = nsContentUtils::CheckSameOrigin(this, aListener); + rv = nsContentUtils::CheckSameOrigin(this, &aListener); if (NS_FAILED(rv)) { - return rv; + aRv.Throw(rv); + return; } static PLDHashTableOps gOps = { @@ -795,25 +805,29 @@ XULDocument::AddBroadcastListenerFor(nsIDOMElement* aBroadcaster, PL_NewDHashTable(&gOps, nullptr, sizeof(BroadcasterMapEntry), PL_DHASH_MIN_SIZE); - if (! mBroadcasterMap) - return NS_ERROR_OUT_OF_MEMORY; + if (! mBroadcasterMap) { + aRv.Throw(NS_ERROR_OUT_OF_MEMORY); + return; + } } BroadcasterMapEntry* entry = static_cast - (PL_DHashTableOperate(mBroadcasterMap, aBroadcaster, + (PL_DHashTableOperate(mBroadcasterMap, &aBroadcaster, PL_DHASH_LOOKUP)); if (PL_DHASH_ENTRY_IS_FREE(entry)) { entry = static_cast - (PL_DHashTableOperate(mBroadcasterMap, aBroadcaster, + (PL_DHashTableOperate(mBroadcasterMap, &aBroadcaster, PL_DHASH_ADD)); - if (! entry) - return NS_ERROR_OUT_OF_MEMORY; + if (! entry) { + aRv.Throw(NS_ERROR_OUT_OF_MEMORY); + return; + } - entry->mBroadcaster = aBroadcaster; + entry->mBroadcaster = &aBroadcaster; // N.B. placement new to construct the nsSmallVoidArray object // in-place @@ -827,38 +841,47 @@ XULDocument::AddBroadcastListenerFor(nsIDOMElement* aBroadcaster, for (int32_t i = entry->mListeners.Count() - 1; i >= 0; --i) { bl = static_cast(entry->mListeners[i]); - nsCOMPtr blListener = do_QueryReferent(bl->mListener); + nsCOMPtr blListener = do_QueryReferent(bl->mListener); - if ((blListener == aListener) && (bl->mAttribute == attr)) - return NS_OK; + if (blListener == &aListener && bl->mAttribute == attr) + return; } bl = new BroadcastListener; - if (! bl) - return NS_ERROR_OUT_OF_MEMORY; - bl->mListener = do_GetWeakReference(aListener); + bl->mListener = do_GetWeakReference(&aListener); bl->mAttribute = attr; entry->mListeners.AppendElement(bl); - SynchronizeBroadcastListener(aBroadcaster, aListener, aAttr); - return NS_OK; + SynchronizeBroadcastListener(&aBroadcaster, &aListener, aAttr); } NS_IMETHODIMP XULDocument::RemoveBroadcastListenerFor(nsIDOMElement* aBroadcaster, nsIDOMElement* aListener, const nsAString& aAttr) +{ + nsCOMPtr broadcaster = do_QueryInterface(aBroadcaster); + nsCOMPtr listener = do_QueryInterface(aListener); + NS_ENSURE_ARG(broadcaster && listener); + RemoveBroadcastListenerFor(*broadcaster, *listener, aAttr); + return NS_OK; +} + +void +XULDocument::RemoveBroadcastListenerFor(Element& aBroadcaster, + Element& aListener, + const nsAString& aAttr) { // If we haven't added any broadcast listeners, then there sure // aren't any to remove. if (! mBroadcasterMap) - return NS_OK; + return; BroadcasterMapEntry* entry = static_cast - (PL_DHashTableOperate(mBroadcasterMap, aBroadcaster, + (PL_DHashTableOperate(mBroadcasterMap, &aBroadcaster, PL_DHASH_LOOKUP)); if (PL_DHASH_ENTRY_IS_BUSY(entry)) { @@ -867,35 +890,32 @@ XULDocument::RemoveBroadcastListenerFor(nsIDOMElement* aBroadcaster, BroadcastListener* bl = static_cast(entry->mListeners[i]); - nsCOMPtr blListener = do_QueryReferent(bl->mListener); + nsCOMPtr blListener = do_QueryReferent(bl->mListener); - if ((blListener == aListener) && (bl->mAttribute == attr)) { + if (blListener == &aListener && bl->mAttribute == attr) { entry->mListeners.RemoveElementAt(i); delete bl; if (entry->mListeners.Count() == 0) - PL_DHashTableOperate(mBroadcasterMap, aBroadcaster, + PL_DHashTableOperate(mBroadcasterMap, &aBroadcaster, PL_DHASH_REMOVE); break; } } } - - return NS_OK; } nsresult -XULDocument::ExecuteOnBroadcastHandlerFor(nsIContent* aBroadcaster, - nsIDOMElement* aListener, +XULDocument::ExecuteOnBroadcastHandlerFor(Element* aBroadcaster, + Element* aListener, nsIAtom* aAttr) { // Now we execute the onchange handler in the context of the // observer. We need to find the observer in order to // execute the handler. - nsCOMPtr listener = do_QueryInterface(aListener); - for (nsIContent* child = listener->GetFirstChild(); + for (nsIContent* child = aListener->GetFirstChild(); child; child = child->GetNextSibling()) { @@ -983,12 +1003,11 @@ XULDocument::AttributeChanged(nsIDocument* aDocument, nsresult rv; // Synchronize broadcast listeners - nsCOMPtr domele = do_QueryInterface(aElement); - if (domele && mBroadcasterMap && + if (mBroadcasterMap && CanBroadcast(aNameSpaceID, aAttribute)) { BroadcasterMapEntry* entry = static_cast - (PL_DHashTableOperate(mBroadcasterMap, domele.get(), + (PL_DHashTableOperate(mBroadcasterMap, aElement, PL_DHASH_LOOKUP)); if (PL_DHASH_ENTRY_IS_BUSY(entry)) { @@ -1003,21 +1022,20 @@ XULDocument::AttributeChanged(nsIDocument* aDocument, if ((bl->mAttribute == aAttribute) || (bl->mAttribute == nsGkAtoms::_asterix)) { - nsCOMPtr listenerEl + nsCOMPtr listenerEl = do_QueryReferent(bl->mListener); - nsCOMPtr l = do_QueryInterface(listenerEl); - if (l) { + if (listenerEl) { nsAutoString currentValue; - bool hasAttr = l->GetAttr(kNameSpaceID_None, - aAttribute, - currentValue); + bool hasAttr = listenerEl->GetAttr(kNameSpaceID_None, + aAttribute, + currentValue); // We need to update listener only if we're // (1) removing an existing attribute, // (2) adding a new attribute or // (3) changing the value of an attribute. bool needsAttrChange = attrSet != hasAttr || !value.Equals(currentValue); - nsDelayedBroadcastUpdate delayedUpdate(domele, + nsDelayedBroadcastUpdate delayedUpdate(aElement, listenerEl, aAttribute, value, @@ -1221,11 +1239,17 @@ NS_IMETHODIMP XULDocument::GetElementsByAttribute(const nsAString& aAttribute, const nsAString& aValue, nsIDOMNodeList** aReturn) +{ + *aReturn = GetElementsByAttribute(aAttribute, aValue).get(); + return NS_OK; +} + +already_AddRefed +XULDocument::GetElementsByAttribute(const nsAString& aAttribute, + const nsAString& aValue) { nsCOMPtr attrAtom(do_GetAtom(aAttribute)); - NS_ENSURE_TRUE(attrAtom, NS_ERROR_OUT_OF_MEMORY); void* attrValue = new nsString(aValue); - NS_ENSURE_TRUE(attrValue, NS_ERROR_OUT_OF_MEMORY); nsContentList *list = new nsContentList(this, MatchAttribute, nsContentUtils::DestroyMatchString, @@ -1233,10 +1257,9 @@ XULDocument::GetElementsByAttribute(const nsAString& aAttribute, true, attrAtom, kNameSpaceID_Unknown); - NS_ENSURE_TRUE(list, NS_ERROR_OUT_OF_MEMORY); - NS_ADDREF(*aReturn = list); - return NS_OK; + NS_ADDREF(list); + return list; } NS_IMETHODIMP @@ -1244,18 +1267,31 @@ XULDocument::GetElementsByAttributeNS(const nsAString& aNamespaceURI, const nsAString& aAttribute, const nsAString& aValue, nsIDOMNodeList** aReturn) +{ + ErrorResult rv; + *aReturn = GetElementsByAttributeNS(aNamespaceURI, aAttribute, + aValue, rv).get(); + return rv.ErrorCode(); +} + +already_AddRefed +XULDocument::GetElementsByAttributeNS(const nsAString& aNamespaceURI, + const nsAString& aAttribute, + const nsAString& aValue, + ErrorResult& aRv) { nsCOMPtr attrAtom(do_GetAtom(aAttribute)); - NS_ENSURE_TRUE(attrAtom, NS_ERROR_OUT_OF_MEMORY); void* attrValue = new nsString(aValue); - NS_ENSURE_TRUE(attrValue, NS_ERROR_OUT_OF_MEMORY); int32_t nameSpaceId = kNameSpaceID_Wildcard; if (!aNamespaceURI.EqualsLiteral("*")) { nsresult rv = nsContentUtils::NameSpaceManager()->RegisterNameSpace(aNamespaceURI, nameSpaceId); - NS_ENSURE_SUCCESS(rv, rv); + if (NS_FAILED(rv)) { + aRv.Throw(rv); + return nullptr; + } } nsContentList *list = new nsContentList(this, @@ -1265,10 +1301,8 @@ XULDocument::GetElementsByAttributeNS(const nsAString& aNamespaceURI, true, attrAtom, nameSpaceId); - NS_ENSURE_TRUE(list, NS_ERROR_OUT_OF_MEMORY); - - NS_ADDREF(*aReturn = list); - return NS_OK; + NS_ADDREF(list); + return list; } NS_IMETHODIMP @@ -1459,6 +1493,14 @@ XULDocument::GetWidth(int32_t* aWidth) return GetViewportSize(aWidth, &height); } +int32_t +XULDocument::GetWidth(ErrorResult& aRv) +{ + int32_t width; + aRv = GetWidth(&width); + return width; +} + NS_IMETHODIMP XULDocument::GetHeight(int32_t* aHeight) { @@ -1468,6 +1510,14 @@ XULDocument::GetHeight(int32_t* aHeight) return GetViewportSize(&width, aHeight); } +int32_t +XULDocument::GetHeight(ErrorResult& aRv) +{ + int32_t height; + aRv = GetHeight(&height); + return height; +} + //---------------------------------------------------------------------- // // nsIDOMXULDocument interface @@ -1496,6 +1546,16 @@ XULDocument::GetPopupNode(nsIDOMNode** aNode) return NS_OK; } +already_AddRefed +XULDocument::GetPopupNode() +{ + nsCOMPtr node; + DebugOnly rv = GetPopupNode(getter_AddRefs(node)); + MOZ_ASSERT(NS_SUCCEEDED(rv)); + nsCOMPtr retval(do_QueryInterface(node)); + return retval.forget(); +} + NS_IMETHODIMP XULDocument::SetPopupNode(nsIDOMNode* aNode) { @@ -1512,6 +1572,14 @@ XULDocument::SetPopupNode(nsIDOMNode* aNode) return NS_OK; } +void +XULDocument::SetPopupNode(nsINode* aNode) +{ + nsCOMPtr node(do_QueryInterface(aNode)); + DebugOnly rv = SetPopupNode(node); + MOZ_ASSERT(NS_SUCCEEDED(rv)); +} + // Returns the rangeOffset element from the XUL Popup Manager. This is for // chrome callers only. NS_IMETHODIMP @@ -1535,26 +1603,44 @@ XULDocument::GetPopupRangeParent(nsIDOMNode** aRangeParent) return NS_OK; } +already_AddRefed +XULDocument::GetPopupRangeParent(ErrorResult& aRv) +{ + nsCOMPtr node; + aRv = GetPopupRangeParent(getter_AddRefs(node)); + nsCOMPtr retval(do_QueryInterface(node)); + return retval.forget(); +} + + // Returns the rangeOffset element from the XUL Popup Manager. We check the // rangeParent to determine if the caller has rights to access to the data. NS_IMETHODIMP XULDocument::GetPopupRangeOffset(int32_t* aRangeOffset) { - NS_ENSURE_ARG_POINTER(aRangeOffset); + ErrorResult rv; + *aRangeOffset = GetPopupRangeOffset(rv); + return rv.ErrorCode(); +} +int32_t +XULDocument::GetPopupRangeOffset(ErrorResult& aRv) +{ nsXULPopupManager* pm = nsXULPopupManager::GetInstance(); - if (!pm) - return NS_ERROR_FAILURE; + if (!pm) { + aRv.Throw(NS_ERROR_FAILURE); + return 0; + } int32_t offset; nsCOMPtr parent; pm->GetMouseLocation(getter_AddRefs(parent), &offset); - if (parent && !nsContentUtils::CanCallerAccess(parent)) - return NS_ERROR_DOM_SECURITY_ERR; - - *aRangeOffset = offset; - return NS_OK; + if (parent && !nsContentUtils::CanCallerAccess(parent)) { + aRv.Throw(NS_ERROR_DOM_SECURITY_ERR); + return 0; + } + return offset; } NS_IMETHODIMP @@ -1572,6 +1658,16 @@ XULDocument::GetTooltipNode(nsIDOMNode** aNode) return NS_OK; } +already_AddRefed +XULDocument::GetTooltipNode() +{ + nsCOMPtr node; + DebugOnly rv = GetTooltipNode(getter_AddRefs(node)); + MOZ_ASSERT(NS_SUCCEEDED(rv)); + nsCOMPtr retval(do_QueryInterface(node)); + return retval.forget(); +} + NS_IMETHODIMP XULDocument::SetTooltipNode(nsIDOMNode* aNode) { @@ -1774,12 +1870,12 @@ XULDocument::RemoveSubtreeFromDocument(nsIContent* aContent) // 4. Remove the element from our broadcaster map, since it is no longer // in the document. - nsCOMPtr broadcaster, listener; + nsCOMPtr broadcaster, listener; nsAutoString attribute, broadcasterID; rv = FindBroadcaster(aElement, getter_AddRefs(listener), broadcasterID, attribute, getter_AddRefs(broadcaster)); if (rv == NS_FINDBROADCASTER_FOUND) { - RemoveBroadcastListenerFor(broadcaster, listener, attribute); + RemoveBroadcastListenerFor(*broadcaster, *listener, attribute); } return NS_OK; @@ -3232,9 +3328,7 @@ XULDocument::MaybeBroadcast() true); } } - nsCOMPtr broadcaster = - do_QueryInterface(mDelayedAttrChangeBroadcasts[i].mBroadcaster); - ExecuteOnBroadcastHandlerFor(broadcaster, + ExecuteOnBroadcastHandlerFor(mDelayedAttrChangeBroadcasts[i].mBroadcaster, mDelayedAttrChangeBroadcasts[i].mListener, attrName); } @@ -4140,12 +4234,11 @@ XULDocument::BroadcastAttributeChangeFromOverlay(nsIContent* aNode, if (!mBroadcasterMap || !CanBroadcast(aNameSpaceID, aAttribute)) return rv; - nsCOMPtr domele = do_QueryInterface(aNode); - if (!domele) + if (!aNode->IsElement()) return rv; BroadcasterMapEntry* entry = static_cast - (PL_DHashTableOperate(mBroadcasterMap, domele.get(), PL_DHASH_LOOKUP)); + (PL_DHashTableOperate(mBroadcasterMap, aNode->AsElement(), PL_DHASH_LOOKUP)); if (!PL_DHASH_ENTRY_IS_BUSY(entry)) return rv; @@ -4171,12 +4264,11 @@ XULDocument::BroadcastAttributeChangeFromOverlay(nsIContent* aNode, nsresult XULDocument::FindBroadcaster(Element* aElement, - nsIDOMElement** aListener, + Element** aListener, nsString& aBroadcasterID, nsString& aAttribute, - nsIDOMElement** aBroadcaster) + Element** aBroadcaster) { - nsresult rv; nsINodeInfo *ni = aElement->NodeInfo(); *aListener = nullptr; *aBroadcaster = nullptr; @@ -4200,8 +4292,8 @@ XULDocument::FindBroadcaster(Element* aElement, return NS_FINDBROADCASTER_AWAIT_OVERLAYS; } - if (NS_FAILED(CallQueryInterface(parent, aListener))) - *aListener = nullptr; + *aListener = parent->IsElement() ? parent->AsElement() : nullptr; + NS_IF_ADDREF(*aListener); aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::element, aBroadcasterID); if (aBroadcasterID.IsEmpty()) { @@ -4235,8 +4327,8 @@ XULDocument::FindBroadcaster(Element* aElement, } } - if (NS_FAILED(CallQueryInterface(aElement, aListener))) - *aListener = nullptr; + *aListener = aElement; + NS_ADDREF(*aListener); aAttribute.AssignLiteral("*"); } @@ -4245,8 +4337,7 @@ XULDocument::FindBroadcaster(Element* aElement, NS_ENSURE_TRUE(*aListener, NS_ERROR_UNEXPECTED); // Try to find the broadcaster element in the document. - rv = GetElementById(aBroadcasterID, aBroadcaster); - if (NS_FAILED(rv)) return rv; + *aBroadcaster = GetElementById(aBroadcasterID); // If we can't find the broadcaster, then we'll need to defer the // hookup. We may need to resolve some of the other overlays @@ -4255,6 +4346,8 @@ XULDocument::FindBroadcaster(Element* aElement, return NS_FINDBROADCASTER_AWAIT_OVERLAYS; } + NS_ADDREF(*aBroadcaster); + return NS_FINDBROADCASTER_FOUND; } @@ -4270,10 +4363,10 @@ XULDocument::CheckBroadcasterHookup(Element* aElement, *aDidResolve = false; - nsCOMPtr listener; + nsCOMPtr listener; nsAutoString broadcasterID; nsAutoString attribute; - nsCOMPtr broadcaster; + nsCOMPtr broadcaster; rv = FindBroadcaster(aElement, getter_AddRefs(listener), broadcasterID, attribute, getter_AddRefs(broadcaster)); @@ -4290,8 +4383,12 @@ XULDocument::CheckBroadcasterHookup(Element* aElement, return rv; } - rv = AddBroadcastListenerFor(broadcaster, listener, attribute); - if (NS_FAILED(rv)) return rv; + NS_ENSURE_ARG(broadcaster && listener); + ErrorResult domRv; + AddBroadcastListenerFor(*broadcaster, *listener, attribute, domRv); + if (domRv.Failed()) { + return domRv.ErrorCode(); + } #ifdef PR_LOGGING // Tell the world we succeeded @@ -4640,7 +4737,10 @@ XULDocument::GetDocumentLWTheme() NS_IMETHODIMP XULDocument::GetBoxObjectFor(nsIDOMElement* aElement, nsIBoxObject** aResult) { - return nsDocument::GetBoxObjectFor(aElement, aResult); + ErrorResult rv; + nsCOMPtr el = do_QueryInterface(aElement); + *aResult = GetBoxObjectFor(el, rv).get(); + return rv.ErrorCode(); } } // namespace dom diff --git a/content/xul/document/src/XULDocument.h b/content/xul/document/src/XULDocument.h index 7d800fb38e5f..c1ec210a9278 100644 --- a/content/xul/document/src/XULDocument.h +++ b/content/xul/document/src/XULDocument.h @@ -152,6 +152,7 @@ public: using nsDocument::GetLastStyleSheetSet; using nsDocument::MozSetImageElement; using nsDocument::GetMozFullScreenElement; + using nsIDocument::GetLocation; // nsDocument interface overrides virtual Element* GetElementById(const nsAString & elementId); @@ -186,6 +187,42 @@ public: void TraceProtos(JSTracer* aTrc, uint32_t aGCNumber); + // WebIDL API + already_AddRefed GetPopupNode(); + void SetPopupNode(nsINode* aNode); + already_AddRefed GetPopupRangeParent(ErrorResult& aRv); + int32_t GetPopupRangeOffset(ErrorResult& aRv); + already_AddRefed GetTooltipNode(); + void SetTooltipNode(nsINode* aNode) { /* do nothing */ } + nsIDOMXULCommandDispatcher* GetCommandDispatcher() const + { + return mCommandDispatcher; + } + int32_t GetWidth(ErrorResult& aRv); + int32_t GetHeight(ErrorResult& aRv); + already_AddRefed + GetElementsByAttribute(const nsAString& aAttribute, + const nsAString& aValue); + already_AddRefed + GetElementsByAttributeNS(const nsAString& aNamespaceURI, + const nsAString& aAttribute, + const nsAString& aValue, + ErrorResult& aRv); + void AddBroadcastListenerFor(Element& aBroadcaster, Element& aListener, + const nsAString& aAttr, ErrorResult& aRv); + void RemoveBroadcastListenerFor(Element& aBroadcaster, Element& aListener, + const nsAString& aAttr); + void Persist(const nsAString& aId, const nsAString& aAttr, ErrorResult& aRv) + { + aRv = Persist(aId, aAttr); + } + using nsDocument::GetBoxObjectFor; + void LoadOverlay(const nsAString& aURL, nsIObserver* aObserver, + ErrorResult& aRv) + { + aRv = LoadOverlay(aURL, aObserver); + } + protected: // Implementation methods friend nsresult @@ -229,8 +266,8 @@ protected: AddElementToDocumentPost(Element* aElement); nsresult - ExecuteOnBroadcastHandlerFor(nsIContent* aBroadcaster, - nsIDOMElement* aListener, + ExecuteOnBroadcastHandlerFor(Element* aBroadcaster, + Element* aListener, nsIAtom* aAttr); nsresult @@ -522,10 +559,10 @@ protected: // *aBroadcaster do need to be released if non-null, of course). nsresult FindBroadcaster(Element* aElement, - nsIDOMElement** aListener, + Element** aListener, nsString& aBroadcasterID, nsString& aAttribute, - nsIDOMElement** aBroadcaster); + Element** aBroadcaster); nsresult CheckBroadcasterHookup(Element* aElement, @@ -533,8 +570,8 @@ protected: bool* aDidResolve); void - SynchronizeBroadcastListener(nsIDOMElement *aBroadcaster, - nsIDOMElement *aListener, + SynchronizeBroadcastListener(Element *aBroadcaster, + Element *aListener, const nsAString &aAttr); static @@ -674,14 +711,14 @@ protected: class nsDelayedBroadcastUpdate { public: - nsDelayedBroadcastUpdate(nsIDOMElement* aBroadcaster, - nsIDOMElement* aListener, + nsDelayedBroadcastUpdate(Element* aBroadcaster, + Element* aListener, const nsAString &aAttr) : mBroadcaster(aBroadcaster), mListener(aListener), mAttr(aAttr), mSetAttr(false), mNeedsAttrChange(false) {} - nsDelayedBroadcastUpdate(nsIDOMElement* aBroadcaster, - nsIDOMElement* aListener, + nsDelayedBroadcastUpdate(Element* aBroadcaster, + Element* aListener, nsIAtom* aAttrName, const nsAString &aAttr, bool aSetAttr, @@ -695,8 +732,8 @@ protected: mAttr(aOther.mAttr), mAttrName(aOther.mAttrName), mSetAttr(aOther.mSetAttr), mNeedsAttrChange(aOther.mNeedsAttrChange) {} - nsCOMPtr mBroadcaster; - nsCOMPtr mListener; + nsCOMPtr mBroadcaster; + nsCOMPtr mListener; // Note if mAttrName isn't used, this is the name of the attr, otherwise // this is the value of the attribute. nsString mAttr; diff --git a/dom/webidl/XULDocument.webidl b/dom/webidl/XULDocument.webidl new file mode 100644 index 000000000000..3a774079bae0 --- /dev/null +++ b/dom/webidl/XULDocument.webidl @@ -0,0 +1,57 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + * + * The origin of this IDL file is: + * dom/interfaces/xul/nsIDOMXULDocument.idl + */ + +interface XULCommandDispatcher; +interface MozBoxObject; +interface MozObserver; + +interface XULDocument : Document { + attribute Node? popupNode; + + /** + * These attributes correspond to trustedGetPopupNode().rangeOffset and + * rangeParent. They will help you find where in the DOM the popup is + * happening. Can be accessed only during a popup event. Accessing any other + * time will be an error. + */ + [Throws, ChromeOnly] + readonly attribute Node? popupRangeParent; + [Throws, ChromeOnly] + readonly attribute long popupRangeOffset; + + attribute Node? tooltipNode; + + readonly attribute XULCommandDispatcher? commandDispatcher; + + [Throws] + readonly attribute long width; + [Throws] + readonly attribute long height; + + NodeList getElementsByAttribute(DOMString name, + [TreatNullAs=EmptyString] DOMString value); + [Throws] + NodeList getElementsByAttributeNS(DOMString? namespaceURI, DOMString name, + [TreatNullAs=EmptyString] DOMString value); + + [Throws] + void addBroadcastListenerFor(Element broadcaster, Element observer, + DOMString attr); + void removeBroadcastListenerFor(Element broadcaster, Element observer, + DOMString attr); + + [Throws] + void persist([TreatNullAs=EmptyString] DOMString id, DOMString attr); + + [Throws] + MozBoxObject? getBoxObjectFor(Element? element); + + [Throws] + void loadOverlay(DOMString url, MozObserver? observer); +}; diff --git a/layout/xul/base/src/nsXULTooltipListener.cpp b/layout/xul/base/src/nsXULTooltipListener.cpp index ee557a67aa69..c7b8962491b2 100644 --- a/layout/xul/base/src/nsXULTooltipListener.cpp +++ b/layout/xul/base/src/nsXULTooltipListener.cpp @@ -340,10 +340,8 @@ nsXULTooltipListener::CheckTreeBodyMove(nsIDOMMouseEvent* aMouseEvent) nsCOMPtr bx; nsIDocument* doc = sourceNode->GetDocument(); if (doc) { - nsCOMPtr docElement = do_QueryInterface(doc->GetRootElement()); - if (docElement) { - doc->GetBoxObjectFor(docElement, getter_AddRefs(bx)); - } + ErrorResult ignored; + bx = doc->GetBoxObjectFor(doc->GetRootElement(), ignored); } nsCOMPtr obx; diff --git a/layout/xul/tree/nsTreeBodyFrame.cpp b/layout/xul/tree/nsTreeBodyFrame.cpp index ebc06adf5b4d..7c88a2a12e71 100644 --- a/layout/xul/tree/nsTreeBodyFrame.cpp +++ b/layout/xul/tree/nsTreeBodyFrame.cpp @@ -313,9 +313,9 @@ nsTreeBodyFrame::EnsureBoxObject() nsIDocument* nsDoc = parent->GetDocument(); if (!nsDoc) // there may be no document, if we're called from Destroy() return; - nsCOMPtr box; - nsCOMPtr domElem = do_QueryInterface(parent); - nsDoc->GetBoxObjectFor(domElem, getter_AddRefs(box)); + ErrorResult ignored; + nsCOMPtr box = + nsDoc->GetBoxObjectFor(parent->AsElement(), ignored); // Ensure that we got a native box object. nsCOMPtr pBox = do_QueryInterface(box); if (pBox) { From 81ed36b9a021d64c561b28540405a62bf650178a Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Tue, 26 Mar 2013 11:31:54 -0400 Subject: [PATCH 020/129] Bug 848796 part 3. Convert XULDocument to WebIDL. r=peterv --- content/xul/document/src/XULDocument.cpp | 14 +++++++++++++- content/xul/document/src/XULDocument.h | 2 ++ dom/bindings/Bindings.conf | 6 ++++++ dom/bindings/Makefile.in | 1 + dom/webidl/WebIDL.mk | 1 + 5 files changed, 23 insertions(+), 1 deletion(-) diff --git a/content/xul/document/src/XULDocument.cpp b/content/xul/document/src/XULDocument.cpp index ee63965ce7e9..e1dbfc1395b8 100644 --- a/content/xul/document/src/XULDocument.cpp +++ b/content/xul/document/src/XULDocument.cpp @@ -87,6 +87,7 @@ #include "nsCCUncollectableMarker.h" #include "nsURILoader.h" #include "mozilla/dom/Element.h" +#include "mozilla/dom/XULDocumentBinding.h" #include "mozilla/Preferences.h" using namespace mozilla; @@ -202,7 +203,6 @@ XULDocument::XULDocument(void) mState(eState_Master), mResolutionPhase(nsForwardReference::eStart) { - // NOTE! nsDocument::operator new() zeroes out all members, so don't // bother initializing members to 0. @@ -215,6 +215,8 @@ XULDocument::XULDocument(void) mDelayFrameLoaderInitialization = true; mAllowXULXBL = eTriTrue; + + SetIsDOMBinding(); } XULDocument::~XULDocument() @@ -4743,5 +4745,15 @@ XULDocument::GetBoxObjectFor(nsIDOMElement* aElement, nsIBoxObject** aResult) return rv.ErrorCode(); } +JSObject* +XULDocument::WrapNode(JSContext *aCx, JSObject *aScope) +{ + JSObject* obj = XULDocumentBinding::Wrap(aCx, aScope, this); + if (obj && !PostCreateWrapper(aCx, obj)) { + return nullptr; + } + return obj; +} + } // namespace dom } // namespace mozilla diff --git a/content/xul/document/src/XULDocument.h b/content/xul/document/src/XULDocument.h index c1ec210a9278..86d1ad9e6678 100644 --- a/content/xul/document/src/XULDocument.h +++ b/content/xul/document/src/XULDocument.h @@ -296,6 +296,8 @@ protected: nsresult Persist(nsIContent* aElement, int32_t aNameSpaceID, nsIAtom* aAttribute); + virtual JSObject* WrapNode(JSContext *aCx, JSObject *aScope) MOZ_OVERRIDE; + // IMPORTANT: The ownership implicit in the following member // variables has been explicitly checked and set using nsCOMPtr // for owning pointers and raw COM interface pointers for weak diff --git a/dom/bindings/Bindings.conf b/dom/bindings/Bindings.conf index 4d62e4636f48..c052d6b0f905 100644 --- a/dom/bindings/Bindings.conf +++ b/dom/bindings/Bindings.conf @@ -1103,6 +1103,10 @@ DOMInterfaces = { 'wrapperCache': False }, +'XULDocument': { + 'headerFile': 'XULDocument.h' +}, + 'XULElement': { 'nativeType': 'nsXULElement', 'resultNotAddRefed': [ 'controllers', 'style' ] @@ -1368,6 +1372,7 @@ addExternalIface('MenuBuilder', nativeType='nsIMenuBuilder', notflattened=True) addExternalIface('MozBoxObject', nativeType='nsIBoxObject') addExternalIface('MozControllers', nativeType='nsIControllers') addExternalIface('MozFrameLoader', nativeType='nsIFrameLoader', notflattened=True) +addExternalIface('MozObserver', nativeType='nsIObserver', notflattened=True) addExternalIface('MozRDFCompositeDataSource', nativeType='nsIRDFCompositeDataSource', notflattened=True) addExternalIface('MozRDFResource', nativeType='nsIRDFResource', notflattened=True) @@ -1398,3 +1403,4 @@ addExternalIface('WindowProxy', nativeType='nsIDOMWindow') addExternalIface('XPathResult', nativeType='nsISupports') addExternalIface('XPathExpression') addExternalIface('XPathNSResolver') +addExternalIface('XULCommandDispatcher') diff --git a/dom/bindings/Makefile.in b/dom/bindings/Makefile.in index c7c682a6049b..dd0f59fd7584 100644 --- a/dom/bindings/Makefile.in +++ b/dom/bindings/Makefile.in @@ -88,6 +88,7 @@ LOCAL_INCLUDES += -I$(topsrcdir)/js/xpconnect/src \ -I$(topsrcdir)/content/xslt/src/xpath \ -I$(topsrcdir)/content/xml/content/src \ -I$(topsrcdir)/content/xul/content/src \ + -I$(topsrcdir)/content/xul/document/src \ $(NULL) ifdef MOZ_AUDIO_CHANNEL_MANAGER diff --git a/dom/webidl/WebIDL.mk b/dom/webidl/WebIDL.mk index 1f44c9f40c17..c62d75b3e99b 100644 --- a/dom/webidl/WebIDL.mk +++ b/dom/webidl/WebIDL.mk @@ -278,6 +278,7 @@ webidl_files = \ XMLSerializer.webidl \ XMLStylesheetProcessingInstruction.webidl \ XPathEvaluator.webidl \ + XULDocument.webidl \ XULElement.webidl \ $(NULL) From 0bf77266026316d2f1881bd5227ca265c1af3b3b Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Tue, 26 Mar 2013 11:31:54 -0400 Subject: [PATCH 021/129] Bug 848332 part 1. Add WebIDL API for XMLDocument. r=peterv --- content/xml/document/src/XMLDocument.cpp | 83 ++++++++++++++++-------- content/xml/document/src/XMLDocument.h | 17 +++++ dom/webidl/XMLDocument.webidl | 23 +++++++ 3 files changed, 95 insertions(+), 28 deletions(-) create mode 100644 dom/webidl/XMLDocument.webidl diff --git a/content/xml/document/src/XMLDocument.cpp b/content/xml/document/src/XMLDocument.cpp index d47f0e5c5beb..4ec0408c71ff 100644 --- a/content/xml/document/src/XMLDocument.cpp +++ b/content/xml/document/src/XMLDocument.cpp @@ -298,17 +298,25 @@ ReportUseOfDeprecatedMethod(nsIDocument *aDoc, const char* aWarning) NS_IMETHODIMP XMLDocument::Load(const nsAString& aUrl, bool *aReturn) +{ + ErrorResult rv; + *aReturn = Load(aUrl, rv); + return rv.ErrorCode(); +} + +bool +XMLDocument::Load(const nsAString& aUrl, ErrorResult& aRv) { bool hasHadScriptObject = true; nsIScriptGlobalObject* scriptObject = GetScriptHandlingObject(hasHadScriptObject); - NS_ENSURE_STATE(scriptObject || !hasHadScriptObject); + if (!scriptObject && hasHadScriptObject) { + aRv.Throw(NS_ERROR_UNEXPECTED); + return false; + } ReportUseOfDeprecatedMethod(this, "UseOfDOM3LoadMethodWarning"); - NS_ENSURE_ARG_POINTER(aReturn); - *aReturn = false; - nsCOMPtr callingDoc = do_QueryInterface(nsContentUtils::GetDocumentFromContext()); @@ -324,7 +332,8 @@ XMLDocument::Load(const nsAString& aUrl, bool *aReturn) nsCOMPtr uri; nsresult rv = NS_NewURI(getter_AddRefs(uri), aUrl, charset.get(), baseURI); if (NS_FAILED(rv)) { - return rv; + aRv.Throw(rv); + return false; } // Check to see whether the current document is allowed to load this URI. @@ -338,7 +347,10 @@ XMLDocument::Load(const nsAString& aUrl, bool *aReturn) nsCOMPtr principal = NodePrincipal(); if (!nsContentUtils::IsSystemPrincipal(principal)) { rv = principal->CheckMayLoad(uri, false, false); - NS_ENSURE_SUCCESS(rv, rv); + if (NS_FAILED(rv)) { + aRv.Throw(rv); + return false; + } int16_t shouldLoad = nsIContentPolicy::ACCEPT; rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_XMLHTTPREQUEST, @@ -351,9 +363,13 @@ XMLDocument::Load(const nsAString& aUrl, bool *aReturn) &shouldLoad, nsContentUtils::GetContentPolicy(), nsContentUtils::GetSecurityManager()); - NS_ENSURE_SUCCESS(rv, rv); + if (NS_FAILED(rv)) { + aRv.Throw(rv); + return false; + } if (NS_CP_REJECTED(shouldLoad)) { - return NS_ERROR_CONTENT_BLOCKED; + aRv.Throw(NS_ERROR_CONTENT_BLOCKED); + return false; } } else { // We're called from chrome, check to make sure the URI we're @@ -370,7 +386,10 @@ XMLDocument::Load(const nsAString& aUrl, bool *aReturn) "longer supported. Use XMLHttpRequest instead."); nsCOMPtr errorObject = do_CreateInstance(NS_SCRIPTERROR_CONTRACTID, &rv); - NS_ENSURE_SUCCESS(rv, rv); + if (NS_FAILED(rv)) { + aRv.Throw(rv); + return false; + } rv = errorObject->InitWithWindowID(error, NS_ConvertUTF8toUTF16(spec), @@ -381,7 +400,10 @@ XMLDocument::Load(const nsAString& aUrl, bool *aReturn) callingDoc->InnerWindowID() : this->InnerWindowID()); - NS_ENSURE_SUCCESS(rv, rv); + if (NS_FAILED(rv)) { + aRv.Throw(rv); + return false; + } nsCOMPtr consoleService = do_GetService(NS_CONSOLESERVICE_CONTRACTID); @@ -389,7 +411,8 @@ XMLDocument::Load(const nsAString& aUrl, bool *aReturn) consoleService->LogMessage(errorObject); } - return NS_ERROR_DOM_SECURITY_ERR; + aRv.Throw(NS_ERROR_DOM_SECURITY_ERR); + return false; } } @@ -418,7 +441,10 @@ XMLDocument::Load(const nsAString& aUrl, bool *aReturn) // Create a channel nsCOMPtr req = nsContentUtils::GetSameOriginChecker(); - NS_ENSURE_TRUE(req, NS_ERROR_OUT_OF_MEMORY); + if (!req) { + aRv.Throw(NS_ERROR_OUT_OF_MEMORY); + return false; + } nsCOMPtr channel; // nsIRequest::LOAD_BACKGROUND prevents throbber from becoming active, @@ -426,7 +452,8 @@ XMLDocument::Load(const nsAString& aUrl, bool *aReturn) rv = NS_NewChannel(getter_AddRefs(channel), uri, nullptr, loadGroup, req, nsIRequest::LOAD_BACKGROUND); if (NS_FAILED(rv)) { - return rv; + aRv.Throw(rv); + return false; } // StartDocumentLoad asserts that readyState is uninitialized, so @@ -444,7 +471,8 @@ XMLDocument::Load(const nsAString& aUrl, bool *aReturn) getter_AddRefs(listener), false))) { NS_ERROR("XMLDocument::Load: Failed to start the document load."); - return rv; + aRv.Throw(rv); + return false; } // After this point, if we error out of this method we should clear @@ -454,7 +482,8 @@ XMLDocument::Load(const nsAString& aUrl, bool *aReturn) rv = channel->AsyncOpen(listener, nullptr); if (NS_FAILED(rv)) { mChannelIsPending = false; - return rv; + aRv.Throw(rv); + return false; } if (!mAsync) { @@ -468,23 +497,21 @@ XMLDocument::Load(const nsAString& aUrl, bool *aReturn) } // We set return to true unless there was a parsing error - nsCOMPtr node = do_QueryInterface(GetRootElement()); - if (node) { - nsAutoString name, ns; - if (NS_SUCCEEDED(node->GetLocalName(name)) && - name.EqualsLiteral("parsererror") && - NS_SUCCEEDED(node->GetNamespaceURI(ns)) && - ns.EqualsLiteral("http://www.mozilla.org/newlayout/xml/parsererror.xml")) { - //return is already false - } else { - *aReturn = true; + Element* rootElement = GetRootElement(); + if (!rootElement) { + return false; + } + + if (rootElement->LocalName().EqualsLiteral("parsererror")) { + nsAutoString ns; + rootElement->GetNamespaceURI(ns); + if (ns.EqualsLiteral("http://www.mozilla.org/newlayout/xml/parsererror.xml")) { + return false; } } - } else { - *aReturn = true; } - return NS_OK; + return true; } nsresult diff --git a/content/xml/document/src/XMLDocument.h b/content/xml/document/src/XMLDocument.h index e05184a3b70d..d163af46f62c 100644 --- a/content/xml/document/src/XMLDocument.h +++ b/content/xml/document/src/XMLDocument.h @@ -51,6 +51,23 @@ public: virtual void DocSizeOfExcludingThis(nsWindowSizes* aWindowSizes) const; // DocSizeOfIncludingThis is inherited from nsIDocument. + + // WebIDL API + bool Load(const nsAString& aUrl, mozilla::ErrorResult& aRv); + bool Async() const + { + return mAsync; + } + // The XPCOM SetAsync is ok for us + + // .location is [Unforgeable], so we have to make it clear that the + // nsIDocument version applies to us (it's shadowed by the XPCOM thing on + // nsDocument). + using nsIDocument::GetLocation; + // But then we need to also pull in the nsDocument XPCOM version + // because nsXULDocument tries to forward to it. + using nsDocument::GetLocation; + protected: // mChannelIsPending indicates whether we're currently asynchronously loading // data from mChannel (via document.load() or normal load). It's set to true diff --git a/dom/webidl/XMLDocument.webidl b/dom/webidl/XMLDocument.webidl new file mode 100644 index 000000000000..0f503c9f5ceb --- /dev/null +++ b/dom/webidl/XMLDocument.webidl @@ -0,0 +1,23 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + * + * The origin of this IDL file is: + * http://dom.spec.whatwg.org/#xmldocument + * http://www.whatwg.org/specs/web-apps/current-work/#xmldocument + */ + +// http://dom.spec.whatwg.org/#xmldocument +interface XMLDocument : Document {}; + +// http://www.whatwg.org/specs/web-apps/current-work/#xmldocument +partial interface XMLDocument { + [Throws] + boolean load(DOMString url); +}; + +// Gecko extensions? +partial interface XMLDocument { + attribute boolean async; +}; From 24422ccd0d3c3f785397e660a9197e7890f9c14b Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Tue, 26 Mar 2013 11:31:54 -0400 Subject: [PATCH 022/129] Bug 848332 part 2. Switch XMLDocument to WebIDL. r=peterv --- content/svg/document/src/SVGDocument.cpp | 1 - content/xml/document/src/XMLDocument.cpp | 14 +++++++++++++- content/xml/document/src/XMLDocument.h | 2 ++ content/xul/document/src/XULDocument.cpp | 2 -- .../tests/approved/test_interfaces.html.json | 4 ---- .../submissions/Ms2ger/test_historical.html.json | 4 +--- dom/webidl/WebIDL.mk | 1 + 7 files changed, 17 insertions(+), 11 deletions(-) diff --git a/content/svg/document/src/SVGDocument.cpp b/content/svg/document/src/SVGDocument.cpp index dce5aea73ba3..73fcc915b395 100644 --- a/content/svg/document/src/SVGDocument.cpp +++ b/content/svg/document/src/SVGDocument.cpp @@ -23,7 +23,6 @@ namespace dom { SVGDocument::SVGDocument() { - SetIsDOMBinding(); } SVGDocument::~SVGDocument() diff --git a/content/xml/document/src/XMLDocument.cpp b/content/xml/document/src/XMLDocument.cpp index 4ec0408c71ff..ce2f7f517cf3 100644 --- a/content/xml/document/src/XMLDocument.cpp +++ b/content/xml/document/src/XMLDocument.cpp @@ -52,6 +52,7 @@ #include "nsIScriptError.h" #include "nsIHTMLDocument.h" #include "mozilla/dom/Element.h" // DOMCI_NODE_DATA +#include "mozilla/dom/XMLDocumentBinding.h" using namespace mozilla; using namespace mozilla::dom; @@ -219,9 +220,10 @@ XMLDocument::XMLDocument(const char* aContentType) : nsDocument(aContentType), mAsync(true) { - // NOTE! nsDocument::operator new() zeroes out all members, so don't // bother initializing members to 0. + + SetIsDOMBinding(); } XMLDocument::~XMLDocument() @@ -625,5 +627,15 @@ XMLDocument::Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const return CallQueryInterface(clone.get(), aResult); } +JSObject* +XMLDocument::WrapNode(JSContext *aCx, JSObject *aScope) +{ + JSObject* obj = XMLDocumentBinding::Wrap(aCx, aScope, this); + if (obj && !PostCreateWrapper(aCx, obj)) { + return nullptr; + } + return obj; +} + } // namespace dom } // namespace mozilla diff --git a/content/xml/document/src/XMLDocument.h b/content/xml/document/src/XMLDocument.h index d163af46f62c..cad4603e2825 100644 --- a/content/xml/document/src/XMLDocument.h +++ b/content/xml/document/src/XMLDocument.h @@ -69,6 +69,8 @@ public: using nsDocument::GetLocation; protected: + virtual JSObject* WrapNode(JSContext *aCx, JSObject *aScope) MOZ_OVERRIDE; + // mChannelIsPending indicates whether we're currently asynchronously loading // data from mChannel (via document.load() or normal load). It's set to true // when we first find out about the channel (StartDocumentLoad) and set to diff --git a/content/xul/document/src/XULDocument.cpp b/content/xul/document/src/XULDocument.cpp index e1dbfc1395b8..8e84ca16a6fb 100644 --- a/content/xul/document/src/XULDocument.cpp +++ b/content/xul/document/src/XULDocument.cpp @@ -215,8 +215,6 @@ XULDocument::XULDocument(void) mDelayFrameLoaderInitialization = true; mAllowXULXBL = eTriTrue; - - SetIsDOMBinding(); } XULDocument::~XULDocument() diff --git a/dom/imptests/failures/webapps/DOMCore/tests/approved/test_interfaces.html.json b/dom/imptests/failures/webapps/DOMCore/tests/approved/test_interfaces.html.json index ea778201df4b..40307e5b8d1d 100644 --- a/dom/imptests/failures/webapps/DOMCore/tests/approved/test_interfaces.html.json +++ b/dom/imptests/failures/webapps/DOMCore/tests/approved/test_interfaces.html.json @@ -51,10 +51,6 @@ "MutationCallback interface: existence and properties of interface prototype object": true, "MutationCallback interface: existence and properties of interface prototype object's \"constructor\" property": true, "MutationCallback interface: operation handleEvent(MutationRecord,MutationObserver)": true, - "XMLDocument interface: existence and properties of interface object": true, - "XMLDocument interface: existence and properties of interface prototype object": true, - "XMLDocument interface: existence and properties of interface prototype object's \"constructor\" property": true, - "Stringification of xmlDoc": "debug", "DocumentType interface: operation remove()": true, "DocumentType interface: document.doctype must inherit property \"remove\" with the proper type (3)": true, "Element interface: attribute namespaceURI": true, diff --git a/dom/imptests/failures/webapps/DOMCore/tests/submissions/Ms2ger/test_historical.html.json b/dom/imptests/failures/webapps/DOMCore/tests/submissions/Ms2ger/test_historical.html.json index 5354b0c20752..d7c832bbbcb9 100644 --- a/dom/imptests/failures/webapps/DOMCore/tests/submissions/Ms2ger/test_historical.html.json +++ b/dom/imptests/failures/webapps/DOMCore/tests/submissions/Ms2ger/test_historical.html.json @@ -9,7 +9,5 @@ "Historical DOM features must be removed: getAttributeNodeNS": true, "Historical DOM features must be removed: setAttributeNode": true, "Historical DOM features must be removed: removeAttributeNode": true, - "DocumentType member must be nuked: internalSubset": true, - "Node member must be nuked: getUserData": true, - "Node member must be nuked: setUserData": true + "DocumentType member must be nuked: internalSubset": true } diff --git a/dom/webidl/WebIDL.mk b/dom/webidl/WebIDL.mk index c62d75b3e99b..bc3816cdfce9 100644 --- a/dom/webidl/WebIDL.mk +++ b/dom/webidl/WebIDL.mk @@ -272,6 +272,7 @@ webidl_files = \ UndoManager.webidl \ URLUtils.webidl \ USSDReceivedEvent.webidl \ + XMLDocument.webidl \ XMLHttpRequest.webidl \ XMLHttpRequestEventTarget.webidl \ XMLHttpRequestUpload.webidl \ From 618492fbf17a454df7313c468c1d35e8bf19d6b5 Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Tue, 26 Mar 2013 11:31:54 -0400 Subject: [PATCH 023/129] Bug 848840. Sniff the first 1024 bytes, not the first 512, for charsets, since can be anywhere in the first 1024 bytes. r=annevk --- netwerk/base/src/nsUnicharStreamLoader.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/netwerk/base/src/nsUnicharStreamLoader.cpp b/netwerk/base/src/nsUnicharStreamLoader.cpp index e2782a9b7a26..0898e39ebd5d 100644 --- a/netwerk/base/src/nsUnicharStreamLoader.cpp +++ b/netwerk/base/src/nsUnicharStreamLoader.cpp @@ -11,7 +11,11 @@ #include "nsIServiceManager.h" #include -#define SNIFFING_BUFFER_SIZE 512 // specified in draft-abarth-mime-sniff-06 +// 1024 bytes is specified in +// http://www.whatwg.org/specs/web-apps/current-work/#charset for HTML; for +// other resource types (e.g. CSS) typically fewer bytes are fine too, since +// they only look at things right at the beginning of the data. +#define SNIFFING_BUFFER_SIZE 1024 using namespace mozilla; From 57ca2ed5ab1191f5caca1c30a889e6c850ed49e4 Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Tue, 26 Mar 2013 11:31:54 -0400 Subject: [PATCH 024/129] Bug 851162. Make the auto-generated WrapObject in JS-implemented WebIDL codegen MOZ_OVERRIDE. r=mccr8 --- dom/bindings/Codegen.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/dom/bindings/Codegen.py b/dom/bindings/Codegen.py index b196fb52af1c..e7feb6a98355 100644 --- a/dom/bindings/Codegen.py +++ b/dom/bindings/Codegen.py @@ -5345,7 +5345,11 @@ class ClassMethod(ClassItem): virtual=False, const=False, bodyInHeader=False, templateArgs=None, visibility='public', body=None, breakAfterReturnDecl="\n", - breakAfterSelf="\n"): + breakAfterSelf="\n", override=False): + """ + override indicates whether to flag the method as MOZ_OVERRIDE + """ + assert not override or virtual self.returnType = returnType self.args = args self.inline = inline or bodyInHeader @@ -5357,6 +5361,7 @@ class ClassMethod(ClassItem): self.body = body self.breakAfterReturnDecl = breakAfterReturnDecl self.breakAfterSelf = breakAfterSelf + self.override = override ClassItem.__init__(self, name, visibility) def getDecorators(self, declaring): @@ -5388,7 +5393,7 @@ class ClassMethod(ClassItem): body = ';' return string.Template("${templateClause}${decorators}${returnType}%s" - "${name}(${args})${const}${body}%s" % + "${name}(${args})${const}${override}${body}%s" % (self.breakAfterReturnDecl, self.breakAfterSelf) ).substitute({ 'templateClause': templateClause, @@ -5396,6 +5401,7 @@ class ClassMethod(ClassItem): 'returnType': self.returnType, 'name': self.name, 'const': ' const' if self.const else '', + 'override': ' MOZ_OVERRIDE' if self.override else '', 'args': args, 'body': body }) @@ -7824,6 +7830,7 @@ class CGBindingImplClass(CGClass): ClassMethod("WrapObject", "JSObject*", wrapArgs, virtual=descriptor.wrapperCache, breakAfterReturnDecl=" ", + override=descriptor.wrapperCache, body=self.getWrapObjectBody())) self.methodDecls.insert(0, ClassMethod("GetParentObject", From c45fad25b0bc252f497b48eb187f4b21f28c6f20 Mon Sep 17 00:00:00 2001 From: Joshua Cranmer Date: Tue, 19 Mar 2013 15:38:00 -0500 Subject: [PATCH 025/129] Bug 852745 - Build clang with gcc 4.7 headers, r=rail. DONTBUILD --HG-- extra : rebase_source : 33518aae835d12387a8fb7f1cdfe8c8e29f5bd2a --- .../tooltool-manifests/linux32/clang.manifest | 20 +++++++++---------- .../tooltool-manifests/linux64/clang.manifest | 12 +++++------ build/unix/build-clang/build-clang.py | 4 ++-- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/browser/config/tooltool-manifests/linux32/clang.manifest b/browser/config/tooltool-manifests/linux32/clang.manifest index 8e62c65905e3..8ce74c6e79cb 100644 --- a/browser/config/tooltool-manifests/linux32/clang.manifest +++ b/browser/config/tooltool-manifests/linux32/clang.manifest @@ -1,17 +1,17 @@ [ { "clang_version": "r170890" -}, +}, { -"size": 47, -"digest": "2005a41fe97a5e00997063705f39d42b6a43b1cf7ba306cbc7b1513de34cdcd050fc6326efa2107f19ba0cc67914745dbf13154fa748010a93cf072481ef4aaa", -"algorithm": "sha512", -"filename": "setup.sh" -}, +"filename": "setup.sh", +"algorithm": "sha512", +"digest": "2005a41fe97a5e00997063705f39d42b6a43b1cf7ba306cbc7b1513de34cdcd050fc6326efa2107f19ba0cc67914745dbf13154fa748010a93cf072481ef4aaa", +"size": 47 +}, { -"size": 61878284, -"digest": "a3f924e7a6d8651b3466f3dc4625eaa00f90ee6cc824ddd4da7a27ce26916220615c1aa33e4a286b757b9283c536b8311edddf469d23e9e1306b90dff19ae11f", -"algorithm": "sha512", -"filename": "clang.tar.bz2" +"filename": "clang.tar.bz2", +"algorithm": "sha512", +"digest": "0bcfc19f05cc0f042befb3823c7ecce9ba411b152921aa29e97e7adc846e0258fd7da521b1620cb1e61a19d2fcac9b60e6d613c922b6c153e01b9b0766651d09", +"size": 62708281 } ] diff --git a/browser/config/tooltool-manifests/linux64/clang.manifest b/browser/config/tooltool-manifests/linux64/clang.manifest index f461fbb14ec0..39ba55904656 100644 --- a/browser/config/tooltool-manifests/linux64/clang.manifest +++ b/browser/config/tooltool-manifests/linux64/clang.manifest @@ -3,15 +3,15 @@ "clang_version": "r170890" }, { -"size": 47, -"digest": "2005a41fe97a5e00997063705f39d42b6a43b1cf7ba306cbc7b1513de34cdcd050fc6326efa2107f19ba0cc67914745dbf13154fa748010a93cf072481ef4aaa", +"filename": "setup.sh", "algorithm": "sha512", -"filename": "setup.sh" +"digest": "2005a41fe97a5e00997063705f39d42b6a43b1cf7ba306cbc7b1513de34cdcd050fc6326efa2107f19ba0cc67914745dbf13154fa748010a93cf072481ef4aaa", +"size": 47 }, { -"size": 62279506, -"digest": "aa886361161a7d32aad71dfe5fd6b6cdff25610d8e32153a80caea66a8475aa8526d8529d8ac26e8ac26bd32878ee0df6d8dbef95dfd9faacec45b4ab918d52d", +"filename": "clang.tar.bz2", "algorithm": "sha512", -"filename": "clang.tar.bz2" +"digest": "e14ccefd965372a57c540647b2b99e21a4aa82f81a8b9a9e18dac7cba4c3436181bef0dfab8c51bcb5c343f504a693fdcfbe7d609f10291b5dd65ab059979d29", +"size": 63034761 } ] diff --git a/build/unix/build-clang/build-clang.py b/build/unix/build-clang/build-clang.py index 212c4777cd45..e9bfe3a074c4 100755 --- a/build/unix/build-clang/build-clang.py +++ b/build/unix/build-clang/build-clang.py @@ -111,9 +111,9 @@ def build_one_stage_aux(stage_dir, is_stage_one): "--enable-targets=x86,x86_64,arm", "--disable-assertions", "--prefix=%s" % inst_dir, - "--with-gcc-toolchain=/tools/gcc-4.5-0moz3"] + "--with-gcc-toolchain=/tools/gcc-4.7.2-0moz1"] build_package(llvm_source_dir, build_dir, configure_opts, - ["CLANG_IS_PRODUCTION=1"]) + []) if isDarwin: os.environ['MACOSX_DEPLOYMENT_TARGET'] = '10.7' From b611899f62731bab2ff51f37a51683513cc352ba Mon Sep 17 00:00:00 2001 From: Andrea Marchesini Date: Tue, 26 Mar 2013 16:52:41 +0100 Subject: [PATCH 026/129] Bug 852620 - Rename nsSVGRect to SVGRect, r=Ms2ger --HG-- rename : content/svg/content/src/nsSVGRect.cpp => content/svg/content/src/SVGRect.cpp rename : content/svg/content/src/nsSVGRect.h => content/svg/content/src/SVGRect.h --- content/svg/content/src/Makefile.in | 4 +- .../src/{nsSVGRect.cpp => SVGRect.cpp} | 38 ++++++++++--------- .../content/src/{nsSVGRect.h => SVGRect.h} | 18 ++++++--- content/svg/content/src/SVGSVGElement.cpp | 2 +- .../content/src/SVGTransformableElement.cpp | 2 +- layout/svg/nsSVGGlyphFrame.cpp | 2 +- layout/svg/nsSVGTextFrame2.cpp | 4 +- 7 files changed, 40 insertions(+), 30 deletions(-) rename content/svg/content/src/{nsSVGRect.cpp => SVGRect.cpp} (73%) rename content/svg/content/src/{nsSVGRect.h => SVGRect.h} (73%) diff --git a/content/svg/content/src/Makefile.in b/content/svg/content/src/Makefile.in index 4b9627479601..e6880e54885e 100644 --- a/content/svg/content/src/Makefile.in +++ b/content/svg/content/src/Makefile.in @@ -50,7 +50,7 @@ CPPSRCS = \ nsSVGPathGeometryElement.cpp \ nsSVGPolyElement.cpp \ nsSVGString.cpp \ - nsSVGRect.cpp \ + SVGRect.cpp \ nsSVGUnknownElement.cpp \ nsSVGViewBox.cpp \ SVGAElement.cpp \ @@ -165,7 +165,6 @@ EXPORTS = \ nsSVGClass.h \ nsSVGElement.h \ nsSVGFeatures.h \ - nsSVGRect.h \ SVGAttrValueWrapper.h \ SVGStringList.h \ $(NULL) @@ -223,6 +222,7 @@ EXPORTS_mozilla/dom = \ SVGPatternElement.h \ SVGPolygonElement.h \ SVGPolylineElement.h \ + SVGRect.h \ SVGRectElement.h \ SVGScriptElement.h \ SVGSetElement.h \ diff --git a/content/svg/content/src/nsSVGRect.cpp b/content/svg/content/src/SVGRect.cpp similarity index 73% rename from content/svg/content/src/nsSVGRect.cpp rename to content/svg/content/src/SVGRect.cpp index f2913682f727..0fd68f7e804b 100644 --- a/content/svg/content/src/nsSVGRect.cpp +++ b/content/svg/content/src/SVGRect.cpp @@ -3,14 +3,19 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#include "nsSVGRect.h" +#include "mozilla/dom/SVGRect.h" #include "nsContentUtils.h" #include "nsDOMClassInfoID.h" +DOMCI_DATA(SVGRect, mozilla::dom::SVGRect) + +namespace mozilla { +namespace dom { + //---------------------------------------------------------------------- // implementation: -nsSVGRect::nsSVGRect(float x, float y, float w, float h) +SVGRect::SVGRect(float x, float y, float w, float h) : mX(x), mY(y), mWidth(w), mHeight(h) { } @@ -18,12 +23,10 @@ nsSVGRect::nsSVGRect(float x, float y, float w, float h) //---------------------------------------------------------------------- // nsISupports methods: -NS_IMPL_ADDREF(nsSVGRect) -NS_IMPL_RELEASE(nsSVGRect) +NS_IMPL_ADDREF(SVGRect) +NS_IMPL_RELEASE(SVGRect) -DOMCI_DATA(SVGRect, nsSVGRect) - -NS_INTERFACE_MAP_BEGIN(nsSVGRect) +NS_INTERFACE_MAP_BEGIN(SVGRect) NS_INTERFACE_MAP_ENTRY(nsIDOMSVGRect) NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGRect) NS_INTERFACE_MAP_ENTRY(nsISupports) @@ -33,12 +36,12 @@ NS_INTERFACE_MAP_END // nsIDOMSVGRect methods: /* attribute float x; */ -NS_IMETHODIMP nsSVGRect::GetX(float *aX) +NS_IMETHODIMP SVGRect::GetX(float *aX) { *aX = mX; return NS_OK; } -NS_IMETHODIMP nsSVGRect::SetX(float aX) +NS_IMETHODIMP SVGRect::SetX(float aX) { NS_ENSURE_FINITE(aX, NS_ERROR_ILLEGAL_VALUE); mX = aX; @@ -46,12 +49,12 @@ NS_IMETHODIMP nsSVGRect::SetX(float aX) } /* attribute float y; */ -NS_IMETHODIMP nsSVGRect::GetY(float *aY) +NS_IMETHODIMP SVGRect::GetY(float *aY) { *aY = mY; return NS_OK; } -NS_IMETHODIMP nsSVGRect::SetY(float aY) +NS_IMETHODIMP SVGRect::SetY(float aY) { NS_ENSURE_FINITE(aY, NS_ERROR_ILLEGAL_VALUE); mY = aY; @@ -59,12 +62,12 @@ NS_IMETHODIMP nsSVGRect::SetY(float aY) } /* attribute float width; */ -NS_IMETHODIMP nsSVGRect::GetWidth(float *aWidth) +NS_IMETHODIMP SVGRect::GetWidth(float *aWidth) { *aWidth = mWidth; return NS_OK; } -NS_IMETHODIMP nsSVGRect::SetWidth(float aWidth) +NS_IMETHODIMP SVGRect::SetWidth(float aWidth) { NS_ENSURE_FINITE(aWidth, NS_ERROR_ILLEGAL_VALUE); mWidth = aWidth; @@ -72,19 +75,20 @@ NS_IMETHODIMP nsSVGRect::SetWidth(float aWidth) } /* attribute float height; */ -NS_IMETHODIMP nsSVGRect::GetHeight(float *aHeight) +NS_IMETHODIMP SVGRect::GetHeight(float *aHeight) { *aHeight = mHeight; return NS_OK; } -NS_IMETHODIMP nsSVGRect::SetHeight(float aHeight) +NS_IMETHODIMP SVGRect::SetHeight(float aHeight) { NS_ENSURE_FINITE(aHeight, NS_ERROR_ILLEGAL_VALUE); mHeight = aHeight; return NS_OK; } - +} // namespace dom +} // namespace mozilla //////////////////////////////////////////////////////////////////////// // Exported creation functions: @@ -93,7 +97,7 @@ nsresult NS_NewSVGRect(nsIDOMSVGRect** result, float x, float y, float width, float height) { - *result = new nsSVGRect(x, y, width, height); + *result = new mozilla::dom::SVGRect(x, y, width, height); if (!*result) return NS_ERROR_OUT_OF_MEMORY; NS_ADDREF(*result); return NS_OK; diff --git a/content/svg/content/src/nsSVGRect.h b/content/svg/content/src/SVGRect.h similarity index 73% rename from content/svg/content/src/nsSVGRect.h rename to content/svg/content/src/SVGRect.h index 648d46d67681..f4c87d66a793 100644 --- a/content/svg/content/src/nsSVGRect.h +++ b/content/svg/content/src/SVGRect.h @@ -3,8 +3,8 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#ifndef __NS_SVGRECT_H__ -#define __NS_SVGRECT_H__ +#ifndef mozilla_dom_SVGRect_h +#define mozilla_dom_SVGRect_h #include "gfxRect.h" #include "nsIDOMSVGRect.h" @@ -19,12 +19,15 @@ nsresult NS_NewSVGRect(nsIDOMSVGRect** result, const gfxRect& rect); //////////////////////////////////////////////////////////////////////// -// nsSVGRect class +// SVGRect class -class nsSVGRect MOZ_FINAL : public nsIDOMSVGRect +namespace mozilla { +namespace dom { + +class SVGRect MOZ_FINAL : public nsIDOMSVGRect { public: - nsSVGRect(float x=0.0f, float y=0.0f, float w=0.0f, float h=0.0f); + SVGRect(float x=0.0f, float y=0.0f, float w=0.0f, float h=0.0f); // nsISupports interface: NS_DECL_ISUPPORTS @@ -36,4 +39,7 @@ protected: float mX, mY, mWidth, mHeight; }; -#endif //__NS_SVGRECT_H__ +} // namespace dom +} // namespace mozilla + +#endif //mozilla_dom_SVGRect_h diff --git a/content/svg/content/src/SVGSVGElement.cpp b/content/svg/content/src/SVGSVGElement.cpp index fb71db8ef714..eddb87c8df76 100644 --- a/content/svg/content/src/SVGSVGElement.cpp +++ b/content/svg/content/src/SVGSVGElement.cpp @@ -20,7 +20,7 @@ #include "DOMSVGPoint.h" #include "nsIFrame.h" #include "nsISVGSVGFrame.h" //XXX -#include "nsSVGRect.h" +#include "mozilla/dom/SVGRect.h" #include "nsError.h" #include "nsISVGChildFrame.h" #include "nsGUIEvent.h" diff --git a/content/svg/content/src/SVGTransformableElement.cpp b/content/svg/content/src/SVGTransformableElement.cpp index be24b919fea4..515d589411a2 100644 --- a/content/svg/content/src/SVGTransformableElement.cpp +++ b/content/svg/content/src/SVGTransformableElement.cpp @@ -11,7 +11,7 @@ #include "nsIDOMMutationEvent.h" #include "nsIFrame.h" #include "nsISVGChildFrame.h" -#include "nsSVGRect.h" +#include "mozilla/dom/SVGRect.h" #include "nsSVGUtils.h" #include "SVGContentUtils.h" diff --git a/layout/svg/nsSVGGlyphFrame.cpp b/layout/svg/nsSVGGlyphFrame.cpp index 3d881c433a33..76cc8810a7b8 100644 --- a/layout/svg/nsSVGGlyphFrame.cpp +++ b/layout/svg/nsSVGGlyphFrame.cpp @@ -21,7 +21,7 @@ #include "nsSVGEffects.h" #include "nsSVGIntegrationUtils.h" #include "nsSVGPaintServerFrame.h" -#include "nsSVGRect.h" +#include "mozilla/dom/SVGRect.h" #include "nsSVGTextPathFrame.h" #include "nsSVGUtils.h" #include "nsTextFragment.h" diff --git a/layout/svg/nsSVGTextFrame2.cpp b/layout/svg/nsSVGTextFrame2.cpp index 7bd083749a73..bf2cad397bd8 100644 --- a/layout/svg/nsSVGTextFrame2.cpp +++ b/layout/svg/nsSVGTextFrame2.cpp @@ -28,7 +28,7 @@ #include "nsSVGGlyphFrame.h" #include "nsSVGOuterSVGFrame.h" #include "nsSVGPaintServerFrame.h" -#include "nsSVGRect.h" +#include "mozilla/dom/SVGRect.h" #include "nsSVGIntegrationUtils.h" #include "nsSVGTextFrame.h" #include "nsSVGTextPathFrame.h" @@ -3845,7 +3845,7 @@ nsSVGTextFrame2::GetExtentOfChar(nsIContent* aContent, // Transform the glyph's rect into user space. gfxRect r = m.TransformBounds(glyphRect); - NS_ADDREF(*aResult = new nsSVGRect(r.x, r.y, r.width, r.height)); + NS_ADDREF(*aResult = new dom::SVGRect(r.x, r.y, r.width, r.height)); return NS_OK; } From 64e6da38ab39c50f7f5bbc4b653406f6085ae4f0 Mon Sep 17 00:00:00 2001 From: Andrea Marchesini Date: Tue, 26 Mar 2013 16:53:13 +0100 Subject: [PATCH 027/129] Bug 852620 - Convert SVGRect to WebIDL, r=Ms2ger --- content/svg/content/src/Makefile.in | 3 +- content/svg/content/src/SVGIRect.h | 108 ++++++++++++++++ content/svg/content/src/SVGRect.cpp | 59 +-------- content/svg/content/src/SVGRect.h | 68 ++++++++-- content/svg/content/src/SVGSVGElement.cpp | 4 +- content/svg/content/src/SVGSVGElement.h | 3 +- .../svg/content/src/SVGTextContentElement.cpp | 6 +- .../svg/content/src/SVGTextContentElement.h | 4 +- .../content/src/SVGTransformableElement.cpp | 4 +- .../svg/content/src/SVGTransformableElement.h | 5 +- content/svg/content/src/nsSVGViewBox.cpp | 20 ++- content/svg/content/src/nsSVGViewBox.h | 119 +++++++++++------- dom/bindings/Bindings.conf | 5 + dom/webidl/SVGGraphicsElement.webidl | 2 +- dom/webidl/SVGRect.webidl | 22 ++++ dom/webidl/SVGSVGElement.webidl | 1 - dom/webidl/SVGTextContentElement.webidl | 3 +- dom/webidl/WebIDL.mk | 1 + layout/svg/nsSVGGlyphFrame.cpp | 11 +- layout/svg/nsSVGGlyphFrame.h | 7 +- layout/svg/nsSVGTextContainerFrame.cpp | 2 +- layout/svg/nsSVGTextContainerFrame.h | 7 +- layout/svg/nsSVGTextFrame.cpp | 4 +- layout/svg/nsSVGTextFrame.h | 8 +- layout/svg/nsSVGTextFrame2.cpp | 3 +- layout/svg/nsSVGTextFrame2.h | 6 +- 26 files changed, 328 insertions(+), 157 deletions(-) create mode 100644 content/svg/content/src/SVGIRect.h create mode 100644 dom/webidl/SVGRect.webidl diff --git a/content/svg/content/src/Makefile.in b/content/svg/content/src/Makefile.in index e6880e54885e..f902f68a03da 100644 --- a/content/svg/content/src/Makefile.in +++ b/content/svg/content/src/Makefile.in @@ -50,7 +50,6 @@ CPPSRCS = \ nsSVGPathGeometryElement.cpp \ nsSVGPolyElement.cpp \ nsSVGString.cpp \ - SVGRect.cpp \ nsSVGUnknownElement.cpp \ nsSVGViewBox.cpp \ SVGAElement.cpp \ @@ -130,6 +129,7 @@ CPPSRCS = \ SVGPolygonElement.cpp \ SVGPolylineElement.cpp \ SVGPreserveAspectRatio.cpp \ + SVGRect.cpp \ SVGRectElement.cpp \ SVGScriptElement.cpp \ SVGSetElement.cpp \ @@ -223,6 +223,7 @@ EXPORTS_mozilla/dom = \ SVGPolygonElement.h \ SVGPolylineElement.h \ SVGRect.h \ + SVGIRect.h \ SVGRectElement.h \ SVGScriptElement.h \ SVGSetElement.h \ diff --git a/content/svg/content/src/SVGIRect.h b/content/svg/content/src/SVGIRect.h new file mode 100644 index 000000000000..9d5e59d73e96 --- /dev/null +++ b/content/svg/content/src/SVGIRect.h @@ -0,0 +1,108 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_SVGIRect_h +#define mozilla_dom_SVGIRect_h + +#include "nsIDOMSVGRect.h" +#include "nsContentUtils.h" +#include "nsCycleCollectionParticipant.h" +#include "mozilla/dom/SVGRectBinding.h" +#include "mozilla/Attributes.h" +#include "mozilla/ErrorResult.h" + +namespace mozilla { +namespace dom { + +class SVGIRect : public nsIDOMSVGRect +{ +public: + JSObject* WrapObject(JSContext* aCx, JSObject* aScope) + { + return SVGRectBinding::Wrap(aCx, aScope, this); + } + + virtual float X() const = 0; + + NS_IMETHOD GetX(float *aX) MOZ_OVERRIDE MOZ_FINAL + { + *aX = X(); + return NS_OK; + } + + virtual void SetX(float aX, ErrorResult& aRv) = 0; + + NS_IMETHOD SetX(float aX) MOZ_OVERRIDE MOZ_FINAL + { + NS_ENSURE_FINITE(aX, NS_ERROR_ILLEGAL_VALUE); + + ErrorResult rv; + SetX(aX, rv); + return rv.ErrorCode(); + } + + virtual float Y() const = 0; + + NS_IMETHOD GetY(float *aY) MOZ_OVERRIDE MOZ_FINAL + { + *aY = Y(); + return NS_OK; + } + + virtual void SetY(float aY, ErrorResult& aRv) = 0; + + NS_IMETHOD SetY(float aY) MOZ_OVERRIDE MOZ_FINAL + { + NS_ENSURE_FINITE(aY, NS_ERROR_ILLEGAL_VALUE); + + ErrorResult rv; + SetY(aY, rv); + return rv.ErrorCode(); + } + + virtual float Width() const = 0; + + NS_IMETHOD GetWidth(float *aWidth) MOZ_OVERRIDE MOZ_FINAL + { + *aWidth = Width(); + return NS_OK; + } + + virtual void SetWidth(float aWidth, ErrorResult& aRv) = 0; + + NS_IMETHOD SetWidth(float aWidth) MOZ_OVERRIDE MOZ_FINAL + { + NS_ENSURE_FINITE(aWidth, NS_ERROR_ILLEGAL_VALUE); + + ErrorResult rv; + SetWidth(aWidth, rv); + return rv.ErrorCode(); + } + + virtual float Height() const = 0; + + NS_IMETHOD GetHeight(float *aHeight) MOZ_OVERRIDE MOZ_FINAL + { + *aHeight = Height(); + return NS_OK; + } + + virtual void SetHeight(float aHeight, ErrorResult& aRv) = 0; + + NS_IMETHOD SetHeight(float aHeight) MOZ_OVERRIDE MOZ_FINAL + { + NS_ENSURE_FINITE(aHeight, NS_ERROR_ILLEGAL_VALUE); + + ErrorResult rv; + SetHeight(aHeight, rv); + return rv.ErrorCode(); + } +}; + +} // namespace dom +} // namespace mozilla + +#endif //mozilla_dom_SVGIRect_h + diff --git a/content/svg/content/src/SVGRect.cpp b/content/svg/content/src/SVGRect.cpp index 0fd68f7e804b..934b8e524831 100644 --- a/content/svg/content/src/SVGRect.cpp +++ b/content/svg/content/src/SVGRect.cpp @@ -32,61 +32,6 @@ NS_INTERFACE_MAP_BEGIN(SVGRect) NS_INTERFACE_MAP_ENTRY(nsISupports) NS_INTERFACE_MAP_END -//---------------------------------------------------------------------- -// nsIDOMSVGRect methods: - -/* attribute float x; */ -NS_IMETHODIMP SVGRect::GetX(float *aX) -{ - *aX = mX; - return NS_OK; -} -NS_IMETHODIMP SVGRect::SetX(float aX) -{ - NS_ENSURE_FINITE(aX, NS_ERROR_ILLEGAL_VALUE); - mX = aX; - return NS_OK; -} - -/* attribute float y; */ -NS_IMETHODIMP SVGRect::GetY(float *aY) -{ - *aY = mY; - return NS_OK; -} -NS_IMETHODIMP SVGRect::SetY(float aY) -{ - NS_ENSURE_FINITE(aY, NS_ERROR_ILLEGAL_VALUE); - mY = aY; - return NS_OK; -} - -/* attribute float width; */ -NS_IMETHODIMP SVGRect::GetWidth(float *aWidth) -{ - *aWidth = mWidth; - return NS_OK; -} -NS_IMETHODIMP SVGRect::SetWidth(float aWidth) -{ - NS_ENSURE_FINITE(aWidth, NS_ERROR_ILLEGAL_VALUE); - mWidth = aWidth; - return NS_OK; -} - -/* attribute float height; */ -NS_IMETHODIMP SVGRect::GetHeight(float *aHeight) -{ - *aHeight = mHeight; - return NS_OK; -} -NS_IMETHODIMP SVGRect::SetHeight(float aHeight) -{ - NS_ENSURE_FINITE(aHeight, NS_ERROR_ILLEGAL_VALUE); - mHeight = aHeight; - return NS_OK; -} - } // namespace dom } // namespace mozilla @@ -94,7 +39,7 @@ NS_IMETHODIMP SVGRect::SetHeight(float aHeight) // Exported creation functions: nsresult -NS_NewSVGRect(nsIDOMSVGRect** result, float x, float y, +NS_NewSVGRect(mozilla::dom::SVGRect** result, float x, float y, float width, float height) { *result = new mozilla::dom::SVGRect(x, y, width, height); @@ -104,7 +49,7 @@ NS_NewSVGRect(nsIDOMSVGRect** result, float x, float y, } nsresult -NS_NewSVGRect(nsIDOMSVGRect** result, const gfxRect& rect) +NS_NewSVGRect(mozilla::dom::SVGRect** result, const gfxRect& rect) { return NS_NewSVGRect(result, rect.X(), rect.Y(), diff --git a/content/svg/content/src/SVGRect.h b/content/svg/content/src/SVGRect.h index f4c87d66a793..9ffd93dd80c6 100644 --- a/content/svg/content/src/SVGRect.h +++ b/content/svg/content/src/SVGRect.h @@ -7,16 +7,7 @@ #define mozilla_dom_SVGRect_h #include "gfxRect.h" -#include "nsIDOMSVGRect.h" -#include "mozilla/Attributes.h" - -nsresult -NS_NewSVGRect(nsIDOMSVGRect** result, - float x=0.0f, float y=0.0f, - float width=0.0f, float height=0.0f); - -nsresult -NS_NewSVGRect(nsIDOMSVGRect** result, const gfxRect& rect); +#include "mozilla/dom/SVGIRect.h" //////////////////////////////////////////////////////////////////////// // SVGRect class @@ -24,7 +15,7 @@ NS_NewSVGRect(nsIDOMSVGRect** result, const gfxRect& rect); namespace mozilla { namespace dom { -class SVGRect MOZ_FINAL : public nsIDOMSVGRect +class SVGRect MOZ_FINAL : public SVGIRect { public: SVGRect(float x=0.0f, float y=0.0f, float w=0.0f, float h=0.0f); @@ -32,8 +23,51 @@ public: // nsISupports interface: NS_DECL_ISUPPORTS - // nsIDOMSVGRect interface: - NS_DECL_NSIDOMSVGRECT + // WebIDL + virtual float X() const MOZ_OVERRIDE MOZ_FINAL + { + return mX; + } + + virtual void SetX(float aX, ErrorResult& aRv) MOZ_FINAL + { + mX = aX; + } + + virtual float Y() const MOZ_OVERRIDE MOZ_FINAL + { + return mY; + } + + virtual void SetY(float aY, ErrorResult& aRv) MOZ_FINAL + { + mY = aY; + } + + virtual float Width() const MOZ_OVERRIDE MOZ_FINAL + { + return mWidth; + } + + virtual void SetWidth(float aWidth, ErrorResult& aRv) MOZ_FINAL + { + mWidth = aWidth; + } + + virtual float Height() const MOZ_OVERRIDE MOZ_FINAL + { + return mHeight; + } + + virtual void SetHeight(float aHeight, ErrorResult& aRv) MOZ_FINAL + { + mHeight = aHeight; + } + + using mozilla::dom::SVGIRect::SetX; + using mozilla::dom::SVGIRect::SetY; + using mozilla::dom::SVGIRect::SetWidth; + using mozilla::dom::SVGIRect::SetHeight; protected: float mX, mY, mWidth, mHeight; @@ -42,4 +76,12 @@ protected: } // namespace dom } // namespace mozilla +nsresult +NS_NewSVGRect(mozilla::dom::SVGRect** result, + float x=0.0f, float y=0.0f, + float width=0.0f, float height=0.0f); + +nsresult +NS_NewSVGRect(mozilla::dom::SVGRect** result, const gfxRect& rect); + #endif //mozilla_dom_SVGRect_h diff --git a/content/svg/content/src/SVGSVGElement.cpp b/content/svg/content/src/SVGSVGElement.cpp index eddb87c8df76..fdbed1a60f34 100644 --- a/content/svg/content/src/SVGSVGElement.cpp +++ b/content/svg/content/src/SVGSVGElement.cpp @@ -409,10 +409,10 @@ SVGSVGElement::CreateSVGMatrix() return matrix.forget(); } -already_AddRefed +already_AddRefed SVGSVGElement::CreateSVGRect() { - nsCOMPtr rect; + nsRefPtr rect; NS_NewSVGRect(getter_AddRefs(rect)); return rect.forget(); } diff --git a/content/svg/content/src/SVGSVGElement.h b/content/svg/content/src/SVGSVGElement.h index 9c81bf60e7fa..b1e680864a18 100644 --- a/content/svg/content/src/SVGSVGElement.h +++ b/content/svg/content/src/SVGSVGElement.h @@ -37,6 +37,7 @@ namespace dom { class SVGAngle; class SVGMatrix; class SVGViewElement; +class SVGIRect; class SVGSVGElement; @@ -247,7 +248,7 @@ public: already_AddRefed CreateSVGAngle(); already_AddRefed CreateSVGPoint(); already_AddRefed CreateSVGMatrix(); - already_AddRefed CreateSVGRect(); + already_AddRefed CreateSVGRect(); already_AddRefed CreateSVGTransform(); already_AddRefed CreateSVGTransformFromMatrix(SVGMatrix& matrix); Element* GetElementById(const nsAString& elementId, ErrorResult& rv); diff --git a/content/svg/content/src/SVGTextContentElement.cpp b/content/svg/content/src/SVGTextContentElement.cpp index 9f2765b6d616..685ae155df53 100644 --- a/content/svg/content/src/SVGTextContentElement.cpp +++ b/content/svg/content/src/SVGTextContentElement.cpp @@ -8,7 +8,7 @@ #include "nsSVGTextContainerFrame.h" #include "nsSVGTextFrame2.h" #include "nsIDOMSVGAnimatedLength.h" -#include "nsIDOMSVGRect.h" +#include "mozilla/dom/SVGIRect.h" #include "nsIDOMSVGAnimatedEnum.h" namespace mozilla { @@ -153,10 +153,10 @@ SVGTextContentElement::GetEndPositionOfChar(uint32_t charnum, ErrorResult& rv) return point.forget(); } -already_AddRefed +already_AddRefed SVGTextContentElement::GetExtentOfChar(uint32_t charnum, ErrorResult& rv) { - nsCOMPtr rect; + nsRefPtr rect; if (FrameIsSVGText()) { nsSVGTextFrame2* textFrame = GetSVGTextFrame(); diff --git a/content/svg/content/src/SVGTextContentElement.h b/content/svg/content/src/SVGTextContentElement.h index 21e3ab9e295d..0c469488c91f 100644 --- a/content/svg/content/src/SVGTextContentElement.h +++ b/content/svg/content/src/SVGTextContentElement.h @@ -16,6 +16,8 @@ class nsISVGPoint; namespace dom { +class SVGIRect; + typedef SVGGraphicsElement SVGTextContentElementBase; class SVGTextContentElement : public SVGTextContentElementBase @@ -29,7 +31,7 @@ public: float GetSubStringLength(uint32_t charnum, uint32_t nchars, ErrorResult& rv); already_AddRefed GetStartPositionOfChar(uint32_t charnum, ErrorResult& rv); already_AddRefed GetEndPositionOfChar(uint32_t charnum, ErrorResult& rv); - already_AddRefed GetExtentOfChar(uint32_t charnum, ErrorResult& rv); + already_AddRefed GetExtentOfChar(uint32_t charnum, ErrorResult& rv); float GetRotationOfChar(uint32_t charnum, ErrorResult& rv); int32_t GetCharNumAtPosition(nsISVGPoint& point); diff --git a/content/svg/content/src/SVGTransformableElement.cpp b/content/svg/content/src/SVGTransformableElement.cpp index 515d589411a2..d3d66de2a784 100644 --- a/content/svg/content/src/SVGTransformableElement.cpp +++ b/content/svg/content/src/SVGTransformableElement.cpp @@ -160,7 +160,7 @@ SVGTransformableElement::GetFarthestViewportElement() return SVGContentUtils::GetOuterSVGElement(this); } -already_AddRefed +already_AddRefed SVGTransformableElement::GetBBox(ErrorResult& rv) { nsIFrame* frame = GetPrimaryFrame(Flush_Layout); @@ -176,7 +176,7 @@ SVGTransformableElement::GetBBox(ErrorResult& rv) return nullptr; } - nsCOMPtr rect; + nsRefPtr rect; rv = NS_NewSVGRect(getter_AddRefs(rect), nsSVGUtils::GetBBox(frame)); return rect.forget(); } diff --git a/content/svg/content/src/SVGTransformableElement.h b/content/svg/content/src/SVGTransformableElement.h index 199ce1d8b6fd..2b74651ba5eb 100644 --- a/content/svg/content/src/SVGTransformableElement.h +++ b/content/svg/content/src/SVGTransformableElement.h @@ -10,8 +10,6 @@ #include "gfxMatrix.h" #include "SVGAnimatedTransformList.h" -class nsIDOMSVGRect; - namespace mozilla { class DOMSVGAnimatedTransformList; @@ -19,6 +17,7 @@ namespace dom { class SVGGraphicsElement; class SVGMatrix; +class SVGIRect; class SVGTransformableElement : public nsSVGElement { @@ -33,7 +32,7 @@ public: already_AddRefed Transform(); nsSVGElement* GetNearestViewportElement(); nsSVGElement* GetFarthestViewportElement(); - already_AddRefed GetBBox(ErrorResult& rv); + already_AddRefed GetBBox(ErrorResult& rv); already_AddRefed GetCTM(); already_AddRefed GetScreenCTM(); already_AddRefed GetTransformToElement(SVGGraphicsElement& aElement, diff --git a/content/svg/content/src/nsSVGViewBox.cpp b/content/svg/content/src/nsSVGViewBox.cpp index 78706b534290..1461dedf920d 100644 --- a/content/svg/content/src/nsSVGViewBox.cpp +++ b/content/svg/content/src/nsSVGViewBox.cpp @@ -280,40 +280,36 @@ nsSVGViewBox::DOMAnimVal::~DOMAnimVal() sAnimSVGViewBoxTearoffTable.RemoveTearoff(mVal); } -NS_IMETHODIMP -nsSVGViewBox::DOMBaseVal::SetX(float aX) +void +nsSVGViewBox::DOMBaseVal::SetX(float aX, ErrorResult& aRv) { nsSVGViewBoxRect rect = mVal->GetBaseValue(); rect.x = aX; mVal->SetBaseValue(rect, mSVGElement); - return NS_OK; } -NS_IMETHODIMP -nsSVGViewBox::DOMBaseVal::SetY(float aY) +void +nsSVGViewBox::DOMBaseVal::SetY(float aY, ErrorResult& aRv) { nsSVGViewBoxRect rect = mVal->GetBaseValue(); rect.y = aY; mVal->SetBaseValue(rect, mSVGElement); - return NS_OK; } -NS_IMETHODIMP -nsSVGViewBox::DOMBaseVal::SetWidth(float aWidth) +void +nsSVGViewBox::DOMBaseVal::SetWidth(float aWidth, ErrorResult& aRv) { nsSVGViewBoxRect rect = mVal->GetBaseValue(); rect.width = aWidth; mVal->SetBaseValue(rect, mSVGElement); - return NS_OK; } -NS_IMETHODIMP -nsSVGViewBox::DOMBaseVal::SetHeight(float aHeight) +void +nsSVGViewBox::DOMBaseVal::SetHeight(float aHeight, ErrorResult& aRv) { nsSVGViewBoxRect rect = mVal->GetBaseValue(); rect.height = aHeight; mVal->SetBaseValue(rect, mSVGElement); - return NS_OK; } nsISMILAttr* diff --git a/content/svg/content/src/nsSVGViewBox.h b/content/svg/content/src/nsSVGViewBox.h index 304159128511..9b856fd98370 100644 --- a/content/svg/content/src/nsSVGViewBox.h +++ b/content/svg/content/src/nsSVGViewBox.h @@ -10,7 +10,7 @@ #include "nsCycleCollectionParticipant.h" #include "nsError.h" #include "nsIDOMSVGAnimatedRect.h" -#include "nsIDOMSVGRect.h" +#include "mozilla/dom/SVGIRect.h" #include "nsISMILAttr.h" #include "nsSVGElement.h" #include "mozilla/Attributes.h" @@ -93,8 +93,13 @@ private: bool mHasBaseVal; public: - struct DOMBaseVal MOZ_FINAL : public nsIDOMSVGRect + struct DOMBaseVal MOZ_FINAL : public mozilla::dom::SVGIRect { + using mozilla::dom::SVGIRect::SetX; + using mozilla::dom::SVGIRect::SetY; + using mozilla::dom::SVGIRect::SetWidth; + using mozilla::dom::SVGIRect::SetHeight; + NS_DECL_CYCLE_COLLECTING_ISUPPORTS NS_DECL_CYCLE_COLLECTION_CLASS(DOMBaseVal) @@ -105,23 +110,39 @@ public: nsSVGViewBox* mVal; // kept alive because it belongs to content nsRefPtr mSVGElement; - NS_IMETHOD GetX(float *aX) - { *aX = mVal->GetBaseValue().x; return NS_OK; } - NS_IMETHOD GetY(float *aY) - { *aY = mVal->GetBaseValue().y; return NS_OK; } - NS_IMETHOD GetWidth(float *aWidth) - { *aWidth = mVal->GetBaseValue().width; return NS_OK; } - NS_IMETHOD GetHeight(float *aHeight) - { *aHeight = mVal->GetBaseValue().height; return NS_OK; } + float X() const MOZ_OVERRIDE MOZ_FINAL + { + return mVal->GetBaseValue().x; + } - NS_IMETHOD SetX(float aX); - NS_IMETHOD SetY(float aY); - NS_IMETHOD SetWidth(float aWidth); - NS_IMETHOD SetHeight(float aHeight); + float Y() const MOZ_OVERRIDE MOZ_FINAL + { + return mVal->GetBaseValue().y; + } + + float Width() const MOZ_OVERRIDE MOZ_FINAL + { + return mVal->GetBaseValue().width; + } + + float Height() const MOZ_OVERRIDE MOZ_FINAL + { + return mVal->GetBaseValue().height; + } + + void SetX(float aX, mozilla::ErrorResult& aRv) MOZ_FINAL; + void SetY(float aY, mozilla::ErrorResult& aRv) MOZ_FINAL; + void SetWidth(float aWidth, mozilla::ErrorResult& aRv) MOZ_FINAL; + void SetHeight(float aHeight, mozilla::ErrorResult& aRv) MOZ_FINAL; }; - struct DOMAnimVal MOZ_FINAL : public nsIDOMSVGRect + struct DOMAnimVal MOZ_FINAL : public mozilla::dom::SVGIRect { + using mozilla::dom::SVGIRect::SetX; + using mozilla::dom::SVGIRect::SetY; + using mozilla::dom::SVGIRect::SetWidth; + using mozilla::dom::SVGIRect::SetHeight; + NS_DECL_CYCLE_COLLECTING_ISUPPORTS NS_DECL_CYCLE_COLLECTION_CLASS(DOMAnimVal) @@ -134,39 +155,49 @@ public: // Script may have modified animation parameters or timeline -- DOM getters // need to flush any resample requests to reflect these modifications. - NS_IMETHOD GetX(float *aX) + float X() const MOZ_OVERRIDE MOZ_FINAL { mSVGElement->FlushAnimations(); - *aX = mVal->GetAnimValue().x; - return NS_OK; - } - NS_IMETHOD GetY(float *aY) - { - mSVGElement->FlushAnimations(); - *aY = mVal->GetAnimValue().y; - return NS_OK; - } - NS_IMETHOD GetWidth(float *aWidth) - { - mSVGElement->FlushAnimations(); - *aWidth = mVal->GetAnimValue().width; - return NS_OK; - } - NS_IMETHOD GetHeight(float *aHeight) - { - mSVGElement->FlushAnimations(); - *aHeight = mVal->GetAnimValue().height; - return NS_OK; + return mVal->GetAnimValue().x; } - NS_IMETHOD SetX(float aX) - { return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR; } - NS_IMETHOD SetY(float aY) - { return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR; } - NS_IMETHOD SetWidth(float aWidth) - { return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR; } - NS_IMETHOD SetHeight(float aHeight) - { return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR; } + float Y() const MOZ_OVERRIDE MOZ_FINAL + { + mSVGElement->FlushAnimations(); + return mVal->GetAnimValue().y; + } + + float Width() const MOZ_OVERRIDE MOZ_FINAL + { + mSVGElement->FlushAnimations(); + return mVal->GetAnimValue().width; + } + + float Height() const MOZ_OVERRIDE MOZ_FINAL + { + mSVGElement->FlushAnimations(); + return mVal->GetAnimValue().height; + } + + void SetX(float aX, mozilla::ErrorResult& aRv) MOZ_FINAL + { + aRv.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR); + } + + void SetY(float aY, mozilla::ErrorResult& aRv) MOZ_FINAL + { + aRv.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR); + } + + void SetWidth(float aWidth, mozilla::ErrorResult& aRv) MOZ_FINAL + { + aRv.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR); + } + + void SetHeight(float aHeight, mozilla::ErrorResult& aRv) MOZ_FINAL + { + aRv.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR); + } }; struct DOMAnimatedRect MOZ_FINAL : public nsIDOMSVGAnimatedRect diff --git a/dom/bindings/Bindings.conf b/dom/bindings/Bindings.conf index c052d6b0f905..0f6c167ca123 100644 --- a/dom/bindings/Bindings.conf +++ b/dom/bindings/Bindings.conf @@ -872,6 +872,11 @@ DOMInterfaces = { 'headerFile': 'mozilla/dom/SVGGradientElement.h', }, +'SVGRect': { + 'wrapperCache': False, + 'nativeType': 'mozilla::dom::SVGIRect' +}, + 'SVGTextContentElement': { 'concrete': False }, diff --git a/dom/webidl/SVGGraphicsElement.webidl b/dom/webidl/SVGGraphicsElement.webidl index c299720e3657..5c4db656eeb2 100644 --- a/dom/webidl/SVGGraphicsElement.webidl +++ b/dom/webidl/SVGGraphicsElement.webidl @@ -16,7 +16,7 @@ interface SVGGraphicsElement : SVGElement { readonly attribute SVGElement? nearestViewportElement; readonly attribute SVGElement? farthestViewportElement; - [Throws] + [Creator, Throws] SVGRect getBBox(); // Not implemented // SVGRect getStrokeBBox(); diff --git a/dom/webidl/SVGRect.webidl b/dom/webidl/SVGRect.webidl new file mode 100644 index 000000000000..0edda0640fb9 --- /dev/null +++ b/dom/webidl/SVGRect.webidl @@ -0,0 +1,22 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + * + * The origin of this IDL file is + * http://www.w3.org/TR/SVG2/ + * + * Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C + * liability, trademark and document use rules apply. + */ + +interface SVGRect { + [SetterThrows] + attribute float x; + [SetterThrows] + attribute float y; + [SetterThrows] + attribute float width; + [SetterThrows] + attribute float height; +}; diff --git a/dom/webidl/SVGSVGElement.webidl b/dom/webidl/SVGSVGElement.webidl index 082b62466f9b..634dc29193ab 100644 --- a/dom/webidl/SVGSVGElement.webidl +++ b/dom/webidl/SVGSVGElement.webidl @@ -13,7 +13,6 @@ interface SVGAnimatedString; interface SVGViewSpec; interface SVGPoint; -interface SVGRect; interface SVGSVGElement : SVGGraphicsElement { diff --git a/dom/webidl/SVGTextContentElement.webidl b/dom/webidl/SVGTextContentElement.webidl index 1d5920cb6c8f..2548034d59de 100644 --- a/dom/webidl/SVGTextContentElement.webidl +++ b/dom/webidl/SVGTextContentElement.webidl @@ -10,7 +10,6 @@ * liability, trademark and document use rules apply. */ -interface SVGRect; interface SVGAnimatedEnumeration; interface SVGTextContentElement : SVGGraphicsElement { @@ -31,7 +30,7 @@ interface SVGTextContentElement : SVGGraphicsElement { SVGPoint getStartPositionOfChar(unsigned long charnum); [Throws] SVGPoint getEndPositionOfChar(unsigned long charnum); - [Throws] + [Creator, Throws] SVGRect getExtentOfChar(unsigned long charnum); [Throws] float getRotationOfChar(unsigned long charnum); diff --git a/dom/webidl/WebIDL.mk b/dom/webidl/WebIDL.mk index bc3816cdfce9..0963f11ba400 100644 --- a/dom/webidl/WebIDL.mk +++ b/dom/webidl/WebIDL.mk @@ -236,6 +236,7 @@ webidl_files = \ SVGPolylineElement.webidl \ SVGPreserveAspectRatio.webidl \ SVGRadialGradientElement.webidl \ + SVGRect.webidl \ SVGRectElement.webidl \ SVGScriptElement.webidl \ SVGSetElement.webidl \ diff --git a/layout/svg/nsSVGGlyphFrame.cpp b/layout/svg/nsSVGGlyphFrame.cpp index 76cc8810a7b8..3bdf9d50a883 100644 --- a/layout/svg/nsSVGGlyphFrame.cpp +++ b/layout/svg/nsSVGGlyphFrame.cpp @@ -16,7 +16,6 @@ #include "nsBidiPresUtils.h" #include "nsDisplayList.h" #include "nsError.h" -#include "nsIDOMSVGRect.h" #include "nsRenderingContext.h" #include "nsSVGEffects.h" #include "nsSVGIntegrationUtils.h" @@ -1256,7 +1255,7 @@ nsSVGGlyphFrame::GetEndPositionOfChar(uint32_t charnum, } nsresult -nsSVGGlyphFrame::GetExtentOfChar(uint32_t charnum, nsIDOMSVGRect **_retval) +nsSVGGlyphFrame::GetExtentOfChar(uint32_t charnum, dom::SVGIRect **_retval) { *_retval = nullptr; @@ -1285,7 +1284,13 @@ nsSVGGlyphFrame::GetExtentOfChar(uint32_t charnum, nsIDOMSVGRect **_retval) metrics.mAdvanceWidth, metrics.mAscent + metrics.mDescent)); tmpCtx->IdentityMatrix(); - return NS_NewSVGRect(_retval, tmpCtx->GetUserPathExtent()); + + nsRefPtr rect; + nsresult rv = NS_NewSVGRect(getter_AddRefs(rect), tmpCtx->GetUserPathExtent()); + NS_ENSURE_SUCCESS(rv, rv); + + rect.forget(_retval); + return NS_OK; } nsresult diff --git a/layout/svg/nsSVGGlyphFrame.h b/layout/svg/nsSVGGlyphFrame.h index 6113af358e3c..10b43165912e 100644 --- a/layout/svg/nsSVGGlyphFrame.h +++ b/layout/svg/nsSVGGlyphFrame.h @@ -18,7 +18,6 @@ class CharacterIterator; class gfxContext; class nsDisplaySVGGlyphs; -class nsIDOMSVGRect; class nsRenderingContext; class nsSVGGlyphFrame; class nsSVGTextFrame; @@ -29,6 +28,10 @@ struct CharacterPosition; namespace mozilla { +namespace dom { +class SVGIRect; +} + // Slightly horrible callback for deferring application of opacity struct SVGTextObjectPaint : public gfxTextObjectPaint { already_AddRefed GetFillPattern(float aOpacity, @@ -135,7 +138,7 @@ public: // These do not use the global transform if NS_STATE_NONDISPLAY_CHILD nsresult GetStartPositionOfChar(uint32_t charnum, nsISupports **_retval); nsresult GetEndPositionOfChar(uint32_t charnum, nsISupports **_retval); - nsresult GetExtentOfChar(uint32_t charnum, nsIDOMSVGRect **_retval); + nsresult GetExtentOfChar(uint32_t charnum, dom::SVGIRect **_retval); nsresult GetRotationOfChar(uint32_t charnum, float *_retval); /** * @param aForceGlobalTransform controls whether to use the diff --git a/layout/svg/nsSVGTextContainerFrame.cpp b/layout/svg/nsSVGTextContainerFrame.cpp index dd57dd621179..16d807bbc241 100644 --- a/layout/svg/nsSVGTextContainerFrame.cpp +++ b/layout/svg/nsSVGTextContainerFrame.cpp @@ -137,7 +137,7 @@ nsSVGTextContainerFrame::GetEndPositionOfChar(uint32_t charnum, nsISupports **_r } NS_IMETHODIMP -nsSVGTextContainerFrame::GetExtentOfChar(uint32_t charnum, nsIDOMSVGRect **_retval) +nsSVGTextContainerFrame::GetExtentOfChar(uint32_t charnum, dom::SVGIRect **_retval) { *_retval = nullptr; diff --git a/layout/svg/nsSVGTextContainerFrame.h b/layout/svg/nsSVGTextContainerFrame.h index ba9cc822e766..bf417da69d49 100644 --- a/layout/svg/nsSVGTextContainerFrame.h +++ b/layout/svg/nsSVGTextContainerFrame.h @@ -15,7 +15,6 @@ #include "nsTArray.h" class nsFrameList; -class nsIDOMSVGRect; class nsISVGGlyphFragmentNode; class nsStyleContext; class nsSVGGlyphFrame; @@ -23,6 +22,10 @@ class nsSVGTextFrame; namespace mozilla { class nsISVGPoint; + +namespace dom { +class SVGIRect; +} } class nsSVGTextContainerFrame : public nsSVGDisplayContainerFrame @@ -49,7 +52,7 @@ public: NS_IMETHOD GetStartPositionOfChar(uint32_t charnum, nsISupports **_retval); NS_IMETHOD GetEndPositionOfChar(uint32_t charnum, nsISupports **_retval); - NS_IMETHOD GetExtentOfChar(uint32_t charnum, nsIDOMSVGRect **_retval); + NS_IMETHOD GetExtentOfChar(uint32_t charnum, mozilla::dom::SVGIRect **_retval); NS_IMETHOD GetRotationOfChar(uint32_t charnum, float *_retval); /* diff --git a/layout/svg/nsSVGTextFrame.cpp b/layout/svg/nsSVGTextFrame.cpp index 84db10aa5041..1b9cbceca3a6 100644 --- a/layout/svg/nsSVGTextFrame.cpp +++ b/layout/svg/nsSVGTextFrame.cpp @@ -8,7 +8,7 @@ // Keep others in (case-insensitive) order: #include "nsGkAtoms.h" -#include "nsIDOMSVGRect.h" +#include "mozilla/dom/SVGIRect.h" #include "nsISVGGlyphFragmentNode.h" #include "nsSVGGlyphFrame.h" #include "nsSVGIntegrationUtils.h" @@ -136,7 +136,7 @@ nsSVGTextFrame::GetEndPositionOfChar(uint32_t charnum, nsISupports **_retval) } NS_IMETHODIMP -nsSVGTextFrame::GetExtentOfChar(uint32_t charnum, nsIDOMSVGRect **_retval) +nsSVGTextFrame::GetExtentOfChar(uint32_t charnum, dom::SVGIRect **_retval) { UpdateGlyphPositioning(false); diff --git a/layout/svg/nsSVGTextFrame.h b/layout/svg/nsSVGTextFrame.h index 5f09bfd51a08..26e35792cb43 100644 --- a/layout/svg/nsSVGTextFrame.h +++ b/layout/svg/nsSVGTextFrame.h @@ -14,6 +14,12 @@ class nsRenderingContext; typedef nsSVGTextContainerFrame nsSVGTextFrameBase; +namespace mozilla { +namespace dom { +class SVGIRect; +} +} + class nsSVGTextFrame : public nsSVGTextFrameBase { friend nsIFrame* @@ -77,7 +83,7 @@ public: NS_IMETHOD GetStartPositionOfChar(uint32_t charnum, nsISupports **_retval); NS_IMETHOD GetEndPositionOfChar(uint32_t charnum, nsISupports **_retval); - NS_IMETHOD GetExtentOfChar(uint32_t charnum, nsIDOMSVGRect **_retval); + NS_IMETHOD GetExtentOfChar(uint32_t charnum, mozilla::dom::SVGIRect **_retval); NS_IMETHOD GetRotationOfChar(uint32_t charnum, float *_retval); // nsSVGTextFrame diff --git a/layout/svg/nsSVGTextFrame2.cpp b/layout/svg/nsSVGTextFrame2.cpp index bf2cad397bd8..01de90562e20 100644 --- a/layout/svg/nsSVGTextFrame2.cpp +++ b/layout/svg/nsSVGTextFrame2.cpp @@ -19,7 +19,6 @@ #include "nsGkAtoms.h" #include "nsIDOMSVGAnimatedNumber.h" #include "nsIDOMSVGLength.h" -#include "nsIDOMSVGRect.h" #include "nsISVGGlyphFragmentNode.h" #include "nsISelection.h" #include "nsQuickSort.h" @@ -3804,7 +3803,7 @@ nsSVGTextFrame2::GetEndPositionOfChar(nsIContent* aContent, nsresult nsSVGTextFrame2::GetExtentOfChar(nsIContent* aContent, uint32_t aCharNum, - nsIDOMSVGRect** aResult) + dom::SVGIRect** aResult) { UpdateGlyphPositioning(false); diff --git a/layout/svg/nsSVGTextFrame2.h b/layout/svg/nsSVGTextFrame2.h index 028c9a49776e..6784f9991ebf 100644 --- a/layout/svg/nsSVGTextFrame2.h +++ b/layout/svg/nsSVGTextFrame2.h @@ -28,6 +28,10 @@ class TextNodeCorrespondenceRecorder; struct TextRenderedRun; class TextRenderedRunIterator; +namespace dom { +class SVGIRect; +} + /** * Information about the positioning for a single character in an SVG * element. @@ -262,7 +266,7 @@ public: nsresult GetEndPositionOfChar(nsIContent* aContent, uint32_t aCharNum, mozilla::nsISVGPoint** aResult); nsresult GetExtentOfChar(nsIContent* aContent, uint32_t aCharNum, - nsIDOMSVGRect** aResult); + mozilla::dom::SVGIRect** aResult); nsresult GetRotationOfChar(nsIContent* aContent, uint32_t aCharNum, float* aResult); From 0cdff773262a187f8c0e9cd78f86c12418da9220 Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Tue, 26 Mar 2013 09:08:29 -0700 Subject: [PATCH 028/129] Bug 854558 - Enforce __exposedProps__ for Sandboxes. r=gabor --- js/xpconnect/tests/chrome/test_cows.xul | 21 ++++++++--------- js/xpconnect/tests/unit/test_bug854558.js | 11 +++++++++ js/xpconnect/tests/unit/xpcshell.ini | 1 + js/xpconnect/wrappers/AccessCheck.cpp | 28 ----------------------- 4 files changed, 21 insertions(+), 40 deletions(-) create mode 100644 js/xpconnect/tests/unit/test_bug854558.js diff --git a/js/xpconnect/tests/chrome/test_cows.xul b/js/xpconnect/tests/chrome/test_cows.xul index 0ace690eed45..e4208e5302ea 100644 --- a/js/xpconnect/tests/chrome/test_cows.xul +++ b/js/xpconnect/tests/chrome/test_cows.xul @@ -70,8 +70,8 @@ function COWTests() { is(obj[propName], value, "getting " + propName + " on " + desc); ok(propName in obj, propName + " on " + desc + " should exist"); - //ok(Object.hasOwnProperty.call(obj, propName), - // propName + " on " + desc + " should exist"); + ok(Object.hasOwnProperty.call(obj, propName), + propName + " on " + desc + " should exist"); } catch (e) { ok(false, "getting " + propName + " on " + desc + " threw " + e); } @@ -82,26 +82,24 @@ function COWTests() { "getting " + propName + " on " + desc + " should return undefined"); ok(!(propName in obj), propName + " on " + desc + " should act as if it doesn't exist"); - //ok(!Object.hasOwnProperty.call(obj, propName), - // propName + " on " + desc + " should act as if it doesn't exist"); + ok(!Object.hasOwnProperty.call(obj, propName), + propName + " on " + desc + " should act as if it doesn't exist"); } catch (e) { ok(false, "getting " + propName + " on " + desc + " threw " + e); } } - //var cow = getCOW({ foo: "fooval", __exposedProps__: {}}); - //Math.sin(1); - //is(cow.foo, undefined, "one test to rule them all"); - //return; - const PROPS_TO_TEST = ['foo', 'bar', 'prototype']; var empty = {}; - // Once we flip the default for __exposedProps__, this should behave - // the same as for function objects below. + var nonempty = {foo: 42, bar: 33}; is(getCOW(empty).foo, undefined, "shouldn't throw when accessing exposed properties that doesn't exist"); + PROPS_TO_TEST.forEach(function(name) { + isPropHidden(getCOW(nonempty), name, "object without exposedProps"); + }); + // Test function objects without __exposedProps__ var func = function(x) { return 42; }; func.foo = "foo property"; @@ -181,7 +179,6 @@ function COWTests() { // Test writable property var writable = getCOW({ __exposedProps__: {foo: 'w'}}); try { - Math.sin("foo" in writable); ok(!("foo" in writable), "non-existing write-only property shouldn't exist"); writable.foo = 5; diff --git a/js/xpconnect/tests/unit/test_bug854558.js b/js/xpconnect/tests/unit/test_bug854558.js new file mode 100644 index 000000000000..d60d23a5baf8 --- /dev/null +++ b/js/xpconnect/tests/unit/test_bug854558.js @@ -0,0 +1,11 @@ +const Cu = Components.utils; +function run_test() { + + var chromeSB = new Cu.Sandbox(this); + var contentSB = new Cu.Sandbox('http://www.example.com'); + Cu.evalInSandbox('this.foo = {a: 2}', chromeSB); + contentSB.foo = chromeSB.foo; + do_check_eq(Cu.evalInSandbox('foo.a', contentSB), undefined, "Default deny with no __exposedProps__"); + Cu.evalInSandbox('this.foo.__exposedProps__ = {a: "r"}', chromeSB); + do_check_eq(Cu.evalInSandbox('foo.a', contentSB), 2, "works with __exposedProps__"); +} diff --git a/js/xpconnect/tests/unit/xpcshell.ini b/js/xpconnect/tests/unit/xpcshell.ini index 4ede121a5b3e..3c3ecf90d9af 100644 --- a/js/xpconnect/tests/unit/xpcshell.ini +++ b/js/xpconnect/tests/unit/xpcshell.ini @@ -19,6 +19,7 @@ tail = [test_bug845201.js] [test_bug849730.js] [test_bug851895.js] +[test_bug854558.js] [test_bug_442086.js] [test_file.js] [test_blob.js] diff --git a/js/xpconnect/wrappers/AccessCheck.cpp b/js/xpconnect/wrappers/AccessCheck.cpp index b157ab785131..280441d97e09 100644 --- a/js/xpconnect/wrappers/AccessCheck.cpp +++ b/js/xpconnect/wrappers/AccessCheck.cpp @@ -287,14 +287,6 @@ OnlyIfSubjectIsSystem::isSafeToUnwrap() enum Access { READ = (1<<0), WRITE = (1<<1), NO_ACCESS = 0 }; -static bool -IsInSandbox(JSContext *cx, JSObject *obj) -{ - JSAutoCompartment ac(cx, obj); - JSObject *global = JS_GetGlobalForObject(cx, obj); - return !strcmp(js::GetObjectJSClass(global)->name, "Sandbox"); -} - static void EnterAndThrow(JSContext *cx, JSObject *wrapper, const char *msg) { @@ -332,26 +324,6 @@ ExposedPropertiesOnly::check(JSContext *cx, JSObject *wrapper, jsid id, Wrapper: // If no __exposedProps__ existed, deny access. if (!found) { - // Everything below here needs to be done in the wrapper's compartment. - JSAutoCompartment wrapperAC(cx, wrapper); - // Make a temporary exception for objects in a chrome sandbox to help - // out jetpack. See bug 784233. - if (!JS_ObjectIsFunction(cx, wrappedObject) && - IsInSandbox(cx, wrappedObject)) - { - // This little loop hole will go away soon! See bug 553102. - nsCOMPtr win = - do_QueryInterface(nsJSUtils::GetStaticScriptGlobal(wrapper)); - if (win) { - nsCOMPtr doc = win->GetExtantDoc(); - if (doc) { - doc->WarnOnceAbout(nsIDocument::eNoExposedProps, - /* asError = */ true); - } - } - - return true; - } return false; } From 28b2d974b343d5acdc0e38d64158f7ea1b04aa77 Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Tue, 26 Mar 2013 09:09:04 -0700 Subject: [PATCH 029/129] Bug 854510 - Convert expected assertion into a 0-1 range. r=RyanVM --- js/xpconnect/tests/chrome/test_bug503926.xul | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/xpconnect/tests/chrome/test_bug503926.xul b/js/xpconnect/tests/chrome/test_bug503926.xul index 853a607cf57c..a6001185e201 100644 --- a/js/xpconnect/tests/chrome/test_bug503926.xul +++ b/js/xpconnect/tests/chrome/test_bug503926.xul @@ -21,7 +21,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=503926 diff --git a/testing/marionette/client/setup.py b/testing/marionette/client/setup.py index 76089949ff54..faceeaf93237 100644 --- a/testing/marionette/client/setup.py +++ b/testing/marionette/client/setup.py @@ -1,7 +1,7 @@ import os from setuptools import setup, find_packages -version = '0.5.22' +version = '0.5.23' # get documentation from the README try: diff --git a/testing/marionette/marionette-actors.js b/testing/marionette/marionette-actors.js index 7dabaed7cace..f1be88058b2b 100644 --- a/testing/marionette/marionette-actors.js +++ b/testing/marionette/marionette-actors.js @@ -1407,7 +1407,8 @@ MarionetteDriverActor.prototype = { this.sendError("Not in Chrome", 500, null, this.command_id); } else { - this.sendAsync("actionChain", {value: aRequest.value, + this.sendAsync("actionChain", {chain: aRequest.chain, + nextId: aRequest.nextId, command_id: this.command_id}); } }, diff --git a/testing/marionette/marionette-listener.js b/testing/marionette/marionette-listener.js index 051c0a76f6a4..e08a49107e04 100644 --- a/testing/marionette/marionette-listener.js +++ b/testing/marionette/marionette-listener.js @@ -941,7 +941,7 @@ function actions(finger, touchId, command_id, i){ i = 0; } if (i == finger.length) { - sendOk(command_id); + sendResponse({value: touchId}, command_id); return; } let pack = finger[i]; @@ -968,12 +968,20 @@ function actions(finger, touchId, command_id, i){ actions(finger,touchId, command_id, i); break; case 'release': + if (lastTouch == null) { + sendError("Element has not been pressed: no such element", 7, null, command_id); + return; + } touch = lastTouch; lastTouch = null; emitTouchEvent('touchend', touch); actions(finger, touchId, command_id, i); break; case 'move': + if (lastTouch == null) { + sendError("Element has not been pressed: no such element", 7, null, command_id); + return; + } el = elementManager.getKnownElement(pack[1], curWindow); let boxTarget = el.getBoundingClientRect(); let startElement = lastTouch.target; @@ -986,6 +994,10 @@ function actions(finger, touchId, command_id, i){ actions(finger, touchId, command_id, i); break; case 'moveByOffset': + if (lastTouch == null) { + sendError("Element has not been pressed: no such element", 7, null, command_id); + return; + } el = lastTouch.target; let doc = el.ownerDocument; let win = doc.defaultView; @@ -1023,12 +1035,14 @@ function actions(finger, touchId, command_id, i){ */ function actionChain(msg) { let command_id = msg.json.command_id; - let args = msg.json.value; + let args = msg.json.chain; + let touchId = msg.json.nextId; try { let commandArray = elementManager.convertWrappedArguments(args, curWindow); - // each finger associates with one touchId - let touchId = nextTouchId++; // loop the action array [ ['press', id], ['move', id], ['release', id] ] + if (touchId == null) { + touchId = nextTouchId++; + } actions(commandArray, touchId, command_id); } catch (e) { From 2ccd150867e4d51de6ef066daf33ef7d5e8a9dfc Mon Sep 17 00:00:00 2001 From: Yiming Yang Date: Thu, 21 Mar 2013 12:31:27 -0700 Subject: [PATCH 047/129] Bug 848489 - send 'contextmenu' event if we are long pressing, r=mdas --- .../marionette/tests/unit/test_long_press.py | 17 +++++++++++++++++ .../client/marionette/www/testAction.html | 7 +++++++ testing/marionette/marionette-listener.js | 16 ++++++++++++++++ 3 files changed, 40 insertions(+) create mode 100644 testing/marionette/client/marionette/tests/unit/test_long_press.py diff --git a/testing/marionette/client/marionette/tests/unit/test_long_press.py b/testing/marionette/client/marionette/tests/unit/test_long_press.py new file mode 100644 index 000000000000..a6d78a2e8942 --- /dev/null +++ b/testing/marionette/client/marionette/tests/unit/test_long_press.py @@ -0,0 +1,17 @@ +# 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/. + +import time +from marionette_test import MarionetteTestCase +from marionette import Actions + +class testSingleFinger(MarionetteTestCase): + def test_chain(self): + testTouch = self.marionette.absolute_url("testAction.html") + self.marionette.navigate(testTouch) + button = self.marionette.find_element("id", "mozLinkCopy") + action = Actions(self.marionette) + action.press(button).wait(5).perform() + time.sleep(15) + self.assertEqual("Context", self.marionette.execute_script("return document.getElementById('mozLinkCopy').innerHTML;")) diff --git a/testing/marionette/client/marionette/www/testAction.html b/testing/marionette/client/marionette/www/testAction.html index 4e500f1e2496..6d13d380b50b 100644 --- a/testing/marionette/client/marionette/www/testAction.html +++ b/testing/marionette/client/marionette/www/testAction.html @@ -37,6 +37,8 @@ // here is second for a tap second.addEventListener("touchstart", function(){changePressText("mozLinkCopy")}, false); second.addEventListener("touchend", function(){changeClickText("mozLinkCopy")}, false); + // change for contextmenu + second.addEventListener("contextmenu", onContextMenuChange, false); // here is third for horizontal move third.addEventListener("touchstart", function(){changePressText("mozLinkStart")}, false); third.addEventListener("touchmove", changeHorizontalMove, false); @@ -129,6 +131,11 @@ document.getElementById("delayed").innerHTML = "End"; } } + + function onContextMenuChange() { + var context = document.getElementById("mozLinkCopy"); + context.innerHTML = "Context"; + } diff --git a/testing/marionette/marionette-listener.js b/testing/marionette/marionette-listener.js index e08a49107e04..a532e2b9a199 100644 --- a/testing/marionette/marionette-listener.js +++ b/testing/marionette/marionette-listener.js @@ -965,6 +965,14 @@ function actions(finger, touchId, command_id, i){ touch = createATouch(el, corx, cory, touchId); lastTouch = touch; emitTouchEvent('touchstart', touch); + // check if it's a long press + // standard waiting time to fire contextmenu + let standard = Services.prefs.getIntPref("ui.click_hold_context_menus.delay"); + // long press only happens when wait follows press + if (finger[i][0] == 'wait' && finger[i][1] != null && finger[i][1]*1000 >= standard) { + finger[i][1] = finger[i][1] - standard/1000; + finger.splice(i, 0, ['wait', standard/1000], ['longPress']); + } actions(finger,touchId, command_id, i); break; case 'release': @@ -1027,6 +1035,14 @@ function actions(finger, touchId, command_id, i){ lastTouch = null; actions(finger, touchId, command_id, i); break; + case 'longPress': + let event = curWindow.document.createEvent('HTMLEvents'); + event.initEvent('contextmenu', + true, + true); + lastTouch.target.dispatchEvent(event); + actions(finger, touchId, command_id, i); + break; } } From 7b9db4e07105dd85c2dcc7c0ec88fb45f902f931 Mon Sep 17 00:00:00 2001 From: Seth Fowler Date: Tue, 26 Mar 2013 11:56:46 -0700 Subject: [PATCH 048/129] Bug 826093 (Part 1) - Add ClippedImage. r=joe --- image/src/ClippedImage.cpp | 325 +++++++++++++++++++++++++++++++++++++ image/src/ClippedImage.h | 82 ++++++++++ image/src/Makefile.in | 1 + 3 files changed, 408 insertions(+) create mode 100644 image/src/ClippedImage.cpp create mode 100644 image/src/ClippedImage.h diff --git a/image/src/ClippedImage.cpp b/image/src/ClippedImage.cpp new file mode 100644 index 000000000000..7f0190806a2d --- /dev/null +++ b/image/src/ClippedImage.cpp @@ -0,0 +1,325 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "gfxDrawable.h" +#include "gfxPlatform.h" +#include "gfxUtils.h" + +#include "ClippedImage.h" + +using mozilla::layers::LayerManager; +using mozilla::layers::ImageContainer; + +namespace mozilla { +namespace image { + +class DrawSingleTileCallback : public gfxDrawingCallback +{ +public: + DrawSingleTileCallback(ClippedImage* aImage, + const nsIntRect& aClip, + const nsIntSize& aViewportSize, + const SVGImageContext* aSVGContext, + uint32_t aWhichFrame, + uint32_t aFlags) + : mImage(aImage) + , mClip(aClip) + , mViewportSize(aViewportSize) + , mSVGContext(aSVGContext) + , mWhichFrame(aWhichFrame) + , mFlags(aFlags) + { + MOZ_ASSERT(mImage, "Must have an image to clip"); + } + + virtual bool operator()(gfxContext* aContext, + const gfxRect& aFillRect, + const gfxPattern::GraphicsFilter& aFilter, + const gfxMatrix& aTransform) + { + // Draw the image. |gfxCallbackDrawable| always calls this function with + // arguments that guarantee we never tile. + mImage->DrawSingleTile(aContext, aFilter, aTransform, aFillRect, mClip, + mViewportSize, mSVGContext, mWhichFrame, mFlags); + + return true; + } + +private: + nsRefPtr mImage; + const nsIntRect mClip; + const nsIntSize mViewportSize; + const SVGImageContext* mSVGContext; + const uint32_t mWhichFrame; + const uint32_t mFlags; +}; + +ClippedImage::ClippedImage(Image* aImage, + nsIntRect aClip) + : ImageWrapper(aImage) + , mClip(aClip) +{ + MOZ_ASSERT(aImage != nullptr, "ClippedImage requires an existing Image"); +} + +bool +ClippedImage::ShouldClip() +{ + // We need to evaluate the clipping region against the image's width and height + // once they're available to determine if it's valid and whether we actually + // need to do any work. We may fail if the image's width and height aren't + // available yet, in which case we'll try again later. + if (mShouldClip.empty()) { + int32_t width, height; + if (InnerImage()->HasError()) { + // If there's a problem with the inner image we'll let it handle everything. + mShouldClip.construct(false); + } else if (NS_SUCCEEDED(InnerImage()->GetWidth(&width)) && width > 0 && + NS_SUCCEEDED(InnerImage()->GetHeight(&height)) && height > 0) { + // Clamp the clipping region to the size of the underlying image. + mClip = mClip.Intersect(nsIntRect(0, 0, width, height)); + + // If the clipping region is the same size as the underlying image we + // don't have to do anything. + mShouldClip.construct(!mClip.IsEqualInterior(nsIntRect(0, 0, width, height))); + } else if (InnerImage()->GetStatusTracker().IsLoading()) { + // The image just hasn't finished loading yet. We don't yet know whether + // clipping with be needed or not for now. Just return without memoizing + // anything. + return false; + } else { + // We have a fully loaded image without a clearly defined width and + // height. This can happen with SVG images. + mShouldClip.construct(false); + } + } + + MOZ_ASSERT(!mShouldClip.empty(), "Should have computed a result"); + return mShouldClip.ref(); +} + +NS_IMPL_ISUPPORTS1(ClippedImage, imgIContainer) + +nsIntRect +ClippedImage::FrameRect(uint32_t aWhichFrame) +{ + if (!ShouldClip()) { + return InnerImage()->FrameRect(aWhichFrame); + } + + return nsIntRect(0, 0, mClip.width, mClip.height); +} + +NS_IMETHODIMP +ClippedImage::GetWidth(int32_t* aWidth) +{ + if (!ShouldClip()) { + return InnerImage()->GetWidth(aWidth); + } + + *aWidth = mClip.width; + return NS_OK; +} + +NS_IMETHODIMP +ClippedImage::GetHeight(int32_t* aHeight) +{ + if (!ShouldClip()) { + return InnerImage()->GetHeight(aHeight); + } + + *aHeight = mClip.height; + return NS_OK; +} + +NS_IMETHODIMP +ClippedImage::GetIntrinsicSize(nsSize* aSize) +{ + if (!ShouldClip()) { + return InnerImage()->GetIntrinsicSize(aSize); + } + + *aSize = nsSize(mClip.width, mClip.height); + return NS_OK; +} + +NS_IMETHODIMP +ClippedImage::GetIntrinsicRatio(nsSize* aRatio) +{ + if (!ShouldClip()) { + return InnerImage()->GetIntrinsicRatio(aRatio); + } + + *aRatio = nsSize(mClip.width, mClip.height); + return NS_OK; +} + +NS_IMETHODIMP +ClippedImage::GetFrame(uint32_t aWhichFrame, + uint32_t aFlags, + gfxASurface** _retval) +{ + if (!ShouldClip()) { + return InnerImage()->GetFrame(aWhichFrame, aFlags, _retval); + } + + // Create a surface to draw into. + gfxImageSurface::gfxImageFormat format = gfxASurface::ImageFormatARGB32; + nsRefPtr surface = gfxPlatform::GetPlatform() + ->CreateOffscreenSurface(gfxIntSize(mClip.width, mClip.height), + gfxImageSurface::ContentFromFormat(format)); + // Create our callback. + nsRefPtr drawTileCallback = + new DrawSingleTileCallback(this, mClip, mClip.Size(), nullptr, aWhichFrame, aFlags); + nsRefPtr drawable = + new gfxCallbackDrawable(drawTileCallback, mClip.Size()); + + // Actually draw. The callback will end up invoking DrawSingleTile. + nsRefPtr ctx = new gfxContext(surface); + gfxRect imageRect(0, 0, mClip.width, mClip.height); + gfxUtils::DrawPixelSnapped(ctx, drawable, gfxMatrix(), + imageRect, imageRect, imageRect, imageRect, + gfxASurface::ImageFormatARGB32, gfxPattern::FILTER_FAST); + + *_retval = surface.forget().get(); + return NS_OK; +} + +NS_IMETHODIMP +ClippedImage::GetImageContainer(LayerManager* aManager, ImageContainer** _retval) +{ + // XXX(seth): We currently don't have a way of clipping the result of + // GetImageContainer. We work around this by always returning null, but if it + // ever turns out that ClippedImage is widely used on codepaths that can + // actually benefit from GetImageContainer, it would be a good idea to fix + // that method for performance reasons. + + *_retval = nullptr; + return NS_OK; +} + +NS_IMETHODIMP +ClippedImage::ExtractFrame(uint32_t /* aWhichFrame */, + const nsIntRect& /* aRegion */, + uint32_t /* aFlags */, + imgIContainer** /* _retval */) +{ + // XXX(seth): This method has to be present in this patch because we haven't + // gotten to the point where we can remove ExtractFrame yet, but implementing + // it would be a waste of effort. + MOZ_ASSERT(false, "ClippedImage::ExtractFrame shouldn't be called"); + return NS_ERROR_NOT_AVAILABLE; +} + +bool +ClippedImage::WillTile(const gfxRect& aSourceRect, + const uint32_t aFlags) const +{ + return !gfxRect(0, 0, mClip.width, mClip.height).Contains(aSourceRect) && + !(aFlags & imgIContainer::FLAG_CLAMP); +} + +NS_IMETHODIMP +ClippedImage::Draw(gfxContext* aContext, + gfxPattern::GraphicsFilter aFilter, + const gfxMatrix& aUserSpaceToImageSpace, + const gfxRect& aFill, + const nsIntRect& aSubimage, + const nsIntSize& aViewportSize, + const SVGImageContext* aSVGContext, + uint32_t aWhichFrame, + uint32_t aFlags) +{ + if (!ShouldClip()) { + return InnerImage()->Draw(aContext, aFilter, aUserSpaceToImageSpace, + aFill, aSubimage, aViewportSize, aSVGContext, + aWhichFrame, aFlags); + } + + // Check for tiling. If we need to tile then we need to create a + // gfxCallbackDrawable to handle drawing for us. + gfxRect sourceRect = aUserSpaceToImageSpace.Transform(aFill); + if (WillTile(sourceRect, aFlags)) { + // Create a temporary surface containing a single tile of this image. + // GetFrame will call DrawSingleTile internally. + nsRefPtr surface; + GetFrame(aWhichFrame, aFlags, getter_AddRefs(surface)); + NS_ENSURE_TRUE(surface, NS_ERROR_FAILURE); + + // Create a drawable from that surface. + nsRefPtr drawable = + new gfxSurfaceDrawable(surface, gfxIntSize(mClip.width, mClip.height)); + + // Draw. + gfxRect imageRect(0, 0, mClip.width, mClip.height); + gfxRect subimage(aSubimage.x, aSubimage.y, aSubimage.width, aSubimage.height); + gfxUtils::DrawPixelSnapped(aContext, drawable, aUserSpaceToImageSpace, + subimage, sourceRect, imageRect, aFill, + gfxASurface::ImageFormatARGB32, aFilter); + + return NS_OK; + } + + nsIntRect subimage(aSubimage); + subimage.MoveBy(mClip.x, mClip.y); + subimage.Intersect(mClip); + + return DrawSingleTile(aContext, aFilter, aUserSpaceToImageSpace, aFill, subimage, + aViewportSize, aSVGContext, aWhichFrame, aFlags); +} + +gfxFloat +ClippedImage::ClampFactor(const gfxFloat aToClamp, const int aReference) const +{ + return aToClamp > aReference ? aReference / aToClamp + : 1.0; +} + +nsresult +ClippedImage::DrawSingleTile(gfxContext* aContext, + gfxPattern::GraphicsFilter aFilter, + const gfxMatrix& aUserSpaceToImageSpace, + const gfxRect& aFill, + const nsIntRect& aSubimage, + const nsIntSize& aViewportSize, + const SVGImageContext* aSVGContext, + uint32_t aWhichFrame, + uint32_t aFlags) +{ + MOZ_ASSERT(!WillTile(aUserSpaceToImageSpace.Transform(aFill), aFlags), + "DrawSingleTile shouldn't get a transform requiring tiling"); + + // Make the viewport reflect the original image's size. + nsIntSize viewportSize(aViewportSize); + int32_t imgWidth, imgHeight; + if (NS_SUCCEEDED(InnerImage()->GetWidth(&imgWidth)) && + NS_SUCCEEDED(InnerImage()->GetHeight(&imgHeight))) { + viewportSize = nsIntSize(imgWidth, imgHeight); + } else { + MOZ_ASSERT(false, "If ShouldClip() led us to draw then we should never get here"); + } + + // Add a translation to the transform to reflect the clipping region. + gfxMatrix transform(aUserSpaceToImageSpace); + transform.Multiply(gfxMatrix().Translate(gfxPoint(mClip.x, mClip.y))); + + // "Clamp the source rectangle" to the clipping region's width and height. + // Really, this means modifying the transform to get the results we want. + gfxRect sourceRect = transform.Transform(aFill); + if (sourceRect.width > mClip.width || sourceRect.height > mClip.height) { + gfxMatrix clampSource; + clampSource.Translate(gfxPoint(sourceRect.x, sourceRect.y)); + clampSource.Scale(ClampFactor(sourceRect.width, mClip.width), + ClampFactor(sourceRect.height, mClip.height)); + clampSource.Translate(gfxPoint(-sourceRect.x, -sourceRect.y)); + transform.Multiply(clampSource); + } + + return InnerImage()->Draw(aContext, aFilter, transform, aFill, aSubimage, + viewportSize, aSVGContext, aWhichFrame, aFlags); +} + +} // namespace image +} // namespace mozilla diff --git a/image/src/ClippedImage.h b/image/src/ClippedImage.h new file mode 100644 index 000000000000..26f94154608b --- /dev/null +++ b/image/src/ClippedImage.h @@ -0,0 +1,82 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef MOZILLA_IMAGELIB_CLIPPEDIMAGE_H_ +#define MOZILLA_IMAGELIB_CLIPPEDIMAGE_H_ + +#include "ImageWrapper.h" + +namespace mozilla { +namespace image { + +class DrawSingleTileCallback; + +/** + * An Image wrapper that clips an image against a rectangle. Right now only + * absolute coordinates in pixels are supported. + * + * XXX(seth): There a known (performance, not correctness) issue with + * GetImageContainer. See the comments for that method for more information. + */ +class ClippedImage : public ImageWrapper +{ +public: + NS_DECL_ISUPPORTS + + virtual ~ClippedImage() { } + + virtual nsIntRect FrameRect(uint32_t aWhichFrame) MOZ_OVERRIDE; + + NS_IMETHOD GetWidth(int32_t* aWidth) MOZ_OVERRIDE; + NS_IMETHOD GetHeight(int32_t* aHeight) MOZ_OVERRIDE; + NS_IMETHOD GetIntrinsicSize(nsSize* aSize) MOZ_OVERRIDE; + NS_IMETHOD GetIntrinsicRatio(nsSize* aRatio) MOZ_OVERRIDE; + NS_IMETHOD GetFrame(uint32_t aWhichFrame, + uint32_t aFlags, + gfxASurface** _retval) MOZ_OVERRIDE; + NS_IMETHOD GetImageContainer(mozilla::layers::LayerManager* aManager, + mozilla::layers::ImageContainer** _retval) MOZ_OVERRIDE; + NS_IMETHOD ExtractFrame(uint32_t aWhichFrame, + const nsIntRect& aRegion, + uint32_t aFlags, + imgIContainer** _retval) MOZ_OVERRIDE; + NS_IMETHOD Draw(gfxContext* aContext, + gfxPattern::GraphicsFilter aFilter, + const gfxMatrix& aUserSpaceToImageSpace, + const gfxRect& aFill, + const nsIntRect& aSubimage, + const nsIntSize& aViewportSize, + const SVGImageContext* aSVGContext, + uint32_t aWhichFrame, + uint32_t aFlags) MOZ_OVERRIDE; + +protected: + ClippedImage(Image* aImage, nsIntRect aClip); + +private: + bool ShouldClip(); + bool WillTile(const gfxRect& aSourceRect, const uint32_t aFlags) const; + gfxFloat ClampFactor(const gfxFloat aToClamp, const int aReference) const; + nsresult DrawSingleTile(gfxContext* aContext, + gfxPattern::GraphicsFilter aFilter, + const gfxMatrix& aUserSpaceToImageSpace, + const gfxRect& aFill, + const nsIntRect& aSubimage, + const nsIntSize& aViewportSize, + const SVGImageContext* aSVGContext, + uint32_t aWhichFrame, + uint32_t aFlags); + + nsIntRect mClip; // The region to clip to. + Maybe mShouldClip; // Memoized ShouldClip() if present. + + friend class DrawSingleTileCallback; + friend class ImageFactory; +}; + +} // namespace image +} // namespace mozilla + +#endif // MOZILLA_IMAGELIB_CLIPPEDIMAGE_H_ diff --git a/image/src/Makefile.in b/image/src/Makefile.in index fd271061709b..c855fa92318c 100644 --- a/image/src/Makefile.in +++ b/image/src/Makefile.in @@ -27,6 +27,7 @@ CPPSRCS = \ ImageFactory.cpp \ ImageMetadata.cpp \ ImageWrapper.cpp \ + ClippedImage.cpp \ Decoder.cpp \ DiscardTracker.cpp \ FrozenImage.cpp \ From f77987538784f7fb9020714488f7aef9580a80ef Mon Sep 17 00:00:00 2001 From: Seth Fowler Date: Tue, 26 Mar 2013 11:56:46 -0700 Subject: [PATCH 049/129] Bug 826093 (Part 2) - Create a static utility class for image operations. r=joe, sr=bz --- image/src/ClippedImage.h | 2 +- image/src/FrozenImage.h | 2 +- image/src/ImageFactory.cpp | 8 ------ image/src/ImageFactory.h | 8 ------ image/src/ImageOps.cpp | 48 ++++++++++++++++++++++++++++++++++ image/src/ImageOps.h | 49 +++++++++++++++++++++++++++++++++++ image/src/Makefile.in | 2 ++ image/src/imgRequestProxy.cpp | 4 +-- 8 files changed, 103 insertions(+), 20 deletions(-) create mode 100644 image/src/ImageOps.cpp create mode 100644 image/src/ImageOps.h diff --git a/image/src/ClippedImage.h b/image/src/ClippedImage.h index 26f94154608b..45e37a7e2380 100644 --- a/image/src/ClippedImage.h +++ b/image/src/ClippedImage.h @@ -73,7 +73,7 @@ private: Maybe mShouldClip; // Memoized ShouldClip() if present. friend class DrawSingleTileCallback; - friend class ImageFactory; + friend class ImageOps; }; } // namespace image diff --git a/image/src/FrozenImage.h b/image/src/FrozenImage.h index 077caa04027e..b4cc255c839a 100644 --- a/image/src/FrozenImage.h +++ b/image/src/FrozenImage.h @@ -62,7 +62,7 @@ protected: FrozenImage(Image* aImage) : ImageWrapper(aImage) { } private: - friend class ImageFactory; + friend class ImageOps; }; } // namespace image diff --git a/image/src/ImageFactory.cpp b/image/src/ImageFactory.cpp index e44416b669bb..92ed5a526c4a 100644 --- a/image/src/ImageFactory.cpp +++ b/image/src/ImageFactory.cpp @@ -21,7 +21,6 @@ #include "imgStatusTracker.h" #include "RasterImage.h" #include "VectorImage.h" -#include "FrozenImage.h" #include "Image.h" #include "nsMediaFragmentURIParser.h" @@ -175,13 +174,6 @@ GetContentSize(nsIRequest* aRequest) return 0; } -/* static */ already_AddRefed -ImageFactory::Freeze(Image* aImage) -{ - nsRefPtr frozenImage = new FrozenImage(aImage); - return frozenImage.forget(); -} - /* static */ already_AddRefed ImageFactory::CreateRasterImage(nsIRequest* aRequest, imgStatusTracker* aStatusTracker, diff --git a/image/src/ImageFactory.h b/image/src/ImageFactory.h index 716ac9797610..dedac3fb6158 100644 --- a/image/src/ImageFactory.h +++ b/image/src/ImageFactory.h @@ -46,14 +46,6 @@ public: */ static already_AddRefed CreateAnonymousImage(const nsCString& aMimeType); - /** - * Creates a version of an existing image which does not animate and is frozen - * at the first frame. - * - * @param aImage The existing image. - */ - static already_AddRefed Freeze(Image* aImage); - private: // Factory functions that create specific types of image containers. static already_AddRefed CreateRasterImage(nsIRequest* aRequest, diff --git a/image/src/ImageOps.cpp b/image/src/ImageOps.cpp new file mode 100644 index 000000000000..add83a89f990 --- /dev/null +++ b/image/src/ImageOps.cpp @@ -0,0 +1,48 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "imgIContainer.h" +#include "ClippedImage.h" +#include "FrozenImage.h" +#include "Image.h" + +#include "ImageOps.h" + +namespace mozilla { +namespace image { + +/* static */ already_AddRefed +ImageOps::Freeze(Image* aImage) +{ + nsRefPtr frozenImage = new FrozenImage(aImage); + return frozenImage.forget(); +} + +/* static */ already_AddRefed +ImageOps::Freeze(imgIContainer* aImage) +{ + nsCOMPtr frozenImage = + new FrozenImage(static_cast(aImage)); + return frozenImage.forget(); +} + +/* static */ already_AddRefed +ImageOps::Clip(Image* aImage, nsIntRect aClip) +{ + nsRefPtr clippedImage = new ClippedImage(aImage, aClip); + return clippedImage.forget(); +} + +/* static */ already_AddRefed +ImageOps::Clip(imgIContainer* aImage, nsIntRect aClip) +{ + nsCOMPtr clippedImage = + new ClippedImage(static_cast(aImage), aClip); + return clippedImage.forget(); +} + +} // namespace image +} // namespace mozilla diff --git a/image/src/ImageOps.h b/image/src/ImageOps.h new file mode 100644 index 000000000000..e68571f19a03 --- /dev/null +++ b/image/src/ImageOps.h @@ -0,0 +1,49 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef MOZILLA_IMAGELIB_IMAGEOPS_H_ +#define MOZILLA_IMAGELIB_IMAGEOPS_H_ + +#include "nsCOMPtr.h" +#include "nsRect.h" + +class imgIContainer; + +namespace mozilla { +namespace image { + +class Image; + +class ImageOps +{ +public: + /** + * Creates a version of an existing image which does not animate and is frozen + * at the first frame. + * + * @param aImage The existing image. + */ + static already_AddRefed Freeze(Image* aImage); + static already_AddRefed Freeze(imgIContainer* aImage); + + /** + * Creates a clipped version of an existing image. Animation is unaffected. + * + * @param aImage The existing image. + * @param aClip The rectangle to clip the image against. + */ + static already_AddRefed Clip(Image* aImage, nsIntRect aClip); + static already_AddRefed Clip(imgIContainer* aImage, nsIntRect aClip); + +private: + // This is a static utility class, so disallow instantiation. + virtual ~ImageOps() = 0; +}; + +} // namespace image +} // namespace mozilla + +#endif // MOZILLA_IMAGELIB_IMAGEOPS_H_ diff --git a/image/src/Makefile.in b/image/src/Makefile.in index c855fa92318c..897a40f02bdb 100644 --- a/image/src/Makefile.in +++ b/image/src/Makefile.in @@ -20,12 +20,14 @@ FAIL_ON_WARNINGS = 1 EXPORTS = imgLoader.h \ imgRequest.h \ imgRequestProxy.h \ + ImageOps.h \ $(NULL) CPPSRCS = \ Image.cpp \ ImageFactory.cpp \ ImageMetadata.cpp \ + ImageOps.cpp \ ImageWrapper.cpp \ ClippedImage.cpp \ Decoder.cpp \ diff --git a/image/src/imgRequestProxy.cpp b/image/src/imgRequestProxy.cpp index d6ad4a34d0df..d5e995422541 100644 --- a/image/src/imgRequestProxy.cpp +++ b/image/src/imgRequestProxy.cpp @@ -18,7 +18,7 @@ #include "nsCRT.h" #include "Image.h" -#include "ImageFactory.h" +#include "ImageOps.h" #include "nsError.h" #include "ImageLogging.h" @@ -915,7 +915,7 @@ imgRequestProxy::GetStaticRequest(imgRequestProxy** aReturn) } // We are animated. We need to create a frozen version of this image. - nsRefPtr frozenImage = ImageFactory::Freeze(image); + nsRefPtr frozenImage = ImageOps::Freeze(image); // Create a static imgRequestProxy with our new extracted frame. nsCOMPtr currentPrincipal; From 3a6ac25d8d924fa32c80a488dce18f203d0b490a Mon Sep 17 00:00:00 2001 From: Seth Fowler Date: Tue, 26 Mar 2013 11:56:46 -0700 Subject: [PATCH 050/129] Bug 826093 (Part 3) - Use ClippedImage instead of ExtractFrame for -moz-image-rect. r=bz --- layout/base/nsCSSRendering.cpp | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/layout/base/nsCSSRendering.cpp b/layout/base/nsCSSRendering.cpp index f2ccb4e5b984..ec0445e168d4 100644 --- a/layout/base/nsCSSRendering.cpp +++ b/layout/base/nsCSSRendering.cpp @@ -30,6 +30,7 @@ #include "nsIScrollableFrame.h" #include "imgIRequest.h" #include "imgIContainer.h" +#include "ImageOps.h" #include "nsCSSRendering.h" #include "nsCSSColorUtils.h" #include "nsITheme.h" @@ -60,6 +61,7 @@ using namespace mozilla; using namespace mozilla::css; +using mozilla::image::ImageOps; static int gFrameTreeLockCount = 0; @@ -4293,18 +4295,7 @@ nsImageRenderer::PrepareImage() // The cropped image is identical to the source image mImageContainer.swap(srcImage); } else { - nsCOMPtr subImage; - uint32_t aExtractFlags = (mFlags & FLAG_SYNC_DECODE_IMAGES) - ? (uint32_t) imgIContainer::FLAG_SYNC_DECODE - : (uint32_t) imgIContainer::FLAG_NONE; - nsresult rv = srcImage->ExtractFrame(imgIContainer::FRAME_CURRENT, - actualCropRect, aExtractFlags, - getter_AddRefs(subImage)); - if (NS_FAILED(rv)) { - NS_WARNING("The cropped image contains no pixels to draw; " - "maybe the crop rect is outside the image frame rect"); - return false; - } + nsCOMPtr subImage = ImageOps::Clip(srcImage, actualCropRect); mImageContainer.swap(subImage); } } From fc19e0b7896e6dba23e24fde74d403ac9dbdbf9e Mon Sep 17 00:00:00 2001 From: Seth Fowler Date: Tue, 26 Mar 2013 11:56:46 -0700 Subject: [PATCH 051/129] Bug 826093 (Part 4) - Use ClippedImage instead of ExtractFrame for border-image. r=bz --- layout/base/nsCSSRendering.cpp | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/layout/base/nsCSSRendering.cpp b/layout/base/nsCSSRendering.cpp index ec0445e168d4..c0c63b5bf9ea 100644 --- a/layout/base/nsCSSRendering.cpp +++ b/layout/base/nsCSSRendering.cpp @@ -3316,20 +3316,10 @@ DrawBorderImageComponent(nsRenderingContext& aRenderingContext, if (aFill.IsEmpty() || aSrc.IsEmpty()) return; - // Don't bother trying to cache sub images if the border image is animated - // We can only sucessfully call GetAnimated() if we are fully decoded, so default to true - bool animated = true; - aImage->GetAnimated(&animated); - nsCOMPtr subImage; - if (animated || (subImage = aStyleBorder.GetSubImage(aIndex)) == 0) { - if (NS_FAILED(aImage->ExtractFrame(imgIContainer::FRAME_CURRENT, aSrc, - imgIContainer::FLAG_SYNC_DECODE, - getter_AddRefs(subImage)))) - return; - - if (!animated) - aStyleBorder.SetSubImage(aIndex, subImage); + if ((subImage = aStyleBorder.GetSubImage(aIndex)) == nullptr) { + subImage = ImageOps::Clip(aImage, aSrc); + aStyleBorder.SetSubImage(aIndex, subImage); } gfxPattern::GraphicsFilter graphicsFilter = From bea17f6576888ebaa137c062f8986af9da321fd5 Mon Sep 17 00:00:00 2001 From: Seth Fowler Date: Tue, 26 Mar 2013 11:56:47 -0700 Subject: [PATCH 052/129] Bug 826093 (Part 5) - Remove imgIContainer::ExtractFrame. r=joe, sr=bz --- image/public/imgIContainer.idl | 29 +++------- image/src/ClippedImage.cpp | 13 ----- image/src/ClippedImage.h | 4 -- image/src/FrozenImage.cpp | 9 ---- image/src/FrozenImage.h | 4 -- image/src/ImageWrapper.cpp | 9 ---- image/src/RasterImage.cpp | 96 ++-------------------------------- image/src/VectorImage.cpp | 82 +++-------------------------- image/src/VectorImage.h | 7 --- 9 files changed, 19 insertions(+), 234 deletions(-) diff --git a/image/public/imgIContainer.idl b/image/public/imgIContainer.idl index ae7f86f9cb97..de2ca0c9e513 100644 --- a/image/public/imgIContainer.idl +++ b/image/public/imgIContainer.idl @@ -52,13 +52,12 @@ native nsSize(nsSize); /** * imgIContainer is the interface that represents an image. It allows - * access to frames as Thebes surfaces, and permits users to extract subregions - * as other imgIContainers. It also allows drawing of images on to Thebes - * contexts. + * access to frames as Thebes surfaces. It also allows drawing of images + * onto Thebes contexts. * * Internally, imgIContainer also manages animation of images. */ -[scriptable, builtinclass, uuid(01c4f92f-f883-4837-a127-d8f30920e374)] +[scriptable, builtinclass, uuid(0c1caf24-bce7-4db5-971d-8e1b6ed07540)] interface imgIContainer : nsISupports { /** @@ -178,19 +177,6 @@ interface imgIContainer : nsISupports */ [noscript] ImageContainer getImageContainer(in LayerManager aManager); - /** - * Create a new imgContainer that contains only a single frame, which itself - * contains a subregion of the given frame. - * - * @param aWhichFrame Frame specifier of the FRAME_* variety. - * @param aRect the area of the current frame to be duplicated in the - * returned imgContainer's frame. - * @param aFlags Flags of the FLAG_* variety - */ - [noscript] imgIContainer extractFrame(in uint32_t aWhichFrame, - [const] in nsIntRect aRect, - in uint32_t aFlags); - /** * Draw a frame onto the context specified. * @@ -229,11 +215,10 @@ interface imgIContainer : nsISupports /* * Ensures that an image is decoding. Calling this function guarantees that - * the image will at some point fire off decode notifications. Calling draw(), - * getFrame(), copyFrame(), or extractCurrentFrame() triggers the same - * mechanism internally. Thus, if you want to be sure that the image will be - * decoded but don't want to access it until then, you must call - * requestDecode(). + * the image will at some point fire off decode notifications. Calling draw() + * or getFrame() triggers the same mechanism internally. Thus, if you want to + * be sure that the image will be decoded but don't want to access it until + * then, you must call requestDecode(). */ void requestDecode(); diff --git a/image/src/ClippedImage.cpp b/image/src/ClippedImage.cpp index 7f0190806a2d..7d8f4ae98f11 100644 --- a/image/src/ClippedImage.cpp +++ b/image/src/ClippedImage.cpp @@ -200,19 +200,6 @@ ClippedImage::GetImageContainer(LayerManager* aManager, ImageContainer** _retval return NS_OK; } -NS_IMETHODIMP -ClippedImage::ExtractFrame(uint32_t /* aWhichFrame */, - const nsIntRect& /* aRegion */, - uint32_t /* aFlags */, - imgIContainer** /* _retval */) -{ - // XXX(seth): This method has to be present in this patch because we haven't - // gotten to the point where we can remove ExtractFrame yet, but implementing - // it would be a waste of effort. - MOZ_ASSERT(false, "ClippedImage::ExtractFrame shouldn't be called"); - return NS_ERROR_NOT_AVAILABLE; -} - bool ClippedImage::WillTile(const gfxRect& aSourceRect, const uint32_t aFlags) const diff --git a/image/src/ClippedImage.h b/image/src/ClippedImage.h index 45e37a7e2380..97a749655203 100644 --- a/image/src/ClippedImage.h +++ b/image/src/ClippedImage.h @@ -38,10 +38,6 @@ public: gfxASurface** _retval) MOZ_OVERRIDE; NS_IMETHOD GetImageContainer(mozilla::layers::LayerManager* aManager, mozilla::layers::ImageContainer** _retval) MOZ_OVERRIDE; - NS_IMETHOD ExtractFrame(uint32_t aWhichFrame, - const nsIntRect& aRegion, - uint32_t aFlags, - imgIContainer** _retval) MOZ_OVERRIDE; NS_IMETHOD Draw(gfxContext* aContext, gfxPattern::GraphicsFilter aFilter, const gfxMatrix& aUserSpaceToImageSpace, diff --git a/image/src/FrozenImage.cpp b/image/src/FrozenImage.cpp index aa7e19661f57..333b7b88e000 100644 --- a/image/src/FrozenImage.cpp +++ b/image/src/FrozenImage.cpp @@ -68,15 +68,6 @@ FrozenImage::GetImageContainer(layers::LayerManager* aManager, return NS_OK; } -NS_IMETHODIMP -FrozenImage::ExtractFrame(uint32_t aWhichFrame, - const nsIntRect& aRegion, - uint32_t aFlags, - imgIContainer** _retval) -{ - return InnerImage()->ExtractFrame(FRAME_FIRST, aRegion, aFlags, _retval); -} - NS_IMETHODIMP FrozenImage::Draw(gfxContext* aContext, gfxPattern::GraphicsFilter aFilter, diff --git a/image/src/FrozenImage.h b/image/src/FrozenImage.h index b4cc255c839a..65428ce7a3cc 100644 --- a/image/src/FrozenImage.h +++ b/image/src/FrozenImage.h @@ -40,10 +40,6 @@ public: NS_IMETHOD_(bool) FrameIsOpaque(uint32_t aWhichFrame) MOZ_OVERRIDE; NS_IMETHOD GetImageContainer(layers::LayerManager* aManager, layers::ImageContainer** _retval) MOZ_OVERRIDE; - NS_IMETHOD ExtractFrame(uint32_t aWhichFrame, - const nsIntRect& aRegion, - uint32_t aFlags, - imgIContainer** _retval) MOZ_OVERRIDE; NS_IMETHOD Draw(gfxContext* aContext, gfxPattern::GraphicsFilter aFilter, const gfxMatrix& aUserSpaceToImageSpace, diff --git a/image/src/ImageWrapper.cpp b/image/src/ImageWrapper.cpp index 193aac3ffc1b..d67e684d9d4c 100644 --- a/image/src/ImageWrapper.cpp +++ b/image/src/ImageWrapper.cpp @@ -203,15 +203,6 @@ ImageWrapper::GetImageContainer(LayerManager* aManager, ImageContainer** _retval return mInnerImage->GetImageContainer(aManager, _retval); } -NS_IMETHODIMP -ImageWrapper::ExtractFrame(uint32_t aWhichFrame, - const nsIntRect& aRegion, - uint32_t aFlags, - imgIContainer** _retval) -{ - return mInnerImage->ExtractFrame(aWhichFrame, aRegion, aFlags, _retval); -} - NS_IMETHODIMP ImageWrapper::Draw(gfxContext* aContext, gfxPattern::GraphicsFilter aFilter, diff --git a/image/src/RasterImage.cpp b/image/src/RasterImage.cpp index 737f22729b18..f197e3944d86 100644 --- a/image/src/RasterImage.cpp +++ b/image/src/RasterImage.cpp @@ -502,14 +502,6 @@ RasterImage::Init(const char* aMimeType, discardable_source_bytes += mSourceData.Length(); } - // If we're being called from ExtractFrame (used by borderimage), - // we don't actually do any decoding. Bail early. - // XXX - This should be removed when we fix borderimage - if (mSourceDataMimeType.Length() == 0) { - mInitialized = true; - return NS_OK; - } - // Instantiate the decoder nsresult rv = InitDecoder(/* aDoSizeDecode = */ true); CONTAINER_ENSURE_SUCCESS(rv); @@ -683,85 +675,6 @@ RasterImage::RequestRefresh(const mozilla::TimeStamp& aTime) } } -//****************************************************************************** -/* [noscript] imgIContainer extractFrame(uint32_t aWhichFrame, - * [const] in nsIntRect aRegion, - * in uint32_t aFlags); */ -NS_IMETHODIMP -RasterImage::ExtractFrame(uint32_t aWhichFrame, - const nsIntRect &aRegion, - uint32_t aFlags, - imgIContainer **_retval) -{ - NS_ENSURE_ARG_POINTER(_retval); - - nsresult rv; - - if (aWhichFrame > FRAME_MAX_VALUE) - return NS_ERROR_INVALID_ARG; - - if (mError) - return NS_ERROR_FAILURE; - - // Disallowed in the API - if (mInDecoder && (aFlags & imgIContainer::FLAG_SYNC_DECODE)) - return NS_ERROR_FAILURE; - - // Make a new container. This should switch to another class with bug 505959. - nsRefPtr img(new RasterImage()); - - // We don't actually have a mimetype in this case. The empty string tells the - // init routine not to try to instantiate a decoder. This should be fixed in - // bug 505959. - img->Init("", INIT_FLAG_NONE); - img->SetSize(aRegion.width, aRegion.height); - img->mDecoded = true; // Also, we need to mark the image as decoded - img->mHasBeenDecoded = true; - img->mFrameDecodeFlags = aFlags & DECODE_FLAGS_MASK; - - if (!ApplyDecodeFlags(aFlags)) - return NS_ERROR_NOT_AVAILABLE; - - // If a synchronous decode was requested, do it - if (aFlags & FLAG_SYNC_DECODE) { - rv = SyncDecode(); - CONTAINER_ENSURE_SUCCESS(rv); - } - - // Get the frame. If it's not there, it's probably the caller's fault for - // not waiting for the data to be loaded from the network or not passing - // FLAG_SYNC_DECODE - uint32_t frameIndex = (aWhichFrame == FRAME_FIRST) ? - 0 : GetCurrentImgFrameIndex(); - imgFrame *frame = GetDrawableImgFrame(frameIndex); - if (!frame) { - *_retval = nullptr; - return NS_ERROR_FAILURE; - } - - // The frame can be smaller than the image. We want to extract only the part - // of the frame that actually exists. - nsIntRect framerect = frame->GetRect(); - framerect.IntersectRect(framerect, aRegion); - - if (framerect.IsEmpty()) - return NS_ERROR_NOT_AVAILABLE; - - nsAutoPtr subframe; - rv = frame->Extract(framerect, getter_Transfers(subframe)); - if (NS_FAILED(rv)) - return rv; - - img->mFrames.AppendElement(subframe.forget()); - - img->mStatusTracker->RecordLoaded(); - img->mStatusTracker->RecordDecoded(); - - *_retval = img.forget().get(); - - return NS_OK; -} - //****************************************************************************** /* readonly attribute int32_t width; */ NS_IMETHODIMP @@ -2743,11 +2656,10 @@ RasterImage::WriteToDecoder(const char *aBuffer, uint32_t aCount) } // This function is called in situations where it's clear that we want the -// frames in decoded form (Draw, GetFrame, CopyFrame, ExtractFrame, etc). -// If we're completely decoded, this method resets the discard timer (if -// we're discardable), since wanting the frames now is a good indicator of -// wanting them again soon. If we're not decoded, this method kicks off -// asynchronous decoding to generate the frames. +// frames in decoded form (Draw, GetFrame, etc). If we're completely decoded, +// this method resets the discard timer (if we're discardable), since wanting +// the frames now is a good indicator of wanting them again soon. If we're not +// decoded, this method kicks off asynchronous decoding to generate the frames. nsresult RasterImage::WantDecodedFrames() { diff --git a/image/src/VectorImage.cpp b/image/src/VectorImage.cpp index 334dd6200509..9c1631a0d782 100644 --- a/image/src/VectorImage.cpp +++ b/image/src/VectorImage.cpp @@ -301,12 +301,10 @@ NS_IMPL_ISUPPORTS3(VectorImage, VectorImage::VectorImage(imgStatusTracker* aStatusTracker, nsIURI* aURI /* = nullptr */) : ImageResource(aStatusTracker, aURI), // invoke superclass's constructor - mRestrictedRegion(0, 0, 0, 0), mIsInitialized(false), mIsFullyLoaded(false), mIsDrawing(false), - mHaveAnimations(false), - mHaveRestrictedRegion(false) + mHaveAnimations(false) { } @@ -326,8 +324,7 @@ VectorImage::Init(const char* aMimeType, if (mIsInitialized) return NS_ERROR_ILLEGAL_VALUE; - MOZ_ASSERT(!mIsFullyLoaded && !mHaveAnimations && - !mHaveRestrictedRegion && !mError, + MOZ_ASSERT(!mIsFullyLoaded && !mHaveAnimations && !mError, "Flags unexpectedly set before initialization"); MOZ_ASSERT(!strcmp(aMimeType, IMAGE_SVG_XML), "Unexpected mimetype"); @@ -595,14 +592,7 @@ VectorImage::GetFrame(uint32_t aWhichFrame, // --------------------------------------------- // Make our surface the size of what will ultimately be drawn to it. // (either the full image size, or the restricted region) - gfxIntSize surfaceSize; - if (mHaveRestrictedRegion) { - surfaceSize.width = mRestrictedRegion.width; - surfaceSize.height = mRestrictedRegion.height; - } else { - surfaceSize.width = imageIntSize.width; - surfaceSize.height = imageIntSize.height; - } + gfxIntSize surfaceSize(imageIntSize.width, imageIntSize.height); nsRefPtr surface = new gfxImageSurface(surfaceSize, gfxASurface::ImageFormatARGB32); @@ -631,54 +621,6 @@ VectorImage::GetImageContainer(LayerManager* aManager, return NS_OK; } -//****************************************************************************** -/* [noscript] imgIContainer extractFrame(uint32_t aWhichFrame, - * [const] in nsIntRect aRegion, - * in uint32_t aFlags); */ -NS_IMETHODIMP -VectorImage::ExtractFrame(uint32_t aWhichFrame, - const nsIntRect& aRegion, - uint32_t aFlags, - imgIContainer** _retval) -{ - NS_ENSURE_ARG_POINTER(_retval); - if (mError || !mIsFullyLoaded) - return NS_ERROR_FAILURE; - - // XXXdholbert NOTE: This method assumes FRAME_CURRENT (not FRAME_FIRST) - // right now, because mozilla doesn't actually contain any clients of this - // method that use FRAME_FIRST. If it's needed, we *could* handle - // FRAME_FIRST by saving the helper-doc's current SMIL time, seeking it to - // time 0, rendering to a RasterImage, and then restoring our saved time. - if (aWhichFrame != FRAME_CURRENT) { - NS_WARNING("VectorImage::ExtractFrame with something other than " - "FRAME_CURRENT isn't supported yet. Assuming FRAME_CURRENT."); - } - - // XXXdholbert This method also doesn't actually freeze animation in the - // returned imgIContainer, because it shares our helper-document. To - // get a true snapshot, we need to clone the document - see bug 590792. - - // Make a new container with same SVG document. - nsRefPtr extractedImg = new VectorImage(); - extractedImg->mSVGDocumentWrapper = mSVGDocumentWrapper; - extractedImg->mAnimationMode = kDontAnimMode; - - extractedImg->mRestrictedRegion.x = aRegion.x; - extractedImg->mRestrictedRegion.y = aRegion.y; - - // (disallow negative width/height on our restricted region) - extractedImg->mRestrictedRegion.width = std::max(aRegion.width, 0); - extractedImg->mRestrictedRegion.height = std::max(aRegion.height, 0); - - extractedImg->mIsInitialized = true; - extractedImg->mIsFullyLoaded = true; - extractedImg->mHaveRestrictedRegion = true; - - *_retval = extractedImg.forget().get(); - return NS_OK; -} - //****************************************************************************** /* [noscript] void draw(in gfxContext aContext, * in gfxGraphicsFilter aFilter, @@ -722,24 +664,19 @@ VectorImage::Draw(gfxContext* aContext, mSVGDocumentWrapper->UpdateViewportBounds(aViewportSize); mSVGDocumentWrapper->FlushImageTransformInvalidation(); - nsIntSize imageSize = mHaveRestrictedRegion ? - mRestrictedRegion.Size() : aViewportSize; - // XXXdholbert Do we need to convert image size from // CSS pixels to dev pixels here? (is gfxCallbackDrawable's 2nd arg in dev // pixels?) - gfxIntSize imageSizeGfx(imageSize.width, imageSize.height); + gfxIntSize imageSizeGfx(aViewportSize.width, aViewportSize.height); // Based on imgFrame::Draw gfxRect sourceRect = aUserSpaceToImageSpace.Transform(aFill); - gfxRect imageRect(0, 0, imageSize.width, imageSize.height); + gfxRect imageRect(0, 0, aViewportSize.width, aViewportSize.height); gfxRect subimage(aSubimage.x, aSubimage.y, aSubimage.width, aSubimage.height); nsRefPtr cb = new SVGDrawingCallback(mSVGDocumentWrapper, - mHaveRestrictedRegion ? - mRestrictedRegion : nsIntRect(nsIntPoint(0, 0), aViewportSize), aFlags); @@ -750,12 +687,9 @@ VectorImage::Draw(gfxContext* aContext, subimage, sourceRect, imageRect, aFill, gfxASurface::ImageFormatARGB32, aFilter); - MOZ_ASSERT(mRenderingObserver || mHaveRestrictedRegion, - "Should have a rendering observer by now unless ExtractFrame created us"); - if (mRenderingObserver) { - // Allow ourselves to fire FrameChanged and OnStopFrame again. - mRenderingObserver->ResumeListening(); - } + // Allow ourselves to fire FrameChanged and OnStopFrame again. + MOZ_ASSERT(mRenderingObserver, "Should have a rendering observer by now"); + mRenderingObserver->ResumeListening(); return NS_OK; } diff --git a/image/src/VectorImage.h b/image/src/VectorImage.h index 69a547b82560..80746ddf9ffd 100644 --- a/image/src/VectorImage.h +++ b/image/src/VectorImage.h @@ -84,18 +84,11 @@ private: nsRefPtr mLoadEventListener; nsRefPtr mParseCompleteListener; - nsIntRect mRestrictedRegion; // If we were created by - // ExtractFrame, this is the region - // that we're restricted to using. - // Otherwise, this is ignored. - bool mIsInitialized; // Have we been initalized? bool mIsFullyLoaded; // Has the SVG document finished loading? bool mIsDrawing; // Are we currently drawing? bool mHaveAnimations; // Is our SVG content SMIL-animated? // (Only set after mIsFullyLoaded.) - bool mHaveRestrictedRegion; // Are we a restricted-region clone - // created via ExtractFrame? friend class ImageFactory; }; From 3b2d758f125b6e471219ed45937bac61d3372db4 Mon Sep 17 00:00:00 2001 From: Olli Pettay Date: Tue, 26 Mar 2013 20:57:54 +0200 Subject: [PATCH 053/129] Additional patch for Bug 767944 (Fix compilation on gcc 4.7.x), r=Ms2ger --HG-- extra : rebase_source : be9d00ca80306dfe57ed917b588cfd30ec8eb8d0 --- dom/quota/StorageMatcher.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dom/quota/StorageMatcher.h b/dom/quota/StorageMatcher.h index 156f4c55add4..69b3fff67ed9 100644 --- a/dom/quota/StorageMatcher.h +++ b/dom/quota/StorageMatcher.h @@ -14,7 +14,7 @@ BEGIN_QUOTA_NAMESPACE -template > +template > class StorageMatcher : public ValueType { typedef StorageMatcher SelfType; From a4a1cdaa5832d9c13c4323a2c14a64a3270aaed1 Mon Sep 17 00:00:00 2001 From: Ryan VanderMeulen Date: Tue, 26 Mar 2013 15:11:22 -0400 Subject: [PATCH 054/129] Backed out changeset 93cbcd7f34b3 (bug 828508) on suspicion of making bug 807442 nearly perma-fail on debug builds on a CLOSED TREE. --- browser/base/content/tabbrowser.xml | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/browser/base/content/tabbrowser.xml b/browser/base/content/tabbrowser.xml index 3acc43118b98..71702c161f1d 100644 --- a/browser/base/content/tabbrowser.xml +++ b/browser/base/content/tabbrowser.xml @@ -694,15 +694,9 @@ this.mFaviconService.FAVICON_LOAD_NON_PRIVATE); } - let sizedIconUrl = browser.mIconURL || ""; - if (sizedIconUrl) { - let size = Math.round(16 * window.devicePixelRatio); - sizedIconUrl += (sizedIconUrl.contains("#") ? "&" : "#") + - "-moz-resolution=" + size + "," + size; - } - if (sizedIconUrl != aTab.getAttribute("image")) { - if (sizedIconUrl) - aTab.setAttribute("image", sizedIconUrl); + if ((browser.mIconURL || "") != aTab.getAttribute("image")) { + if (browser.mIconURL) + aTab.setAttribute("image", browser.mIconURL); else aTab.removeAttribute("image"); this._tabAttrModified(aTab); From c58297757bbbeeb754a633d893317273321aa11d Mon Sep 17 00:00:00 2001 From: Ryan VanderMeulen Date: Tue, 26 Mar 2013 15:45:57 -0400 Subject: [PATCH 055/129] Backed out changeset 74ca9737e076 (bug 829456)on suspicion of making bug 807442 nearly perma-fail on debug builds on a CLOSED TREE. --- browser/base/content/browser-fullZoom.js | 345 +++++------------- .../base/content/test/browser_bug386835.js | 164 ++++++--- .../base/content/test/browser_bug416661.js | 68 ++-- .../base/content/test/browser_bug419612.js | 61 ++-- .../base/content/test/browser_bug441778.js | 22 +- .../base/content/test/browser_bug555224.js | 61 +++- .../base/content/test/browser_bug559991.js | 63 ++-- .../base/content/test/browser_bug575830.js | 21 +- .../base/content/test/browser_bug719271.js | 152 +++++--- browser/base/content/test/head.js | 104 ------ .../browser/browser_privatebrowsing_zoom.js | 36 +- .../browser_privatebrowsing_zoomrestore.js | 24 +- .../base/nsIContentPrefService2.idl | 23 +- .../contentprefs/ContentPrefService2.jsm | 60 ++- .../contentprefs/tests/unit_cps2/head.js | 15 +- .../tests/unit_cps2/test_extractDomain.js | 20 - .../tests/unit_cps2/test_observers.js | 32 +- .../contentprefs/tests/unit_cps2/xpcshell.ini | 1 - 18 files changed, 573 insertions(+), 699 deletions(-) delete mode 100644 toolkit/components/contentprefs/tests/unit_cps2/test_extractDomain.js diff --git a/browser/base/content/browser-fullZoom.js b/browser/base/content/browser-fullZoom.js index ebcaaa0e0911..574f384b935c 100644 --- a/browser/base/content/browser-fullZoom.js +++ b/browser/base/content/browser-fullZoom.js @@ -10,6 +10,15 @@ // From nsEventStateManager.cpp. const MOUSE_SCROLL_ZOOM = 3; +Cu.import('resource://gre/modules/ContentPrefInstance.jsm'); + +function getContentPrefs(aWindow) { + let context = aWindow ? aWindow.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIWebNavigation) + .QueryInterface(Ci.nsILoadContext) : null; + return new ContentPrefInstance(context); +} + /** * Controls the "full zoom" setting and its site-specific preferences. */ @@ -17,6 +26,17 @@ var FullZoom = { // Identifies the setting in the content prefs database. name: "browser.content.full-zoom", + // The global value (if any) for the setting. Lazily loaded from the service + // when first requested, then updated by the pref change listener as it changes. + // If there is no global value, then this should be undefined. + get globalValue() { + var globalValue = getContentPrefs(gBrowser.contentDocument.defaultView).getPref(null, this.name); + if (typeof globalValue != "undefined") + globalValue = this._ensureValid(globalValue); + delete this.globalValue; + return this.globalValue = globalValue; + }, + // browser.zoom.siteSpecific preference cache _siteSpecificPref: undefined, @@ -44,9 +64,7 @@ var FullZoom = { window.addEventListener("DOMMouseScroll", this, false); // Register ourselves with the service so we know when our pref changes. - this._cps2 = Cc["@mozilla.org/content-pref/service;1"]. - getService(Ci.nsIContentPrefService2); - this._cps2.addObserverForName(this.name, this); + getContentPrefs().addObserver(this.name, this); this._siteSpecificPref = gPrefService.getBoolPref("browser.zoom.siteSpecific"); @@ -59,7 +77,7 @@ var FullZoom = { destroy: function FullZoom_destroy() { gPrefService.removeObserver("browser.zoom.", this); - this._cps2.removeObserverForName(this.name, this); + getContentPrefs().removeObserver(this.name, this); window.removeEventListener("DOMMouseScroll", this, false); }, @@ -115,14 +133,7 @@ var FullZoom = { // We have to call _applySettingToPref in a timeout because we handle // the event before the event state manager has a chance to apply the zoom // during nsEventStateManager::PostHandleEvent. - // - // Since the zoom will have already been updated by the time - // _applySettingToPref is called, pass true to suppress updating the zoom - // again. Note that this is not an optimization: due to asynchronicity of - // the content preference service, the zoom may have been updated again by - // the time that onContentPrefSet is called as a result of this call to - // _applySettingToPref. - window.setTimeout(function (self) self._applySettingToPref(true), 0, this); + window.setTimeout(function (self) { self._applySettingToPref() }, 0, this); }, // nsIObserver @@ -147,53 +158,33 @@ var FullZoom = { // nsIContentPrefObserver onContentPrefSet: function FullZoom_onContentPrefSet(aGroup, aName, aValue) { - if (this._ignoreNextOnContentPrefSet) { - delete this._ignoreNextOnContentPrefSet; - return; + let contentPrefs = getContentPrefs(gBrowser.contentDocument.defaultView); + if (aGroup == contentPrefs.grouper.group(gBrowser.currentURI)) + this._applyPrefToSetting(aValue); + else if (aGroup == null) { + this.globalValue = this._ensureValid(aValue); + + // If the current page doesn't have a site-specific preference, + // then its zoom should be set to the new global preference now that + // the global preference has changed. + if (!contentPrefs.hasPref(gBrowser.currentURI, this.name)) + this._applyPrefToSetting(); } - this._onContentPrefChanged(aGroup, aValue); }, onContentPrefRemoved: function FullZoom_onContentPrefRemoved(aGroup, aName) { - this._onContentPrefChanged(aGroup, undefined); - }, + let contentPrefs = getContentPrefs(gBrowser.contentDocument.defaultView); + if (aGroup == contentPrefs.grouper.group(gBrowser.currentURI)) + this._applyPrefToSetting(); + else if (aGroup == null) { + this.globalValue = undefined; - /** - * Appropriately updates the zoom level after a content preference has - * changed. - * - * @param aGroup The group of the changed preference. - * @param aValue The new value of the changed preference. Pass undefined to - * indicate the preference's removal. - */ - _onContentPrefChanged: function FullZoom__onContentPrefChanged(aGroup, aValue) { - if (!gBrowser.currentURI) - return; - - let domain = this._cps2.extractDomain(gBrowser.currentURI.spec); - if (aGroup) { - if (aGroup == domain) - this._applyPrefToSetting(aValue); - return; + // If the current page doesn't have a site-specific preference, + // then its zoom should be set to the default preference now that + // the global preference has changed. + if (!contentPrefs.hasPref(gBrowser.currentURI, this.name)) + this._applyPrefToSetting(); } - - this._globalValue = aValue === undefined ? aValue : - this._ensureValid(aValue); - - // If the current page doesn't have a site-specific preference, then its - // zoom should be set to the new global preference now that the global - // preference has changed. - let hasPref = false; - let ctxt = this._loadContextFromWindow(gBrowser.contentWindow); - this._cps2.getByDomainAndName(gBrowser.currentURI.spec, this.name, ctxt, { - handleResult: function () hasPref = true, - handleCompletion: function () { - if (!hasPref && - gBrowser.currentURI && - this._cps2.extractDomain(gBrowser.currentURI.spec) == domain) - this._applyPrefToSetting(); - }.bind(this) - }); }, // location change observer @@ -210,16 +201,12 @@ var FullZoom = { * (optional) browser object displaying the document */ onLocationChange: function FullZoom_onLocationChange(aURI, aIsTabSwitch, aBrowser) { - if (!aURI || (aIsTabSwitch && !this.siteSpecific)) { - this._notifyOnLocationChange(); + if (!aURI || (aIsTabSwitch && !this.siteSpecific)) return; - } // Avoid the cps roundtrip and apply the default/global pref. if (aURI.spec == "about:blank") { - this._applyPrefToSetting(undefined, aBrowser, function () { - this._notifyOnLocationChange(); - }.bind(this)); + this._applyPrefToSetting(undefined, aBrowser); return; } @@ -228,32 +215,24 @@ var FullZoom = { // Media documents should always start at 1, and are not affected by prefs. if (!aIsTabSwitch && browser.contentDocument.mozSyntheticDocument) { ZoomManager.setZoomForBrowser(browser, 1); - this._notifyOnLocationChange(); return; } - let ctxt = this._loadContextFromWindow(browser.contentWindow); - let pref = this._cps2.getCachedByDomainAndName(aURI.spec, this.name, ctxt); - if (pref) { - this._applyPrefToSetting(pref.value, browser, function () { - this._notifyOnLocationChange(); - }.bind(this)); - return; - } - - let value = undefined; - this._cps2.getByDomainAndName(aURI.spec, this.name, ctxt, { - handleResult: function (resultPref) value = resultPref.value, - handleCompletion: function () { - if (browser.currentURI && - this._cps2.extractDomain(browser.currentURI.spec) == - this._cps2.extractDomain(aURI.spec)) { - this._applyPrefToSetting(value, browser, function () { - this._notifyOnLocationChange(); - }.bind(this)); + let contentPrefs = getContentPrefs(gBrowser.contentDocument.defaultView); + if (contentPrefs.hasCachedPref(aURI, this.name)) { + let zoomValue = contentPrefs.getPref(aURI, this.name); + this._applyPrefToSetting(zoomValue, browser); + } else { + var self = this; + contentPrefs.getPref(aURI, this.name, function (aResult) { + // Check that we're still where we expect to be in case this took a while. + // Null check currentURI, since the window may have been destroyed before + // we were called. + if (browser.currentURI && aURI.equals(browser.currentURI)) { + self._applyPrefToSetting(aResult, browser); } - }.bind(this) - }); + }); + } }, // update state of zoom type menu item @@ -267,43 +246,23 @@ var FullZoom = { //**************************************************************************// // Setting & Pref Manipulation - /** - * Reduces the zoom level of the page in the current browser. - * - * @param callback Optional. If given, it's asynchronously called when the - * zoom update completes. - */ - reduce: function FullZoom_reduce(callback) { + reduce: function FullZoom_reduce() { ZoomManager.reduce(); - this._applySettingToPref(false, callback); + this._applySettingToPref(); }, - /** - * Enlarges the zoom level of the page in the current browser. - * - * @param callback Optional. If given, it's asynchronously called when the - * zoom update completes. - */ - enlarge: function FullZoom_enlarge(callback) { + enlarge: function FullZoom_enlarge() { ZoomManager.enlarge(); - this._applySettingToPref(false, callback); + this._applySettingToPref(); }, - /** - * Sets the zoom level of the page in the current browser to the global zoom - * level. - * - * @param callback Optional. If given, it's asynchronously called when the - * zoom update completes. - */ - reset: function FullZoom_reset(callback) { - this._getGlobalValue(gBrowser.contentWindow, function (value) { - if (value === undefined) - ZoomManager.reset(); - else - ZoomManager.zoom = value; - this._removePref(callback); - }); + reset: function FullZoom_reset() { + if (typeof this.globalValue != "undefined") + ZoomManager.zoom = this.globalValue; + else + ZoomManager.reset(); + + this._removePref(); }, /** @@ -324,91 +283,38 @@ var FullZoom = { * So when we apply new zoom values to the browser, we simply set the zoom. * We don't check first to see if the new value is the same as the current * one. - * - * @param aValue The zoom level value. - * @param aBrowser The browser containing the page whose zoom level is to be - * set. If falsey, the currently selected browser is used. - * @param aCallback Optional. If given, it's asynchronously called when - * complete. - */ - _applyPrefToSetting: function FullZoom__applyPrefToSetting(aValue, aBrowser, aCallback) { - if (!this.siteSpecific || gInPrintPreviewMode) { - this._executeSoon(aCallback); + **/ + _applyPrefToSetting: function FullZoom__applyPrefToSetting(aValue, aBrowser) { + if ((!this.siteSpecific) || gInPrintPreviewMode) return; - } var browser = aBrowser || (gBrowser && gBrowser.selectedBrowser); - if (browser.contentDocument.mozSyntheticDocument) { - this._executeSoon(aCallback); - return; - } + try { + if (browser.contentDocument.mozSyntheticDocument) + return; - if (aValue !== undefined) { - ZoomManager.setZoomForBrowser(browser, this._ensureValid(aValue)); - this._executeSoon(aCallback); - return; + if (typeof aValue != "undefined") + ZoomManager.setZoomForBrowser(browser, this._ensureValid(aValue)); + else if (typeof this.globalValue != "undefined") + ZoomManager.setZoomForBrowser(browser, this.globalValue); + else + ZoomManager.setZoomForBrowser(browser, 1); } - - this._getGlobalValue(browser.contentWindow, function (value) { - if (gBrowser.selectedBrowser == browser) - ZoomManager.setZoomForBrowser(browser, value === undefined ? 1 : value); - this._executeSoon(aCallback); - }); + catch(ex) {} }, - /** - * Saves the zoom level of the page in the current browser to the content - * prefs store. - * - * @param suppressZoomChange Because this method sets a content preference, - * our onContentPrefSet method is called as a - * result, which updates the current zoom level. - * If suppressZoomChange is true, then the next - * call to onContentPrefSet will not update the - * zoom level. - * @param callback Optional. If given, it's asynchronously called - * when done. - */ - _applySettingToPref: function FullZoom__applySettingToPref(suppressZoomChange, callback) { - if (!this.siteSpecific || - gInPrintPreviewMode || - content.document.mozSyntheticDocument) { - this._executeSoon(callback); + _applySettingToPref: function FullZoom__applySettingToPref() { + if (!this.siteSpecific || gInPrintPreviewMode || + content.document.mozSyntheticDocument) return; - } - this._cps2.set(gBrowser.currentURI.spec, this.name, ZoomManager.zoom, - this._loadContextFromWindow(gBrowser.contentWindow), { - handleCompletion: function () { - if (suppressZoomChange) - // The content preference service calls observers after callbacks, and - // it calls both in the same turn of the event loop. onContentPrefSet - // will therefore be called next, in the same turn of the event loop, - // and it will check this flag. - this._ignoreNextOnContentPrefSet = true; - if (callback) - callback(); - }.bind(this) - }); + var zoomLevel = ZoomManager.zoom; + getContentPrefs(gBrowser.contentDocument.defaultView).setPref(gBrowser.currentURI, this.name, zoomLevel); }, - /** - * Removes from the content prefs store the zoom level of the current browser. - * - * @param callback Optional. If given, it's asynchronously called when done. - */ - _removePref: function FullZoom__removePref(callback) { - if (content.document.mozSyntheticDocument) { - this._executeSoon(callback); - return; - } - let ctxt = this._loadContextFromWindow(gBrowser.contentWindow); - this._cps2.removeByDomainAndName(gBrowser.currentURI.spec, this.name, ctxt, { - handleCompletion: function () { - if (callback) - callback(); - } - }); + _removePref: function FullZoom__removePref() { + if (!(content.document.mozSyntheticDocument)) + getContentPrefs(gBrowser.contentDocument.defaultView).removePref(gBrowser.currentURI, this.name); }, @@ -416,8 +322,6 @@ var FullZoom = { // Utilities _ensureValid: function FullZoom__ensureValid(aValue) { - // Note that undefined is a valid value for aValue that indicates a known- - // not-to-exist value. if (isNaN(aValue)) return 1; @@ -428,68 +332,5 @@ var FullZoom = { return ZoomManager.MAX; return aValue; - }, - - /** - * Gets the global browser.content.full-zoom content preference. - * - * WARNING: callback may be called synchronously or asynchronously. The - * reason is that it's usually desirable to avoid turns of the event loop - * where possible, since they can lead to visible, jarring jumps in zoom - * level. It's not always possible to avoid them, though. As a convenience, - * then, this method takes a callback and returns nothing. - * - * @param window The content window pertaining to the zoom. - * @param callback Synchronously or asynchronously called when done. It's - * bound to this object (FullZoom) and passed the preference - * value. - */ - _getGlobalValue: function FullZoom__getGlobalValue(window, callback) { - // * !("_globalValue" in this) => global value not yet cached. - // * this._globalValue === undefined => global value known not to exist. - // * Otherwise, this._globalValue is a number, the global value. - if ("_globalValue" in this) { - callback.call(this, this._globalValue); - return; - } - let value = undefined; - this._cps2.getGlobal(this.name, this._loadContextFromWindow(window), { - handleResult: function (pref) value = pref.value, - handleCompletion: function () { - this._globalValue = this._ensureValid(value); - callback.call(this, this._globalValue); - }.bind(this) - }); - }, - - /** - * Gets the load context from the given window. - * - * @param window The window whose load context will be returned. - * @return The nsILoadContext of the given window. - */ - _loadContextFromWindow: function FullZoom__loadContextFromWindow(window) { - return window. - QueryInterface(Ci.nsIInterfaceRequestor). - getInterface(Ci.nsIWebNavigation). - QueryInterface(Ci.nsILoadContext); - }, - - /** - * Asynchronously broadcasts a "browser-fullZoom:locationChange" notification - * so that tests can select tabs, load pages, etc. and be notified when the - * zoom levels on those pages change. The notification is always asynchronous - * so that observers are guaranteed a consistent behavior. - */ - _notifyOnLocationChange: function FullZoom__notifyOnLocationChange() { - this._executeSoon(function () { - Services.obs.notifyObservers(null, "browser-fullZoom:locationChange", ""); - }); - }, - - _executeSoon: function FullZoom__executeSoon(callback) { - if (!callback) - return; - Services.tm.mainThread.dispatch(callback, Ci.nsIThread.DISPATCH_NORMAL); - }, + } }; diff --git a/browser/base/content/test/browser_bug386835.js b/browser/base/content/test/browser_bug386835.js index ea4ffbc94414..46a69ec395c7 100644 --- a/browser/base/content/test/browser_bug386835.js +++ b/browser/base/content/test/browser_bug386835.js @@ -8,82 +8,136 @@ const FORWARD = 1; function test() { waitForExplicitFinish(); - Task.spawn(function () { - gTab1 = gBrowser.addTab(gTestPage); - gTab2 = gBrowser.addTab(); - gTab3 = gBrowser.addTab(); + gTab1 = gBrowser.addTab(gTestPage); + gTab2 = gBrowser.addTab(); + gTab3 = gBrowser.addTab(); + gBrowser.selectedTab = gTab1; - yield FullZoomHelper.selectTabAndWaitForLocationChange(gTab1); - yield FullZoomHelper.load(gTab1, gTestPage); - yield FullZoomHelper.load(gTab2, gTestPage); - }).then(secondPageLoaded, FullZoomHelper.failAndContinue(finish)); + load(gTab1, gTestPage, function () { + load(gTab2, gTestPage, secondPageLoaded); + }); } function secondPageLoaded() { - Task.spawn(function () { - FullZoomHelper.zoomTest(gTab1, 1, "Initial zoom of tab 1 should be 1"); - FullZoomHelper.zoomTest(gTab2, 1, "Initial zoom of tab 2 should be 1"); - FullZoomHelper.zoomTest(gTab3, 1, "Initial zoom of tab 3 should be 1"); + zoomTest(gTab1, 1, "Initial zoom of tab 1 should be 1"); + zoomTest(gTab2, 1, "Initial zoom of tab 2 should be 1"); + zoomTest(gTab3, 1, "Initial zoom of tab 3 should be 1"); - // Now have three tabs, two with the test page, one blank. Tab 1 is selected - // Zoom tab 1 - yield FullZoomHelper.enlarge(); - gLevel = ZoomManager.getZoomForBrowser(gBrowser.getBrowserForTab(gTab1)); + // Now have three tabs, two with the test page, one blank. Tab 1 is selected + // Zoom tab 1 + FullZoom.enlarge(); + gLevel = ZoomManager.getZoomForBrowser(gBrowser.getBrowserForTab(gTab1)); - ok(gLevel > 1, "New zoom for tab 1 should be greater than 1"); - FullZoomHelper.zoomTest(gTab2, 1, "Zooming tab 1 should not affect tab 2"); - FullZoomHelper.zoomTest(gTab3, 1, "Zooming tab 1 should not affect tab 3"); + ok(gLevel > 1, "New zoom for tab 1 should be greater than 1"); + zoomTest(gTab2, 1, "Zooming tab 1 should not affect tab 2"); + zoomTest(gTab3, 1, "Zooming tab 1 should not affect tab 3"); - yield FullZoomHelper.load(gTab3, gTestPage); - }).then(thirdPageLoaded, FullZoomHelper.failAndContinue(finish)); + load(gTab3, gTestPage, thirdPageLoaded); } function thirdPageLoaded() { - Task.spawn(function () { - FullZoomHelper.zoomTest(gTab1, gLevel, "Tab 1 should still be zoomed"); - FullZoomHelper.zoomTest(gTab2, 1, "Tab 2 should still not be affected"); - FullZoomHelper.zoomTest(gTab3, gLevel, "Tab 3 should have zoomed as it was loading in the background"); + zoomTest(gTab1, gLevel, "Tab 1 should still be zoomed"); + zoomTest(gTab2, 1, "Tab 2 should still not be affected"); + zoomTest(gTab3, gLevel, "Tab 3 should have zoomed as it was loading in the background"); - // Switching to tab 2 should update its zoom setting. - yield FullZoomHelper.selectTabAndWaitForLocationChange(gTab2); - FullZoomHelper.zoomTest(gTab1, gLevel, "Tab 1 should still be zoomed"); - FullZoomHelper.zoomTest(gTab2, gLevel, "Tab 2 should be zoomed now"); - FullZoomHelper.zoomTest(gTab3, gLevel, "Tab 3 should still be zoomed"); + // Switching to tab 2 should update its zoom setting. + afterZoom(function() { + zoomTest(gTab1, gLevel, "Tab 1 should still be zoomed"); + zoomTest(gTab2, gLevel, "Tab 2 should be zoomed now"); + zoomTest(gTab3, gLevel, "Tab 3 should still be zoomed"); - yield FullZoomHelper.load(gTab1, gTestImage); - }).then(imageLoaded, FullZoomHelper.failAndContinue(finish)); + load(gTab1, gTestImage, imageLoaded); + }); + + gBrowser.selectedTab = gTab2; } function imageLoaded() { - Task.spawn(function () { - FullZoomHelper.zoomTest(gTab1, 1, "Zoom should be 1 when image was loaded in the background"); - yield FullZoomHelper.selectTabAndWaitForLocationChange(gTab1); - FullZoomHelper.zoomTest(gTab1, 1, "Zoom should still be 1 when tab with image is selected"); - }).then(imageZoomSwitch, FullZoomHelper.failAndContinue(finish)); + zoomTest(gTab1, 1, "Zoom should be 1 when image was loaded in the background"); + gBrowser.selectedTab = gTab1; + zoomTest(gTab1, 1, "Zoom should still be 1 when tab with image is selected"); + + executeSoon(imageZoomSwitch); } function imageZoomSwitch() { - Task.spawn(function () { - yield FullZoomHelper.navigate(BACK); - yield FullZoomHelper.navigate(FORWARD); - FullZoomHelper.zoomTest(gTab1, 1, "Tab 1 should not be zoomed when an image loads"); + navigate(BACK, function () { + navigate(FORWARD, function () { + zoomTest(gTab1, 1, "Tab 1 should not be zoomed when an image loads"); - yield FullZoomHelper.selectTabAndWaitForLocationChange(gTab2); - FullZoomHelper.zoomTest(gTab1, 1, "Tab 1 should still not be zoomed when deselected"); - }).then(finishTest, FullZoomHelper.failAndContinue(finish)); + afterZoom(function() { + zoomTest(gTab1, 1, "Tab 1 should still not be zoomed when deselected"); + finishTest(); + }); + gBrowser.selectedTab = gTab2; + }); + }); } var finishTestStarted = false; function finishTest() { - Task.spawn(function () { - ok(!finishTestStarted, "finishTest called more than once"); - finishTestStarted = true; - yield FullZoomHelper.selectTabAndWaitForLocationChange(gTab1); - yield FullZoomHelper.reset(); - gBrowser.removeTab(gTab1); - yield FullZoomHelper.reset(); - gBrowser.removeTab(gTab2); - yield FullZoomHelper.reset(); - gBrowser.removeTab(gTab3); - }).then(finish, FullZoomHelper.failAndContinue(finish)); + ok(!finishTestStarted, "finishTest called more than once"); + finishTestStarted = true; + gBrowser.selectedTab = gTab1; + FullZoom.reset(); + gBrowser.removeTab(gTab1); + FullZoom.reset(); + gBrowser.removeTab(gTab2); + FullZoom.reset(); + gBrowser.removeTab(gTab3); + finish(); +} + +function zoomTest(tab, val, msg) { + is(ZoomManager.getZoomForBrowser(tab.linkedBrowser), val, msg); +} + +function load(tab, url, cb) { + let didLoad = false; + let didZoom = false; + tab.linkedBrowser.addEventListener("load", function (event) { + event.currentTarget.removeEventListener("load", arguments.callee, true); + didLoad = true; + if (didZoom) + executeSoon(cb); + }, true); + + afterZoom(function() { + didZoom = true; + if (didLoad) + executeSoon(cb); + }); + + tab.linkedBrowser.loadURI(url); +} + +function navigate(direction, cb) { + let didPs = false; + let didZoom = false; + gBrowser.addEventListener("pageshow", function (event) { + gBrowser.removeEventListener("pageshow", arguments.callee, true); + didPs = true; + if (didZoom) + executeSoon(cb); + }, true); + + afterZoom(function() { + didZoom = true; + if (didPs) + executeSoon(cb); + }); + + if (direction == BACK) + gBrowser.goBack(); + else if (direction == FORWARD) + gBrowser.goForward(); +} + +function afterZoom(cb) { + let oldSZFB = ZoomManager.setZoomForBrowser; + ZoomManager.setZoomForBrowser = function(browser, value) { + oldSZFB.call(ZoomManager, browser, value); + ZoomManager.setZoomForBrowser = oldSZFB; + executeSoon(cb); + }; } diff --git a/browser/base/content/test/browser_bug416661.js b/browser/base/content/test/browser_bug416661.js index af0fe24fedcd..f459284eeeba 100644 --- a/browser/base/content/test/browser_bug416661.js +++ b/browser/base/content/test/browser_bug416661.js @@ -1,42 +1,62 @@ var tabElm, zoomLevel; function start_test_prefNotSet() { - Task.spawn(function () { - is(ZoomManager.zoom, 1, "initial zoom level should be 1"); - yield FullZoomHelper.enlarge(); + is(ZoomManager.zoom, 1, "initial zoom level should be 1"); + FullZoom.enlarge(); - //capture the zoom level to test later - zoomLevel = ZoomManager.zoom; - isnot(zoomLevel, 1, "zoom level should have changed"); + //capture the zoom level to test later + zoomLevel = ZoomManager.zoom; + isnot(zoomLevel, 1, "zoom level should have changed"); - yield FullZoomHelper.load(gBrowser.selectedTab, "http://mochi.test:8888/browser/browser/base/content/test/moz.png"); - }).then(continue_test_prefNotSet, FullZoomHelper.failAndContinue(finish)); + afterZoomAndLoad(continue_test_prefNotSet); + content.location = + "http://mochi.test:8888/browser/browser/base/content/test/moz.png"; } function continue_test_prefNotSet () { - Task.spawn(function () { - is(ZoomManager.zoom, 1, "zoom level pref should not apply to an image"); - yield FullZoomHelper.reset(); + is(ZoomManager.zoom, 1, "zoom level pref should not apply to an image"); + FullZoom.reset(); - yield FullZoomHelper.load(gBrowser.selectedTab, "http://mochi.test:8888/browser/browser/base/content/test/zoom_test.html"); - }).then(end_test_prefNotSet, FullZoomHelper.failAndContinue(finish)); + afterZoomAndLoad(end_test_prefNotSet); + content.location = + "http://mochi.test:8888/browser/browser/base/content/test/zoom_test.html"; } function end_test_prefNotSet() { - Task.spawn(function () { - is(ZoomManager.zoom, zoomLevel, "the zoom level should have persisted"); + is(ZoomManager.zoom, zoomLevel, "the zoom level should have persisted"); - // Reset the zoom so that other tests have a fresh zoom level - yield FullZoomHelper.reset(); - gBrowser.removeCurrentTab(); - }).then(finish, FullZoomHelper.failAndContinue(finish)); + // Reset the zoom so that other tests have a fresh zoom level + FullZoom.reset(); + gBrowser.removeCurrentTab(); + finish(); } + function test() { waitForExplicitFinish(); - Task.spawn(function () { - tabElm = gBrowser.addTab(); - yield FullZoomHelper.selectTabAndWaitForLocationChange(tabElm); - yield FullZoomHelper.load(tabElm, "http://mochi.test:8888/browser/browser/base/content/test/zoom_test.html"); - }).then(start_test_prefNotSet, FullZoomHelper.failAndContinue(finish)); + tabElm = gBrowser.addTab(); + gBrowser.selectedTab = tabElm; + + afterZoomAndLoad(start_test_prefNotSet); + content.location = + "http://mochi.test:8888/browser/browser/base/content/test/zoom_test.html"; +} + +function afterZoomAndLoad(cb) { + let didLoad = false; + let didZoom = false; + tabElm.linkedBrowser.addEventListener("load", function() { + tabElm.linkedBrowser.removeEventListener("load", arguments.callee, true); + didLoad = true; + if (didZoom) + executeSoon(cb); + }, true); + let oldSZFB = ZoomManager.setZoomForBrowser; + ZoomManager.setZoomForBrowser = function(browser, value) { + oldSZFB.call(ZoomManager, browser, value); + ZoomManager.setZoomForBrowser = oldSZFB; + didZoom = true; + if (didLoad) + executeSoon(cb); + }; } diff --git a/browser/base/content/test/browser_bug419612.js b/browser/base/content/test/browser_bug419612.js index 76194c9f9bc9..2ff094873dc8 100644 --- a/browser/base/content/test/browser_bug419612.js +++ b/browser/base/content/test/browser_bug419612.js @@ -1,32 +1,49 @@ function test() { waitForExplicitFinish(); - Task.spawn(function () { - let testPage = "http://example.org/browser/browser/base/content/test/dummy_page.html"; - let tab1 = gBrowser.addTab(); - yield FullZoomHelper.selectTabAndWaitForLocationChange(tab1); - yield FullZoomHelper.load(tab1, testPage); + let testPage = "http://example.org/browser/browser/base/content/test/dummy_page.html"; + let tab1 = gBrowser.selectedTab = gBrowser.addTab(); + tab1.linkedBrowser.addEventListener("load", (function(event) { + event.currentTarget.removeEventListener("load", arguments.callee, true); let tab2 = gBrowser.addTab(); - yield FullZoomHelper.load(tab2, testPage); + tab2.linkedBrowser.addEventListener("load", (function(event) { + event.currentTarget.removeEventListener("load", arguments.callee, true); - yield FullZoomHelper.enlarge(); - let tab1Zoom = ZoomManager.getZoomForBrowser(tab1.linkedBrowser); + FullZoom.enlarge(); + let tab1Zoom = ZoomManager.getZoomForBrowser(tab1.linkedBrowser); - yield FullZoomHelper.selectTabAndWaitForLocationChange(tab2); - let tab2Zoom = ZoomManager.getZoomForBrowser(tab2.linkedBrowser); - is(tab2Zoom, tab1Zoom, "Zoom should affect background tabs"); + afterZoom(function() { + let tab2Zoom = ZoomManager.getZoomForBrowser(tab2.linkedBrowser); + is(tab2Zoom, tab1Zoom, "Zoom should affect background tabs"); - gPrefService.setBoolPref("browser.zoom.updateBackgroundTabs", false); - yield FullZoomHelper.reset(); - gBrowser.selectedTab = tab1; - tab1Zoom = ZoomManager.getZoomForBrowser(tab1.linkedBrowser); - tab2Zoom = ZoomManager.getZoomForBrowser(tab2.linkedBrowser); - isnot(tab1Zoom, tab2Zoom, "Zoom should not affect background tabs"); + gPrefService.setBoolPref("browser.zoom.updateBackgroundTabs", false); + FullZoom.reset(); + gBrowser.selectedTab = tab1; + tab1Zoom = ZoomManager.getZoomForBrowser(tab1.linkedBrowser); + tab2Zoom = ZoomManager.getZoomForBrowser(tab2.linkedBrowser); + isnot(tab1Zoom, tab2Zoom, "Zoom should not affect background tabs"); - if (gPrefService.prefHasUserValue("browser.zoom.updateBackgroundTabs")) - gPrefService.clearUserPref("browser.zoom.updateBackgroundTabs"); - gBrowser.removeTab(tab1); - gBrowser.removeTab(tab2); - }).then(finish, FullZoomHelper.failAndContinue(finish)); + if (gPrefService.prefHasUserValue("browser.zoom.updateBackgroundTabs")) + gPrefService.clearUserPref("browser.zoom.updateBackgroundTabs"); + gBrowser.removeTab(tab1); + gBrowser.removeTab(tab2); + finish(); + }); + gBrowser.selectedTab = tab2; + }), true); + tab2.linkedBrowser.loadURI(testPage); + }), true); + content.location = testPage; +} + +function afterZoom(cb) { + let oldAPTS = FullZoom._applyPrefToSetting; + FullZoom._applyPrefToSetting = function(value, browser) { + if (!value) + value = undefined; + oldAPTS.call(FullZoom, value, browser); + FullZoom._applyPrefToSetting = oldAPTS; + executeSoon(cb); + }; } diff --git a/browser/base/content/test/browser_bug441778.js b/browser/base/content/test/browser_bug441778.js index dd51d70e65ba..7fa37c65e70e 100644 --- a/browser/base/content/test/browser_bug441778.js +++ b/browser/base/content/test/browser_bug441778.js @@ -13,22 +13,19 @@ function test() { const TEST_PAGE_URL = 'data:text/html,'; const TEST_IFRAME_URL = "http://test2.example.org/"; - Task.spawn(function () { - // Prepare the test tab - let tab = gBrowser.addTab(); - yield FullZoomHelper.selectTabAndWaitForLocationChange(tab); + // Prepare the test tab + gBrowser.selectedTab = gBrowser.addTab(); + let testBrowser = gBrowser.selectedBrowser; - let testBrowser = tab.linkedBrowser; - - yield FullZoomHelper.load(tab, TEST_PAGE_URL); + testBrowser.addEventListener("load", function () { + testBrowser.removeEventListener("load", arguments.callee, true); // Change the zoom level and then save it so we can compare it to the level // after loading the sub-document. - yield FullZoomHelper.enlarge(); + FullZoom.enlarge(); var zoomLevel = ZoomManager.zoom; // Start the sub-document load. - let deferred = Promise.defer(); executeSoon(function () { testBrowser.addEventListener("load", function (e) { testBrowser.removeEventListener("load", arguments.callee, true); @@ -37,10 +34,11 @@ function test() { is(ZoomManager.zoom, zoomLevel, "zoom is retained after sub-document load"); gBrowser.removeCurrentTab(); - deferred.resolve(); + finish(); }, true); content.document.querySelector("iframe").src = TEST_IFRAME_URL; }); - yield deferred.promise; - }).then(finish, FullZoomHelper.failAndContinue(finish)); + }, true); + + content.location = TEST_PAGE_URL; } diff --git a/browser/base/content/test/browser_bug555224.js b/browser/base/content/test/browser_bug555224.js index cff1ee12b6b4..fa38a471d32a 100644 --- a/browser/base/content/test/browser_bug555224.js +++ b/browser/base/content/test/browser_bug555224.js @@ -4,36 +4,59 @@ const TEST_PAGE = "/browser/browser/base/content/test/dummy_page.html"; var gTestTab, gBgTab, gTestZoom; +function afterZoomAndLoad(aCallback, aTab) { + let didLoad = false; + let didZoom = false; + aTab.linkedBrowser.addEventListener("load", function() { + aTab.linkedBrowser.removeEventListener("load", arguments.callee, true); + didLoad = true; + if (didZoom) + executeSoon(aCallback); + }, true); + let oldAPTS = FullZoom._applyPrefToSetting; + FullZoom._applyPrefToSetting = function(value, browser) { + if (!value) + value = undefined; + oldAPTS.call(FullZoom, value, browser); + // Don't reset _applyPrefToSetting until we've seen the about:blank load(s) + if (browser && browser.currentURI.spec.startsWith("http:")) { + FullZoom._applyPrefToSetting = oldAPTS; + didZoom = true; + } + if (didLoad && didZoom) + executeSoon(aCallback); + }; +} + function testBackgroundLoad() { - Task.spawn(function () { - is(ZoomManager.zoom, gTestZoom, "opening a background tab should not change foreground zoom"); + is(ZoomManager.zoom, gTestZoom, "opening a background tab should not change foreground zoom"); - gBrowser.removeTab(gBgTab); + gBrowser.removeTab(gBgTab); - yield FullZoomHelper.reset(); - gBrowser.removeTab(gTestTab); - }).then(finish, FullZoomHelper.failAndContinue(finish)); + FullZoom.reset(); + gBrowser.removeTab(gTestTab); + + finish(); } function testInitialZoom() { - Task.spawn(function () { - is(ZoomManager.zoom, 1, "initial zoom level should be 1"); - yield FullZoomHelper.enlarge(); + is(ZoomManager.zoom, 1, "initial zoom level should be 1"); + FullZoom.enlarge(); - gTestZoom = ZoomManager.zoom; - isnot(gTestZoom, 1, "zoom level should have changed"); + gTestZoom = ZoomManager.zoom; + isnot(gTestZoom, 1, "zoom level should have changed"); - gBgTab = gBrowser.addTab(); - yield FullZoomHelper.load(gBgTab, "http://mochi.test:8888" + TEST_PAGE); - }).then(testBackgroundLoad, FullZoomHelper.failAndContinue(finish)); + afterZoomAndLoad(testBackgroundLoad, + gBgTab = gBrowser.loadOneTab("http://mochi.test:8888" + TEST_PAGE, + {inBackground: true})); } function test() { waitForExplicitFinish(); - Task.spawn(function () { - gTestTab = gBrowser.addTab(); - yield FullZoomHelper.selectTabAndWaitForLocationChange(gTestTab); - yield FullZoomHelper.load(gTestTab, "http://example.org" + TEST_PAGE); - }).then(testInitialZoom, FullZoomHelper.failAndContinue(finish)); + gTestTab = gBrowser.addTab(); + gBrowser.selectedTab = gTestTab; + + afterZoomAndLoad(testInitialZoom, gTestTab); + content.location = "http://example.org" + TEST_PAGE; } diff --git a/browser/base/content/test/browser_bug559991.js b/browser/base/content/test/browser_bug559991.js index 3bebc16e4f59..19d6127a0e8a 100644 --- a/browser/base/content/test/browser_bug559991.js +++ b/browser/base/content/test/browser_bug559991.js @@ -1,5 +1,3 @@ -var tab; - function test() { // ---------- @@ -7,34 +5,53 @@ function test() { waitForExplicitFinish(); + let oldOLC = FullZoom.onLocationChange; + FullZoom.onLocationChange = function(aURI, aIsTabSwitch, aBrowser) { + // Ignore calls that are not about tab switching on this test + if (aIsTabSwitch) + oldOLC.call(FullZoom, aURI, aIsTabSwitch, aBrowser); + }; + gPrefService.setBoolPref("browser.zoom.updateBackgroundTabs", true); gPrefService.setBoolPref("browser.zoom.siteSpecific", true); + let oldAPTS = FullZoom._applyPrefToSetting; let uri = "http://example.org/browser/browser/base/content/test/dummy_page.html"; - Task.spawn(function () { - tab = gBrowser.addTab(); - yield FullZoomHelper.load(tab, uri); + let tab = gBrowser.addTab(); + tab.linkedBrowser.addEventListener("load", function(event) { + tab.linkedBrowser.removeEventListener("load", arguments.callee, true); // ------------------------------------------------------------------- // Test - Trigger a tab switch that should update the zoom level - yield FullZoomHelper.selectTabAndWaitForLocationChange(tab); - ok(true, "applyPrefToSetting was called"); - }).then(endTest, FullZoomHelper.failAndContinue(endTest)); + FullZoom._applyPrefToSetting = function() { + ok(true, "applyPrefToSetting was called"); + endTest(); + } + gBrowser.selectedTab = tab; + + }, true); + tab.linkedBrowser.loadURI(uri); + + // ------------- + // Test clean-up + function endTest() { + FullZoom._applyPrefToSetting = oldAPTS; + FullZoom.onLocationChange = oldOLC; + gBrowser.removeTab(tab); + + oldAPTS = null; + oldOLC = null; + tab = null; + + if (gPrefService.prefHasUserValue("browser.zoom.updateBackgroundTabs")) + gPrefService.clearUserPref("browser.zoom.updateBackgroundTabs"); + + if (gPrefService.prefHasUserValue("browser.zoom.siteSpecific")) + gPrefService.clearUserPref("browser.zoom.siteSpecific"); + + finish(); + } + } -// ------------- -// Test clean-up -function endTest() { - gBrowser.removeTab(tab); - - tab = null; - - if (gPrefService.prefHasUserValue("browser.zoom.updateBackgroundTabs")) - gPrefService.clearUserPref("browser.zoom.updateBackgroundTabs"); - - if (gPrefService.prefHasUserValue("browser.zoom.siteSpecific")) - gPrefService.clearUserPref("browser.zoom.siteSpecific"); - - finish(); -} diff --git a/browser/base/content/test/browser_bug575830.js b/browser/base/content/test/browser_bug575830.js index aed13eea5522..9f08d6779f8b 100644 --- a/browser/base/content/test/browser_bug575830.js +++ b/browser/base/content/test/browser_bug575830.js @@ -13,22 +13,25 @@ function test() { gBrowser.removeTab(tab2); }); - Task.spawn(function () { - tab1 = gBrowser.addTab(); - tab2 = gBrowser.addTab(); - yield FullZoomHelper.selectTabAndWaitForLocationChange(tab1); - yield FullZoomHelper.load(tab1, TEST_IMAGE); + tab1 = gBrowser.addTab(TEST_IMAGE); + tab2 = gBrowser.addTab(); + gBrowser.selectedTab = tab1; + tab1.linkedBrowser.addEventListener("load", function onload() { + tab1.linkedBrowser.removeEventListener("load", onload, true); is(ZoomManager.zoom, 1, "initial zoom level for first should be 1"); - yield FullZoomHelper.enlarge(); + FullZoom.enlarge(); let zoom = ZoomManager.zoom; isnot(zoom, 1, "zoom level should have changed"); - yield FullZoomHelper.selectTabAndWaitForLocationChange(tab2); + gBrowser.selectedTab = tab2; is(ZoomManager.zoom, 1, "initial zoom level for second tab should be 1"); - yield FullZoomHelper.selectTabAndWaitForLocationChange(tab1); + gBrowser.selectedTab = tab1; is(ZoomManager.zoom, zoom, "zoom level for first tab should not have changed"); - }).then(finish, FullZoomHelper.failAndContinue(finish)); + + finish(); + }, true); } + diff --git a/browser/base/content/test/browser_bug719271.js b/browser/base/content/test/browser_bug719271.js index 53aca641e457..6db54554f50d 100644 --- a/browser/base/content/test/browser_bug719271.js +++ b/browser/base/content/test/browser_bug719271.js @@ -11,71 +11,131 @@ var gTab1, gTab2, gLevel1, gLevel2; function test() { waitForExplicitFinish(); - Task.spawn(function () { - gTab1 = gBrowser.addTab(); - gTab2 = gBrowser.addTab(); + gTab1 = gBrowser.addTab(); + gTab2 = gBrowser.addTab(); + gBrowser.selectedTab = gTab1; - yield FullZoomHelper.selectTabAndWaitForLocationChange(gTab1); - yield FullZoomHelper.load(gTab1, TEST_PAGE); - yield FullZoomHelper.load(gTab2, TEST_VIDEO); - }).then(zoomTab1, FullZoomHelper.failAndContinue(finish)); + load(gTab1, TEST_PAGE, function() { + load(gTab2, TEST_VIDEO, zoomTab1); + }); } function zoomTab1() { - Task.spawn(function () { - is(gBrowser.selectedTab, gTab1, "Tab 1 is selected"); - FullZoomHelper.zoomTest(gTab1, 1, "Initial zoom of tab 1 should be 1"); - FullZoomHelper.zoomTest(gTab2, 1, "Initial zoom of tab 2 should be 1"); + is(gBrowser.selectedTab, gTab1, "Tab 1 is selected"); + zoomTest(gTab1, 1, "Initial zoom of tab 1 should be 1"); + zoomTest(gTab2, 1, "Initial zoom of tab 2 should be 1"); - yield FullZoomHelper.enlarge(); - gLevel1 = ZoomManager.getZoomForBrowser(gBrowser.getBrowserForTab(gTab1)); + FullZoom.enlarge(); + gLevel1 = ZoomManager.getZoomForBrowser(gBrowser.getBrowserForTab(gTab1)); - ok(gLevel1 > 1, "New zoom for tab 1 should be greater than 1"); - FullZoomHelper.zoomTest(gTab2, 1, "Zooming tab 1 should not affect tab 2"); + ok(gLevel1 > 1, "New zoom for tab 1 should be greater than 1"); + zoomTest(gTab2, 1, "Zooming tab 1 should not affect tab 2"); - yield FullZoomHelper.selectTabAndWaitForLocationChange(gTab2); - FullZoomHelper.zoomTest(gTab2, 1, "Tab 2 is still unzoomed after it is selected"); - FullZoomHelper.zoomTest(gTab1, gLevel1, "Tab 1 is still zoomed"); - }).then(zoomTab2, FullZoomHelper.failAndContinue(finish)); + gBrowser.selectedTab = gTab2; + zoomTest(gTab2, 1, "Tab 2 is still unzoomed after it is selected"); + zoomTest(gTab1, gLevel1, "Tab 1 is still zoomed"); + + zoomTab2(); } function zoomTab2() { - Task.spawn(function () { - is(gBrowser.selectedTab, gTab2, "Tab 2 is selected"); + is(gBrowser.selectedTab, gTab2, "Tab 2 is selected"); - yield FullZoomHelper.reduce(); - let gLevel2 = ZoomManager.getZoomForBrowser(gBrowser.getBrowserForTab(gTab2)); + FullZoom.reduce(); + let gLevel2 = ZoomManager.getZoomForBrowser(gBrowser.getBrowserForTab(gTab2)); - ok(gLevel2 < 1, "New zoom for tab 2 should be less than 1"); - FullZoomHelper.zoomTest(gTab1, gLevel1, "Zooming tab 2 should not affect tab 1"); + ok(gLevel2 < 1, "New zoom for tab 2 should be less than 1"); + zoomTest(gTab1, gLevel1, "Zooming tab 2 should not affect tab 1"); - yield FullZoomHelper.selectTabAndWaitForLocationChange(gTab1); - FullZoomHelper.zoomTest(gTab1, gLevel1, "Tab 1 should have the same zoom after it's selected"); - }).then(testNavigation, FullZoomHelper.failAndContinue(finish)); + afterZoom(function() { + zoomTest(gTab1, gLevel1, "Tab 1 should have the same zoom after it's selected"); + + testNavigation(); + }); + gBrowser.selectedTab = gTab1; } function testNavigation() { - Task.spawn(function () { - yield FullZoomHelper.load(gTab1, TEST_VIDEO); - FullZoomHelper.zoomTest(gTab1, 1, "Zoom should be 1 when a video was loaded"); - yield FullZoomHelper.navigate(FullZoomHelper.BACK); - FullZoomHelper.zoomTest(gTab1, gLevel1, "Zoom should be restored when a page is loaded"); - yield FullZoomHelper.navigate(FullZoomHelper.FORWARD); - FullZoomHelper.zoomTest(gTab1, 1, "Zoom should be 1 again when navigating back to a video"); - }).then(finishTest, FullZoomHelper.failAndContinue(finish)); + load(gTab1, TEST_VIDEO, function() { + zoomTest(gTab1, 1, "Zoom should be 1 when a video was loaded"); + navigate(BACK, function() { + zoomTest(gTab1, gLevel1, "Zoom should be restored when a page is loaded"); + navigate(FORWARD, function() { + zoomTest(gTab1, 1, "Zoom should be 1 again when navigating back to a video"); + finishTest(); + }); + }); + }); } var finishTestStarted = false; function finishTest() { - Task.spawn(function () { - ok(!finishTestStarted, "finishTest called more than once"); - finishTestStarted = true; + ok(!finishTestStarted, "finishTest called more than once"); + finishTestStarted = true; - yield FullZoomHelper.selectTabAndWaitForLocationChange(gTab1); - yield FullZoomHelper.reset(); - gBrowser.removeTab(gTab1); - yield FullZoomHelper.selectTabAndWaitForLocationChange(gTab2); - yield FullZoomHelper.reset(); - gBrowser.removeTab(gTab2); - }).then(finish, FullZoomHelper.failAndContinue(finish)); + gBrowser.selectedTab = gTab1; + FullZoom.reset(); + gBrowser.removeTab(gTab1); + + gBrowser.selectedTab = gTab2; + FullZoom.reset(); + gBrowser.removeTab(gTab2); + + finish(); +} + +function zoomTest(tab, val, msg) { + is(ZoomManager.getZoomForBrowser(tab.linkedBrowser), val, msg); +} + +function load(tab, url, cb) { + let didLoad = false; + let didZoom = false; + tab.linkedBrowser.addEventListener("load", function onload(event) { + event.currentTarget.removeEventListener("load", onload, true); + didLoad = true; + if (didZoom) + executeSoon(cb); + }, true); + + afterZoom(function() { + didZoom = true; + if (didLoad) + executeSoon(cb); + }); + + tab.linkedBrowser.loadURI(url); +} + +const BACK = 0; +const FORWARD = 1; +function navigate(direction, cb) { + let didPs = false; + let didZoom = false; + gBrowser.addEventListener("pageshow", function onpageshow(event) { + gBrowser.removeEventListener("pageshow", onpageshow, true); + didPs = true; + if (didZoom) + executeSoon(cb); + }, true); + + afterZoom(function() { + didZoom = true; + if (didPs) + executeSoon(cb); + }); + + if (direction == BACK) + gBrowser.goBack(); + else if (direction == FORWARD) + gBrowser.goForward(); +} + +function afterZoom(cb) { + let oldSZFB = ZoomManager.setZoomForBrowser; + ZoomManager.setZoomForBrowser = function(browser, value) { + oldSZFB.call(ZoomManager, browser, value); + ZoomManager.setZoomForBrowser = oldSZFB; + executeSoon(cb); + }; } diff --git a/browser/base/content/test/head.js b/browser/base/content/test/head.js index 43107dbd71be..8570e1613e12 100644 --- a/browser/base/content/test/head.js +++ b/browser/base/content/test/head.js @@ -261,107 +261,3 @@ function promiseHistoryClearedState(aURIs, aShouldBeCleared) { return deferred.promise; } - -let FullZoomHelper = { - - selectTabAndWaitForLocationChange: function selectTabAndWaitForLocationChange(tab) { - let deferred = Promise.defer(); - if (tab && gBrowser.selectedTab == tab) { - deferred.resolve(); - return deferred.promise; - } - if (tab) - gBrowser.selectedTab = tab; - Services.obs.addObserver(function obs() { - Services.obs.removeObserver(obs, "browser-fullZoom:locationChange"); - deferred.resolve(); - }, "browser-fullZoom:locationChange", false); - return deferred.promise; - }, - - load: function load(tab, url) { - let deferred = Promise.defer(); - let didLoad = false; - let didZoom = false; - - tab.linkedBrowser.addEventListener("load", function (event) { - event.currentTarget.removeEventListener("load", arguments.callee, true); - didLoad = true; - if (didZoom) - deferred.resolve(); - }, true); - - // Don't select background tabs. That way tests can use this method on - // background tabs without having them automatically be selected. Just wait - // for the zoom to change on the current tab if it's `tab`. - if (tab == gBrowser.selectedTab) { - this.selectTabAndWaitForLocationChange(null).then(function () { - didZoom = true; - if (didLoad) - deferred.resolve(); - }); - } - else - didZoom = true; - - tab.linkedBrowser.loadURI(url); - - return deferred.promise; - }, - - zoomTest: function zoomTest(tab, val, msg) { - is(ZoomManager.getZoomForBrowser(tab.linkedBrowser), val, msg); - }, - - enlarge: function enlarge() { - let deferred = Promise.defer(); - FullZoom.enlarge(function () deferred.resolve()); - return deferred.promise; - }, - - reduce: function reduce() { - let deferred = Promise.defer(); - FullZoom.reduce(function () deferred.resolve()); - return deferred.promise; - }, - - reset: function reset() { - let deferred = Promise.defer(); - FullZoom.reset(function () deferred.resolve()); - return deferred.promise; - }, - - BACK: 0, - FORWARD: 1, - navigate: function navigate(direction) { - let deferred = Promise.defer(); - let didPs = false; - let didZoom = false; - - gBrowser.addEventListener("pageshow", function (event) { - gBrowser.removeEventListener("pageshow", arguments.callee, true); - didPs = true; - if (didZoom) - deferred.resolve(); - }, true); - - if (direction == this.BACK) - gBrowser.goBack(); - else if (direction == this.FORWARD) - gBrowser.goForward(); - - this.selectTabAndWaitForLocationChange(null).then(function () { - didZoom = true; - if (didPs) - deferred.resolve(); - }); - return deferred.promise; - }, - - failAndContinue: function failAndContinue(func) { - return function (err) { - ok(false, err); - func(); - }; - }, -}; diff --git a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_zoom.js b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_zoom.js index 827b915629d4..cf4df0301ab6 100644 --- a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_zoom.js +++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_zoom.js @@ -25,29 +25,27 @@ function test() { let mozillaZoom = aWindow.ZoomManager.zoom; // change the zoom on the mozilla page - aWindow.FullZoom.enlarge(function () { - // make sure the zoom level has been changed - isnot(aWindow.ZoomManager.zoom, mozillaZoom, "Zoom level can be changed"); - mozillaZoom = aWindow.ZoomManager.zoom; + aWindow.FullZoom.enlarge(); + // make sure the zoom level has been changed + isnot(aWindow.ZoomManager.zoom, mozillaZoom, "Zoom level can be changed"); + mozillaZoom = aWindow.ZoomManager.zoom; - // switch to about: tab - aWindow.gBrowser.selectedTab = tabAbout; + // switch to about: tab + aWindow.gBrowser.selectedTab = tabAbout; - // switch back to mozilla tab - aWindow.gBrowser.selectedTab = tabMozilla; + // switch back to mozilla tab + aWindow.gBrowser.selectedTab = tabMozilla; - // make sure the zoom level has not changed - is(aWindow.ZoomManager.zoom, mozillaZoom, - "Entering private browsing should not reset the zoom on a tab"); + // make sure the zoom level has not changed + is(aWindow.ZoomManager.zoom, mozillaZoom, + "Entering private browsing should not reset the zoom on a tab"); - // cleanup - aWindow.FullZoom.reset(function () { - aWindow.gBrowser.removeTab(tabMozilla); - aWindow.gBrowser.removeTab(tabAbout); - aWindow.close(); - aCallback(); - }); - }); + // cleanup + aWindow.FullZoom.reset(); + aWindow.gBrowser.removeTab(tabMozilla); + aWindow.gBrowser.removeTab(tabAbout); + aWindow.close(); + aCallback(); }, true); mozillaBrowser.contentWindow.location = "about:mozilla"; }, true); diff --git a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_zoomrestore.js b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_zoomrestore.js index 9bac502a35a7..46a5ba76624d 100644 --- a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_zoomrestore.js +++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_zoomrestore.js @@ -16,14 +16,12 @@ function test() { aWindow.gBrowser.selectedBrowser.removeEventListener("load", onLoad, true); if (aIsZoomedWindow) { // change the zoom on the blank page - aWindow.FullZoom.enlarge(function () { - isnot(aWindow.ZoomManager.zoom, 1, "Zoom level for about:blank should be changed"); - aCallback(); - }); - return; + aWindow.FullZoom.enlarge(); + isnot(aWindow.ZoomManager.zoom, 1, "Zoom level for about:blank should be changed"); + } else { + // make sure the zoom level is set to 1 + is(aWindow.ZoomManager.zoom, 1, "Zoom level for about:privatebrowsing should be reset"); } - // make sure the zoom level is set to 1 - is(aWindow.ZoomManager.zoom, 1, "Zoom level for about:privatebrowsing should be reset"); aCallback(); }, true); @@ -33,18 +31,10 @@ function test() { function finishTest() { // cleanup - let numWindows = windowsToReset.length; - if (!numWindows) { - finish(); - return; - } windowsToReset.forEach(function(win) { - win.FullZoom.reset(function onReset() { - numWindows--; - if (!numWindows) - finish(); - }); + win.FullZoom.reset(); }); + finish(); } function testOnWindow(options, callback) { diff --git a/dom/interfaces/base/nsIContentPrefService2.idl b/dom/interfaces/base/nsIContentPrefService2.idl index 22f8cd1714fc..4ff2434e4af7 100644 --- a/dom/interfaces/base/nsIContentPrefService2.idl +++ b/dom/interfaces/base/nsIContentPrefService2.idl @@ -59,15 +59,11 @@ interface nsIContentPref; * * Callbacks * - * The methods of callback objects are always called asynchronously. - * - * Observers are called after callbacks are called, but they are called in the - * same turn of the event loop as callbacks. - * - * See nsIContentPrefCallback2 below for more information about callbacks. + * The methods of callback objects are always called asynchronously. See + * nsIContentPrefCallback2 below for more information about callbacks. */ -[scriptable, uuid(133608c7-f812-41ca-bc1c-62a4eb95e52a)] +[scriptable, uuid(51e1d34a-5e9d-4b77-b14c-0f8346e264ca)] interface nsIContentPrefService2 : nsISupports { /** @@ -322,17 +318,6 @@ interface nsIContentPrefService2 : nsISupports */ void removeObserverForName(in AString name, in nsIContentPrefObserver observer); - - /** - * Extracts and returns the domain from the given string representation of a - * URI. This is how the API extracts domains from URIs passed to it. - * - * @param str The string representation of a URI, like - * "http://example.com/foo/bar". - * @return If the given string is a valid URI, the domain of that URI is - * returned. Otherwise, the string itself is returned. - */ - AString extractDomain(in AString str); }; /** @@ -351,7 +336,7 @@ interface nsIContentPrefCallback2 : nsISupports /** * Called when an error occurs. This may be called multiple times before - * handleCompletion is called. + * onComplete is called. * * @param error A number in Components.results describing the error. */ diff --git a/toolkit/components/contentprefs/ContentPrefService2.jsm b/toolkit/components/contentprefs/ContentPrefService2.jsm index 9722fe4e5679..6b4085e03dca 100644 --- a/toolkit/components/contentprefs/ContentPrefService2.jsm +++ b/toolkit/components/contentprefs/ContentPrefService2.jsm @@ -195,8 +195,8 @@ ContentPrefService2.prototype = { if (context && context.usePrivateBrowsing) { this._pbStore.set(group, name, value); this._schedule(function () { - cbHandleCompletion(callback, Ci.nsIContentPrefCallback2.COMPLETE_OK); this._cps._broadcastPrefSet(group, name, value); + cbHandleCompletion(callback, Ci.nsIContentPrefCallback2.COMPLETE_OK); }); return; } @@ -258,11 +258,11 @@ ContentPrefService2.prototype = { this._execStmts(stmts, { onDone: function onDone(reason, ok) { - if (ok) + if (ok) { this._cache.setWithCast(group, name, value); - cbHandleCompletion(callback, reason); - if (ok) this._cps._broadcastPrefSet(group, name, value); + } + cbHandleCompletion(callback, reason); }, onError: function onError(nsresult) { cbHandleError(callback, nsresult); @@ -342,13 +342,11 @@ ContentPrefService2.prototype = { this._pbStore.remove(sgroup, name); } } - } - cbHandleCompletion(callback, reason); - if (ok) { for (let [sgroup, , ] in prefs) { this._cps._broadcastPrefRemoved(sgroup, name); } } + cbHandleCompletion(callback, reason); }, onError: function onError(nsresult) { cbHandleError(callback, nsresult); @@ -423,18 +421,18 @@ ContentPrefService2.prototype = { this._cache.set(grp, name, undefined); }, onDone: function onDone(reason, ok) { - if (ok && context && context.usePrivateBrowsing) { - for (let [sgroup, sname, ] in this._pbStore) { - prefs.set(sgroup, sname); - this._pbStore.remove(sgroup, sname); - } - } - cbHandleCompletion(callback, reason); if (ok) { + if (context && context.usePrivateBrowsing) { + for (let [sgroup, sname, ] in this._pbStore) { + prefs.set(sgroup, sname); + this._pbStore.remove(sgroup, sname); + } + } for (let [sgroup, sname, ] in prefs) { this._cps._broadcastPrefRemoved(sgroup, sname); } } + cbHandleCompletion(callback, reason); }, onError: function onError(nsresult) { cbHandleError(callback, nsresult); @@ -475,18 +473,18 @@ ContentPrefService2.prototype = { this._cache.set(grp, name, undefined); }, onDone: function onDone(reason, ok) { - if (ok && context && context.usePrivateBrowsing) { - for (let [sgroup, sname, ] in this._pbStore) { - prefs.set(sgroup, sname); - } - this._pbStore.removeGrouped(); - } - cbHandleCompletion(callback, reason); if (ok) { + if (context && context.usePrivateBrowsing) { + for (let [sgroup, sname, ] in this._pbStore) { + prefs.set(sgroup, sname); + } + this._pbStore.removeGrouped(); + } for (let [sgroup, sname, ] in prefs) { this._cps._broadcastPrefRemoved(sgroup, sname); } } + cbHandleCompletion(callback, reason); }, onError: function onError(nsresult) { cbHandleError(callback, nsresult); @@ -546,20 +544,20 @@ ContentPrefService2.prototype = { this._cache.set(grp, name, undefined); }, onDone: function onDone(reason, ok) { - if (ok && context && context.usePrivateBrowsing) { - for (let [sgroup, sname, ] in this._pbStore) { - if (sname === name) { - prefs.set(sgroup, name); - this._pbStore.remove(sgroup, name); + if (ok) { + if (context && context.usePrivateBrowsing) { + for (let [sgroup, sname, ] in this._pbStore) { + if (sname === name) { + prefs.set(sgroup, name); + this._pbStore.remove(sgroup, name); + } } } - } - cbHandleCompletion(callback, reason); - if (ok) { for (let [sgroup, , ] in prefs) { this._cps._broadcastPrefRemoved(sgroup, name); } } + cbHandleCompletion(callback, reason); }, onError: function onError(nsresult) { cbHandleError(callback, nsresult); @@ -684,10 +682,6 @@ ContentPrefService2.prototype = { this._cps.removeObserver(name, observer); }, - extractDomain: function CPS2_extractDomain(str) { - return this._parseGroup(str); - }, - /** * Tests use this as a backchannel by calling it directly. * diff --git a/toolkit/components/contentprefs/tests/unit_cps2/head.js b/toolkit/components/contentprefs/tests/unit_cps2/head.js index 03e4bd4cf820..ac0c45a2c86b 100644 --- a/toolkit/components/contentprefs/tests/unit_cps2/head.js +++ b/toolkit/components/contentprefs/tests/unit_cps2/head.js @@ -273,7 +273,7 @@ function dbOK(expectedRows) { stmt.finalize(); } -function on(event, names, dontRemove) { +function on(event, names) { let args = { reset: function () { for (let prop in this) { @@ -281,6 +281,9 @@ function on(event, names, dontRemove) { this[prop].splice(0, this[prop].length); } }, + destroy: function () { + names.forEach(function (n) cps.removeObserverForName(n, observers[n])); + }, }; let observers = {}; @@ -299,15 +302,7 @@ function on(event, names, dontRemove) { cps.addObserverForName(name, obs); }); - do_execute_soon(function () { - if (!dontRemove) - names.forEach(function (n) cps.removeObserverForName(n, observers[n])); - next(args); - }); -} - -function wait() { - do_execute_soon(next); + return args; } function observerArgsOK(actualArgs, expectedArgs) { diff --git a/toolkit/components/contentprefs/tests/unit_cps2/test_extractDomain.js b/toolkit/components/contentprefs/tests/unit_cps2/test_extractDomain.js deleted file mode 100644 index 2ec3d6878b68..000000000000 --- a/toolkit/components/contentprefs/tests/unit_cps2/test_extractDomain.js +++ /dev/null @@ -1,20 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -function run_test() { - let tests = { - "http://example.com": "example.com", - "http://example.com/": "example.com", - "http://example.com/foo/bar/baz": "example.com", - "http://subdomain.example.com/foo/bar/baz": "subdomain.example.com", - "http://qix.quux.example.com/foo/bar/baz": "qix.quux.example.com", - "file:///home/foo/bar": "file:///home/foo/bar", - "not a url": "not a url", - }; - let cps = Cc["@mozilla.org/content-pref/service;1"]. - getService(Ci.nsIContentPrefService2); - for (let url in tests) { - do_check_eq(cps.extractDomain(url), tests[url]); - } -} diff --git a/toolkit/components/contentprefs/tests/unit_cps2/test_observers.js b/toolkit/components/contentprefs/tests/unit_cps2/test_observers.js index 398d4b80edb3..421d0693068f 100644 --- a/toolkit/components/contentprefs/tests/unit_cps2/test_observers.js +++ b/toolkit/components/contentprefs/tests/unit_cps2/test_observers.js @@ -9,40 +9,43 @@ function run_test() { let tests = [ function observerForName_set() { + let args = on("Set", ["foo", null, "bar"]); + yield set("a.com", "foo", 1); - let args = yield on("Set", ["foo", null, "bar"]); observerArgsOK(args.foo, [["a.com", "foo", 1]]); observerArgsOK(args.null, [["a.com", "foo", 1]]); observerArgsOK(args.bar, []); + args.reset(); yield setGlobal("foo", 2); - args = yield on("Set", ["foo", null, "bar"]); observerArgsOK(args.foo, [[null, "foo", 2]]); observerArgsOK(args.null, [[null, "foo", 2]]); observerArgsOK(args.bar, []); + args.reset(); }, function observerForName_remove() { yield set("a.com", "foo", 1); yield setGlobal("foo", 2); + let args = on("Removed", ["foo", null, "bar"]); yield cps.removeByDomainAndName("a.com", "bogus", null, makeCallback()); - let args = yield on("Removed", ["foo", null, "bar"]); observerArgsOK(args.foo, []); observerArgsOK(args.null, []); observerArgsOK(args.bar, []); + args.reset(); yield cps.removeByDomainAndName("a.com", "foo", null, makeCallback()); - args = yield on("Removed", ["foo", null, "bar"]); observerArgsOK(args.foo, [["a.com", "foo"]]); observerArgsOK(args.null, [["a.com", "foo"]]); observerArgsOK(args.bar, []); + args.reset(); yield cps.removeGlobal("foo", null, makeCallback()); - args = yield on("Removed", ["foo", null, "bar"]); observerArgsOK(args.foo, [[null, "foo"]]); observerArgsOK(args.null, [[null, "foo"]]); observerArgsOK(args.bar, []); + args.reset(); }, function observerForName_removeByDomain() { @@ -50,23 +53,24 @@ let tests = [ yield set("b.a.com", "bar", 2); yield setGlobal("foo", 3); + let args = on("Removed", ["foo", null, "bar"]); yield cps.removeByDomain("bogus", null, makeCallback()); - let args = yield on("Removed", ["foo", null, "bar"]); observerArgsOK(args.foo, []); observerArgsOK(args.null, []); observerArgsOK(args.bar, []); + args.reset(); yield cps.removeBySubdomain("a.com", null, makeCallback()); - args = yield on("Removed", ["foo", null, "bar"]); observerArgsOK(args.foo, [["a.com", "foo"]]); observerArgsOK(args.null, [["a.com", "foo"], ["b.a.com", "bar"]]); observerArgsOK(args.bar, [["b.a.com", "bar"]]); + args.reset(); yield cps.removeAllGlobals(null, makeCallback()); - args = yield on("Removed", ["foo", null, "bar"]); observerArgsOK(args.foo, [[null, "foo"]]); observerArgsOK(args.null, [[null, "foo"]]); observerArgsOK(args.bar, []); + args.reset(); }, function observerForName_removeAllDomains() { @@ -74,11 +78,12 @@ let tests = [ yield setGlobal("foo", 2); yield set("b.com", "bar", 3); + let args = on("Removed", ["foo", null, "bar"]); yield cps.removeAllDomains(null, makeCallback()); - let args = yield on("Removed", ["foo", null, "bar"]); observerArgsOK(args.foo, [["a.com", "foo"]]); observerArgsOK(args.null, [["a.com", "foo"], ["b.com", "bar"]]); observerArgsOK(args.bar, [["b.com", "bar"]]); + args.reset(); }, function observerForName_removeByName() { @@ -86,25 +91,25 @@ let tests = [ yield set("a.com", "bar", 2); yield setGlobal("foo", 3); + let args = on("Removed", ["foo", null, "bar"]); yield cps.removeByName("bogus", null, makeCallback()); - let args = yield on("Removed", ["foo", null, "bar"]); observerArgsOK(args.foo, []); observerArgsOK(args.null, []); observerArgsOK(args.bar, []); + args.reset(); yield cps.removeByName("foo", null, makeCallback()); - args = yield on("Removed", ["foo", null, "bar"]); observerArgsOK(args.foo, [["a.com", "foo"], [null, "foo"]]); observerArgsOK(args.null, [["a.com", "foo"], [null, "foo"]]); observerArgsOK(args.bar, []); + args.reset(); }, function removeObserverForName() { - let args = yield on("Set", ["foo", null, "bar"], true); + let args = on("Set", ["foo", null, "bar"]); cps.removeObserverForName("foo", args.foo.observer); yield set("a.com", "foo", 1); - yield wait(); observerArgsOK(args.foo, []); observerArgsOK(args.null, [["a.com", "foo", 1]]); observerArgsOK(args.bar, []); @@ -112,7 +117,6 @@ let tests = [ cps.removeObserverForName(null, args.null.observer); yield set("a.com", "foo", 2); - yield wait(); observerArgsOK(args.foo, []); observerArgsOK(args.null, []); observerArgsOK(args.bar, []); diff --git a/toolkit/components/contentprefs/tests/unit_cps2/xpcshell.ini b/toolkit/components/contentprefs/tests/unit_cps2/xpcshell.ini index cf1e1f5eb159..0fad2a9f2a94 100644 --- a/toolkit/components/contentprefs/tests/unit_cps2/xpcshell.ini +++ b/toolkit/components/contentprefs/tests/unit_cps2/xpcshell.ini @@ -12,4 +12,3 @@ tail = [test_getCached.js] [test_getCachedSubdomains.js] [test_observers.js] -[test_extractDomain.js] From 34dad8a91ade23f42bb8ae32e6584794e8a5d808 Mon Sep 17 00:00:00 2001 From: Ryan VanderMeulen Date: Tue, 26 Mar 2013 16:07:31 -0400 Subject: [PATCH 056/129] Backed out changeset 48d2538788ec (bug 848489) for Marionette failures on a CLOSED TREE. --- .../marionette/tests/unit/test_long_press.py | 17 ----------------- .../client/marionette/www/testAction.html | 7 ------- testing/marionette/marionette-listener.js | 16 ---------------- 3 files changed, 40 deletions(-) delete mode 100644 testing/marionette/client/marionette/tests/unit/test_long_press.py diff --git a/testing/marionette/client/marionette/tests/unit/test_long_press.py b/testing/marionette/client/marionette/tests/unit/test_long_press.py deleted file mode 100644 index a6d78a2e8942..000000000000 --- a/testing/marionette/client/marionette/tests/unit/test_long_press.py +++ /dev/null @@ -1,17 +0,0 @@ -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. - -import time -from marionette_test import MarionetteTestCase -from marionette import Actions - -class testSingleFinger(MarionetteTestCase): - def test_chain(self): - testTouch = self.marionette.absolute_url("testAction.html") - self.marionette.navigate(testTouch) - button = self.marionette.find_element("id", "mozLinkCopy") - action = Actions(self.marionette) - action.press(button).wait(5).perform() - time.sleep(15) - self.assertEqual("Context", self.marionette.execute_script("return document.getElementById('mozLinkCopy').innerHTML;")) diff --git a/testing/marionette/client/marionette/www/testAction.html b/testing/marionette/client/marionette/www/testAction.html index 6d13d380b50b..4e500f1e2496 100644 --- a/testing/marionette/client/marionette/www/testAction.html +++ b/testing/marionette/client/marionette/www/testAction.html @@ -37,8 +37,6 @@ // here is second for a tap second.addEventListener("touchstart", function(){changePressText("mozLinkCopy")}, false); second.addEventListener("touchend", function(){changeClickText("mozLinkCopy")}, false); - // change for contextmenu - second.addEventListener("contextmenu", onContextMenuChange, false); // here is third for horizontal move third.addEventListener("touchstart", function(){changePressText("mozLinkStart")}, false); third.addEventListener("touchmove", changeHorizontalMove, false); @@ -131,11 +129,6 @@ document.getElementById("delayed").innerHTML = "End"; } } - - function onContextMenuChange() { - var context = document.getElementById("mozLinkCopy"); - context.innerHTML = "Context"; - } diff --git a/testing/marionette/marionette-listener.js b/testing/marionette/marionette-listener.js index a532e2b9a199..e08a49107e04 100644 --- a/testing/marionette/marionette-listener.js +++ b/testing/marionette/marionette-listener.js @@ -965,14 +965,6 @@ function actions(finger, touchId, command_id, i){ touch = createATouch(el, corx, cory, touchId); lastTouch = touch; emitTouchEvent('touchstart', touch); - // check if it's a long press - // standard waiting time to fire contextmenu - let standard = Services.prefs.getIntPref("ui.click_hold_context_menus.delay"); - // long press only happens when wait follows press - if (finger[i][0] == 'wait' && finger[i][1] != null && finger[i][1]*1000 >= standard) { - finger[i][1] = finger[i][1] - standard/1000; - finger.splice(i, 0, ['wait', standard/1000], ['longPress']); - } actions(finger,touchId, command_id, i); break; case 'release': @@ -1035,14 +1027,6 @@ function actions(finger, touchId, command_id, i){ lastTouch = null; actions(finger, touchId, command_id, i); break; - case 'longPress': - let event = curWindow.document.createEvent('HTMLEvents'); - event.initEvent('contextmenu', - true, - true); - lastTouch.target.dispatchEvent(event); - actions(finger, touchId, command_id, i); - break; } } From a0420848186c30f819802916454ce42ab6aa3436 Mon Sep 17 00:00:00 2001 From: Benoit Girard Date: Tue, 26 Mar 2013 16:10:29 -0400 Subject: [PATCH 057/129] Backed out changeset f5a256c02fc6 (bug 851828) for Mochitest failures on a CLOSED TREE. --- tools/profiler/JSCustomObjectBuilder.cpp | 4 ++-- tools/profiler/PseudoStack.h | 4 ++-- tools/profiler/TableTicker.cpp | 4 ++-- tools/profiler/nsProfiler.cpp | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tools/profiler/JSCustomObjectBuilder.cpp b/tools/profiler/JSCustomObjectBuilder.cpp index fcc4df43d81a..3b3b6f0f0ede 100644 --- a/tools/profiler/JSCustomObjectBuilder.cpp +++ b/tools/profiler/JSCustomObjectBuilder.cpp @@ -87,7 +87,7 @@ void EscapeToStream(std::ostream& stream, const char* str) { } else if (ucs4Char > 0xFF) { PRUnichar chr[2]; ConvertUTF8toUTF16 encoder(chr); - encoder.write(utf8CharStart, uint32_t(str-utf8CharStart)); + encoder.write(utf8CharStart, str-utf8CharStart); char escChar[13]; snprintf(escChar, mozilla::ArrayLength(escChar), "\\u%04X\\u%04X", chr[0], chr[1]); stream << escChar; @@ -210,7 +210,7 @@ operator<<(std::ostream& stream, JSCustomArray* entry) { bool needsComma = false; stream << "["; - for (uint32_t i = 0; i < entry->mValues.Length(); i++) { + for (size_t i = 0; i < entry->mValues.Length(); i++) { if (needsComma) { stream << ","; } diff --git a/tools/profiler/PseudoStack.h b/tools/profiler/PseudoStack.h index 9079ffbfc3a8..21af92a74309 100644 --- a/tools/profiler/PseudoStack.h +++ b/tools/profiler/PseudoStack.h @@ -194,7 +194,7 @@ public: } uint32_t stackSize() const { - return std::min(mStackPointer, mozilla::sig_safe_t(mozilla::ArrayLength(mStack))); + return std::min(mStackPointer, mozilla::ArrayLength(mStack)); } void sampleRuntime(JSRuntime *runtime) { @@ -208,7 +208,7 @@ public: js::SetRuntimeProfilingStack(runtime, (js::ProfileEntry*) mStack, (uint32_t*) &mStackPointer, - uint32_t(mozilla::ArrayLength(mStack))); + mozilla::ArrayLength(mStack)); if (mStartJSSampling) enableJSSampling(); } diff --git a/tools/profiler/TableTicker.cpp b/tools/profiler/TableTicker.cpp index c31d9d94e4fa..44f61541cffd 100644 --- a/tools/profiler/TableTicker.cpp +++ b/tools/profiler/TableTicker.cpp @@ -196,7 +196,7 @@ void addDynamicTag(ThreadProfile &aProfile, char aTagName, const char *aStr) for (size_t j = 0; j < strLen;) { // Store as many characters in the void* as the platform allows char text[sizeof(void*)]; - size_t len = sizeof(void*)/sizeof(char); + int len = sizeof(void*)/sizeof(char); if (j+len >= strLen) { len = strLen - j; } @@ -300,7 +300,7 @@ void TableTicker::doNativeBacktrace(ThreadProfile &aProfile, TickSample* aSample // Start with the current function. StackWalkCallback(aSample->pc, aSample->sp, &array); - uint32_t maxFrames = uint32_t(array.size - array.count); + uint32_t maxFrames = array.size - array.count; #ifdef XP_MACOSX pthread_t pt = GetProfiledThread(platform_data()); void *stackEnd = reinterpret_cast(-1); diff --git a/tools/profiler/nsProfiler.cpp b/tools/profiler/nsProfiler.cpp index 5c8e16abbaad..b296c1bc913b 100644 --- a/tools/profiler/nsProfiler.cpp +++ b/tools/profiler/nsProfiler.cpp @@ -103,7 +103,7 @@ nsProfiler::GetProfile(char **aProfile) { char *profile = profiler_get_profile(); if (profile) { - size_t len = strlen(profile); + uint32_t len = strlen(profile); char *profileStr = static_cast (nsMemory::Clone(profile, (len + 1) * sizeof(char))); profileStr[len] = '\0'; @@ -233,7 +233,7 @@ nsProfiler::GetFeatures(uint32_t *aCount, char ***aFeatures) (nsMemory::Alloc(len * sizeof(char*))); for (size_t i = 0; i < len; i++) { - size_t strLen = strlen(features[i]); + uint32_t strLen = strlen(features[i]); featureList[i] = static_cast (nsMemory::Clone(features[i], (strLen + 1) * sizeof(char))); } From 0cedc1cf7c935d78765219207d94f8c859c64ea9 Mon Sep 17 00:00:00 2001 From: Ryan VanderMeulen Date: Tue, 26 Mar 2013 16:52:17 -0400 Subject: [PATCH 058/129] Backed out changesets 4b97cab51e59:5e573640e390 (bug 826093) for Android reftest-2 failures on a CLOSED TREE. --- image/public/imgIContainer.idl | 29 ++- image/src/ClippedImage.cpp | 312 --------------------------------- image/src/ClippedImage.h | 78 --------- image/src/FrozenImage.cpp | 9 + image/src/FrozenImage.h | 6 +- image/src/ImageFactory.cpp | 8 + image/src/ImageFactory.h | 8 + image/src/ImageOps.cpp | 48 ----- image/src/ImageOps.h | 49 ------ image/src/ImageWrapper.cpp | 9 + image/src/Makefile.in | 3 - image/src/RasterImage.cpp | 96 +++++++++- image/src/VectorImage.cpp | 82 ++++++++- image/src/VectorImage.h | 7 + image/src/imgRequestProxy.cpp | 4 +- layout/base/nsCSSRendering.cpp | 31 +++- 16 files changed, 261 insertions(+), 518 deletions(-) delete mode 100644 image/src/ClippedImage.cpp delete mode 100644 image/src/ClippedImage.h delete mode 100644 image/src/ImageOps.cpp delete mode 100644 image/src/ImageOps.h diff --git a/image/public/imgIContainer.idl b/image/public/imgIContainer.idl index de2ca0c9e513..ae7f86f9cb97 100644 --- a/image/public/imgIContainer.idl +++ b/image/public/imgIContainer.idl @@ -52,12 +52,13 @@ native nsSize(nsSize); /** * imgIContainer is the interface that represents an image. It allows - * access to frames as Thebes surfaces. It also allows drawing of images - * onto Thebes contexts. + * access to frames as Thebes surfaces, and permits users to extract subregions + * as other imgIContainers. It also allows drawing of images on to Thebes + * contexts. * * Internally, imgIContainer also manages animation of images. */ -[scriptable, builtinclass, uuid(0c1caf24-bce7-4db5-971d-8e1b6ed07540)] +[scriptable, builtinclass, uuid(01c4f92f-f883-4837-a127-d8f30920e374)] interface imgIContainer : nsISupports { /** @@ -177,6 +178,19 @@ interface imgIContainer : nsISupports */ [noscript] ImageContainer getImageContainer(in LayerManager aManager); + /** + * Create a new imgContainer that contains only a single frame, which itself + * contains a subregion of the given frame. + * + * @param aWhichFrame Frame specifier of the FRAME_* variety. + * @param aRect the area of the current frame to be duplicated in the + * returned imgContainer's frame. + * @param aFlags Flags of the FLAG_* variety + */ + [noscript] imgIContainer extractFrame(in uint32_t aWhichFrame, + [const] in nsIntRect aRect, + in uint32_t aFlags); + /** * Draw a frame onto the context specified. * @@ -215,10 +229,11 @@ interface imgIContainer : nsISupports /* * Ensures that an image is decoding. Calling this function guarantees that - * the image will at some point fire off decode notifications. Calling draw() - * or getFrame() triggers the same mechanism internally. Thus, if you want to - * be sure that the image will be decoded but don't want to access it until - * then, you must call requestDecode(). + * the image will at some point fire off decode notifications. Calling draw(), + * getFrame(), copyFrame(), or extractCurrentFrame() triggers the same + * mechanism internally. Thus, if you want to be sure that the image will be + * decoded but don't want to access it until then, you must call + * requestDecode(). */ void requestDecode(); diff --git a/image/src/ClippedImage.cpp b/image/src/ClippedImage.cpp deleted file mode 100644 index 7d8f4ae98f11..000000000000 --- a/image/src/ClippedImage.cpp +++ /dev/null @@ -1,312 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "gfxDrawable.h" -#include "gfxPlatform.h" -#include "gfxUtils.h" - -#include "ClippedImage.h" - -using mozilla::layers::LayerManager; -using mozilla::layers::ImageContainer; - -namespace mozilla { -namespace image { - -class DrawSingleTileCallback : public gfxDrawingCallback -{ -public: - DrawSingleTileCallback(ClippedImage* aImage, - const nsIntRect& aClip, - const nsIntSize& aViewportSize, - const SVGImageContext* aSVGContext, - uint32_t aWhichFrame, - uint32_t aFlags) - : mImage(aImage) - , mClip(aClip) - , mViewportSize(aViewportSize) - , mSVGContext(aSVGContext) - , mWhichFrame(aWhichFrame) - , mFlags(aFlags) - { - MOZ_ASSERT(mImage, "Must have an image to clip"); - } - - virtual bool operator()(gfxContext* aContext, - const gfxRect& aFillRect, - const gfxPattern::GraphicsFilter& aFilter, - const gfxMatrix& aTransform) - { - // Draw the image. |gfxCallbackDrawable| always calls this function with - // arguments that guarantee we never tile. - mImage->DrawSingleTile(aContext, aFilter, aTransform, aFillRect, mClip, - mViewportSize, mSVGContext, mWhichFrame, mFlags); - - return true; - } - -private: - nsRefPtr mImage; - const nsIntRect mClip; - const nsIntSize mViewportSize; - const SVGImageContext* mSVGContext; - const uint32_t mWhichFrame; - const uint32_t mFlags; -}; - -ClippedImage::ClippedImage(Image* aImage, - nsIntRect aClip) - : ImageWrapper(aImage) - , mClip(aClip) -{ - MOZ_ASSERT(aImage != nullptr, "ClippedImage requires an existing Image"); -} - -bool -ClippedImage::ShouldClip() -{ - // We need to evaluate the clipping region against the image's width and height - // once they're available to determine if it's valid and whether we actually - // need to do any work. We may fail if the image's width and height aren't - // available yet, in which case we'll try again later. - if (mShouldClip.empty()) { - int32_t width, height; - if (InnerImage()->HasError()) { - // If there's a problem with the inner image we'll let it handle everything. - mShouldClip.construct(false); - } else if (NS_SUCCEEDED(InnerImage()->GetWidth(&width)) && width > 0 && - NS_SUCCEEDED(InnerImage()->GetHeight(&height)) && height > 0) { - // Clamp the clipping region to the size of the underlying image. - mClip = mClip.Intersect(nsIntRect(0, 0, width, height)); - - // If the clipping region is the same size as the underlying image we - // don't have to do anything. - mShouldClip.construct(!mClip.IsEqualInterior(nsIntRect(0, 0, width, height))); - } else if (InnerImage()->GetStatusTracker().IsLoading()) { - // The image just hasn't finished loading yet. We don't yet know whether - // clipping with be needed or not for now. Just return without memoizing - // anything. - return false; - } else { - // We have a fully loaded image without a clearly defined width and - // height. This can happen with SVG images. - mShouldClip.construct(false); - } - } - - MOZ_ASSERT(!mShouldClip.empty(), "Should have computed a result"); - return mShouldClip.ref(); -} - -NS_IMPL_ISUPPORTS1(ClippedImage, imgIContainer) - -nsIntRect -ClippedImage::FrameRect(uint32_t aWhichFrame) -{ - if (!ShouldClip()) { - return InnerImage()->FrameRect(aWhichFrame); - } - - return nsIntRect(0, 0, mClip.width, mClip.height); -} - -NS_IMETHODIMP -ClippedImage::GetWidth(int32_t* aWidth) -{ - if (!ShouldClip()) { - return InnerImage()->GetWidth(aWidth); - } - - *aWidth = mClip.width; - return NS_OK; -} - -NS_IMETHODIMP -ClippedImage::GetHeight(int32_t* aHeight) -{ - if (!ShouldClip()) { - return InnerImage()->GetHeight(aHeight); - } - - *aHeight = mClip.height; - return NS_OK; -} - -NS_IMETHODIMP -ClippedImage::GetIntrinsicSize(nsSize* aSize) -{ - if (!ShouldClip()) { - return InnerImage()->GetIntrinsicSize(aSize); - } - - *aSize = nsSize(mClip.width, mClip.height); - return NS_OK; -} - -NS_IMETHODIMP -ClippedImage::GetIntrinsicRatio(nsSize* aRatio) -{ - if (!ShouldClip()) { - return InnerImage()->GetIntrinsicRatio(aRatio); - } - - *aRatio = nsSize(mClip.width, mClip.height); - return NS_OK; -} - -NS_IMETHODIMP -ClippedImage::GetFrame(uint32_t aWhichFrame, - uint32_t aFlags, - gfxASurface** _retval) -{ - if (!ShouldClip()) { - return InnerImage()->GetFrame(aWhichFrame, aFlags, _retval); - } - - // Create a surface to draw into. - gfxImageSurface::gfxImageFormat format = gfxASurface::ImageFormatARGB32; - nsRefPtr surface = gfxPlatform::GetPlatform() - ->CreateOffscreenSurface(gfxIntSize(mClip.width, mClip.height), - gfxImageSurface::ContentFromFormat(format)); - // Create our callback. - nsRefPtr drawTileCallback = - new DrawSingleTileCallback(this, mClip, mClip.Size(), nullptr, aWhichFrame, aFlags); - nsRefPtr drawable = - new gfxCallbackDrawable(drawTileCallback, mClip.Size()); - - // Actually draw. The callback will end up invoking DrawSingleTile. - nsRefPtr ctx = new gfxContext(surface); - gfxRect imageRect(0, 0, mClip.width, mClip.height); - gfxUtils::DrawPixelSnapped(ctx, drawable, gfxMatrix(), - imageRect, imageRect, imageRect, imageRect, - gfxASurface::ImageFormatARGB32, gfxPattern::FILTER_FAST); - - *_retval = surface.forget().get(); - return NS_OK; -} - -NS_IMETHODIMP -ClippedImage::GetImageContainer(LayerManager* aManager, ImageContainer** _retval) -{ - // XXX(seth): We currently don't have a way of clipping the result of - // GetImageContainer. We work around this by always returning null, but if it - // ever turns out that ClippedImage is widely used on codepaths that can - // actually benefit from GetImageContainer, it would be a good idea to fix - // that method for performance reasons. - - *_retval = nullptr; - return NS_OK; -} - -bool -ClippedImage::WillTile(const gfxRect& aSourceRect, - const uint32_t aFlags) const -{ - return !gfxRect(0, 0, mClip.width, mClip.height).Contains(aSourceRect) && - !(aFlags & imgIContainer::FLAG_CLAMP); -} - -NS_IMETHODIMP -ClippedImage::Draw(gfxContext* aContext, - gfxPattern::GraphicsFilter aFilter, - const gfxMatrix& aUserSpaceToImageSpace, - const gfxRect& aFill, - const nsIntRect& aSubimage, - const nsIntSize& aViewportSize, - const SVGImageContext* aSVGContext, - uint32_t aWhichFrame, - uint32_t aFlags) -{ - if (!ShouldClip()) { - return InnerImage()->Draw(aContext, aFilter, aUserSpaceToImageSpace, - aFill, aSubimage, aViewportSize, aSVGContext, - aWhichFrame, aFlags); - } - - // Check for tiling. If we need to tile then we need to create a - // gfxCallbackDrawable to handle drawing for us. - gfxRect sourceRect = aUserSpaceToImageSpace.Transform(aFill); - if (WillTile(sourceRect, aFlags)) { - // Create a temporary surface containing a single tile of this image. - // GetFrame will call DrawSingleTile internally. - nsRefPtr surface; - GetFrame(aWhichFrame, aFlags, getter_AddRefs(surface)); - NS_ENSURE_TRUE(surface, NS_ERROR_FAILURE); - - // Create a drawable from that surface. - nsRefPtr drawable = - new gfxSurfaceDrawable(surface, gfxIntSize(mClip.width, mClip.height)); - - // Draw. - gfxRect imageRect(0, 0, mClip.width, mClip.height); - gfxRect subimage(aSubimage.x, aSubimage.y, aSubimage.width, aSubimage.height); - gfxUtils::DrawPixelSnapped(aContext, drawable, aUserSpaceToImageSpace, - subimage, sourceRect, imageRect, aFill, - gfxASurface::ImageFormatARGB32, aFilter); - - return NS_OK; - } - - nsIntRect subimage(aSubimage); - subimage.MoveBy(mClip.x, mClip.y); - subimage.Intersect(mClip); - - return DrawSingleTile(aContext, aFilter, aUserSpaceToImageSpace, aFill, subimage, - aViewportSize, aSVGContext, aWhichFrame, aFlags); -} - -gfxFloat -ClippedImage::ClampFactor(const gfxFloat aToClamp, const int aReference) const -{ - return aToClamp > aReference ? aReference / aToClamp - : 1.0; -} - -nsresult -ClippedImage::DrawSingleTile(gfxContext* aContext, - gfxPattern::GraphicsFilter aFilter, - const gfxMatrix& aUserSpaceToImageSpace, - const gfxRect& aFill, - const nsIntRect& aSubimage, - const nsIntSize& aViewportSize, - const SVGImageContext* aSVGContext, - uint32_t aWhichFrame, - uint32_t aFlags) -{ - MOZ_ASSERT(!WillTile(aUserSpaceToImageSpace.Transform(aFill), aFlags), - "DrawSingleTile shouldn't get a transform requiring tiling"); - - // Make the viewport reflect the original image's size. - nsIntSize viewportSize(aViewportSize); - int32_t imgWidth, imgHeight; - if (NS_SUCCEEDED(InnerImage()->GetWidth(&imgWidth)) && - NS_SUCCEEDED(InnerImage()->GetHeight(&imgHeight))) { - viewportSize = nsIntSize(imgWidth, imgHeight); - } else { - MOZ_ASSERT(false, "If ShouldClip() led us to draw then we should never get here"); - } - - // Add a translation to the transform to reflect the clipping region. - gfxMatrix transform(aUserSpaceToImageSpace); - transform.Multiply(gfxMatrix().Translate(gfxPoint(mClip.x, mClip.y))); - - // "Clamp the source rectangle" to the clipping region's width and height. - // Really, this means modifying the transform to get the results we want. - gfxRect sourceRect = transform.Transform(aFill); - if (sourceRect.width > mClip.width || sourceRect.height > mClip.height) { - gfxMatrix clampSource; - clampSource.Translate(gfxPoint(sourceRect.x, sourceRect.y)); - clampSource.Scale(ClampFactor(sourceRect.width, mClip.width), - ClampFactor(sourceRect.height, mClip.height)); - clampSource.Translate(gfxPoint(-sourceRect.x, -sourceRect.y)); - transform.Multiply(clampSource); - } - - return InnerImage()->Draw(aContext, aFilter, transform, aFill, aSubimage, - viewportSize, aSVGContext, aWhichFrame, aFlags); -} - -} // namespace image -} // namespace mozilla diff --git a/image/src/ClippedImage.h b/image/src/ClippedImage.h deleted file mode 100644 index 97a749655203..000000000000 --- a/image/src/ClippedImage.h +++ /dev/null @@ -1,78 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef MOZILLA_IMAGELIB_CLIPPEDIMAGE_H_ -#define MOZILLA_IMAGELIB_CLIPPEDIMAGE_H_ - -#include "ImageWrapper.h" - -namespace mozilla { -namespace image { - -class DrawSingleTileCallback; - -/** - * An Image wrapper that clips an image against a rectangle. Right now only - * absolute coordinates in pixels are supported. - * - * XXX(seth): There a known (performance, not correctness) issue with - * GetImageContainer. See the comments for that method for more information. - */ -class ClippedImage : public ImageWrapper -{ -public: - NS_DECL_ISUPPORTS - - virtual ~ClippedImage() { } - - virtual nsIntRect FrameRect(uint32_t aWhichFrame) MOZ_OVERRIDE; - - NS_IMETHOD GetWidth(int32_t* aWidth) MOZ_OVERRIDE; - NS_IMETHOD GetHeight(int32_t* aHeight) MOZ_OVERRIDE; - NS_IMETHOD GetIntrinsicSize(nsSize* aSize) MOZ_OVERRIDE; - NS_IMETHOD GetIntrinsicRatio(nsSize* aRatio) MOZ_OVERRIDE; - NS_IMETHOD GetFrame(uint32_t aWhichFrame, - uint32_t aFlags, - gfxASurface** _retval) MOZ_OVERRIDE; - NS_IMETHOD GetImageContainer(mozilla::layers::LayerManager* aManager, - mozilla::layers::ImageContainer** _retval) MOZ_OVERRIDE; - NS_IMETHOD Draw(gfxContext* aContext, - gfxPattern::GraphicsFilter aFilter, - const gfxMatrix& aUserSpaceToImageSpace, - const gfxRect& aFill, - const nsIntRect& aSubimage, - const nsIntSize& aViewportSize, - const SVGImageContext* aSVGContext, - uint32_t aWhichFrame, - uint32_t aFlags) MOZ_OVERRIDE; - -protected: - ClippedImage(Image* aImage, nsIntRect aClip); - -private: - bool ShouldClip(); - bool WillTile(const gfxRect& aSourceRect, const uint32_t aFlags) const; - gfxFloat ClampFactor(const gfxFloat aToClamp, const int aReference) const; - nsresult DrawSingleTile(gfxContext* aContext, - gfxPattern::GraphicsFilter aFilter, - const gfxMatrix& aUserSpaceToImageSpace, - const gfxRect& aFill, - const nsIntRect& aSubimage, - const nsIntSize& aViewportSize, - const SVGImageContext* aSVGContext, - uint32_t aWhichFrame, - uint32_t aFlags); - - nsIntRect mClip; // The region to clip to. - Maybe mShouldClip; // Memoized ShouldClip() if present. - - friend class DrawSingleTileCallback; - friend class ImageOps; -}; - -} // namespace image -} // namespace mozilla - -#endif // MOZILLA_IMAGELIB_CLIPPEDIMAGE_H_ diff --git a/image/src/FrozenImage.cpp b/image/src/FrozenImage.cpp index 333b7b88e000..aa7e19661f57 100644 --- a/image/src/FrozenImage.cpp +++ b/image/src/FrozenImage.cpp @@ -68,6 +68,15 @@ FrozenImage::GetImageContainer(layers::LayerManager* aManager, return NS_OK; } +NS_IMETHODIMP +FrozenImage::ExtractFrame(uint32_t aWhichFrame, + const nsIntRect& aRegion, + uint32_t aFlags, + imgIContainer** _retval) +{ + return InnerImage()->ExtractFrame(FRAME_FIRST, aRegion, aFlags, _retval); +} + NS_IMETHODIMP FrozenImage::Draw(gfxContext* aContext, gfxPattern::GraphicsFilter aFilter, diff --git a/image/src/FrozenImage.h b/image/src/FrozenImage.h index 65428ce7a3cc..077caa04027e 100644 --- a/image/src/FrozenImage.h +++ b/image/src/FrozenImage.h @@ -40,6 +40,10 @@ public: NS_IMETHOD_(bool) FrameIsOpaque(uint32_t aWhichFrame) MOZ_OVERRIDE; NS_IMETHOD GetImageContainer(layers::LayerManager* aManager, layers::ImageContainer** _retval) MOZ_OVERRIDE; + NS_IMETHOD ExtractFrame(uint32_t aWhichFrame, + const nsIntRect& aRegion, + uint32_t aFlags, + imgIContainer** _retval) MOZ_OVERRIDE; NS_IMETHOD Draw(gfxContext* aContext, gfxPattern::GraphicsFilter aFilter, const gfxMatrix& aUserSpaceToImageSpace, @@ -58,7 +62,7 @@ protected: FrozenImage(Image* aImage) : ImageWrapper(aImage) { } private: - friend class ImageOps; + friend class ImageFactory; }; } // namespace image diff --git a/image/src/ImageFactory.cpp b/image/src/ImageFactory.cpp index 92ed5a526c4a..e44416b669bb 100644 --- a/image/src/ImageFactory.cpp +++ b/image/src/ImageFactory.cpp @@ -21,6 +21,7 @@ #include "imgStatusTracker.h" #include "RasterImage.h" #include "VectorImage.h" +#include "FrozenImage.h" #include "Image.h" #include "nsMediaFragmentURIParser.h" @@ -174,6 +175,13 @@ GetContentSize(nsIRequest* aRequest) return 0; } +/* static */ already_AddRefed +ImageFactory::Freeze(Image* aImage) +{ + nsRefPtr frozenImage = new FrozenImage(aImage); + return frozenImage.forget(); +} + /* static */ already_AddRefed ImageFactory::CreateRasterImage(nsIRequest* aRequest, imgStatusTracker* aStatusTracker, diff --git a/image/src/ImageFactory.h b/image/src/ImageFactory.h index dedac3fb6158..716ac9797610 100644 --- a/image/src/ImageFactory.h +++ b/image/src/ImageFactory.h @@ -46,6 +46,14 @@ public: */ static already_AddRefed CreateAnonymousImage(const nsCString& aMimeType); + /** + * Creates a version of an existing image which does not animate and is frozen + * at the first frame. + * + * @param aImage The existing image. + */ + static already_AddRefed Freeze(Image* aImage); + private: // Factory functions that create specific types of image containers. static already_AddRefed CreateRasterImage(nsIRequest* aRequest, diff --git a/image/src/ImageOps.cpp b/image/src/ImageOps.cpp deleted file mode 100644 index add83a89f990..000000000000 --- a/image/src/ImageOps.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "imgIContainer.h" -#include "ClippedImage.h" -#include "FrozenImage.h" -#include "Image.h" - -#include "ImageOps.h" - -namespace mozilla { -namespace image { - -/* static */ already_AddRefed -ImageOps::Freeze(Image* aImage) -{ - nsRefPtr frozenImage = new FrozenImage(aImage); - return frozenImage.forget(); -} - -/* static */ already_AddRefed -ImageOps::Freeze(imgIContainer* aImage) -{ - nsCOMPtr frozenImage = - new FrozenImage(static_cast(aImage)); - return frozenImage.forget(); -} - -/* static */ already_AddRefed -ImageOps::Clip(Image* aImage, nsIntRect aClip) -{ - nsRefPtr clippedImage = new ClippedImage(aImage, aClip); - return clippedImage.forget(); -} - -/* static */ already_AddRefed -ImageOps::Clip(imgIContainer* aImage, nsIntRect aClip) -{ - nsCOMPtr clippedImage = - new ClippedImage(static_cast(aImage), aClip); - return clippedImage.forget(); -} - -} // namespace image -} // namespace mozilla diff --git a/image/src/ImageOps.h b/image/src/ImageOps.h deleted file mode 100644 index e68571f19a03..000000000000 --- a/image/src/ImageOps.h +++ /dev/null @@ -1,49 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef MOZILLA_IMAGELIB_IMAGEOPS_H_ -#define MOZILLA_IMAGELIB_IMAGEOPS_H_ - -#include "nsCOMPtr.h" -#include "nsRect.h" - -class imgIContainer; - -namespace mozilla { -namespace image { - -class Image; - -class ImageOps -{ -public: - /** - * Creates a version of an existing image which does not animate and is frozen - * at the first frame. - * - * @param aImage The existing image. - */ - static already_AddRefed Freeze(Image* aImage); - static already_AddRefed Freeze(imgIContainer* aImage); - - /** - * Creates a clipped version of an existing image. Animation is unaffected. - * - * @param aImage The existing image. - * @param aClip The rectangle to clip the image against. - */ - static already_AddRefed Clip(Image* aImage, nsIntRect aClip); - static already_AddRefed Clip(imgIContainer* aImage, nsIntRect aClip); - -private: - // This is a static utility class, so disallow instantiation. - virtual ~ImageOps() = 0; -}; - -} // namespace image -} // namespace mozilla - -#endif // MOZILLA_IMAGELIB_IMAGEOPS_H_ diff --git a/image/src/ImageWrapper.cpp b/image/src/ImageWrapper.cpp index d67e684d9d4c..193aac3ffc1b 100644 --- a/image/src/ImageWrapper.cpp +++ b/image/src/ImageWrapper.cpp @@ -203,6 +203,15 @@ ImageWrapper::GetImageContainer(LayerManager* aManager, ImageContainer** _retval return mInnerImage->GetImageContainer(aManager, _retval); } +NS_IMETHODIMP +ImageWrapper::ExtractFrame(uint32_t aWhichFrame, + const nsIntRect& aRegion, + uint32_t aFlags, + imgIContainer** _retval) +{ + return mInnerImage->ExtractFrame(aWhichFrame, aRegion, aFlags, _retval); +} + NS_IMETHODIMP ImageWrapper::Draw(gfxContext* aContext, gfxPattern::GraphicsFilter aFilter, diff --git a/image/src/Makefile.in b/image/src/Makefile.in index 897a40f02bdb..fd271061709b 100644 --- a/image/src/Makefile.in +++ b/image/src/Makefile.in @@ -20,16 +20,13 @@ FAIL_ON_WARNINGS = 1 EXPORTS = imgLoader.h \ imgRequest.h \ imgRequestProxy.h \ - ImageOps.h \ $(NULL) CPPSRCS = \ Image.cpp \ ImageFactory.cpp \ ImageMetadata.cpp \ - ImageOps.cpp \ ImageWrapper.cpp \ - ClippedImage.cpp \ Decoder.cpp \ DiscardTracker.cpp \ FrozenImage.cpp \ diff --git a/image/src/RasterImage.cpp b/image/src/RasterImage.cpp index f197e3944d86..737f22729b18 100644 --- a/image/src/RasterImage.cpp +++ b/image/src/RasterImage.cpp @@ -502,6 +502,14 @@ RasterImage::Init(const char* aMimeType, discardable_source_bytes += mSourceData.Length(); } + // If we're being called from ExtractFrame (used by borderimage), + // we don't actually do any decoding. Bail early. + // XXX - This should be removed when we fix borderimage + if (mSourceDataMimeType.Length() == 0) { + mInitialized = true; + return NS_OK; + } + // Instantiate the decoder nsresult rv = InitDecoder(/* aDoSizeDecode = */ true); CONTAINER_ENSURE_SUCCESS(rv); @@ -675,6 +683,85 @@ RasterImage::RequestRefresh(const mozilla::TimeStamp& aTime) } } +//****************************************************************************** +/* [noscript] imgIContainer extractFrame(uint32_t aWhichFrame, + * [const] in nsIntRect aRegion, + * in uint32_t aFlags); */ +NS_IMETHODIMP +RasterImage::ExtractFrame(uint32_t aWhichFrame, + const nsIntRect &aRegion, + uint32_t aFlags, + imgIContainer **_retval) +{ + NS_ENSURE_ARG_POINTER(_retval); + + nsresult rv; + + if (aWhichFrame > FRAME_MAX_VALUE) + return NS_ERROR_INVALID_ARG; + + if (mError) + return NS_ERROR_FAILURE; + + // Disallowed in the API + if (mInDecoder && (aFlags & imgIContainer::FLAG_SYNC_DECODE)) + return NS_ERROR_FAILURE; + + // Make a new container. This should switch to another class with bug 505959. + nsRefPtr img(new RasterImage()); + + // We don't actually have a mimetype in this case. The empty string tells the + // init routine not to try to instantiate a decoder. This should be fixed in + // bug 505959. + img->Init("", INIT_FLAG_NONE); + img->SetSize(aRegion.width, aRegion.height); + img->mDecoded = true; // Also, we need to mark the image as decoded + img->mHasBeenDecoded = true; + img->mFrameDecodeFlags = aFlags & DECODE_FLAGS_MASK; + + if (!ApplyDecodeFlags(aFlags)) + return NS_ERROR_NOT_AVAILABLE; + + // If a synchronous decode was requested, do it + if (aFlags & FLAG_SYNC_DECODE) { + rv = SyncDecode(); + CONTAINER_ENSURE_SUCCESS(rv); + } + + // Get the frame. If it's not there, it's probably the caller's fault for + // not waiting for the data to be loaded from the network or not passing + // FLAG_SYNC_DECODE + uint32_t frameIndex = (aWhichFrame == FRAME_FIRST) ? + 0 : GetCurrentImgFrameIndex(); + imgFrame *frame = GetDrawableImgFrame(frameIndex); + if (!frame) { + *_retval = nullptr; + return NS_ERROR_FAILURE; + } + + // The frame can be smaller than the image. We want to extract only the part + // of the frame that actually exists. + nsIntRect framerect = frame->GetRect(); + framerect.IntersectRect(framerect, aRegion); + + if (framerect.IsEmpty()) + return NS_ERROR_NOT_AVAILABLE; + + nsAutoPtr subframe; + rv = frame->Extract(framerect, getter_Transfers(subframe)); + if (NS_FAILED(rv)) + return rv; + + img->mFrames.AppendElement(subframe.forget()); + + img->mStatusTracker->RecordLoaded(); + img->mStatusTracker->RecordDecoded(); + + *_retval = img.forget().get(); + + return NS_OK; +} + //****************************************************************************** /* readonly attribute int32_t width; */ NS_IMETHODIMP @@ -2656,10 +2743,11 @@ RasterImage::WriteToDecoder(const char *aBuffer, uint32_t aCount) } // This function is called in situations where it's clear that we want the -// frames in decoded form (Draw, GetFrame, etc). If we're completely decoded, -// this method resets the discard timer (if we're discardable), since wanting -// the frames now is a good indicator of wanting them again soon. If we're not -// decoded, this method kicks off asynchronous decoding to generate the frames. +// frames in decoded form (Draw, GetFrame, CopyFrame, ExtractFrame, etc). +// If we're completely decoded, this method resets the discard timer (if +// we're discardable), since wanting the frames now is a good indicator of +// wanting them again soon. If we're not decoded, this method kicks off +// asynchronous decoding to generate the frames. nsresult RasterImage::WantDecodedFrames() { diff --git a/image/src/VectorImage.cpp b/image/src/VectorImage.cpp index 9c1631a0d782..334dd6200509 100644 --- a/image/src/VectorImage.cpp +++ b/image/src/VectorImage.cpp @@ -301,10 +301,12 @@ NS_IMPL_ISUPPORTS3(VectorImage, VectorImage::VectorImage(imgStatusTracker* aStatusTracker, nsIURI* aURI /* = nullptr */) : ImageResource(aStatusTracker, aURI), // invoke superclass's constructor + mRestrictedRegion(0, 0, 0, 0), mIsInitialized(false), mIsFullyLoaded(false), mIsDrawing(false), - mHaveAnimations(false) + mHaveAnimations(false), + mHaveRestrictedRegion(false) { } @@ -324,7 +326,8 @@ VectorImage::Init(const char* aMimeType, if (mIsInitialized) return NS_ERROR_ILLEGAL_VALUE; - MOZ_ASSERT(!mIsFullyLoaded && !mHaveAnimations && !mError, + MOZ_ASSERT(!mIsFullyLoaded && !mHaveAnimations && + !mHaveRestrictedRegion && !mError, "Flags unexpectedly set before initialization"); MOZ_ASSERT(!strcmp(aMimeType, IMAGE_SVG_XML), "Unexpected mimetype"); @@ -592,7 +595,14 @@ VectorImage::GetFrame(uint32_t aWhichFrame, // --------------------------------------------- // Make our surface the size of what will ultimately be drawn to it. // (either the full image size, or the restricted region) - gfxIntSize surfaceSize(imageIntSize.width, imageIntSize.height); + gfxIntSize surfaceSize; + if (mHaveRestrictedRegion) { + surfaceSize.width = mRestrictedRegion.width; + surfaceSize.height = mRestrictedRegion.height; + } else { + surfaceSize.width = imageIntSize.width; + surfaceSize.height = imageIntSize.height; + } nsRefPtr surface = new gfxImageSurface(surfaceSize, gfxASurface::ImageFormatARGB32); @@ -621,6 +631,54 @@ VectorImage::GetImageContainer(LayerManager* aManager, return NS_OK; } +//****************************************************************************** +/* [noscript] imgIContainer extractFrame(uint32_t aWhichFrame, + * [const] in nsIntRect aRegion, + * in uint32_t aFlags); */ +NS_IMETHODIMP +VectorImage::ExtractFrame(uint32_t aWhichFrame, + const nsIntRect& aRegion, + uint32_t aFlags, + imgIContainer** _retval) +{ + NS_ENSURE_ARG_POINTER(_retval); + if (mError || !mIsFullyLoaded) + return NS_ERROR_FAILURE; + + // XXXdholbert NOTE: This method assumes FRAME_CURRENT (not FRAME_FIRST) + // right now, because mozilla doesn't actually contain any clients of this + // method that use FRAME_FIRST. If it's needed, we *could* handle + // FRAME_FIRST by saving the helper-doc's current SMIL time, seeking it to + // time 0, rendering to a RasterImage, and then restoring our saved time. + if (aWhichFrame != FRAME_CURRENT) { + NS_WARNING("VectorImage::ExtractFrame with something other than " + "FRAME_CURRENT isn't supported yet. Assuming FRAME_CURRENT."); + } + + // XXXdholbert This method also doesn't actually freeze animation in the + // returned imgIContainer, because it shares our helper-document. To + // get a true snapshot, we need to clone the document - see bug 590792. + + // Make a new container with same SVG document. + nsRefPtr extractedImg = new VectorImage(); + extractedImg->mSVGDocumentWrapper = mSVGDocumentWrapper; + extractedImg->mAnimationMode = kDontAnimMode; + + extractedImg->mRestrictedRegion.x = aRegion.x; + extractedImg->mRestrictedRegion.y = aRegion.y; + + // (disallow negative width/height on our restricted region) + extractedImg->mRestrictedRegion.width = std::max(aRegion.width, 0); + extractedImg->mRestrictedRegion.height = std::max(aRegion.height, 0); + + extractedImg->mIsInitialized = true; + extractedImg->mIsFullyLoaded = true; + extractedImg->mHaveRestrictedRegion = true; + + *_retval = extractedImg.forget().get(); + return NS_OK; +} + //****************************************************************************** /* [noscript] void draw(in gfxContext aContext, * in gfxGraphicsFilter aFilter, @@ -664,19 +722,24 @@ VectorImage::Draw(gfxContext* aContext, mSVGDocumentWrapper->UpdateViewportBounds(aViewportSize); mSVGDocumentWrapper->FlushImageTransformInvalidation(); + nsIntSize imageSize = mHaveRestrictedRegion ? + mRestrictedRegion.Size() : aViewportSize; + // XXXdholbert Do we need to convert image size from // CSS pixels to dev pixels here? (is gfxCallbackDrawable's 2nd arg in dev // pixels?) - gfxIntSize imageSizeGfx(aViewportSize.width, aViewportSize.height); + gfxIntSize imageSizeGfx(imageSize.width, imageSize.height); // Based on imgFrame::Draw gfxRect sourceRect = aUserSpaceToImageSpace.Transform(aFill); - gfxRect imageRect(0, 0, aViewportSize.width, aViewportSize.height); + gfxRect imageRect(0, 0, imageSize.width, imageSize.height); gfxRect subimage(aSubimage.x, aSubimage.y, aSubimage.width, aSubimage.height); nsRefPtr cb = new SVGDrawingCallback(mSVGDocumentWrapper, + mHaveRestrictedRegion ? + mRestrictedRegion : nsIntRect(nsIntPoint(0, 0), aViewportSize), aFlags); @@ -687,9 +750,12 @@ VectorImage::Draw(gfxContext* aContext, subimage, sourceRect, imageRect, aFill, gfxASurface::ImageFormatARGB32, aFilter); - // Allow ourselves to fire FrameChanged and OnStopFrame again. - MOZ_ASSERT(mRenderingObserver, "Should have a rendering observer by now"); - mRenderingObserver->ResumeListening(); + MOZ_ASSERT(mRenderingObserver || mHaveRestrictedRegion, + "Should have a rendering observer by now unless ExtractFrame created us"); + if (mRenderingObserver) { + // Allow ourselves to fire FrameChanged and OnStopFrame again. + mRenderingObserver->ResumeListening(); + } return NS_OK; } diff --git a/image/src/VectorImage.h b/image/src/VectorImage.h index 80746ddf9ffd..69a547b82560 100644 --- a/image/src/VectorImage.h +++ b/image/src/VectorImage.h @@ -84,11 +84,18 @@ private: nsRefPtr mLoadEventListener; nsRefPtr mParseCompleteListener; + nsIntRect mRestrictedRegion; // If we were created by + // ExtractFrame, this is the region + // that we're restricted to using. + // Otherwise, this is ignored. + bool mIsInitialized; // Have we been initalized? bool mIsFullyLoaded; // Has the SVG document finished loading? bool mIsDrawing; // Are we currently drawing? bool mHaveAnimations; // Is our SVG content SMIL-animated? // (Only set after mIsFullyLoaded.) + bool mHaveRestrictedRegion; // Are we a restricted-region clone + // created via ExtractFrame? friend class ImageFactory; }; diff --git a/image/src/imgRequestProxy.cpp b/image/src/imgRequestProxy.cpp index d5e995422541..d6ad4a34d0df 100644 --- a/image/src/imgRequestProxy.cpp +++ b/image/src/imgRequestProxy.cpp @@ -18,7 +18,7 @@ #include "nsCRT.h" #include "Image.h" -#include "ImageOps.h" +#include "ImageFactory.h" #include "nsError.h" #include "ImageLogging.h" @@ -915,7 +915,7 @@ imgRequestProxy::GetStaticRequest(imgRequestProxy** aReturn) } // We are animated. We need to create a frozen version of this image. - nsRefPtr frozenImage = ImageOps::Freeze(image); + nsRefPtr frozenImage = ImageFactory::Freeze(image); // Create a static imgRequestProxy with our new extracted frame. nsCOMPtr currentPrincipal; diff --git a/layout/base/nsCSSRendering.cpp b/layout/base/nsCSSRendering.cpp index c0c63b5bf9ea..f2ccb4e5b984 100644 --- a/layout/base/nsCSSRendering.cpp +++ b/layout/base/nsCSSRendering.cpp @@ -30,7 +30,6 @@ #include "nsIScrollableFrame.h" #include "imgIRequest.h" #include "imgIContainer.h" -#include "ImageOps.h" #include "nsCSSRendering.h" #include "nsCSSColorUtils.h" #include "nsITheme.h" @@ -61,7 +60,6 @@ using namespace mozilla; using namespace mozilla::css; -using mozilla::image::ImageOps; static int gFrameTreeLockCount = 0; @@ -3316,10 +3314,20 @@ DrawBorderImageComponent(nsRenderingContext& aRenderingContext, if (aFill.IsEmpty() || aSrc.IsEmpty()) return; + // Don't bother trying to cache sub images if the border image is animated + // We can only sucessfully call GetAnimated() if we are fully decoded, so default to true + bool animated = true; + aImage->GetAnimated(&animated); + nsCOMPtr subImage; - if ((subImage = aStyleBorder.GetSubImage(aIndex)) == nullptr) { - subImage = ImageOps::Clip(aImage, aSrc); - aStyleBorder.SetSubImage(aIndex, subImage); + if (animated || (subImage = aStyleBorder.GetSubImage(aIndex)) == 0) { + if (NS_FAILED(aImage->ExtractFrame(imgIContainer::FRAME_CURRENT, aSrc, + imgIContainer::FLAG_SYNC_DECODE, + getter_AddRefs(subImage)))) + return; + + if (!animated) + aStyleBorder.SetSubImage(aIndex, subImage); } gfxPattern::GraphicsFilter graphicsFilter = @@ -4285,7 +4293,18 @@ nsImageRenderer::PrepareImage() // The cropped image is identical to the source image mImageContainer.swap(srcImage); } else { - nsCOMPtr subImage = ImageOps::Clip(srcImage, actualCropRect); + nsCOMPtr subImage; + uint32_t aExtractFlags = (mFlags & FLAG_SYNC_DECODE_IMAGES) + ? (uint32_t) imgIContainer::FLAG_SYNC_DECODE + : (uint32_t) imgIContainer::FLAG_NONE; + nsresult rv = srcImage->ExtractFrame(imgIContainer::FRAME_CURRENT, + actualCropRect, aExtractFlags, + getter_AddRefs(subImage)); + if (NS_FAILED(rv)) { + NS_WARNING("The cropped image contains no pixels to draw; " + "maybe the crop rect is outside the image frame rect"); + return false; + } mImageContainer.swap(subImage); } } From 4bc14288e0a6eed728493fa4e7f5233f905c711d Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Tue, 26 Mar 2013 13:32:09 -0400 Subject: [PATCH 059/129] Bug 851828 - Type safety improvements for the profiler in Win64 builds. r=benwa --- tools/profiler/JSCustomObjectBuilder.cpp | 4 ++-- tools/profiler/PseudoStack.h | 4 ++-- tools/profiler/TableTicker.cpp | 4 ++-- tools/profiler/nsProfiler.cpp | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tools/profiler/JSCustomObjectBuilder.cpp b/tools/profiler/JSCustomObjectBuilder.cpp index 3b3b6f0f0ede..fcc4df43d81a 100644 --- a/tools/profiler/JSCustomObjectBuilder.cpp +++ b/tools/profiler/JSCustomObjectBuilder.cpp @@ -87,7 +87,7 @@ void EscapeToStream(std::ostream& stream, const char* str) { } else if (ucs4Char > 0xFF) { PRUnichar chr[2]; ConvertUTF8toUTF16 encoder(chr); - encoder.write(utf8CharStart, str-utf8CharStart); + encoder.write(utf8CharStart, uint32_t(str-utf8CharStart)); char escChar[13]; snprintf(escChar, mozilla::ArrayLength(escChar), "\\u%04X\\u%04X", chr[0], chr[1]); stream << escChar; @@ -210,7 +210,7 @@ operator<<(std::ostream& stream, JSCustomArray* entry) { bool needsComma = false; stream << "["; - for (size_t i = 0; i < entry->mValues.Length(); i++) { + for (uint32_t i = 0; i < entry->mValues.Length(); i++) { if (needsComma) { stream << ","; } diff --git a/tools/profiler/PseudoStack.h b/tools/profiler/PseudoStack.h index 21af92a74309..9079ffbfc3a8 100644 --- a/tools/profiler/PseudoStack.h +++ b/tools/profiler/PseudoStack.h @@ -194,7 +194,7 @@ public: } uint32_t stackSize() const { - return std::min(mStackPointer, mozilla::ArrayLength(mStack)); + return std::min(mStackPointer, mozilla::sig_safe_t(mozilla::ArrayLength(mStack))); } void sampleRuntime(JSRuntime *runtime) { @@ -208,7 +208,7 @@ public: js::SetRuntimeProfilingStack(runtime, (js::ProfileEntry*) mStack, (uint32_t*) &mStackPointer, - mozilla::ArrayLength(mStack)); + uint32_t(mozilla::ArrayLength(mStack))); if (mStartJSSampling) enableJSSampling(); } diff --git a/tools/profiler/TableTicker.cpp b/tools/profiler/TableTicker.cpp index 44f61541cffd..c31d9d94e4fa 100644 --- a/tools/profiler/TableTicker.cpp +++ b/tools/profiler/TableTicker.cpp @@ -196,7 +196,7 @@ void addDynamicTag(ThreadProfile &aProfile, char aTagName, const char *aStr) for (size_t j = 0; j < strLen;) { // Store as many characters in the void* as the platform allows char text[sizeof(void*)]; - int len = sizeof(void*)/sizeof(char); + size_t len = sizeof(void*)/sizeof(char); if (j+len >= strLen) { len = strLen - j; } @@ -300,7 +300,7 @@ void TableTicker::doNativeBacktrace(ThreadProfile &aProfile, TickSample* aSample // Start with the current function. StackWalkCallback(aSample->pc, aSample->sp, &array); - uint32_t maxFrames = array.size - array.count; + uint32_t maxFrames = uint32_t(array.size - array.count); #ifdef XP_MACOSX pthread_t pt = GetProfiledThread(platform_data()); void *stackEnd = reinterpret_cast(-1); diff --git a/tools/profiler/nsProfiler.cpp b/tools/profiler/nsProfiler.cpp index b296c1bc913b..5c8e16abbaad 100644 --- a/tools/profiler/nsProfiler.cpp +++ b/tools/profiler/nsProfiler.cpp @@ -103,7 +103,7 @@ nsProfiler::GetProfile(char **aProfile) { char *profile = profiler_get_profile(); if (profile) { - uint32_t len = strlen(profile); + size_t len = strlen(profile); char *profileStr = static_cast (nsMemory::Clone(profile, (len + 1) * sizeof(char))); profileStr[len] = '\0'; @@ -233,7 +233,7 @@ nsProfiler::GetFeatures(uint32_t *aCount, char ***aFeatures) (nsMemory::Alloc(len * sizeof(char*))); for (size_t i = 0; i < len; i++) { - uint32_t strLen = strlen(features[i]); + size_t strLen = strlen(features[i]); featureList[i] = static_cast (nsMemory::Clone(features[i], (strLen + 1) * sizeof(char))); } From 93bd285a285429b7239af11864736d5bd9eee12e Mon Sep 17 00:00:00 2001 From: Jonathan Kew Date: Tue, 26 Mar 2013 17:49:37 +0000 Subject: [PATCH 060/129] bug 828508 - use higher-res favicons for tab titles in hidpi mode if available. r=dao --- browser/base/content/tabbrowser.xml | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/browser/base/content/tabbrowser.xml b/browser/base/content/tabbrowser.xml index 71702c161f1d..3acc43118b98 100644 --- a/browser/base/content/tabbrowser.xml +++ b/browser/base/content/tabbrowser.xml @@ -694,9 +694,15 @@ this.mFaviconService.FAVICON_LOAD_NON_PRIVATE); } - if ((browser.mIconURL || "") != aTab.getAttribute("image")) { - if (browser.mIconURL) - aTab.setAttribute("image", browser.mIconURL); + let sizedIconUrl = browser.mIconURL || ""; + if (sizedIconUrl) { + let size = Math.round(16 * window.devicePixelRatio); + sizedIconUrl += (sizedIconUrl.contains("#") ? "&" : "#") + + "-moz-resolution=" + size + "," + size; + } + if (sizedIconUrl != aTab.getAttribute("image")) { + if (sizedIconUrl) + aTab.setAttribute("image", sizedIconUrl); else aTab.removeAttribute("image"); this._tabAttrModified(aTab); From 295b15ad0e14618f617cfbd936a0babfc18254e4 Mon Sep 17 00:00:00 2001 From: Landry Breuil Date: Tue, 26 Mar 2013 22:13:12 +0100 Subject: [PATCH 061/129] Bug 849253 - Followup to really unbreak BE archs: use USE_SKIA_GPU in HelpersSkia.h too r=gwright --- gfx/2d/HelpersSkia.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/gfx/2d/HelpersSkia.h b/gfx/2d/HelpersSkia.h index 4785e4826617..ad7d5ae98427 100644 --- a/gfx/2d/HelpersSkia.h +++ b/gfx/2d/HelpersSkia.h @@ -10,7 +10,9 @@ #include "skia/SkCanvas.h" #include "skia/SkDashPathEffect.h" #include "skia/SkShader.h" +#ifdef USE_SKIA_GPU #include "skia/GrTypes.h" +#endif #include "mozilla/Assertions.h" #include @@ -37,6 +39,7 @@ GfxFormatToSkiaConfig(SurfaceFormat format) return SkBitmap::kARGB_8888_Config; } +#ifdef USE_SKIA_GPU static inline GrPixelConfig GfxFormatToGrConfig(SurfaceFormat format) { @@ -56,6 +59,7 @@ GfxFormatToGrConfig(SurfaceFormat format) } } +#endif static inline void GfxMatrixToSkiaMatrix(const Matrix& mat, SkMatrix& retval) { From 3626f2b2c99829efb1f1aaf0c5a4da6b77a8a443 Mon Sep 17 00:00:00 2001 From: Jonathan Kew Date: Tue, 26 Mar 2013 21:57:21 +0000 Subject: [PATCH 062/129] bug 818935 - explicitly control the size of icons in the downloaded items list. r=jimm --- .../themes/windows/downloads/allDownloadsViewOverlay.css | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/browser/themes/windows/downloads/allDownloadsViewOverlay.css b/browser/themes/windows/downloads/allDownloadsViewOverlay.css index 230d8082a3c8..62457d4b99c0 100644 --- a/browser/themes/windows/downloads/allDownloadsViewOverlay.css +++ b/browser/themes/windows/downloads/allDownloadsViewOverlay.css @@ -20,9 +20,9 @@ %ifdef WINDOWS_AERO -moz-margin-start: 8px; %endif - /* Prevent flickering when changing states. */ - min-height: 32px; - min-width: 32px; + /* explicitly size the icon, so size doesn't vary on hidpi systems */ + height: 32px; + width: 32px; } .blockedIcon { From 7c0ab1999f17578bb966cfb9e0b81c930263b8a5 Mon Sep 17 00:00:00 2001 From: Luis de Bethencourt Date: Sun, 24 Mar 2013 12:37:21 -0400 Subject: [PATCH 063/129] Bug 795376 - Use high-quality scaler for upscaling raster images [r=joedrew] --- image/src/RasterImage.cpp | 26 ++++++++++++++++++-------- image/src/RasterImage.h | 1 + modules/libpref/src/init/all.js | 4 ++++ 3 files changed, 23 insertions(+), 8 deletions(-) diff --git a/image/src/RasterImage.cpp b/image/src/RasterImage.cpp index 737f22729b18..2418eceef93d 100644 --- a/image/src/RasterImage.cpp +++ b/image/src/RasterImage.cpp @@ -78,6 +78,9 @@ static bool gHQDownscaling = false; static uint32_t gHQDownscalingMinFactor = 1000; static bool gMultithreadedDecoding = true; static int32_t gDecodingThreadLimit = -1; ++// The number of pixels in a 5 megapixel decoded image. ++// Equivalent to an example 3125x1600 resolution. ++static uint32_t gHQUpscalingMaxSize = 20971520; // The maximum number of times any one RasterImage was decoded. This is only // used for statistics. @@ -98,6 +101,8 @@ InitPrefCaches() "image.multithreaded_decoding.enabled", true); Preferences::AddIntVarCache(&gDecodingThreadLimit, "image.multithreaded_decoding.limit", -1); + Preferences::AddUintVarCache(&gHQUpscalingMaxSize, + "image.high_quality_upscaling.max_size", 20971520); } /* We define our own error checking macros here for 2 reasons: @@ -2981,16 +2986,20 @@ RasterImage::SyncDecode() return mError ? NS_ERROR_FAILURE : NS_OK; } -static inline bool -IsDownscale(const gfxSize& scale) +bool +RasterImage::CanQualityScale(const gfxSize& scale) { - if (scale.width > 1.0) - return false; - if (scale.height > 1.0) - return false; + // If target size is 1:1 with original, don't scale. if (scale.width == 1.0 && scale.height == 1.0) return false; + // To save memory don't quality upscale images bigger than the limit. + if (scale.width > 1.0 || scale.height > 1.0) { + uint32_t scaled_size = static_cast(mSize.width * mSize.height * scale.width * scale.height); + if (scaled_size > gHQUpscalingMaxSize) + return false; + } + return true; } @@ -3003,8 +3012,9 @@ RasterImage::CanScale(gfxPattern::GraphicsFilter aFilter, // We don't use the scaler for animated or multipart images to avoid doing a // bunch of work on an image that just gets thrown away. if (gHQDownscaling && aFilter == gfxPattern::FILTER_GOOD && - !mAnim && mDecoded && !mMultipart && IsDownscale(aScale)) { + !mAnim && mDecoded && !mMultipart && CanQualityScale(aScale)) { gfxFloat factor = gHQDownscalingMinFactor / 1000.0; + return (aScale.width < factor || aScale.height < factor); } #endif @@ -3081,7 +3091,7 @@ RasterImage::DrawWithPreDownscaleIfNeeded(imgFrame *aFrame, frame = mScaleResult.frame; userSpaceToImageSpace.Multiply(gfxMatrix().Scale(scale.width, scale.height)); - // Since we're switching to a scaled image, we we need to transform the + // Since we're switching to a scaled image, we need to transform the // area of the subimage to draw accordingly, since imgFrame::Draw() // doesn't know about scaled frames. subimage.ScaleRoundOut(scale.width, scale.height); diff --git a/image/src/RasterImage.h b/image/src/RasterImage.h index 3634ce0937d1..e49f1a9d3b3a 100644 --- a/image/src/RasterImage.h +++ b/image/src/RasterImage.h @@ -816,6 +816,7 @@ private: // data bool IsDecodeFinished(); TimeStamp mDrawStartTime; + inline bool CanQualityScale(const gfxSize& scale); inline bool CanScale(gfxPattern::GraphicsFilter aFilter, gfxSize aScale); struct ScaleResult diff --git a/modules/libpref/src/init/all.js b/modules/libpref/src/init/all.js index b07e6e9797b6..46c10df52794 100644 --- a/modules/libpref/src/init/all.js +++ b/modules/libpref/src/init/all.js @@ -3839,6 +3839,10 @@ pref("image.high_quality_downscaling.enabled", true); // interpreted as a floating-point number / 1000. pref("image.high_quality_downscaling.min_factor", 1000); +// The maximum memory size which we'll use high-quality uspcaling on, +// interpreted as number of decoded bytes. +pref("image.high_quality_upscaling.max_size", 20971520); + // // Image memory management prefs // From 3b6429f54c2e9f2dd2e54c0f882a6cf1aca7e2fb Mon Sep 17 00:00:00 2001 From: Raymond Lee Date: Wed, 27 Mar 2013 03:41:46 +0800 Subject: [PATCH 064/129] Bug 846636 - Use asynchronous getCharsetForURI in getShortcutOrURI for metro r=mbrubeck --- browser/metro/base/content/browser-scripts.js | 6 + browser/metro/base/content/browser-ui.js | 20 +- browser/metro/base/content/browser.js | 229 +++++++++--------- 3 files changed, 134 insertions(+), 121 deletions(-) diff --git a/browser/metro/base/content/browser-scripts.js b/browser/metro/base/content/browser-scripts.js index bb1022e49e0d..5ba1072a4172 100644 --- a/browser/metro/base/content/browser-scripts.js +++ b/browser/metro/base/content/browser-scripts.js @@ -25,6 +25,12 @@ XPCOMUtils.defineLazyModuleGetter(this, "PdfJs", XPCOMUtils.defineLazyModuleGetter(this, "DownloadUtils", "resource://gre/modules/DownloadUtils.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "Promise", + "resource://gre/modules/commonjs/sdk/core/promise.js"); + +XPCOMUtils.defineLazyModuleGetter(this, "Task", + "resource://gre/modules/Task.jsm"); + /* * Services */ diff --git a/browser/metro/base/content/browser-ui.js b/browser/metro/base/content/browser-ui.js index 115e01705c02..af6bd568bcae 100644 --- a/browser/metro/base/content/browser-ui.js +++ b/browser/metro/base/content/browser-ui.js @@ -278,17 +278,19 @@ var BrowserUI = { content.focus(); this._setURI(aURI); - let postData = {}; - aURI = Browser.getShortcutOrURI(aURI, postData); - Browser.loadURI(aURI, { flags: Ci.nsIWebNavigation.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP, postData: postData }); + Task.spawn(function() { + let postData = {}; + aURI = yield Browser.getShortcutOrURI(aURI, postData); + Browser.loadURI(aURI, { flags: Ci.nsIWebNavigation.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP, postData: postData }); - // Delay doing the fixup so the raw URI is passed to loadURIWithFlags - // and the proper third-party fixup can be done - let fixupFlags = Ci.nsIURIFixup.FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP; - let uri = gURIFixup.createFixupURI(aURI, fixupFlags); - gHistSvc.markPageAsTyped(uri); + // Delay doing the fixup so the raw URI is passed to loadURIWithFlags + // and the proper third-party fixup can be done + let fixupFlags = Ci.nsIURIFixup.FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP; + let uri = gURIFixup.createFixupURI(aURI, fixupFlags); + gHistSvc.markPageAsTyped(uri); - this._titleChanged(Browser.selectedBrowser); + BrowserUI._titleChanged(Browser.selectedBrowser); + }); }, handleUrlbarEnter: function handleUrlbarEnter(aEvent) { diff --git a/browser/metro/base/content/browser.js b/browser/metro/base/content/browser.js index 12a00c738475..c7f707371f56 100644 --- a/browser/metro/base/content/browser.js +++ b/browser/metro/base/content/browser.js @@ -133,53 +133,6 @@ var Browser = { if (window.arguments && window.arguments[0]) commandURL = window.arguments[0]; - // Activation URIs come from protocol activations, secondary tiles, and file activations - let activationURI = this.getShortcutOrURI(MetroUtils.activationURI); - - let self = this; - function loadStartupURI() { - let uri = activationURI || commandURL || Browser.getHomePage(); - if (StartUI.isStartURI(uri)) { - self.addTab(uri, true); - StartUI.show(); // This makes about:start load a lot faster - } else if (activationURI) { - self.addTab(uri, true, null, { flags: Ci.nsIWebNavigation.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP }); - } else { - self.addTab(uri, true); - } - } - - // Should we restore the previous session (crash or some other event) - let ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore); - if (ss.shouldRestore() || Services.prefs.getBoolPref("browser.startup.sessionRestore")) { - let bringFront = false; - // First open any commandline URLs, except the homepage - if (activationURI && !StartUI.isStartURI(activationURI)) { - this.addTab(activationURI, true, null, { flags: Ci.nsIWebNavigation.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP }); - } else if (commandURL && !StartUI.isStartURI(commandURL)) { - this.addTab(commandURL, true); - } else { - bringFront = true; - // Initial window resizes call functions that assume a tab is in the tab list - // and restored tabs are added too late. We add a dummy to to satisfy the resize - // code and then remove the dummy after the session has been restored. - let dummy = this.addTab("about:blank", true); - let dummyCleanup = { - observe: function(aSubject, aTopic, aData) { - Services.obs.removeObserver(dummyCleanup, "sessionstore-windows-restored"); - if (aData == "fail") - loadStartupURI(); - dummy.chromeTab.ignoreUndo = true; - Browser.closeTab(dummy, { forceClose: true }); - } - }; - Services.obs.addObserver(dummyCleanup, "sessionstore-windows-restored", false); - } - ss.restoreLastSession(bringFront); - } else { - loadStartupURI(); - } - messageManager.addMessageListener("DOMLinkAdded", this); messageManager.addMessageListener("MozScrolledAreaChanged", this); messageManager.addMessageListener("Browser:ViewportMetadata", this); @@ -197,10 +150,59 @@ var Browser = { // starting with: InputSourceHelper.fireUpdate(); - // Broadcast a UIReady message so add-ons know we are finished with startup - let event = document.createEvent("Events"); - event.initEvent("UIReady", true, false); - window.dispatchEvent(event); + Task.spawn(function() { + // Activation URIs come from protocol activations, secondary tiles, and file activations + let activationURI = yield this.getShortcutOrURI(MetroUtils.activationURI); + + let self = this; + function loadStartupURI() { + let uri = activationURI || commandURL || Browser.getHomePage(); + if (StartUI.isStartURI(uri)) { + self.addTab(uri, true); + StartUI.show(); // This makes about:start load a lot faster + } else if (activationURI) { + self.addTab(uri, true, null, { flags: Ci.nsIWebNavigation.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP }); + } else { + self.addTab(uri, true); + } + } + + // Should we restore the previous session (crash or some other event) + let ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore); + if (ss.shouldRestore() || Services.prefs.getBoolPref("browser.startup.sessionRestore")) { + let bringFront = false; + // First open any commandline URLs, except the homepage + if (activationURI && !StartUI.isStartURI(activationURI)) { + this.addTab(activationURI, true, null, { flags: Ci.nsIWebNavigation.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP }); + } else if (commandURL && !StartUI.isStartURI(commandURL)) { + this.addTab(commandURL, true); + } else { + bringFront = true; + // Initial window resizes call functions that assume a tab is in the tab list + // and restored tabs are added too late. We add a dummy to to satisfy the resize + // code and then remove the dummy after the session has been restored. + let dummy = this.addTab("about:blank", true); + let dummyCleanup = { + observe: function(aSubject, aTopic, aData) { + Services.obs.removeObserver(dummyCleanup, "sessionstore-windows-restored"); + if (aData == "fail") + loadStartupURI(); + dummy.chromeTab.ignoreUndo = true; + Browser.closeTab(dummy, { forceClose: true }); + } + }; + Services.obs.addObserver(dummyCleanup, "sessionstore-windows-restored", false); + } + ss.restoreLastSession(bringFront); + } else { + loadStartupURI(); + } + + // Broadcast a UIReady message so add-ons know we are finished with startup + let event = document.createEvent("Events"); + event.initEvent("UIReady", true, false); + window.dispatchEvent(event); + }.bind(this)); }, quit: function quit() { @@ -348,77 +350,80 @@ var Browser = { * Determine if the given URL is a shortcut/keyword and, if so, expand it * @param aURL String * @param aPostDataRef Out param contains any required post data for a search - * @returns the expanded shortcut, or the original URL if not a shortcut + * @return {Promise} + * @result the expanded shortcut, or the original URL if not a shortcut */ getShortcutOrURI: function getShortcutOrURI(aURL, aPostDataRef) { - if (!aURL) - return aURL; + return Task.spawn(function() { + if (!aURL) + throw new Task.Result(aURL); - let shortcutURL = null; - let keyword = aURL; - let param = ""; + let shortcutURL = null; + let keyword = aURL; + let param = ""; - let offset = aURL.indexOf(" "); - if (offset > 0) { - keyword = aURL.substr(0, offset); - param = aURL.substr(offset + 1); - } - - if (!aPostDataRef) - aPostDataRef = {}; - - let engine = Services.search.getEngineByAlias(keyword); - if (engine) { - let submission = engine.getSubmission(param); - aPostDataRef.value = submission.postData; - return submission.uri.spec; - } - - try { - [shortcutURL, aPostDataRef.value] = PlacesUtils.getURLAndPostDataForKeyword(keyword); - } catch (e) {} - - if (!shortcutURL) - return aURL; - - let postData = ""; - if (aPostDataRef.value) - postData = unescape(aPostDataRef.value); - - if (/%s/i.test(shortcutURL) || /%s/i.test(postData)) { - let charset = ""; - const re = /^(.*)\&mozcharset=([a-zA-Z][_\-a-zA-Z0-9]+)\s*$/; - let matches = shortcutURL.match(re); - if (matches) - [, shortcutURL, charset] = matches; - else { - // Try to get the saved character-set. - try { - // makeURI throws if URI is invalid. - // Will return an empty string if character-set is not found. - charset = PlacesUtils.history.getCharsetForURI(Util.makeURI(shortcutURL)); - } catch (e) { dump("--- error " + e + "\n"); } + let offset = aURL.indexOf(" "); + if (offset > 0) { + keyword = aURL.substr(0, offset); + param = aURL.substr(offset + 1); } - let encodedParam = ""; - if (charset) - encodedParam = escape(convertFromUnicode(charset, param)); - else // Default charset is UTF-8 - encodedParam = encodeURIComponent(param); + if (!aPostDataRef) + aPostDataRef = {}; - shortcutURL = shortcutURL.replace(/%s/g, encodedParam).replace(/%S/g, param); + let engine = Services.search.getEngineByAlias(keyword); + if (engine) { + let submission = engine.getSubmission(param); + aPostDataRef.value = submission.postData; + throw new Task.Result(submission.uri.spec); + } - if (/%s/i.test(postData)) // POST keyword - aPostDataRef.value = getPostDataStream(postData, param, encodedParam, "application/x-www-form-urlencoded"); - } else if (param) { - // This keyword doesn't take a parameter, but one was provided. Just return - // the original URL. - aPostDataRef.value = null; + try { + [shortcutURL, aPostDataRef.value] = PlacesUtils.getURLAndPostDataForKeyword(keyword); + } catch (e) {} - return aURL; - } + if (!shortcutURL) + throw new Task.Result(aURL); - return shortcutURL; + let postData = ""; + if (aPostDataRef.value) + postData = unescape(aPostDataRef.value); + + if (/%s/i.test(shortcutURL) || /%s/i.test(postData)) { + let charset = ""; + const re = /^(.*)\&mozcharset=([a-zA-Z][_\-a-zA-Z0-9]+)\s*$/; + let matches = shortcutURL.match(re); + if (matches) + [, shortcutURL, charset] = matches; + else { + // Try to get the saved character-set. + try { + // makeURI throws if URI is invalid. + // Will return an empty string if character-set is not found. + charset = yield PlacesUtils.getCharsetForURI(Util.makeURI(shortcutURL)); + } catch (e) { dump("--- error " + e + "\n"); } + } + + let encodedParam = ""; + if (charset) + encodedParam = escape(convertFromUnicode(charset, param)); + else // Default charset is UTF-8 + encodedParam = encodeURIComponent(param); + + shortcutURL = shortcutURL.replace(/%s/g, encodedParam).replace(/%S/g, param); + + if (/%s/i.test(postData)) // POST keyword + aPostDataRef.value = getPostDataStream(postData, param, encodedParam, "application/x-www-form-urlencoded"); + } else if (param) { + // This keyword doesn't take a parameter, but one was provided. Just return + // the original URL. + aPostDataRef.value = null; + + throw new Task.Result(aURL); + } + + throw new Task.Result(shortcutURL); + }); }, /** From 82851eabcbcadd3dcfcabdb7860827b3dcb63aae Mon Sep 17 00:00:00 2001 From: Gregory Szorc Date: Tue, 26 Mar 2013 15:00:43 -0700 Subject: [PATCH 065/129] Bug 818819 - Revamp mach's interaction with mochitests; r=Ms2ger mach now invokes mochitests using the native Python API (as opposed to make targets). mach now supports --shuffle, --rerun-failures, --keep-open, --no-autorun, --repeat, and --slow. --- build/mach_bootstrap.py | 2 + testing/mochitest/mach_commands.py | 244 ++++++++++++++++++----------- 2 files changed, 158 insertions(+), 88 deletions(-) diff --git a/build/mach_bootstrap.py b/build/mach_bootstrap.py index 32ac92acc7dd..9259d53c7a94 100644 --- a/build/mach_bootstrap.py +++ b/build/mach_bootstrap.py @@ -22,6 +22,8 @@ SEARCH_PATHS = [ 'xpcom/idl-parser', 'testing', 'testing/xpcshell', + 'testing/mozbase/mozcrash', + 'testing/mozbase/mozlog', 'testing/mozbase/mozprocess', 'testing/mozbase/mozfile', 'testing/mozbase/mozinfo', diff --git a/testing/mochitest/mach_commands.py b/testing/mochitest/mach_commands.py index a6d03a617c42..aca27d452e08 100644 --- a/testing/mochitest/mach_commands.py +++ b/testing/mochitest/mach_commands.py @@ -6,6 +6,7 @@ from __future__ import unicode_literals import os import platform +import sys from mozbuild.base import ( MachCommandBase, @@ -19,49 +20,15 @@ from mach.decorators import ( ) -generic_help = 'Test to run. Can be specified as a single file, a ' +\ -'directory, or omitted. If omitted, the entire test suite is executed.' - -debugger_help = 'Debugger binary to run test in. Program name or path.' - - class MochitestRunner(MozbuildObject): """Easily run mochitests. This currently contains just the basics for running mochitests. We may want to hook up result parsing, etc. """ - def run_plain_suite(self): - """Runs all plain mochitests.""" - # TODO hook up Python harness runner. - self._run_make(directory='.', target='mochitest-plain') - - def run_chrome_suite(self): - """Runs all chrome mochitests.""" - # TODO hook up Python harness runner. - self._run_make(directory='.', target='mochitest-chrome') - - def run_browser_chrome_suite(self): - """Runs browser chrome mochitests.""" - # TODO hook up Python harness runner. - self._run_make(directory='.', target='mochitest-browser-chrome') - - def run_metro_chrome_suite(self): - """Runs Windows 8 Metro browser chrome mochitests.""" - # TODO hook up Python harness runner. - self._run_make(directory='.', target='mochitest-metro-chrome') - - def run_all(self): - self.run_plain_suite() - self.run_chrome_suite() - self.run_browser_chrome_suite() - # Run Metro tests only on Windows 8 and higher - if platform.system() is 'Windows': - version = tuple(map(int, platform.version().split('.'))) - if version >= (6, 2): - self.run_metro_chrome_suite() - - def run_mochitest_test(self, suite=None, test_file=None, debugger=None): + def run_mochitest_test(self, suite=None, test_file=None, debugger=None, + shuffle=False, keep_open=False, rerun_failures=False, no_autorun=False, + repeat=0, slow=False): """Runs a mochitest. test_file is a path to a test file. It can be a relative path from the @@ -73,86 +40,187 @@ class MochitestRunner(MozbuildObject): debugger is a program name or path to a binary (presumably a debugger) to run the test in. e.g. 'gdb' - """ - # TODO hook up harness via native Python - target = None + shuffle is whether test order should be shuffled (defaults to false). + + keep_open denotes whether to keep the browser open after tests + complete. + """ + # TODO Bug 794506 remove once mach integrates with virtualenv. + build_path = os.path.join(self.topobjdir, 'build') + if build_path not in sys.path: + sys.path.append(build_path) + + if rerun_failures and test_file: + print('Cannot specify both --rerun-failures and a test path.') + return 1 + + # Need to perform path test before os.chdir() below. + if test_file: + path_arg = self._wrap_path_argument(test_file) + if not os.path.exists(path_arg.srcdir_path()): + print('Specified test path does not exist: %s' % test_file) + return 1 + + test_file = path_arg.relpath() + + failure_file_path = os.path.join(self.statedir, 'mochitest_failures.json') + + if rerun_failures and not os.path.exists(failure_file_path): + print('No failure file present. Did you run mochitests before?') + return 1 + + from automation import Automation + + # runtests.py is ambiguous, so we load the file/module manually. + if 'mochitest' not in sys.modules: + import imp + path = os.path.join(self.topobjdir, '_tests', 'testing', + 'mochitest', 'runtests.py') + with open(path, 'r') as fh: + imp.load_module('mochitest', fh, path, + ('.py', 'r', imp.PY_SOURCE)) + + import mochitest + + # This is required to make other components happy. Sad, isn't it? + os.chdir(self.topobjdir) + + automation = Automation() + runner = mochitest.Mochitest(automation) + + opts = mochitest.MochitestOptions(automation, + os.path.join(self.topobjdir, '_tests')) + options, args = opts.parse_args([]) + + options = opts.verifyOptions(options, runner) + + if options is None: + raise Exception('mochitest option validator failed.') + + tests_dir = os.path.join(self.topobjdir, '_tests') + + if test_file: + env = {'TEST_PATH': test_file} + + options.autorun = not no_autorun + options.closeWhenDone = not keep_open + options.shuffle = shuffle + options.consoleLevel = 'INFO' + options.repeat = repeat + options.runSlower = slow + options.testingModulesDir = os.path.join(tests_dir, 'modules') + options.extraProfileFiles.append(os.path.join(self.distdir, 'plugins')) + options.symbolsPath = os.path.join(self.distdir, 'crashreporter-symbols') + + options.failureFile = failure_file_path + + automation.setServerInfo(options.webServer, options.httpPort, + options.sslPort, options.webSocketPort) + if suite == 'plain': - target = 'mochitest-plain' + # Don't need additional options for plain. + pass elif suite == 'chrome': - target = 'mochitest-chrome' + options.chrome = True elif suite == 'browser': - target = 'mochitest-browser-chrome' + options.browserChrome = True elif suite == 'metro': - target = 'mochitest-metro-chrome' + options.immersiveMode = True + options.browser = True elif suite == 'a11y': - target = 'mochitest-a11y' + options.a11y = True else: raise Exception('None or unrecognized mochitest suite type.') if test_file: - path_arg = self._wrap_path_argument(test_file) - if not os.path.exists(path_arg.srcdir_path()): - raise Exception('No test file was found at %s.' % test_file) - env = {'TEST_PATH': path_arg.relpath()} - else: - env = {} + options.testPath = test_file - pass_thru = False + if rerun_failures: + options.testManifest = failure_file_path if debugger: - env[b'EXTRA_TEST_ARGS'] = '--debugger=%s' % debugger - pass_thru = True + options.debugger = debugger - return self._run_make(directory='.', target=target, append_env=env, - ensure_exit_code=False, pass_thru=pass_thru) + return runner.runTests(options) + + +def MochitestCommand(func): + """Decorator that adds shared command arguments to mochitest commands.""" + + # This employs light Python magic. Keep in mind a decorator is just a + # function that takes a function, does something with it, then returns a + # (modified) function. Here, we chain decorators onto the passed in + # function. + + debugger = CommandArgument('--debugger', '-d', metavar='DEBUGGER', + help='Debugger binary to run test in. Program name or path.') + func = debugger(func) + + shuffle = CommandArgument('--shuffle', action='store_true', + help='Shuffle execution order.') + func = shuffle(func) + + keep_open = CommandArgument('--keep-open', action='store_true', + help='Keep the browser open after tests complete.') + func = keep_open(func) + + rerun = CommandArgument('--rerun-failures', action='store_true', + help='Run only the tests that filed during the last test run.') + func = rerun(func) + + autorun = CommandArgument('--no-autorun', action='store_true', + help='Do not starting running tests automatically.') + func = autorun(func) + + repeat = CommandArgument('--repeat', type=int, default=0, + help='Repeat the test the given number of times.') + func = repeat(func) + + slow = CommandArgument('--slow', action='store_true', + help='Delay execution between tests.') + func = slow(func) + + path = CommandArgument('test_file', default=None, nargs='?', + metavar='TEST', + help='Test to run. Can be specified as a single file, a ' \ + 'directory, or omitted. If omitted, the entire test suite is ' \ + 'executed.') + func = path(func) + + return func @CommandProvider class MachCommands(MachCommandBase): @Command('mochitest-plain', help='Run a plain mochitest.') - @CommandArgument('--debugger', '-d', metavar='DEBUGGER', - help=debugger_help) - @CommandArgument('test_file', default=None, nargs='?', metavar='TEST', - help=generic_help) - def run_mochitest_plain(self, test_file, debugger=None): - return self.run_mochitest(test_file, 'plain', debugger=debugger) + @MochitestCommand + def run_mochitest_plain(self, test_file, **kwargs): + return self.run_mochitest(test_file, 'plain', **kwargs) @Command('mochitest-chrome', help='Run a chrome mochitest.') - @CommandArgument('--debugger', '-d', metavar='DEBUGGER', - help=debugger_help) - @CommandArgument('test_file', default=None, nargs='?', metavar='TEST', - help=generic_help) - def run_mochitest_chrome(self, test_file, debugger=None): - return self.run_mochitest(test_file, 'chrome', debugger=debugger) + @MochitestCommand + def run_mochitest_chrome(self, test_file, **kwargs): + return self.run_mochitest(test_file, 'chrome', **kwargs) @Command('mochitest-browser', help='Run a mochitest with browser chrome.') - @CommandArgument('--debugger', '-d', metavar='DEBUGGER', - help=debugger_help) - @CommandArgument('test_file', default=None, nargs='?', metavar='TEST', - help=generic_help) - def run_mochitest_browser(self, test_file, debugger=None): - return self.run_mochitest(test_file, 'browser', debugger=debugger) + @MochitestCommand + def run_mochitest_browser(self, test_file, **kwargs): + return self.run_mochitest(test_file, 'browser', **kwargs) @Command('mochitest-metro', help='Run a mochitest with metro browser chrome.') - @CommandArgument('--debugger', '-d', metavar='DEBUGGER', - help=debugger_help) - @CommandArgument('test_file', default=None, nargs='?', metavar='TEST', - help=generic_help) - def run_mochitest_metro(self, test_file, debugger=None): - return self.run_mochitest(test_file, 'metro', debugger=debugger) + @MochitestCommand + def run_mochitest_metro(self, test_file, **kwargs): + return self.run_mochitest(test_file, 'metro', **kwargs) @Command('mochitest-a11y', help='Run an a11y mochitest.') - @CommandArgument('--debugger', '-d', metavar='DEBUGGER', - help=debugger_help) - @CommandArgument('test_file', default=None, nargs='?', metavar='TEST', - help=generic_help) - def run_mochitest_a11y(self, test_file, debugger=None): - return self.run_mochitest(test_file, 'a11y', debugger=debugger) + @MochitestCommand + def run_mochitest_a11y(self, test_file, **kwargs): + return self.run_mochitest(test_file, 'a11y', **kwargs) - def run_mochitest(self, test_file, flavor, debugger=None): + def run_mochitest(self, test_file, flavor, **kwargs): self._ensure_state_subdir_exists('.') mochitest = self._spawn(MochitestRunner) return mochitest.run_mochitest_test(test_file=test_file, suite=flavor, - debugger=debugger) + **kwargs) From e59527182ae4e815e4d029ee8f0e1eedd5989a12 Mon Sep 17 00:00:00 2001 From: Jim Mathies Date: Tue, 26 Mar 2013 17:01:15 -0500 Subject: [PATCH 066/129] Bug 854921 - Pass firefox path to metrotestharness so tests.ini can be written to a location that works with test zips / test slaves. Also add metro tests to mochitest tests.jar. r=mbrubeck, bbondy --- .../metro/shell/testing/metrotestharness.cpp | 89 ++++++++++++++----- testing/mochitest/Makefile.in | 3 + testing/mochitest/runtests.py | 1 + 3 files changed, 72 insertions(+), 21 deletions(-) diff --git a/browser/metro/shell/testing/metrotestharness.cpp b/browser/metro/shell/testing/metrotestharness.cpp index 953fc2e1c77e..ae418dd7c50e 100644 --- a/browser/metro/shell/testing/metrotestharness.cpp +++ b/browser/metro/shell/testing/metrotestharness.cpp @@ -28,6 +28,13 @@ static const WCHAR* kFirefoxExe = L"firefox.exe"; static const WCHAR* kDefaultMetroBrowserIDPathKey = L"FirefoxURL"; static const WCHAR* kDemoMetroBrowserIDPathKey = L"Mozilla.Firefox.URL"; +CString sAppParams; +CString sFirefoxPath; + +// The tests file we write out for firefox.exe which contains test +// startup command line paramters. +#define kMetroTestFile "tests.ini" + static void Log(const wchar_t *fmt, ...) { va_list a = NULL; @@ -134,7 +141,20 @@ static bool GetDefaultBrowserAppModelID(WCHAR* aIDBuffer, return true; } -CString sAppParams; +// Tests.ini file cleanup helper +class DeleteTestFileHelper +{ + CStringA mTestFile; +public: + DeleteTestFileHelper(CStringA& aTestFile) : + mTestFile(aTestFile) {} + ~DeleteTestFileHelper() { + if (mTestFile.GetLength()) { + Log(L"Deleting %s", CStringW(mTestFile)); + DeleteFileA(mTestFile); + } + } +}; static bool Launch() { @@ -143,7 +163,7 @@ static bool Launch() DWORD processID; // The interface that allows us to activate the browser - IApplicationActivationManager* activateMgr = NULL; + CComPtr activateMgr; if (FAILED(CoCreateInstance(CLSID_ApplicationActivationManager, NULL, CLSCTX_LOCAL_SERVER, IID_IApplicationActivationManager, @@ -157,7 +177,6 @@ static bool Launch() // Activation is based on the browser's registered app model id if (!GetDefaultBrowserAppModelID(appModelID, (sizeof(appModelID)/sizeof(WCHAR)))) { Fail(L"GetDefaultBrowserAppModelID failed."); - activateMgr->Release(); return false; } Log(L"App model id='%s'", appModelID); @@ -167,7 +186,6 @@ static bool Launch() hr = CoAllowSetForegroundWindow(activateMgr, NULL); if (FAILED(hr)) { Fail(L"CoAllowSetForegroundWindow result %X", hr); - activateMgr->Release(); return false; } @@ -175,34 +193,49 @@ static bool Launch() // Because we can't pass command line args, we store params in a // tests.ini file in dist/bin which the browser picks up on launch. - char path[MAX_PATH]; - if (!GetModuleFileNameA(NULL, path, MAX_PATH)) { - Fail(L"GetModuleFileNameA errorno=%d", GetLastError()); - activateMgr->Release(); - return false; + CStringA testFilePath; + if (sFirefoxPath.GetLength()) { + // Use the firefoxpath passed to us by the test harness + int index = sFirefoxPath.ReverseFind('\\'); + if (index == -1) { + Fail(L"Bad firefoxpath path"); + return false; + } + testFilePath = sFirefoxPath.Mid(0, index); + testFilePath += "\\"; + testFilePath += kMetroTestFile; + } else { + // Use the module path + char path[MAX_PATH]; + if (!GetModuleFileNameA(NULL, path, MAX_PATH)) { + Fail(L"GetModuleFileNameA errorno=%d", GetLastError()); + return false; + } + char* slash = strrchr(path, '\\'); + if (!slash) + return false; + *slash = '\0'; // no trailing slash + testFilePath = path; + testFilePath += "\\"; + testFilePath += kMetroTestFile; } - char* slash = strrchr(path, '\\'); - if (!slash) - return false; - *slash = '\0'; // no trailing slash - CStringA testFilePath = path; - testFilePath += "\\tests.ini"; + Log(L"Writing out tests.ini to: '%s'", CStringW(testFilePath)); HANDLE hTestFile = CreateFileA(testFilePath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hTestFile == INVALID_HANDLE_VALUE) { Fail(L"CreateFileA errorno=%d", GetLastError()); - activateMgr->Release(); return false; } + DeleteTestFileHelper dtf(testFilePath); + CStringA asciiParams = sAppParams; if (!WriteFile(hTestFile, asciiParams, asciiParams.GetLength(), NULL, 0)) { CloseHandle(hTestFile); Fail(L"WriteFile errorno=%d", GetLastError()); - activateMgr->Release(); return false; } FlushFileBuffers(hTestFile); @@ -212,7 +245,6 @@ static bool Launch() hr = activateMgr->ActivateApplication(appModelID, L"", AO_NOERRORUI, &processID); if (FAILED(hr)) { Fail(L"ActivateApplication result %X", hr); - activateMgr->Release(); return false; } @@ -221,7 +253,6 @@ static bool Launch() HANDLE child = OpenProcess(SYNCHRONIZE, FALSE, processID); if (!child) { Fail(L"Couldn't find child process. (%d)", GetLastError()); - activateMgr->Release(); return false; } @@ -237,8 +268,6 @@ static bool Launch() } Log(L"Exiting."); - activateMgr->Release(); - DeleteFileA(testFilePath); return true; } @@ -247,11 +276,29 @@ int wmain(int argc, WCHAR* argv[]) CoInitialize(NULL); int idx; + bool firefoxParam = false; for (idx = 1; idx < argc; idx++) { + CString param = argv[idx]; + param.Trim(); + + // Pickup the firefox path param and store it, we'll need this + // when we create the tests.ini file. + if (param == "-firefoxpath") { + firefoxParam = true; + continue; + } else if (firefoxParam) { + firefoxParam = false; + sFirefoxPath = param; + continue; + } + sAppParams.Append(argv[idx]); sAppParams.Append(L" "); } sAppParams.Trim(); + if (sFirefoxPath.GetLength()) { + Log(L"firefoxpath: '%s'", sFirefoxPath); + } Log(L"args: '%s'", sAppParams); Launch(); diff --git a/testing/mochitest/Makefile.in b/testing/mochitest/Makefile.in index 015aae3c15e6..4f8240cc21cb 100644 --- a/testing/mochitest/Makefile.in +++ b/testing/mochitest/Makefile.in @@ -180,6 +180,9 @@ stage-chromejar: $(NSINSTALL) -D $(PKG_CHROMEJAR) cp -RL $(DEPTH)/_tests/testing/mochitest/browser $(PKG_CHROMEJAR) cp -RL $(DEPTH)/_tests/testing/mochitest/chrome $(PKG_CHROMEJAR) +ifdef MOZ_METRO + cp -RL $(DEPTH)/_tests/testing/mochitest/metro $(PKG_CHROMEJAR) +endif ifdef ACCESSIBILITY cp -RL $(DEPTH)/_tests/testing/mochitest/a11y $(PKG_CHROMEJAR) endif diff --git a/testing/mochitest/runtests.py b/testing/mochitest/runtests.py index 0890bd185ad9..a1b4abb1307d 100644 --- a/testing/mochitest/runtests.py +++ b/testing/mochitest/runtests.py @@ -735,6 +735,7 @@ class Mochitest(object): testURL = None if options.immersiveMode: + options.browserArgs.extend(('-firefoxpath', options.app)) options.app = self.immersiveHelperPath # Remove the leak detection file so it can't "leak" to the tests run. From 8ba333026add89b09947377071bf0a88101a7862 Mon Sep 17 00:00:00 2001 From: Jim Mathies Date: Tue, 26 Mar 2013 17:01:15 -0500 Subject: [PATCH 067/129] Bug 833016 - Fix for FrameworkView addrefing which is causing crashes on shutdown. r=bbondy --- widget/windows/winrt/FrameworkView.cpp | 27 ++++++++++++++---------- widget/windows/winrt/MetroApp.cpp | 27 ++++++++++++------------ widget/windows/winrt/MetroApp.h | 1 - widget/windows/winrt/nsWinMetroUtils.cpp | 6 +++--- 4 files changed, 32 insertions(+), 29 deletions(-) diff --git a/widget/windows/winrt/FrameworkView.cpp b/widget/windows/winrt/FrameworkView.cpp index b1f80e90724b..99be5a57a8e0 100644 --- a/widget/windows/winrt/FrameworkView.cpp +++ b/widget/windows/winrt/FrameworkView.cpp @@ -86,9 +86,25 @@ FrameworkView::Uninitialize() { LogFunction(); mShuttingDown = true; + + if (mAutomationProvider) { + ComPtr provider; + mAutomationProvider.As(&provider); + if (provider) { + provider->Disconnect(); + } + } + mAutomationProvider = nullptr; + + mMetroInput = nullptr; mD2DWindowSurface = nullptr; delete sSettingsArray; sSettingsArray = nullptr; + mWidget = nullptr; + mMetroApp = nullptr; + mDispatcher = nullptr; + mWindow = nullptr; + return S_OK; } @@ -192,17 +208,6 @@ FrameworkView::AddEventHandlers() { void FrameworkView::ShutdownXPCOM() { - mShuttingDown = true; - mWidget = nullptr; - ComPtr provider; - if (mAutomationProvider) { - mAutomationProvider.As(&provider); - if (provider) { - provider->Disconnect(); - } - } - mAutomationProvider = nullptr; - mMetroInput = nullptr; Uninitialize(); } diff --git a/widget/windows/winrt/MetroApp.cpp b/widget/windows/winrt/MetroApp.cpp index 22f293dfd606..88a2f55cb032 100644 --- a/widget/windows/winrt/MetroApp.cpp +++ b/widget/windows/winrt/MetroApp.cpp @@ -52,6 +52,7 @@ MetroApp::CreateView(ABI::Windows::ApplicationModel::Core::IFrameworkView **aVie LogFunction(); + sFrameworkView.Get()->AddRef(); *aViewProvider = sFrameworkView.Get(); return !sFrameworkView ? E_FAIL : S_OK; } @@ -101,10 +102,14 @@ MetroApp::ShutdownXPCOM() mozilla::widget::StopAudioSession(); - sCoreApp->remove_Suspending(mSuspendEvent); - sCoreApp->remove_Resuming(mResumeEvent); + if (sCoreApp) { + sCoreApp->remove_Suspending(mSuspendEvent); + sCoreApp->remove_Resuming(mResumeEvent); + } - MetroApp::GetView()->ShutdownXPCOM(); + if (sFrameworkView) { + sFrameworkView->ShutdownXPCOM(); + } // Shut down xpcom XRE_metroShutdown(); @@ -124,14 +129,6 @@ MetroApp::CoreExit() } } -// static -FrameworkView* -MetroApp::GetView() -{ - NS_ASSERTION(sFrameworkView, "view has not been created."); - return sFrameworkView.Get(); -} - //////////////////////////////////////////////////// // MetroApp events @@ -164,7 +161,10 @@ void MetroApp::SetBaseWidget(MetroWidget* aPtr) { LogThread(); + NS_ASSERTION(aPtr, "setting null base widget?"); + + // Both of these calls AddRef the ptr we pass in aPtr->SetView(sFrameworkView.Get()); sFrameworkView->SetWidget(aPtr); } @@ -231,8 +231,6 @@ XRE_MetroCoreApplicationRun() return false; } - sFrameworkView = Make(sMetroApp.Get()); - // Perform any cleanup for unclean shutdowns here, such as when the background session // is closed via the appbar on the left when outside of Metro. Windows restarts the // process solely for cleanup reasons. @@ -253,11 +251,12 @@ XRE_MetroCoreApplicationRun() return false; } + sFrameworkView = Make(sMetroApp.Get()); hr = sCoreApp->Run(sMetroApp.Get()); + sFrameworkView = nullptr; Log(L"Exiting CoreApplication::Run"); - sFrameworkView = nullptr; sCoreApp = nullptr; sMetroApp = nullptr; diff --git a/widget/windows/winrt/MetroApp.h b/widget/windows/winrt/MetroApp.h index 8c94f3e8b92c..b6fa1dbbc8ab 100644 --- a/widget/windows/winrt/MetroApp.h +++ b/widget/windows/winrt/MetroApp.h @@ -48,7 +48,6 @@ public: void ShutdownXPCOM(); // Shared pointers between framework and widget - static FrameworkView* GetView(); static void SetBaseWidget(MetroWidget* aPtr); static void PostSuspendResumeProcessNotification(bool aIsSuspend); static void PostSleepWakeNotification(bool aIsSuspend); diff --git a/widget/windows/winrt/nsWinMetroUtils.cpp b/widget/windows/winrt/nsWinMetroUtils.cpp index b303479ea3b5..0f8e06ca16fa 100644 --- a/widget/windows/winrt/nsWinMetroUtils.cpp +++ b/widget/windows/winrt/nsWinMetroUtils.cpp @@ -28,6 +28,7 @@ namespace widget { namespace winrt { extern ComPtr sMetroApp; extern nsTArray* sSettingsArray; +extern ComPtr sFrameworkView; } } } namespace mozilla { @@ -412,12 +413,11 @@ nsWinMetroUtils::GetHandPreference(int32_t *aHandPreference) NS_IMETHODIMP nsWinMetroUtils::GetActivationURI(nsAString &aActivationURI) { - FrameworkView *view = MetroApp::GetView(); - if (!view) { + if (!sFrameworkView) { NS_WARNING("GetActivationURI used before view is created!"); return NS_OK; } - view->GetActivationURI(aActivationURI); + sFrameworkView->GetActivationURI(aActivationURI); return NS_OK; } From db56ef4064993ed71324aae7f9bb36127ed113ea Mon Sep 17 00:00:00 2001 From: Trevor Saunders Date: Sun, 18 Nov 2012 07:37:19 -0500 Subject: [PATCH 068/129] bug 809871 - patch 1/3 - nsTreeColumns should store nsTreeBodyFrame* r=mats --- layout/xul/tree/nsTreeBodyFrame.cpp | 3 +-- layout/xul/tree/nsTreeBodyFrame.h | 6 +++--- layout/xul/tree/nsTreeColumns.cpp | 15 ++++----------- layout/xul/tree/nsTreeColumns.h | 6 +++--- 4 files changed, 11 insertions(+), 19 deletions(-) diff --git a/layout/xul/tree/nsTreeBodyFrame.cpp b/layout/xul/tree/nsTreeBodyFrame.cpp index 7c88a2a12e71..343407058770 100644 --- a/layout/xul/tree/nsTreeBodyFrame.cpp +++ b/layout/xul/tree/nsTreeBodyFrame.cpp @@ -126,7 +126,7 @@ nsTreeBodyFrame::nsTreeBodyFrame(nsIPresShell* aPresShell, nsStyleContext* aCont mHorizontalOverflow(false), mReflowCallbackPosted(false) { - mColumns = new nsTreeColumns(nullptr); + mColumns = new nsTreeColumns(this); } // Destructor @@ -326,7 +326,6 @@ nsTreeBodyFrame::EnsureBoxObject() ->GetCachedTreeBody(); ENSURE_TRUE(!innerTreeBoxObject || innerTreeBoxObject == this); mTreeBoxObject = realTreeBoxObject; - mColumns->SetTree(mTreeBoxObject); } } } diff --git a/layout/xul/tree/nsTreeBodyFrame.h b/layout/xul/tree/nsTreeBodyFrame.h index a3744758db69..c53617c49bb5 100644 --- a/layout/xul/tree/nsTreeBodyFrame.h +++ b/layout/xul/tree/nsTreeBodyFrame.h @@ -153,6 +153,9 @@ public: nsITreeBoxObject* GetTreeBoxObject() const { return mTreeBoxObject; } + // Get the base element, or - nsIContent* GetBaseElement(); - nsresult GetCellWidth(int32_t aRow, nsTreeColumn* aCol, nsRenderingContext* aRenderingContext, nscoord& aDesiredSize, nscoord& aCurrentSize); diff --git a/layout/xul/tree/nsTreeColumns.cpp b/layout/xul/tree/nsTreeColumns.cpp index a5d97769b21f..f02adfdfacfe 100644 --- a/layout/xul/tree/nsTreeColumns.cpp +++ b/layout/xul/tree/nsTreeColumns.cpp @@ -339,7 +339,7 @@ nsTreeColumn::Invalidate() } -nsTreeColumns::nsTreeColumns(nsITreeBoxObject* aTree) +nsTreeColumns::nsTreeColumns(nsTreeBodyFrame* aTree) : mTree(aTree), mFirstColumn(nullptr) { @@ -365,7 +365,7 @@ NS_IMPL_RELEASE(nsTreeColumns) NS_IMETHODIMP nsTreeColumns::GetTree(nsITreeBoxObject** _retval) { - NS_IF_ADDREF(*_retval = mTree); + NS_IF_ADDREF(*_retval = mTree ? mTree->GetTreeBoxObject() : nullptr); return NS_OK; } @@ -552,10 +552,7 @@ nsTreeColumns::RestoreNaturalOrder() if (!mTree) return NS_OK; - nsCOMPtr boxObject = do_QueryInterface(mTree); - nsCOMPtr element; - boxObject->GetElement(getter_AddRefs(element)); - nsCOMPtr content = do_QueryInterface(element); + nsIContent* content = mTree->GetBaseElement(); // Strong ref, since we'll be setting attributes nsCOMPtr colsContent = @@ -594,11 +591,7 @@ void nsTreeColumns::EnsureColumns() { if (mTree && !mFirstColumn) { - nsCOMPtr boxObject = do_QueryInterface(mTree); - nsCOMPtr treeElement; - boxObject->GetElement(getter_AddRefs(treeElement)); - nsCOMPtr treeContent = do_QueryInterface(treeElement); - + nsIContent* treeContent = mTree->GetBaseElement(); nsIContent* colsContent = nsTreeUtils::GetDescendantChild(treeContent, nsGkAtoms::treecols); if (!colsContent) diff --git a/layout/xul/tree/nsTreeColumns.h b/layout/xul/tree/nsTreeColumns.h index bd186fce6293..3ef087501eab 100644 --- a/layout/xul/tree/nsTreeColumns.h +++ b/layout/xul/tree/nsTreeColumns.h @@ -117,7 +117,7 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsTreeColumn, NS_TREECOLUMN_IMPL_CID) class nsTreeColumns MOZ_FINAL : public nsITreeColumns { public: - nsTreeColumns(nsITreeBoxObject* aTree); + nsTreeColumns(nsTreeBodyFrame* aTree); ~nsTreeColumns(); NS_DECL_ISUPPORTS @@ -145,7 +145,7 @@ public: friend class nsTreeBodyFrame; protected: - void SetTree(nsITreeBoxObject* aTree) { mTree = aTree; } + void SetTree(nsTreeBodyFrame* aTree) { mTree = aTree; } // Builds our cache of column info. void EnsureColumns(); @@ -154,7 +154,7 @@ protected: nsTreeColumn* GetPrimaryColumn(); private: - nsITreeBoxObject* mTree; + nsTreeBodyFrame* mTree; /** * The first column in the list of columns. All of the columns are supposed From 603a38f6166638329bf074d52e2ebb5139ca6590 Mon Sep 17 00:00:00 2001 From: Trevor Saunders Date: Sun, 18 Nov 2012 07:40:17 -0500 Subject: [PATCH 069/129] bug 809871 - part 2/3 - outparamdel some nsTreeBodyFrame methods r=mats --- layout/xul/tree/nsTreeBodyFrame.cpp | 38 ++++------------------------- layout/xul/tree/nsTreeBodyFrame.h | 21 ++++++++++------ layout/xul/tree/nsTreeBoxObject.cpp | 8 +++--- layout/xul/tree/nsTreeColFrame.cpp | 2 +- 4 files changed, 23 insertions(+), 46 deletions(-) diff --git a/layout/xul/tree/nsTreeBodyFrame.cpp b/layout/xul/tree/nsTreeBodyFrame.cpp index 343407058770..47be33c04a62 100644 --- a/layout/xul/tree/nsTreeBodyFrame.cpp +++ b/layout/xul/tree/nsTreeBodyFrame.cpp @@ -546,13 +546,6 @@ nsTreeBodyFrame::GetTreeBody(nsIDOMElement** aElement) return mContent->QueryInterface(NS_GET_IID(nsIDOMElement), (void**)aElement); } -nsresult -nsTreeBodyFrame::GetColumns(nsITreeColumns** aColumns) -{ - NS_IF_ADDREF(*aColumns = mColumns); - return NS_OK; -} - nsresult nsTreeBodyFrame::GetRowHeight(int32_t* _retval) { @@ -567,20 +560,6 @@ nsTreeBodyFrame::GetRowWidth(int32_t *aRowWidth) return NS_OK; } -nsresult -nsTreeBodyFrame::GetFirstVisibleRow(int32_t *_retval) -{ - *_retval = mTopRowIndex; - return NS_OK; -} - -nsresult -nsTreeBodyFrame::GetLastVisibleRow(int32_t *_retval) -{ - *_retval = GetLastVisibleRow(); - return NS_OK; -} - nsresult nsTreeBodyFrame::GetHorizontalPosition(int32_t *aHorizontalPosition) { @@ -588,13 +567,6 @@ nsTreeBodyFrame::GetHorizontalPosition(int32_t *aHorizontalPosition) return NS_OK; } -nsresult -nsTreeBodyFrame::GetPageLength(int32_t *_retval) -{ - *_retval = mPageLength; - return NS_OK; -} - nsresult nsTreeBodyFrame::GetSelectionRegion(nsIScriptableRegion **aRegion) { @@ -619,7 +591,7 @@ nsTreeBodyFrame::GetSelectionRegion(nsIScriptableRegion **aRegion) int32_t x = nsPresContext::AppUnitsToIntCSSPixels(origin.x); int32_t y = nsPresContext::AppUnitsToIntCSSPixels(origin.y); int32_t top = y; - int32_t end = GetLastVisibleRow(); + int32_t end = LastVisibleRow(); int32_t rowHeight = nsPresContext::AppUnitsToIntCSSPixels(mRowHeight); for (int32_t i = mTopRowIndex; i <= end; i++) { bool isSelected; @@ -733,7 +705,7 @@ nsTreeBodyFrame::InvalidateRange(int32_t aStart, int32_t aEnd) if (aStart == aEnd) return InvalidateRow(aStart); - int32_t last = GetLastVisibleRow(); + int32_t last = LastVisibleRow(); if (aStart > aEnd || aEnd < mTopRowIndex || aStart > last) return NS_OK; @@ -770,7 +742,7 @@ nsTreeBodyFrame::InvalidateColumnRange(int32_t aStart, int32_t aEnd, nsITreeColu if (aStart == aEnd) return InvalidateCell(aStart, col); - int32_t last = GetLastVisibleRow(); + int32_t last = LastVisibleRow(); if (aStart > aEnd || aEnd < mTopRowIndex || aStart > last) return NS_OK; @@ -1827,8 +1799,8 @@ nsTreeBodyFrame::RowCountChanged(int32_t aIndex, int32_t aCount) NS_ASSERTION(rowCount == mRowCount, "row count did not change by the amount suggested, check caller"); #endif - int32_t count = DeprecatedAbs(aCount); - int32_t last = GetLastVisibleRow(); + int32_t count = Abs(aCount); + int32_t last = LastVisibleRow(); if (aIndex >= mTopRowIndex && aIndex <= last) InvalidateRange(aIndex, last); diff --git a/layout/xul/tree/nsTreeBodyFrame.h b/layout/xul/tree/nsTreeBodyFrame.h index c53617c49bb5..52f13a573563 100644 --- a/layout/xul/tree/nsTreeBodyFrame.h +++ b/layout/xul/tree/nsTreeBodyFrame.h @@ -60,7 +60,16 @@ public: nsresult OnImageIsAnimated(imgIRequest* aRequest); // non-virtual signatures like nsITreeBodyFrame - nsresult GetColumns(nsITreeColumns **aColumns); + already_AddRefed Columns() const + { + nsRefPtr cols = mColumns; + return cols.forget(); + } + already_AddRefed GetExistingView() const + { + nsCOMPtr view = mView; + return view.forget(); + } nsresult GetView(nsITreeView **aView); nsresult SetView(nsITreeView *aView); nsresult GetFocused(bool *aFocused); @@ -70,9 +79,9 @@ public: nsresult GetRowWidth(int32_t *aValue); nsresult GetHorizontalPosition(int32_t *aValue); nsresult GetSelectionRegion(nsIScriptableRegion **aRegion); - nsresult GetFirstVisibleRow(int32_t *aValue); - nsresult GetLastVisibleRow(int32_t *aValue); - nsresult GetPageLength(int32_t *aValue); + int32_t FirstVisibleRow() const { return mTopRowIndex; } + int32_t LastVisibleRow() const { return mTopRowIndex + mPageLength; } + int32_t PageLength() const { return mPageLength; } nsresult EnsureRowIsVisible(int32_t aRow); nsresult EnsureCellIsVisible(int32_t aRow, nsITreeColumn *aCol); nsresult ScrollToRow(int32_t aRow); @@ -256,10 +265,6 @@ protected: const nsRect& aDirtyRect); - int32_t GetLastVisibleRow() { - return mTopRowIndex + mPageLength; - } - // An internal hit test. aX and aY are expected to be in twips in the // coordinate system of this frame. int32_t GetRowAt(nscoord aX, nscoord aY); diff --git a/layout/xul/tree/nsTreeBoxObject.cpp b/layout/xul/tree/nsTreeBoxObject.cpp index 4c012c0d959c..e00c8a3e25ff 100644 --- a/layout/xul/tree/nsTreeBoxObject.cpp +++ b/layout/xul/tree/nsTreeBoxObject.cpp @@ -216,7 +216,7 @@ NS_IMETHODIMP nsTreeBoxObject::GetColumns(nsITreeColumns** aColumns) *aColumns = nullptr; nsTreeBodyFrame* body = GetTreeBody(); if (body) - return body->GetColumns(aColumns); + *aColumns = body->Columns().get(); return NS_OK; } @@ -243,7 +243,7 @@ NS_IMETHODIMP nsTreeBoxObject::GetFirstVisibleRow(int32_t *aFirstVisibleRow) *aFirstVisibleRow = 0; nsTreeBodyFrame* body = GetTreeBody(); if (body) - return body->GetFirstVisibleRow(aFirstVisibleRow); + *aFirstVisibleRow = body->FirstVisibleRow(); return NS_OK; } @@ -252,7 +252,7 @@ NS_IMETHODIMP nsTreeBoxObject::GetLastVisibleRow(int32_t *aLastVisibleRow) *aLastVisibleRow = 0; nsTreeBodyFrame* body = GetTreeBody(); if (body) - return body->GetLastVisibleRow(aLastVisibleRow); + *aLastVisibleRow = body->LastVisibleRow(); return NS_OK; } @@ -270,7 +270,7 @@ NS_IMETHODIMP nsTreeBoxObject::GetPageLength(int32_t *aPageLength) *aPageLength = 0; nsTreeBodyFrame* body = GetTreeBody(); if (body) - return body->GetPageLength(aPageLength); + *aPageLength = body->PageLength(); return NS_OK; } diff --git a/layout/xul/tree/nsTreeColFrame.cpp b/layout/xul/tree/nsTreeColFrame.cpp index bb99d3ced6e9..2a958a0b1fa3 100644 --- a/layout/xul/tree/nsTreeColFrame.cpp +++ b/layout/xul/tree/nsTreeColFrame.cpp @@ -189,7 +189,7 @@ nsTreeColFrame::InvalidateColumns(bool aCanWalkFrameTree) } else { nsTreeBodyFrame* body = static_cast(treeBoxObject)->GetCachedTreeBody(); if (body) { - body->GetColumns(getter_AddRefs(columns)); + columns = body->Columns(); } } From a99c8f2af290f23a75eff8d5c01db721933660c3 Mon Sep 17 00:00:00 2001 From: Trevor Saunders Date: Mon, 19 Nov 2012 15:36:05 -0500 Subject: [PATCH 070/129] bug 809871 - patch 3/3 - xul tree accessible creation flushes layout r=surkov --- accessible/src/base/Makefile.in | 1 + .../src/base/nsAccessibilityService.cpp | 20 +++++++------ .../windows/msaa/XULTreeGridAccessibleWrap.h | 5 ++-- accessible/src/xul/Makefile.in | 1 + accessible/src/xul/XULTreeAccessible.cpp | 28 +++++++++++-------- accessible/src/xul/XULTreeAccessible.h | 5 +++- accessible/src/xul/XULTreeGridAccessible.cpp | 11 -------- accessible/src/xul/XULTreeGridAccessible.h | 5 +++- .../events/test_focus_autocomplete.xul | 3 -- .../tests/mochitest/tree/test_txtctrl.xul | 5 ---- 10 files changed, 42 insertions(+), 42 deletions(-) diff --git a/accessible/src/base/Makefile.in b/accessible/src/base/Makefile.in index ca8df9514c57..403ef9591d1e 100644 --- a/accessible/src/base/Makefile.in +++ b/accessible/src/base/Makefile.in @@ -85,6 +85,7 @@ LOCAL_INCLUDES += \ -I$(srcdir)/../../../layout/style \ -I$(srcdir)/../../../layout/svg \ -I$(srcdir)/../../../layout/xul/base/src \ + -I$(srcdir)/../../../layout/xul/tree/ \ $(NULL) ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2) diff --git a/accessible/src/base/nsAccessibilityService.cpp b/accessible/src/base/nsAccessibilityService.cpp index c3f9a1950c77..c624ff0be2e3 100644 --- a/accessible/src/base/nsAccessibilityService.cpp +++ b/accessible/src/base/nsAccessibilityService.cpp @@ -57,6 +57,9 @@ #include "nsNPAPIPluginInstance.h" #include "nsObjectFrame.h" #include "nsSVGPathGeometryFrame.h" +#include "nsTreeBodyFrame.h" +#include "nsTreeColumns.h" +#include "nsTreeUtils.h" #include "mozilla/dom/Element.h" #include "mozilla/Preferences.h" #include "mozilla/Services.h" @@ -1572,27 +1575,28 @@ already_AddRefed nsAccessibilityService::CreateAccessibleForXULTree(nsIContent* aContent, DocAccessible* aDoc) { - nsCOMPtr treeBoxObj = nsCoreUtils::GetTreeBoxObject(aContent); - if (!treeBoxObj) + nsIContent* child = nsTreeUtils::GetDescendantChild(aContent, + nsGkAtoms::treechildren); + if (!child) return nullptr; - nsCOMPtr treeColumns; - treeBoxObj->GetColumns(getter_AddRefs(treeColumns)); - if (!treeColumns) + nsTreeBodyFrame* treeFrame = do_QueryFrame(child->GetPrimaryFrame()); + if (!treeFrame) return nullptr; + nsRefPtr treeCols = treeFrame->Columns(); int32_t count = 0; - treeColumns->GetCount(&count); + treeCols->GetCount(&count); // Outline of list accessible. if (count == 1) { - Accessible* accessible = new XULTreeAccessible(aContent, aDoc); + Accessible* accessible = new XULTreeAccessible(aContent, aDoc, treeFrame); NS_ADDREF(accessible); return accessible; } // Table or tree table accessible. - Accessible* accessible = new XULTreeGridAccessibleWrap(aContent, aDoc); + Accessible* accessible = new XULTreeGridAccessibleWrap(aContent, aDoc, treeFrame); NS_ADDREF(accessible); return accessible; } diff --git a/accessible/src/windows/msaa/XULTreeGridAccessibleWrap.h b/accessible/src/windows/msaa/XULTreeGridAccessibleWrap.h index 98e424f967ab..374432dc6051 100644 --- a/accessible/src/windows/msaa/XULTreeGridAccessibleWrap.h +++ b/accessible/src/windows/msaa/XULTreeGridAccessibleWrap.h @@ -22,8 +22,9 @@ class XULTreeGridAccessibleWrap : public XULTreeGridAccessible, public ia2AccessibleTable { public: - XULTreeGridAccessibleWrap(nsIContent* aContent, DocAccessible* aDoc) : - XULTreeGridAccessible(aContent, aDoc), ia2AccessibleTable(this) {} + XULTreeGridAccessibleWrap(nsIContent* aContent, DocAccessible* aDoc, + nsTreeBodyFrame* aTree) : + XULTreeGridAccessible(aContent, aDoc, aTree), ia2AccessibleTable(this) {} // IUnknown DECL_IUNKNOWN_INHERITED diff --git a/accessible/src/xul/Makefile.in b/accessible/src/xul/Makefile.in index ff9cfc166603..87f204f575c6 100644 --- a/accessible/src/xul/Makefile.in +++ b/accessible/src/xul/Makefile.in @@ -43,6 +43,7 @@ LOCAL_INCLUDES = \ -I$(srcdir)/../xpcom \ -I$(srcdir)/../../../layout/generic \ -I$(srcdir)/../../../layout/xul/base/src \ + -I$(srcdir)/../../../layout/xul/tree// \ $(NULL) ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2) diff --git a/accessible/src/xul/XULTreeAccessible.cpp b/accessible/src/xul/XULTreeAccessible.cpp index 5b1f7c4cc76f..2291a67106c1 100644 --- a/accessible/src/xul/XULTreeAccessible.cpp +++ b/accessible/src/xul/XULTreeAccessible.cpp @@ -27,6 +27,9 @@ #include "nsIDOMXULTreeElement.h" #include "nsITreeSelection.h" #include "nsIMutableArray.h" +#include "nsTreeBodyFrame.h" +#include "nsTreeColumns.h" +#include "nsTreeUtils.h" using namespace mozilla::a11y; @@ -35,21 +38,19 @@ using namespace mozilla::a11y; //////////////////////////////////////////////////////////////////////////////// XULTreeAccessible:: - XULTreeAccessible(nsIContent* aContent, DocAccessible* aDoc) : + XULTreeAccessible(nsIContent* aContent, DocAccessible* aDoc, + nsTreeBodyFrame* aTreeFrame) : AccessibleWrap(aContent, aDoc) { mType = eXULTreeType; mGenericTypes |= eSelect; + nsCOMPtr view = aTreeFrame->GetExistingView(); + mTreeView = view; + mTree = nsCoreUtils::GetTreeBoxObject(aContent); NS_ASSERTION(mTree, "Can't get mTree!\n"); - if (mTree) { - nsCOMPtr treeView; - mTree->GetView(getter_AddRefs(treeView)); - mTreeView = treeView; - } - nsIContent* parentContent = mContent->GetParent(); if (parentContent) { nsCOMPtr autoCompletePopupElm = @@ -159,11 +160,16 @@ XULTreeAccessible::NativeRole() // No primary column means we're in a list. In fact, history and mail turn off // the primary flag when switching to a flat view. - nsCOMPtr cols; - mTree->GetColumns(getter_AddRefs(cols)); + nsIContent* child = nsTreeUtils::GetDescendantChild(mContent, nsGkAtoms::treechildren); + NS_ASSERTION(child, "tree without treechildren!"); + nsTreeBodyFrame* treeFrame = do_QueryFrame(child->GetPrimaryFrame()); + NS_ASSERTION(treeFrame, "xul tree accessible for tree without a frame!"); + if (!treeFrame) + return roles::LIST; + + nsRefPtr cols = treeFrame->Columns(); nsCOMPtr primaryCol; - if (cols) - cols->GetPrimaryColumn(getter_AddRefs(primaryCol)); + cols->GetPrimaryColumn(getter_AddRefs(primaryCol)); return primaryCol ? roles::OUTLINE : roles::LIST; } diff --git a/accessible/src/xul/XULTreeAccessible.h b/accessible/src/xul/XULTreeAccessible.h index 6c8750bc4a11..c6e987df56c9 100644 --- a/accessible/src/xul/XULTreeAccessible.h +++ b/accessible/src/xul/XULTreeAccessible.h @@ -11,6 +11,8 @@ #include "nsITreeColumns.h" #include "XULListboxAccessible.h" +class nsTreeBodyFrame; + namespace mozilla { namespace a11y { @@ -29,7 +31,8 @@ class XULTreeAccessible : public AccessibleWrap public: using Accessible::GetChildAt; - XULTreeAccessible(nsIContent* aContent, DocAccessible* aDoc); + XULTreeAccessible(nsIContent* aContent, DocAccessible* aDoc, + nsTreeBodyFrame* aTreeframe); // nsISupports and cycle collection NS_DECL_ISUPPORTS_INHERITED diff --git a/accessible/src/xul/XULTreeGridAccessible.cpp b/accessible/src/xul/XULTreeGridAccessible.cpp index 47517c446048..ebb7f245acfb 100644 --- a/accessible/src/xul/XULTreeGridAccessible.cpp +++ b/accessible/src/xul/XULTreeGridAccessible.cpp @@ -20,17 +20,6 @@ using namespace mozilla::a11y; -//////////////////////////////////////////////////////////////////////////////// -// XULTreeGridAccessible -//////////////////////////////////////////////////////////////////////////////// - -XULTreeGridAccessible:: - XULTreeGridAccessible(nsIContent* aContent, DocAccessible* aDoc) : - XULTreeAccessible(aContent, aDoc), xpcAccessibleTable(this) -{ - mGenericTypes |= eTable; -} - //////////////////////////////////////////////////////////////////////////////// // XULTreeGridAccessible: nsISupports implementation diff --git a/accessible/src/xul/XULTreeGridAccessible.h b/accessible/src/xul/XULTreeGridAccessible.h index 0ae8d97a4a1c..341cc13c2801 100644 --- a/accessible/src/xul/XULTreeGridAccessible.h +++ b/accessible/src/xul/XULTreeGridAccessible.h @@ -24,7 +24,10 @@ class XULTreeGridAccessible : public XULTreeAccessible, public TableAccessible { public: - XULTreeGridAccessible(nsIContent* aContent, DocAccessible* aDoc); + XULTreeGridAccessible(nsIContent* aContent, DocAccessible* aDoc, + nsTreeBodyFrame* aTreeFrame) : + XULTreeAccessible(aContent, aDoc, aTreeFrame), xpcAccessibleTable(this) + { mGenericTypes |= eTable; } // nsISupports NS_DECL_ISUPPORTS_INHERITED diff --git a/accessible/tests/mochitest/events/test_focus_autocomplete.xul b/accessible/tests/mochitest/events/test_focus_autocomplete.xul index 51da3e4c3531..5e0e6fb8ee77 100644 --- a/accessible/tests/mochitest/events/test_focus_autocomplete.xul +++ b/accessible/tests/mochitest/events/test_focus_autocomplete.xul @@ -32,9 +32,6 @@ + + diff --git a/content/base/test/file_mixed_content_frameNavigation_grandchild.html b/content/base/test/file_mixed_content_frameNavigation_grandchild.html new file mode 100644 index 000000000000..eb49f78073b1 --- /dev/null +++ b/content/base/test/file_mixed_content_frameNavigation_grandchild.html @@ -0,0 +1,54 @@ + + + + + + Tests for Mixed Content Frame Navigation + + + + + + + diff --git a/content/base/test/file_mixed_content_frameNavigation_innermost.html b/content/base/test/file_mixed_content_frameNavigation_innermost.html new file mode 100644 index 000000000000..4fbdd0356580 --- /dev/null +++ b/content/base/test/file_mixed_content_frameNavigation_innermost.html @@ -0,0 +1,61 @@ + + + +
+ + + diff --git a/content/base/test/file_mixed_content_frameNavigation_secure.html b/content/base/test/file_mixed_content_frameNavigation_secure.html new file mode 100644 index 000000000000..786bfd7c7cad --- /dev/null +++ b/content/base/test/file_mixed_content_frameNavigation_secure.html @@ -0,0 +1,75 @@ + + + + + + Tests for Mixed Content Frame Navigation + + +
+ + + + diff --git a/content/base/test/file_mixed_content_frameNavigation_secure_grandchild.html b/content/base/test/file_mixed_content_frameNavigation_secure_grandchild.html new file mode 100644 index 000000000000..dbe264ba4346 --- /dev/null +++ b/content/base/test/file_mixed_content_frameNavigation_secure_grandchild.html @@ -0,0 +1,54 @@ + + + + + + Tests for Mixed Content Frame Navigation + + + + + + + diff --git a/content/base/test/test_mixed_content_blocker_frameNavigation.html b/content/base/test/test_mixed_content_blocker_frameNavigation.html new file mode 100644 index 000000000000..188db64e784f --- /dev/null +++ b/content/base/test/test_mixed_content_blocker_frameNavigation.html @@ -0,0 +1,111 @@ + + + + + + Tests for Bug 840388 + + + + + + + +
+ +
+
+ +
+ +

+
+

From 2144eccec0fdd330c3865ddfc7d55d15230dec83 Mon Sep 17 00:00:00 2001
From: Seth Fowler 
Date: Tue, 26 Mar 2013 16:29:12 -0700
Subject: [PATCH 082/129] Bug 826093 (Part 1) - Add ClippedImage. r=joe

---
 image/src/ClippedImage.cpp | 337 +++++++++++++++++++++++++++++++++++++
 image/src/ClippedImage.h   |  86 ++++++++++
 image/src/Makefile.in      |   1 +
 3 files changed, 424 insertions(+)
 create mode 100644 image/src/ClippedImage.cpp
 create mode 100644 image/src/ClippedImage.h

diff --git a/image/src/ClippedImage.cpp b/image/src/ClippedImage.cpp
new file mode 100644
index 000000000000..55afabb8987a
--- /dev/null
+++ b/image/src/ClippedImage.cpp
@@ -0,0 +1,337 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "gfxDrawable.h"
+#include "gfxPlatform.h"
+#include "gfxUtils.h"
+
+#include "ClippedImage.h"
+
+using mozilla::layers::LayerManager;
+using mozilla::layers::ImageContainer;
+
+namespace mozilla {
+namespace image {
+
+class DrawSingleTileCallback : public gfxDrawingCallback
+{
+public:
+  DrawSingleTileCallback(ClippedImage* aImage,
+                         const nsIntRect& aClip,
+                         const nsIntSize& aViewportSize,
+                         const SVGImageContext* aSVGContext,
+                         uint32_t aWhichFrame,
+                         uint32_t aFlags)
+    : mImage(aImage)
+    , mClip(aClip)
+    , mViewportSize(aViewportSize)
+    , mSVGContext(aSVGContext)
+    , mWhichFrame(aWhichFrame)
+    , mFlags(aFlags)
+  {
+    MOZ_ASSERT(mImage, "Must have an image to clip");
+  }
+
+  virtual bool operator()(gfxContext* aContext,
+                          const gfxRect& aFillRect,
+                          const gfxPattern::GraphicsFilter& aFilter,
+                          const gfxMatrix& aTransform)
+  {
+    // Draw the image. |gfxCallbackDrawable| always calls this function with
+    // arguments that guarantee we never tile.
+    mImage->DrawSingleTile(aContext, aFilter, aTransform, aFillRect, mClip,
+                           mViewportSize, mSVGContext, mWhichFrame, mFlags);
+
+    return true;
+  }
+
+private:
+  nsRefPtr mImage;
+  const nsIntRect        mClip;
+  const nsIntSize        mViewportSize;
+  const SVGImageContext* mSVGContext;
+  const uint32_t         mWhichFrame;
+  const uint32_t         mFlags;
+};
+
+ClippedImage::ClippedImage(Image* aImage,
+                           nsIntRect aClip)
+  : ImageWrapper(aImage)
+  , mClip(aClip)
+{
+  MOZ_ASSERT(aImage != nullptr, "ClippedImage requires an existing Image");
+}
+
+bool
+ClippedImage::ShouldClip()
+{
+  // We need to evaluate the clipping region against the image's width and height
+  // once they're available to determine if it's valid and whether we actually
+  // need to do any work. We may fail if the image's width and height aren't
+  // available yet, in which case we'll try again later.
+  if (mShouldClip.empty()) {
+    int32_t width, height;
+    if (InnerImage()->HasError()) {
+      // If there's a problem with the inner image we'll let it handle everything.
+      mShouldClip.construct(false);
+    } else if (NS_SUCCEEDED(InnerImage()->GetWidth(&width)) && width > 0 &&
+               NS_SUCCEEDED(InnerImage()->GetHeight(&height)) && height > 0) {
+      // Clamp the clipping region to the size of the underlying image.
+      mClip = mClip.Intersect(nsIntRect(0, 0, width, height));
+
+      // If the clipping region is the same size as the underlying image we
+      // don't have to do anything.
+      mShouldClip.construct(!mClip.IsEqualInterior(nsIntRect(0, 0, width, height)));
+    } else if (InnerImage()->GetStatusTracker().IsLoading()) {
+      // The image just hasn't finished loading yet. We don't yet know whether
+      // clipping with be needed or not for now. Just return without memoizing
+      // anything.
+      return false;
+    } else {
+      // We have a fully loaded image without a clearly defined width and
+      // height. This can happen with SVG images.
+      mShouldClip.construct(false);
+    }
+  }
+
+  MOZ_ASSERT(!mShouldClip.empty(), "Should have computed a result");
+  return mShouldClip.ref();
+}
+
+NS_IMPL_ISUPPORTS1(ClippedImage, imgIContainer)
+
+nsIntRect
+ClippedImage::FrameRect(uint32_t aWhichFrame)
+{
+  if (!ShouldClip()) {
+    return InnerImage()->FrameRect(aWhichFrame);
+  }
+
+  return nsIntRect(0, 0, mClip.width, mClip.height);
+}
+
+NS_IMETHODIMP
+ClippedImage::GetWidth(int32_t* aWidth)
+{
+  if (!ShouldClip()) {
+    return InnerImage()->GetWidth(aWidth);
+  }
+
+  *aWidth = mClip.width;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+ClippedImage::GetHeight(int32_t* aHeight)
+{
+  if (!ShouldClip()) {
+    return InnerImage()->GetHeight(aHeight);
+  }
+
+  *aHeight = mClip.height;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+ClippedImage::GetIntrinsicSize(nsSize* aSize)
+{
+  if (!ShouldClip()) {
+    return InnerImage()->GetIntrinsicSize(aSize);
+  }
+
+  *aSize = nsSize(mClip.width, mClip.height);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+ClippedImage::GetIntrinsicRatio(nsSize* aRatio)
+{
+  if (!ShouldClip()) {
+    return InnerImage()->GetIntrinsicRatio(aRatio);
+  }
+
+  *aRatio = nsSize(mClip.width, mClip.height);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+ClippedImage::GetFrame(uint32_t aWhichFrame,
+                       uint32_t aFlags,
+                       gfxASurface** _retval)
+{
+  if (!ShouldClip()) {
+    return InnerImage()->GetFrame(aWhichFrame, aFlags, _retval);
+  }
+
+  // Create a surface to draw into.
+  gfxImageSurface::gfxImageFormat format = gfxASurface::ImageFormatARGB32;
+  nsRefPtr surface = gfxPlatform::GetPlatform()
+    ->CreateOffscreenSurface(gfxIntSize(mClip.width, mClip.height),
+                             gfxImageSurface::ContentFromFormat(format));
+  // Create our callback.
+  nsRefPtr drawTileCallback =
+    new DrawSingleTileCallback(this, mClip, mClip.Size(), nullptr, aWhichFrame, aFlags);
+  nsRefPtr drawable =
+    new gfxCallbackDrawable(drawTileCallback, mClip.Size());
+
+  // Actually draw. The callback will end up invoking DrawSingleTile.
+  nsRefPtr ctx = new gfxContext(surface);
+  gfxRect imageRect(0, 0, mClip.width, mClip.height);
+  gfxUtils::DrawPixelSnapped(ctx, drawable, gfxMatrix(),
+                             imageRect, imageRect, imageRect, imageRect,
+                             gfxASurface::ImageFormatARGB32, gfxPattern::FILTER_FAST);
+
+  *_retval = surface.forget().get();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+ClippedImage::GetImageContainer(LayerManager* aManager, ImageContainer** _retval)
+{
+  // XXX(seth): We currently don't have a way of clipping the result of
+  // GetImageContainer. We work around this by always returning null, but if it
+  // ever turns out that ClippedImage is widely used on codepaths that can
+  // actually benefit from GetImageContainer, it would be a good idea to fix
+  // that method for performance reasons.
+
+  *_retval = nullptr;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+ClippedImage::ExtractFrame(uint32_t /* aWhichFrame */,
+                           const nsIntRect& /* aRegion */,
+                           uint32_t /* aFlags */,
+                           imgIContainer** /* _retval */)
+{
+  // XXX(seth): This method has to be present in this patch because we haven't
+  // gotten to the point where we can remove ExtractFrame yet, but implementing
+  // it would be a waste of effort.
+  MOZ_ASSERT(false, "ClippedImage::ExtractFrame shouldn't be called");
+  return NS_ERROR_NOT_AVAILABLE;
+}
+
+bool
+ClippedImage::MustCreateSurface(gfxContext* aContext,
+                                const gfxMatrix& aTransform,
+                                const gfxRect& aSourceRect,
+                                const nsIntRect& aSubimage,
+                                const uint32_t aFlags) const
+{
+  gfxRect gfxImageRect(0, 0, mClip.width, mClip.height);
+  nsIntRect intImageRect(0, 0, mClip.width, mClip.height);
+  bool willTile = !gfxImageRect.Contains(aSourceRect) &&
+                  !(aFlags & imgIContainer::FLAG_CLAMP);
+  bool willResample = (aContext->CurrentMatrix().HasNonIntegerTranslation() ||
+                       aTransform.HasNonIntegerTranslation()) &&
+                      (willTile || !aSubimage.Contains(intImageRect));
+  return willTile || willResample;
+}
+
+NS_IMETHODIMP
+ClippedImage::Draw(gfxContext* aContext,
+                   gfxPattern::GraphicsFilter aFilter,
+                   const gfxMatrix& aUserSpaceToImageSpace,
+                   const gfxRect& aFill,
+                   const nsIntRect& aSubimage,
+                   const nsIntSize& aViewportSize,
+                   const SVGImageContext* aSVGContext,
+                   uint32_t aWhichFrame,
+                   uint32_t aFlags)
+{
+  if (!ShouldClip()) {
+    return InnerImage()->Draw(aContext, aFilter, aUserSpaceToImageSpace,
+                              aFill, aSubimage, aViewportSize, aSVGContext,
+                              aWhichFrame, aFlags);
+  }
+
+  // Check for tiling. If we need to tile then we need to create a
+  // gfxCallbackDrawable to handle drawing for us.
+  gfxRect sourceRect = aUserSpaceToImageSpace.Transform(aFill);
+  if (MustCreateSurface(aContext, aUserSpaceToImageSpace, sourceRect, aSubimage, aFlags)) {
+    // Create a temporary surface containing a single tile of this image.
+    // GetFrame will call DrawSingleTile internally.
+    nsRefPtr surface;
+    GetFrame(aWhichFrame, aFlags, getter_AddRefs(surface));
+    NS_ENSURE_TRUE(surface, NS_ERROR_FAILURE);
+
+    // Create a drawable from that surface.
+    nsRefPtr drawable =
+      new gfxSurfaceDrawable(surface, gfxIntSize(mClip.width, mClip.height));
+
+    // Draw.
+    gfxRect imageRect(0, 0, mClip.width, mClip.height);
+    gfxRect subimage(aSubimage.x, aSubimage.y, aSubimage.width, aSubimage.height);
+    gfxUtils::DrawPixelSnapped(aContext, drawable, aUserSpaceToImageSpace,
+                               subimage, sourceRect, imageRect, aFill,
+                               gfxASurface::ImageFormatARGB32, aFilter);
+
+    return NS_OK;
+  }
+
+  // Determine the appropriate subimage for the inner image.
+  nsIntRect innerSubimage(aSubimage);
+  innerSubimage.MoveBy(mClip.x, mClip.y);
+  innerSubimage.Intersect(mClip);
+
+  return DrawSingleTile(aContext, aFilter, aUserSpaceToImageSpace, aFill, innerSubimage,
+                        aViewportSize, aSVGContext, aWhichFrame, aFlags);
+}
+
+gfxFloat
+ClippedImage::ClampFactor(const gfxFloat aToClamp, const int aReference) const
+{
+  return aToClamp > aReference ? aReference / aToClamp
+                               : 1.0;
+}
+
+nsresult
+ClippedImage::DrawSingleTile(gfxContext* aContext,
+                             gfxPattern::GraphicsFilter aFilter,
+                             const gfxMatrix& aUserSpaceToImageSpace,
+                             const gfxRect& aFill,
+                             const nsIntRect& aSubimage,
+                             const nsIntSize& aViewportSize,
+                             const SVGImageContext* aSVGContext,
+                             uint32_t aWhichFrame,
+                             uint32_t aFlags)
+{
+  MOZ_ASSERT(!MustCreateSurface(aContext, aUserSpaceToImageSpace,
+                                aUserSpaceToImageSpace.Transform(aFill),
+                                aSubimage - nsIntPoint(mClip.x, mClip.y), aFlags),
+             "DrawSingleTile shouldn't need to create a surface");
+
+  // Make the viewport reflect the original image's size.
+  nsIntSize viewportSize(aViewportSize);
+  int32_t imgWidth, imgHeight;
+  if (NS_SUCCEEDED(InnerImage()->GetWidth(&imgWidth)) &&
+      NS_SUCCEEDED(InnerImage()->GetHeight(&imgHeight))) {
+    viewportSize = nsIntSize(imgWidth, imgHeight);
+  } else {
+    MOZ_ASSERT(false, "If ShouldClip() led us to draw then we should never get here");
+  }
+
+  // Add a translation to the transform to reflect the clipping region.
+  gfxMatrix transform(aUserSpaceToImageSpace);
+  transform.Multiply(gfxMatrix().Translate(gfxPoint(mClip.x, mClip.y)));
+
+  // "Clamp the source rectangle" to the clipping region's width and height.
+  // Really, this means modifying the transform to get the results we want.
+  gfxRect sourceRect = transform.Transform(aFill);
+  if (sourceRect.width > mClip.width || sourceRect.height > mClip.height) {
+    gfxMatrix clampSource;
+    clampSource.Translate(gfxPoint(sourceRect.x, sourceRect.y));
+    clampSource.Scale(ClampFactor(sourceRect.width, mClip.width),
+                      ClampFactor(sourceRect.height, mClip.height));
+    clampSource.Translate(gfxPoint(-sourceRect.x, -sourceRect.y));
+    transform.Multiply(clampSource);
+  }
+
+  return InnerImage()->Draw(aContext, aFilter, transform, aFill, aSubimage,
+                            viewportSize, aSVGContext, aWhichFrame, aFlags);
+}
+
+} // namespace image
+} // namespace mozilla
diff --git a/image/src/ClippedImage.h b/image/src/ClippedImage.h
new file mode 100644
index 000000000000..b74aa4fa62a3
--- /dev/null
+++ b/image/src/ClippedImage.h
@@ -0,0 +1,86 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef MOZILLA_IMAGELIB_CLIPPEDIMAGE_H_
+#define MOZILLA_IMAGELIB_CLIPPEDIMAGE_H_
+
+#include "ImageWrapper.h"
+
+namespace mozilla {
+namespace image {
+
+class DrawSingleTileCallback;
+
+/**
+ * An Image wrapper that clips an image against a rectangle. Right now only
+ * absolute coordinates in pixels are supported.
+ *
+ * XXX(seth): There a known (performance, not correctness) issue with
+ * GetImageContainer. See the comments for that method for more information.
+ */
+class ClippedImage : public ImageWrapper
+{
+public:
+  NS_DECL_ISUPPORTS
+
+  virtual ~ClippedImage() { }
+
+  virtual nsIntRect FrameRect(uint32_t aWhichFrame) MOZ_OVERRIDE;
+
+  NS_IMETHOD GetWidth(int32_t* aWidth) MOZ_OVERRIDE;
+  NS_IMETHOD GetHeight(int32_t* aHeight) MOZ_OVERRIDE;
+  NS_IMETHOD GetIntrinsicSize(nsSize* aSize) MOZ_OVERRIDE;
+  NS_IMETHOD GetIntrinsicRatio(nsSize* aRatio) MOZ_OVERRIDE;
+  NS_IMETHOD GetFrame(uint32_t aWhichFrame,
+                      uint32_t aFlags,
+                      gfxASurface** _retval) MOZ_OVERRIDE;
+  NS_IMETHOD GetImageContainer(mozilla::layers::LayerManager* aManager,
+                               mozilla::layers::ImageContainer** _retval) MOZ_OVERRIDE;
+  NS_IMETHOD ExtractFrame(uint32_t aWhichFrame,
+                          const nsIntRect& aRegion,
+                          uint32_t aFlags,
+                          imgIContainer** _retval) MOZ_OVERRIDE;
+  NS_IMETHOD Draw(gfxContext* aContext,
+                  gfxPattern::GraphicsFilter aFilter,
+                  const gfxMatrix& aUserSpaceToImageSpace,
+                  const gfxRect& aFill,
+                  const nsIntRect& aSubimage,
+                  const nsIntSize& aViewportSize,
+                  const SVGImageContext* aSVGContext,
+                  uint32_t aWhichFrame,
+                  uint32_t aFlags) MOZ_OVERRIDE;
+
+protected:
+  ClippedImage(Image* aImage, nsIntRect aClip);
+
+private:
+  bool ShouldClip();
+  bool MustCreateSurface(gfxContext* aContext,
+                         const gfxMatrix& aTransform,
+                         const gfxRect& aSourceRect,
+                         const nsIntRect& aSubimage,
+                         const uint32_t aFlags) const;
+  gfxFloat ClampFactor(const gfxFloat aToClamp, const int aReference) const;
+  nsresult DrawSingleTile(gfxContext* aContext,
+                          gfxPattern::GraphicsFilter aFilter,
+                          const gfxMatrix& aUserSpaceToImageSpace,
+                          const gfxRect& aFill,
+                          const nsIntRect& aSubimage,
+                          const nsIntSize& aViewportSize,
+                          const SVGImageContext* aSVGContext,
+                          uint32_t aWhichFrame,
+                          uint32_t aFlags);
+
+  nsIntRect   mClip;              // The region to clip to.
+  Maybe mShouldClip;        // Memoized ShouldClip() if present.
+
+  friend class DrawSingleTileCallback;
+  friend class ImageFactory;
+};
+
+} // namespace image
+} // namespace mozilla
+
+#endif // MOZILLA_IMAGELIB_CLIPPEDIMAGE_H_
diff --git a/image/src/Makefile.in b/image/src/Makefile.in
index fd271061709b..c855fa92318c 100644
--- a/image/src/Makefile.in
+++ b/image/src/Makefile.in
@@ -27,6 +27,7 @@ CPPSRCS		= \
 			ImageFactory.cpp \
                         ImageMetadata.cpp \
 			ImageWrapper.cpp \
+			ClippedImage.cpp \
 			Decoder.cpp \
 			DiscardTracker.cpp \
 			FrozenImage.cpp \

From 485f15bb87bda1f3d2cf082cae2d930289521b8b Mon Sep 17 00:00:00 2001
From: Seth Fowler 
Date: Tue, 26 Mar 2013 16:29:13 -0700
Subject: [PATCH 083/129] Bug 826093 (Part 2) - Create a static utility class
 for image operations. r=joe, sr=bz

---
 image/src/ClippedImage.h      |  2 +-
 image/src/FrozenImage.h       |  2 +-
 image/src/ImageFactory.cpp    |  8 ------
 image/src/ImageFactory.h      |  8 ------
 image/src/ImageOps.cpp        | 48 ++++++++++++++++++++++++++++++++++
 image/src/ImageOps.h          | 49 +++++++++++++++++++++++++++++++++++
 image/src/Makefile.in         |  2 ++
 image/src/imgRequestProxy.cpp |  4 +--
 8 files changed, 103 insertions(+), 20 deletions(-)
 create mode 100644 image/src/ImageOps.cpp
 create mode 100644 image/src/ImageOps.h

diff --git a/image/src/ClippedImage.h b/image/src/ClippedImage.h
index b74aa4fa62a3..305212efcde6 100644
--- a/image/src/ClippedImage.h
+++ b/image/src/ClippedImage.h
@@ -77,7 +77,7 @@ private:
   Maybe mShouldClip;        // Memoized ShouldClip() if present.
 
   friend class DrawSingleTileCallback;
-  friend class ImageFactory;
+  friend class ImageOps;
 };
 
 } // namespace image
diff --git a/image/src/FrozenImage.h b/image/src/FrozenImage.h
index 077caa04027e..b4cc255c839a 100644
--- a/image/src/FrozenImage.h
+++ b/image/src/FrozenImage.h
@@ -62,7 +62,7 @@ protected:
   FrozenImage(Image* aImage) : ImageWrapper(aImage) { }
 
 private:
-  friend class ImageFactory;
+  friend class ImageOps;
 };
 
 } // namespace image
diff --git a/image/src/ImageFactory.cpp b/image/src/ImageFactory.cpp
index e44416b669bb..92ed5a526c4a 100644
--- a/image/src/ImageFactory.cpp
+++ b/image/src/ImageFactory.cpp
@@ -21,7 +21,6 @@
 #include "imgStatusTracker.h"
 #include "RasterImage.h"
 #include "VectorImage.h"
-#include "FrozenImage.h"
 #include "Image.h"
 #include "nsMediaFragmentURIParser.h"
 
@@ -175,13 +174,6 @@ GetContentSize(nsIRequest* aRequest)
   return 0;
 }
 
-/* static */ already_AddRefed
-ImageFactory::Freeze(Image* aImage)
-{
-  nsRefPtr frozenImage = new FrozenImage(aImage);
-  return frozenImage.forget();
-}
-
 /* static */ already_AddRefed
 ImageFactory::CreateRasterImage(nsIRequest* aRequest,
                                 imgStatusTracker* aStatusTracker,
diff --git a/image/src/ImageFactory.h b/image/src/ImageFactory.h
index 716ac9797610..dedac3fb6158 100644
--- a/image/src/ImageFactory.h
+++ b/image/src/ImageFactory.h
@@ -46,14 +46,6 @@ public:
    */
   static already_AddRefed CreateAnonymousImage(const nsCString& aMimeType);
 
-  /**
-   * Creates a version of an existing image which does not animate and is frozen
-   * at the first frame.
-   *
-   * @param aImage         The existing image.
-   */
-  static already_AddRefed Freeze(Image* aImage);
-
 private:
   // Factory functions that create specific types of image containers.
   static already_AddRefed CreateRasterImage(nsIRequest* aRequest,
diff --git a/image/src/ImageOps.cpp b/image/src/ImageOps.cpp
new file mode 100644
index 000000000000..add83a89f990
--- /dev/null
+++ b/image/src/ImageOps.cpp
@@ -0,0 +1,48 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "imgIContainer.h"
+#include "ClippedImage.h"
+#include "FrozenImage.h"
+#include "Image.h"
+
+#include "ImageOps.h"
+
+namespace mozilla {
+namespace image {
+
+/* static */ already_AddRefed
+ImageOps::Freeze(Image* aImage)
+{
+  nsRefPtr frozenImage = new FrozenImage(aImage);
+  return frozenImage.forget();
+}
+
+/* static */ already_AddRefed
+ImageOps::Freeze(imgIContainer* aImage)
+{
+  nsCOMPtr frozenImage =
+    new FrozenImage(static_cast(aImage));
+  return frozenImage.forget();
+}
+
+/* static */ already_AddRefed
+ImageOps::Clip(Image* aImage, nsIntRect aClip)
+{
+  nsRefPtr clippedImage = new ClippedImage(aImage, aClip);
+  return clippedImage.forget();
+}
+
+/* static */ already_AddRefed
+ImageOps::Clip(imgIContainer* aImage, nsIntRect aClip)
+{
+  nsCOMPtr clippedImage =
+    new ClippedImage(static_cast(aImage), aClip);
+  return clippedImage.forget();
+}
+
+} // namespace image
+} // namespace mozilla
diff --git a/image/src/ImageOps.h b/image/src/ImageOps.h
new file mode 100644
index 000000000000..e68571f19a03
--- /dev/null
+++ b/image/src/ImageOps.h
@@ -0,0 +1,49 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef MOZILLA_IMAGELIB_IMAGEOPS_H_
+#define MOZILLA_IMAGELIB_IMAGEOPS_H_
+
+#include "nsCOMPtr.h"
+#include "nsRect.h"
+
+class imgIContainer;
+
+namespace mozilla {
+namespace image {
+
+class Image;
+
+class ImageOps
+{
+public:
+  /**
+   * Creates a version of an existing image which does not animate and is frozen
+   * at the first frame.
+   *
+   * @param aImage         The existing image.
+   */
+  static already_AddRefed Freeze(Image* aImage);
+  static already_AddRefed Freeze(imgIContainer* aImage);
+
+  /**
+   * Creates a clipped version of an existing image. Animation is unaffected.
+   *
+   * @param aImage         The existing image.
+   * @param aClip          The rectangle to clip the image against.
+   */
+  static already_AddRefed Clip(Image* aImage, nsIntRect aClip);
+  static already_AddRefed Clip(imgIContainer* aImage, nsIntRect aClip);
+
+private:
+  // This is a static utility class, so disallow instantiation.
+  virtual ~ImageOps() = 0;
+};
+
+} // namespace image
+} // namespace mozilla
+
+#endif // MOZILLA_IMAGELIB_IMAGEOPS_H_
diff --git a/image/src/Makefile.in b/image/src/Makefile.in
index c855fa92318c..897a40f02bdb 100644
--- a/image/src/Makefile.in
+++ b/image/src/Makefile.in
@@ -20,12 +20,14 @@ FAIL_ON_WARNINGS = 1
 EXPORTS		=  imgLoader.h \
 		   imgRequest.h \
 		   imgRequestProxy.h \
+		   ImageOps.h \
 		   $(NULL)
 
 CPPSRCS		= \
 			Image.cpp \
 			ImageFactory.cpp \
                         ImageMetadata.cpp \
+			ImageOps.cpp \
 			ImageWrapper.cpp \
 			ClippedImage.cpp \
 			Decoder.cpp \
diff --git a/image/src/imgRequestProxy.cpp b/image/src/imgRequestProxy.cpp
index d6ad4a34d0df..d5e995422541 100644
--- a/image/src/imgRequestProxy.cpp
+++ b/image/src/imgRequestProxy.cpp
@@ -18,7 +18,7 @@
 #include "nsCRT.h"
 
 #include "Image.h"
-#include "ImageFactory.h"
+#include "ImageOps.h"
 #include "nsError.h"
 #include "ImageLogging.h"
 
@@ -915,7 +915,7 @@ imgRequestProxy::GetStaticRequest(imgRequestProxy** aReturn)
   }
 
   // We are animated. We need to create a frozen version of this image.
-  nsRefPtr frozenImage = ImageFactory::Freeze(image);
+  nsRefPtr frozenImage = ImageOps::Freeze(image);
 
   // Create a static imgRequestProxy with our new extracted frame.
   nsCOMPtr currentPrincipal;

From 71c2c2b7ae48b412d518d31890c609125d50431e Mon Sep 17 00:00:00 2001
From: Seth Fowler 
Date: Tue, 26 Mar 2013 16:29:13 -0700
Subject: [PATCH 084/129] Bug 826093 (Part 3) - Use ClippedImage instead of
 ExtractFrame for -moz-image-rect. r=bz

---
 layout/base/nsCSSRendering.cpp | 15 +++------------
 1 file changed, 3 insertions(+), 12 deletions(-)

diff --git a/layout/base/nsCSSRendering.cpp b/layout/base/nsCSSRendering.cpp
index f2ccb4e5b984..ec0445e168d4 100644
--- a/layout/base/nsCSSRendering.cpp
+++ b/layout/base/nsCSSRendering.cpp
@@ -30,6 +30,7 @@
 #include "nsIScrollableFrame.h"
 #include "imgIRequest.h"
 #include "imgIContainer.h"
+#include "ImageOps.h"
 #include "nsCSSRendering.h"
 #include "nsCSSColorUtils.h"
 #include "nsITheme.h"
@@ -60,6 +61,7 @@
 
 using namespace mozilla;
 using namespace mozilla::css;
+using mozilla::image::ImageOps;
 
 static int gFrameTreeLockCount = 0;
 
@@ -4293,18 +4295,7 @@ nsImageRenderer::PrepareImage()
           // The cropped image is identical to the source image
           mImageContainer.swap(srcImage);
         } else {
-          nsCOMPtr subImage;
-          uint32_t aExtractFlags = (mFlags & FLAG_SYNC_DECODE_IMAGES)
-                                     ? (uint32_t) imgIContainer::FLAG_SYNC_DECODE
-                                     : (uint32_t) imgIContainer::FLAG_NONE;
-          nsresult rv = srcImage->ExtractFrame(imgIContainer::FRAME_CURRENT,
-                                               actualCropRect, aExtractFlags,
-                                               getter_AddRefs(subImage));
-          if (NS_FAILED(rv)) {
-            NS_WARNING("The cropped image contains no pixels to draw; "
-                       "maybe the crop rect is outside the image frame rect");
-            return false;
-          }
+          nsCOMPtr subImage = ImageOps::Clip(srcImage, actualCropRect);
           mImageContainer.swap(subImage);
         }
       }

From 1620097925988420153e9f67e7cb8c76353410af Mon Sep 17 00:00:00 2001
From: Seth Fowler 
Date: Tue, 26 Mar 2013 16:29:13 -0700
Subject: [PATCH 085/129] Bug 826093 (Part 4) - Use ClippedImage instead of
 ExtractFrame for border-image. r=bz

---
 layout/base/nsCSSRendering.cpp | 16 +++-------------
 1 file changed, 3 insertions(+), 13 deletions(-)

diff --git a/layout/base/nsCSSRendering.cpp b/layout/base/nsCSSRendering.cpp
index ec0445e168d4..c0c63b5bf9ea 100644
--- a/layout/base/nsCSSRendering.cpp
+++ b/layout/base/nsCSSRendering.cpp
@@ -3316,20 +3316,10 @@ DrawBorderImageComponent(nsRenderingContext&  aRenderingContext,
   if (aFill.IsEmpty() || aSrc.IsEmpty())
     return;
 
-  // Don't bother trying to cache sub images if the border image is animated
-  // We can only sucessfully call GetAnimated() if we are fully decoded, so default to true
-  bool animated = true;
-  aImage->GetAnimated(&animated);
-
   nsCOMPtr subImage;
-  if (animated || (subImage = aStyleBorder.GetSubImage(aIndex)) == 0) {
-    if (NS_FAILED(aImage->ExtractFrame(imgIContainer::FRAME_CURRENT, aSrc,
-                                       imgIContainer::FLAG_SYNC_DECODE,
-                                       getter_AddRefs(subImage))))
-      return;
-
-    if (!animated)
-      aStyleBorder.SetSubImage(aIndex, subImage);
+  if ((subImage = aStyleBorder.GetSubImage(aIndex)) == nullptr) {
+    subImage = ImageOps::Clip(aImage, aSrc);
+    aStyleBorder.SetSubImage(aIndex, subImage);
   }
 
   gfxPattern::GraphicsFilter graphicsFilter =

From f06f37b782250ec88d71f6f43e81a73dd498dc80 Mon Sep 17 00:00:00 2001
From: Seth Fowler 
Date: Tue, 26 Mar 2013 16:29:13 -0700
Subject: [PATCH 086/129] Bug 826093 (Part 5) - Remove
 imgIContainer::ExtractFrame. r=joe, sr=bz

---
 image/public/imgIContainer.idl | 29 +++-------
 image/src/ClippedImage.cpp     | 13 -----
 image/src/ClippedImage.h       |  4 --
 image/src/FrozenImage.cpp      |  9 ----
 image/src/FrozenImage.h        |  4 --
 image/src/ImageWrapper.cpp     |  9 ----
 image/src/RasterImage.cpp      | 96 ++--------------------------------
 image/src/VectorImage.cpp      | 82 +++--------------------------
 image/src/VectorImage.h        |  7 ---
 9 files changed, 19 insertions(+), 234 deletions(-)

diff --git a/image/public/imgIContainer.idl b/image/public/imgIContainer.idl
index ae7f86f9cb97..de2ca0c9e513 100644
--- a/image/public/imgIContainer.idl
+++ b/image/public/imgIContainer.idl
@@ -52,13 +52,12 @@ native nsSize(nsSize);
 
 /**
  * imgIContainer is the interface that represents an image. It allows
- * access to frames as Thebes surfaces, and permits users to extract subregions
- * as other imgIContainers. It also allows drawing of images on to Thebes
- * contexts.
+ * access to frames as Thebes surfaces. It also allows drawing of images
+ * onto Thebes contexts.
  *
  * Internally, imgIContainer also manages animation of images.
  */
-[scriptable, builtinclass, uuid(01c4f92f-f883-4837-a127-d8f30920e374)]
+[scriptable, builtinclass, uuid(0c1caf24-bce7-4db5-971d-8e1b6ed07540)]
 interface imgIContainer : nsISupports
 {
   /**
@@ -178,19 +177,6 @@ interface imgIContainer : nsISupports
    */
   [noscript] ImageContainer getImageContainer(in LayerManager aManager);
 
-  /**
-   * Create a new imgContainer that contains only a single frame, which itself
-   * contains a subregion of the given frame.
-   *
-   * @param aWhichFrame Frame specifier of the FRAME_* variety.
-   * @param aRect the area of the current frame to be duplicated in the
-   *              returned imgContainer's frame.
-   * @param aFlags Flags of the FLAG_* variety
-   */
-  [noscript] imgIContainer extractFrame(in uint32_t aWhichFrame,
-                                        [const] in nsIntRect aRect,
-                                        in uint32_t aFlags);
-
   /**
    * Draw a frame onto the context specified.
    *
@@ -229,11 +215,10 @@ interface imgIContainer : nsISupports
 
   /*
    * Ensures that an image is decoding. Calling this function guarantees that
-   * the image will at some point fire off decode notifications. Calling draw(),
-   * getFrame(), copyFrame(), or extractCurrentFrame() triggers the same
-   * mechanism internally. Thus, if you want to be sure that the image will be
-   * decoded but don't want to access it until then, you must call
-   * requestDecode().
+   * the image will at some point fire off decode notifications. Calling draw()
+   * or getFrame() triggers the same mechanism internally. Thus, if you want to
+   * be sure that the image will be decoded but don't want to access it until
+   * then, you must call requestDecode().
    */
   void requestDecode();
 
diff --git a/image/src/ClippedImage.cpp b/image/src/ClippedImage.cpp
index 55afabb8987a..dfdc3f04aea6 100644
--- a/image/src/ClippedImage.cpp
+++ b/image/src/ClippedImage.cpp
@@ -200,19 +200,6 @@ ClippedImage::GetImageContainer(LayerManager* aManager, ImageContainer** _retval
   return NS_OK;
 }
 
-NS_IMETHODIMP
-ClippedImage::ExtractFrame(uint32_t /* aWhichFrame */,
-                           const nsIntRect& /* aRegion */,
-                           uint32_t /* aFlags */,
-                           imgIContainer** /* _retval */)
-{
-  // XXX(seth): This method has to be present in this patch because we haven't
-  // gotten to the point where we can remove ExtractFrame yet, but implementing
-  // it would be a waste of effort.
-  MOZ_ASSERT(false, "ClippedImage::ExtractFrame shouldn't be called");
-  return NS_ERROR_NOT_AVAILABLE;
-}
-
 bool
 ClippedImage::MustCreateSurface(gfxContext* aContext,
                                 const gfxMatrix& aTransform,
diff --git a/image/src/ClippedImage.h b/image/src/ClippedImage.h
index 305212efcde6..39d47b7f3ccc 100644
--- a/image/src/ClippedImage.h
+++ b/image/src/ClippedImage.h
@@ -38,10 +38,6 @@ public:
                       gfxASurface** _retval) MOZ_OVERRIDE;
   NS_IMETHOD GetImageContainer(mozilla::layers::LayerManager* aManager,
                                mozilla::layers::ImageContainer** _retval) MOZ_OVERRIDE;
-  NS_IMETHOD ExtractFrame(uint32_t aWhichFrame,
-                          const nsIntRect& aRegion,
-                          uint32_t aFlags,
-                          imgIContainer** _retval) MOZ_OVERRIDE;
   NS_IMETHOD Draw(gfxContext* aContext,
                   gfxPattern::GraphicsFilter aFilter,
                   const gfxMatrix& aUserSpaceToImageSpace,
diff --git a/image/src/FrozenImage.cpp b/image/src/FrozenImage.cpp
index aa7e19661f57..333b7b88e000 100644
--- a/image/src/FrozenImage.cpp
+++ b/image/src/FrozenImage.cpp
@@ -68,15 +68,6 @@ FrozenImage::GetImageContainer(layers::LayerManager* aManager,
   return NS_OK;
 }
 
-NS_IMETHODIMP
-FrozenImage::ExtractFrame(uint32_t aWhichFrame,
-                          const nsIntRect& aRegion,
-                          uint32_t aFlags,
-                          imgIContainer** _retval)
-{
-  return InnerImage()->ExtractFrame(FRAME_FIRST, aRegion, aFlags, _retval);
-}
-
 NS_IMETHODIMP
 FrozenImage::Draw(gfxContext* aContext,
                   gfxPattern::GraphicsFilter aFilter,
diff --git a/image/src/FrozenImage.h b/image/src/FrozenImage.h
index b4cc255c839a..65428ce7a3cc 100644
--- a/image/src/FrozenImage.h
+++ b/image/src/FrozenImage.h
@@ -40,10 +40,6 @@ public:
   NS_IMETHOD_(bool) FrameIsOpaque(uint32_t aWhichFrame) MOZ_OVERRIDE;
   NS_IMETHOD GetImageContainer(layers::LayerManager* aManager,
                                layers::ImageContainer** _retval) MOZ_OVERRIDE;
-  NS_IMETHOD ExtractFrame(uint32_t aWhichFrame,
-                          const nsIntRect& aRegion,
-                          uint32_t aFlags,
-                          imgIContainer** _retval) MOZ_OVERRIDE;
   NS_IMETHOD Draw(gfxContext* aContext,
                   gfxPattern::GraphicsFilter aFilter,
                   const gfxMatrix& aUserSpaceToImageSpace,
diff --git a/image/src/ImageWrapper.cpp b/image/src/ImageWrapper.cpp
index 193aac3ffc1b..d67e684d9d4c 100644
--- a/image/src/ImageWrapper.cpp
+++ b/image/src/ImageWrapper.cpp
@@ -203,15 +203,6 @@ ImageWrapper::GetImageContainer(LayerManager* aManager, ImageContainer** _retval
   return mInnerImage->GetImageContainer(aManager, _retval);
 }
 
-NS_IMETHODIMP
-ImageWrapper::ExtractFrame(uint32_t aWhichFrame,
-                           const nsIntRect& aRegion,
-                           uint32_t aFlags,
-                           imgIContainer** _retval)
-{
-  return mInnerImage->ExtractFrame(aWhichFrame, aRegion, aFlags, _retval);
-}
-
 NS_IMETHODIMP
 ImageWrapper::Draw(gfxContext* aContext,
                    gfxPattern::GraphicsFilter aFilter,
diff --git a/image/src/RasterImage.cpp b/image/src/RasterImage.cpp
index 6ca0e55bc59a..1cecf24bc3ed 100644
--- a/image/src/RasterImage.cpp
+++ b/image/src/RasterImage.cpp
@@ -507,14 +507,6 @@ RasterImage::Init(const char* aMimeType,
     discardable_source_bytes += mSourceData.Length();
   }
 
-  // If we're being called from ExtractFrame (used by borderimage),
-  // we don't actually do any decoding. Bail early.
-  // XXX - This should be removed when we fix borderimage
-  if (mSourceDataMimeType.Length() == 0) {
-    mInitialized = true;
-    return NS_OK;
-  }
-
   // Instantiate the decoder
   nsresult rv = InitDecoder(/* aDoSizeDecode = */ true);
   CONTAINER_ENSURE_SUCCESS(rv);
@@ -688,85 +680,6 @@ RasterImage::RequestRefresh(const mozilla::TimeStamp& aTime)
   }
 }
 
-//******************************************************************************
-/* [noscript] imgIContainer extractFrame(uint32_t aWhichFrame,
- *                                       [const] in nsIntRect aRegion,
- *                                       in uint32_t aFlags); */
-NS_IMETHODIMP
-RasterImage::ExtractFrame(uint32_t aWhichFrame,
-                          const nsIntRect &aRegion,
-                          uint32_t aFlags,
-                          imgIContainer **_retval)
-{
-  NS_ENSURE_ARG_POINTER(_retval);
-
-  nsresult rv;
-
-  if (aWhichFrame > FRAME_MAX_VALUE)
-    return NS_ERROR_INVALID_ARG;
-
-  if (mError)
-    return NS_ERROR_FAILURE;
-
-  // Disallowed in the API
-  if (mInDecoder && (aFlags & imgIContainer::FLAG_SYNC_DECODE))
-    return NS_ERROR_FAILURE;
-
-  // Make a new container. This should switch to another class with bug 505959.
-  nsRefPtr img(new RasterImage());
-
-  // We don't actually have a mimetype in this case. The empty string tells the
-  // init routine not to try to instantiate a decoder. This should be fixed in
-  // bug 505959.
-  img->Init("", INIT_FLAG_NONE);
-  img->SetSize(aRegion.width, aRegion.height);
-  img->mDecoded = true; // Also, we need to mark the image as decoded
-  img->mHasBeenDecoded = true;
-  img->mFrameDecodeFlags = aFlags & DECODE_FLAGS_MASK;
-
-  if (!ApplyDecodeFlags(aFlags))
-    return NS_ERROR_NOT_AVAILABLE;
-  
-  // If a synchronous decode was requested, do it
-  if (aFlags & FLAG_SYNC_DECODE) {
-    rv = SyncDecode();
-    CONTAINER_ENSURE_SUCCESS(rv);
-  }
-
-  // Get the frame. If it's not there, it's probably the caller's fault for
-  // not waiting for the data to be loaded from the network or not passing
-  // FLAG_SYNC_DECODE
-  uint32_t frameIndex = (aWhichFrame == FRAME_FIRST) ?
-                        0 : GetCurrentImgFrameIndex();
-  imgFrame *frame = GetDrawableImgFrame(frameIndex);
-  if (!frame) {
-    *_retval = nullptr;
-    return NS_ERROR_FAILURE;
-  }
-
-  // The frame can be smaller than the image. We want to extract only the part
-  // of the frame that actually exists.
-  nsIntRect framerect = frame->GetRect();
-  framerect.IntersectRect(framerect, aRegion);
-
-  if (framerect.IsEmpty())
-    return NS_ERROR_NOT_AVAILABLE;
-
-  nsAutoPtr subframe;
-  rv = frame->Extract(framerect, getter_Transfers(subframe));
-  if (NS_FAILED(rv))
-    return rv;
-
-  img->mFrames.AppendElement(subframe.forget());
-
-  img->mStatusTracker->RecordLoaded();
-  img->mStatusTracker->RecordDecoded();
-
-  *_retval = img.forget().get();
-
-  return NS_OK;
-}
-
 //******************************************************************************
 /* readonly attribute int32_t width; */
 NS_IMETHODIMP
@@ -2748,11 +2661,10 @@ RasterImage::WriteToDecoder(const char *aBuffer, uint32_t aCount)
 }
 
 // This function is called in situations where it's clear that we want the
-// frames in decoded form (Draw, GetFrame, CopyFrame, ExtractFrame, etc).
-// If we're completely decoded, this method resets the discard timer (if
-// we're discardable), since wanting the frames now is a good indicator of
-// wanting them again soon. If we're not decoded, this method kicks off
-// asynchronous decoding to generate the frames.
+// frames in decoded form (Draw, GetFrame, etc).  If we're completely decoded,
+// this method resets the discard timer (if we're discardable), since wanting
+// the frames now is a good indicator of wanting them again soon. If we're not
+// decoded, this method kicks off asynchronous decoding to generate the frames.
 nsresult
 RasterImage::WantDecodedFrames()
 {
diff --git a/image/src/VectorImage.cpp b/image/src/VectorImage.cpp
index 334dd6200509..9c1631a0d782 100644
--- a/image/src/VectorImage.cpp
+++ b/image/src/VectorImage.cpp
@@ -301,12 +301,10 @@ NS_IMPL_ISUPPORTS3(VectorImage,
 VectorImage::VectorImage(imgStatusTracker* aStatusTracker,
                          nsIURI* aURI /* = nullptr */) :
   ImageResource(aStatusTracker, aURI), // invoke superclass's constructor
-  mRestrictedRegion(0, 0, 0, 0),
   mIsInitialized(false),
   mIsFullyLoaded(false),
   mIsDrawing(false),
-  mHaveAnimations(false),
-  mHaveRestrictedRegion(false)
+  mHaveAnimations(false)
 {
 }
 
@@ -326,8 +324,7 @@ VectorImage::Init(const char* aMimeType,
   if (mIsInitialized)
     return NS_ERROR_ILLEGAL_VALUE;
 
-  MOZ_ASSERT(!mIsFullyLoaded && !mHaveAnimations &&
-             !mHaveRestrictedRegion && !mError,
+  MOZ_ASSERT(!mIsFullyLoaded && !mHaveAnimations && !mError,
              "Flags unexpectedly set before initialization");
   MOZ_ASSERT(!strcmp(aMimeType, IMAGE_SVG_XML), "Unexpected mimetype");
 
@@ -595,14 +592,7 @@ VectorImage::GetFrame(uint32_t aWhichFrame,
   // ---------------------------------------------
   // Make our surface the size of what will ultimately be drawn to it.
   // (either the full image size, or the restricted region)
-  gfxIntSize surfaceSize;
-  if (mHaveRestrictedRegion) {
-    surfaceSize.width = mRestrictedRegion.width;
-    surfaceSize.height = mRestrictedRegion.height;
-  } else {
-    surfaceSize.width = imageIntSize.width;
-    surfaceSize.height = imageIntSize.height;
-  }
+  gfxIntSize surfaceSize(imageIntSize.width, imageIntSize.height);
 
   nsRefPtr surface =
     new gfxImageSurface(surfaceSize, gfxASurface::ImageFormatARGB32);
@@ -631,54 +621,6 @@ VectorImage::GetImageContainer(LayerManager* aManager,
   return NS_OK;
 }
 
-//******************************************************************************
-/* [noscript] imgIContainer extractFrame(uint32_t aWhichFrame,
- *                                       [const] in nsIntRect aRegion,
- *                                       in uint32_t aFlags); */
-NS_IMETHODIMP
-VectorImage::ExtractFrame(uint32_t aWhichFrame,
-                          const nsIntRect& aRegion,
-                          uint32_t aFlags,
-                          imgIContainer** _retval)
-{
-  NS_ENSURE_ARG_POINTER(_retval);
-  if (mError || !mIsFullyLoaded)
-    return NS_ERROR_FAILURE;
-
-  // XXXdholbert NOTE: This method assumes FRAME_CURRENT (not FRAME_FIRST)
-  // right now, because mozilla doesn't actually contain any clients of this
-  // method that use FRAME_FIRST.  If it's needed, we *could* handle
-  // FRAME_FIRST by saving the helper-doc's current SMIL time, seeking it to
-  // time 0, rendering to a RasterImage, and then restoring our saved time.
-  if (aWhichFrame != FRAME_CURRENT) {
-    NS_WARNING("VectorImage::ExtractFrame with something other than "
-               "FRAME_CURRENT isn't supported yet. Assuming FRAME_CURRENT.");
-  }
-
-  // XXXdholbert This method also doesn't actually freeze animation in the
-  // returned imgIContainer, because it shares our helper-document. To
-  // get a true snapshot, we need to clone the document - see bug 590792.
-
-  // Make a new container with same SVG document.
-  nsRefPtr extractedImg = new VectorImage();
-  extractedImg->mSVGDocumentWrapper = mSVGDocumentWrapper;
-  extractedImg->mAnimationMode = kDontAnimMode;
-
-  extractedImg->mRestrictedRegion.x = aRegion.x;
-  extractedImg->mRestrictedRegion.y = aRegion.y;
-
-  // (disallow negative width/height on our restricted region)
-  extractedImg->mRestrictedRegion.width  = std::max(aRegion.width,  0);
-  extractedImg->mRestrictedRegion.height = std::max(aRegion.height, 0);
-
-  extractedImg->mIsInitialized = true;
-  extractedImg->mIsFullyLoaded = true;
-  extractedImg->mHaveRestrictedRegion = true;
-
-  *_retval = extractedImg.forget().get();
-  return NS_OK;
-}
-
 //******************************************************************************
 /* [noscript] void draw(in gfxContext aContext,
  *                      in gfxGraphicsFilter aFilter,
@@ -722,24 +664,19 @@ VectorImage::Draw(gfxContext* aContext,
   mSVGDocumentWrapper->UpdateViewportBounds(aViewportSize);
   mSVGDocumentWrapper->FlushImageTransformInvalidation();
 
-  nsIntSize imageSize = mHaveRestrictedRegion ?
-    mRestrictedRegion.Size() : aViewportSize;
-
   // XXXdholbert Do we need to convert image size from
   // CSS pixels to dev pixels here? (is gfxCallbackDrawable's 2nd arg in dev
   // pixels?)
-  gfxIntSize imageSizeGfx(imageSize.width, imageSize.height);
+  gfxIntSize imageSizeGfx(aViewportSize.width, aViewportSize.height);
 
   // Based on imgFrame::Draw
   gfxRect sourceRect = aUserSpaceToImageSpace.Transform(aFill);
-  gfxRect imageRect(0, 0, imageSize.width, imageSize.height);
+  gfxRect imageRect(0, 0, aViewportSize.width, aViewportSize.height);
   gfxRect subimage(aSubimage.x, aSubimage.y, aSubimage.width, aSubimage.height);
 
 
   nsRefPtr cb =
     new SVGDrawingCallback(mSVGDocumentWrapper,
-                           mHaveRestrictedRegion ?
-                           mRestrictedRegion :
                            nsIntRect(nsIntPoint(0, 0), aViewportSize),
                            aFlags);
 
@@ -750,12 +687,9 @@ VectorImage::Draw(gfxContext* aContext,
                              subimage, sourceRect, imageRect, aFill,
                              gfxASurface::ImageFormatARGB32, aFilter);
 
-  MOZ_ASSERT(mRenderingObserver || mHaveRestrictedRegion, 
-      "Should have a rendering observer by now unless ExtractFrame created us");
-  if (mRenderingObserver) {
-    // Allow ourselves to fire FrameChanged and OnStopFrame again.
-    mRenderingObserver->ResumeListening();
-  }
+  // Allow ourselves to fire FrameChanged and OnStopFrame again.
+  MOZ_ASSERT(mRenderingObserver, "Should have a rendering observer by now");
+  mRenderingObserver->ResumeListening();
 
   return NS_OK;
 }
diff --git a/image/src/VectorImage.h b/image/src/VectorImage.h
index 69a547b82560..80746ddf9ffd 100644
--- a/image/src/VectorImage.h
+++ b/image/src/VectorImage.h
@@ -84,18 +84,11 @@ private:
   nsRefPtr     mLoadEventListener;
   nsRefPtr mParseCompleteListener;
 
-  nsIntRect      mRestrictedRegion;       // If we were created by
-                                          // ExtractFrame, this is the region
-                                          // that we're restricted to using.
-                                          // Otherwise, this is ignored.
-
   bool           mIsInitialized;          // Have we been initalized?
   bool           mIsFullyLoaded;          // Has the SVG document finished loading?
   bool           mIsDrawing;              // Are we currently drawing?
   bool           mHaveAnimations;         // Is our SVG content SMIL-animated?
                                           // (Only set after mIsFullyLoaded.)
-  bool           mHaveRestrictedRegion;   // Are we a restricted-region clone
-                                          // created via ExtractFrame?
 
   friend class ImageFactory;
 };

From eb0c64e93d9cded6b8d902d0cefae0384e768b5b Mon Sep 17 00:00:00 2001
From: Tanvi Vyas 
Date: Tue, 26 Mar 2013 16:37:46 -0700
Subject: [PATCH 087/129] Bug 836951 - Add mDocShell to nsSecureBrowserUIImpl.
 Traverse up to the root doc shell. r=bsmith,smaug

---
 docshell/base/nsDocShell.cpp                  |  1 +
 dom/ipc/TabParent.cpp                         |  9 +++++++
 netwerk/base/public/nsISecureBrowserUI.idl    |  4 ++-
 .../boot/src/nsSecureBrowserUIImpl.cpp        | 26 ++++++++++++++++---
 .../manager/boot/src/nsSecureBrowserUIImpl.h  |  2 ++
 5 files changed, 37 insertions(+), 5 deletions(-)

diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
index 3570a825db69..4cad99537d71 100644
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -2508,6 +2508,7 @@ NS_IMETHODIMP
 nsDocShell::SetSecurityUI(nsISecureBrowserUI *aSecurityUI)
 {
     mSecurityUI = aSecurityUI;
+    mSecurityUI->SetDocShell(this);
     return NS_OK;
 }
 
diff --git a/dom/ipc/TabParent.cpp b/dom/ipc/TabParent.cpp
index 7deb7db39d2c..a7df668e0e3a 100644
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -30,6 +30,7 @@
 #include "nsFocusManager.h"
 #include "nsFrameLoader.h"
 #include "nsIContent.h"
+#include "nsIDocShell.h"
 #include "nsIDOMApplicationRegistry.h"
 #include "nsIDOMElement.h"
 #include "nsIDOMEvent.h"
@@ -501,6 +502,14 @@ TabParent::GetState(uint32_t *aState)
   return NS_OK;
 }
 
+NS_IMETHODIMP
+TabParent::SetDocShell(nsIDocShell *aDocShell)
+{
+  NS_ENSURE_ARG(aDocShell);
+  NS_WARNING("No mDocShell member in TabParent so there is no docShell to set");
+  return NS_OK;
+}
+
 NS_IMETHODIMP
 TabParent::GetTooltipText(nsAString & aTooltipText)
 {
diff --git a/netwerk/base/public/nsISecureBrowserUI.idl b/netwerk/base/public/nsISecureBrowserUI.idl
index b04a0e719e80..fb8c00663dee 100644
--- a/netwerk/base/public/nsISecureBrowserUI.idl
+++ b/netwerk/base/public/nsISecureBrowserUI.idl
@@ -8,11 +8,13 @@
 
 interface nsIDOMWindow;
 interface nsIDOMElement;
+interface nsIDocShell;
 
-[scriptable, uuid(081e31e0-a144-11d3-8c7c-00609792278c)]
+[scriptable, uuid(e97e5688-add2-4a1d-acae-396d7702e382)]
 interface nsISecureBrowserUI : nsISupports
 {
     void init(in nsIDOMWindow window);
+    void setDocShell(in nsIDocShell docShell);
 
     readonly attribute unsigned long state;
     readonly attribute AString tooltipText;
diff --git a/security/manager/boot/src/nsSecureBrowserUIImpl.cpp b/security/manager/boot/src/nsSecureBrowserUIImpl.cpp
index e4246723e9f6..f679eb57a8cd 100644
--- a/security/manager/boot/src/nsSecureBrowserUIImpl.cpp
+++ b/security/manager/boot/src/nsSecureBrowserUIImpl.cpp
@@ -19,6 +19,7 @@
 #include "nsIObserverService.h"
 #include "nsCURILoader.h"
 #include "nsIDocShell.h"
+#include "nsIDocShellTreeItem.h"
 #include "nsIDocument.h"
 #include "nsIPrincipal.h"
 #include "nsIDOMElement.h"
@@ -286,12 +287,21 @@ nsSecureBrowserUIImpl::MapInternalToExternalState(uint32_t* aState, lockIconStat
   if (ev && (*aState & STATE_IS_SECURE))
     *aState |= nsIWebProgressListener::STATE_IDENTITY_EV_TOPLEVEL;
 
-  nsCOMPtr piwin = do_QueryReferent(mWindow);
-  if (!piwin)
+  nsCOMPtr docShell = do_QueryReferent(mDocShell);
+  if (!docShell)
     return NS_OK;
 
-  nsIDocShell* docShell = piwin->GetDocShell();
-  MOZ_ASSERT(docShell);
+  int32_t docShellType;
+  // For content docShell's, the mixed content security state is set on the root docShell.
+  if (NS_SUCCEEDED(docShell->GetItemType(&docShellType)) && docShellType == nsIDocShellTreeItem::typeContent) {
+    nsCOMPtr docShellTreeItem(do_QueryInterface(docShell));
+    nsCOMPtr sameTypeRoot;
+    docShellTreeItem->GetSameTypeRootTreeItem(getter_AddRefs(sameTypeRoot));
+    NS_ASSERTION(sameTypeRoot, "No document shell root tree item from document shell tree item!");
+    docShell = do_QueryInterface(sameTypeRoot);
+    if (!docShell)
+      return NS_OK;
+  }
 
   // Has a Mixed Content Load initiated in nsMixedContentBlocker?
   // If so, the state should be broken; overriding the previous state
@@ -319,6 +329,14 @@ nsSecureBrowserUIImpl::MapInternalToExternalState(uint32_t* aState, lockIconStat
   return NS_OK;
 }
 
+NS_IMETHODIMP
+nsSecureBrowserUIImpl::SetDocShell(nsIDocShell *aDocShell)
+{
+  nsresult rv;
+  mDocShell = do_GetWeakReference(aDocShell, &rv);
+  return rv;
+}
+
 NS_IMETHODIMP
 nsSecureBrowserUIImpl::GetTooltipText(nsAString& aText)
 {
diff --git a/security/manager/boot/src/nsSecureBrowserUIImpl.h b/security/manager/boot/src/nsSecureBrowserUIImpl.h
index 9d9975fca9e8..fc614663208f 100644
--- a/security/manager/boot/src/nsSecureBrowserUIImpl.h
+++ b/security/manager/boot/src/nsSecureBrowserUIImpl.h
@@ -17,6 +17,7 @@
 #include "nsIStringBundle.h"
 #include "nsISecureBrowserUI.h"
 #include "nsIDocShell.h"
+#include "nsIDocShellTreeItem.h"
 #include "nsIWebProgressListener.h"
 #include "nsIFormSubmitObserver.h"
 #include "nsIURI.h"
@@ -66,6 +67,7 @@ protected:
   mozilla::ReentrantMonitor mReentrantMonitor;
   
   nsWeakPtr mWindow;
+  nsWeakPtr mDocShell;
   nsCOMPtr mIOService;
   nsCOMPtr mStringBundle;
   nsCOMPtr mCurrentURI;

From b552b9b4af20bd5f180df605f9330f7f3e6beb4c Mon Sep 17 00:00:00 2001
From: Hannes Verschore 
Date: Wed, 27 Mar 2013 00:41:19 +0100
Subject: [PATCH 088/129] Bug 849781: IonMonkey: Only allow inlining when
 TypeSet of caller and callee intersects, r=nbp

---
 js/src/ion/IonBuilder.cpp                | 102 +++++++++++------------
 js/src/ion/IonBuilder.h                  |  22 ++---
 js/src/ion/TypeOracle.cpp                |  87 +++++++++++++++++--
 js/src/ion/TypeOracle.h                  |  31 +++++--
 js/src/jit-test/tests/ion/bug849781-2.js |   9 ++
 js/src/jit-test/tests/ion/bug849781.js   |   8 ++
 js/src/jsinfer.cpp                       |  34 ++++++++
 js/src/jsinfer.h                         |   1 +
 8 files changed, 217 insertions(+), 77 deletions(-)
 create mode 100644 js/src/jit-test/tests/ion/bug849781-2.js
 create mode 100644 js/src/jit-test/tests/ion/bug849781.js

diff --git a/js/src/ion/IonBuilder.cpp b/js/src/ion/IonBuilder.cpp
index f95edd9c2ecd..22fdff647b6e 100644
--- a/js/src/ion/IonBuilder.cpp
+++ b/js/src/ion/IonBuilder.cpp
@@ -185,7 +185,7 @@ IonBuilder::getPolyCallTargets(types::StackTypeSet *calleeTypes,
 }
 
 bool
-IonBuilder::canInlineTarget(JSFunction *target)
+IonBuilder::canInlineTarget(JSFunction *target, CallInfo &callInfo)
 {
     if (!target->isInterpreted()) {
         IonSpew(IonSpew_Inlining, "Cannot inline due to non-interpreted");
@@ -215,13 +215,42 @@ IonBuilder::canInlineTarget(JSFunction *target)
     }
 
     RootedScript callerScript(cx, script());
-    bool canInline = oracle->canEnterInlinedFunction(callerScript, pc, target);
 
-    if (!canInline) {
+    if (!oracle->canEnterInlinedFunction(target)) {
         IonSpew(IonSpew_Inlining, "Cannot inline due to oracle veto %d", script()->lineno);
         return false;
     }
 
+    if (!oracle->callReturnTypeSetMatches(callerScript, pc, target)) {
+        IonSpew(IonSpew_Inlining, "Cannot inline due to return typeset mismatch");
+        return false;
+    }
+
+    JS_ASSERT(callInfo.hasCallType());
+    if (callInfo.constructing()) {
+        // For constructing calls the typeset of caller should intersect the callee's typeset.
+        // Except for the |this| type, because that is created during execution depending on target.
+        if (!oracle->callArgsTypeSetIntersects(NULL, callInfo.argvType(), target)) {
+            IonSpew(IonSpew_Inlining, "Cannot inline due to arguments typeset mismatch");
+            return false;
+        }
+    } else if (JSOp(*pc) == JSOP_FUNAPPLY) {
+        // For fun.apply() the typeset of the caller should be a subset of the callee.
+        // Currently we can't loosen this, since there are no type barriers at the call boundary
+        // of fun.apply. Seeing a new type will only be noticed in the inlined call and
+        // result in missed types in TI.
+        if (!oracle->callArgsTypeSetMatches(callInfo.thisType(), callInfo.argvType(), target)) {
+            IonSpew(IonSpew_Inlining, "Cannot inline due to arguments typeset mismatch");
+            return false;
+        }
+    } else {
+        // For normal calls the typeset of caller should intersect the callee's typeset.
+        if (!oracle->callArgsTypeSetIntersects(callInfo.thisType(), callInfo.argvType(), target)) {
+            IonSpew(IonSpew_Inlining, "Cannot inline due to arguments typeset mismatch");
+            return false;
+        }
+    }
+
     IonSpew(IonSpew_Inlining, "Inlining good to go!");
     return true;
 }
@@ -434,7 +463,10 @@ IonBuilder::buildInline(IonBuilder *callerBuilder, MResumePoint *callerResumePoi
     // Save the actual arguments the caller used to call this inlined call,
     // to shortcut operations on "arguments" in the inlined call.
     JS_ASSERT(inlinedArguments_.length() == 0);
-    if (!inlinedArguments_.append(callInfo.argv()->begin(), callInfo.argv()->end()))
+    JS_ASSERT(inlinedArgumentTypes_.length() == 0);
+    if (!inlinedArguments_.append(callInfo.argv().begin(), callInfo.argv().end()))
+        return false;
+    if (!inlinedArgumentTypes_.append(callInfo.argvType().begin(), callInfo.argvType().end()))
         return false;
 
     // The Oracle ensures that the inlined script does not use the scope chain.
@@ -3019,6 +3051,9 @@ IonBuilder::addTypeBarrier(uint32_t i, CallInfo &callinfo, types::StackTypeSet *
     types::TypeBarrier *excluded = callinfo.argsBarrier();
 
     if (i == 0) {
+        // The |this| type get's created during execution, no need to add type barrier.
+        if (callinfo.constructing())
+            return;
         ins = callinfo.thisArg();
         callerObs = callinfo.thisType();
     } else {
@@ -3068,16 +3103,6 @@ IonBuilder::addTypeBarrier(uint32_t i, CallInfo &callinfo, types::StackTypeSet *
     if (needsBarrier) {
         MTypeBarrier *barrier = MTypeBarrier::New(ins, cloneTypeSet(calleeObs), Bailout_Normal);
         current->add(barrier);
-
-        // Non-matching types are boxed such as the MIRType does not conflict
-        // with the inferred type.
-        if (callerObs->getKnownTypeTag() != calleeObs->getKnownTypeTag() &&
-            ins->type() != MIRType_Value)
-        {
-            MBox *box = MBox::New(ins);
-            current->add(box);
-            ins = box;
-        }
     }
 
     if (i == 0)
@@ -3140,7 +3165,7 @@ IonBuilder::patchInlinedReturns(CallInfo &callInfo, MIRGraphExits &exits, MBasic
 }
 
 bool
-IonBuilder::makeInliningDecision(AutoObjectVector &targets)
+IonBuilder::makeInliningDecision(AutoObjectVector &targets, CallInfo &callInfo)
 {
     // For "small" functions, we should be more aggressive about inlining.
     // This is based on the following intuition:
@@ -3197,47 +3222,12 @@ IonBuilder::makeInliningDecision(AutoObjectVector &targets)
         return false;
     }
 
-    JSOp op = JSOp(*pc);
     for (size_t i = 0; i < targets.length(); i++) {
         JSFunction *target = targets[i]->toFunction();
-        JSScript *targetScript = target->nonLazyScript();
-
-        if (!canInlineTarget(target)) {
+        if (!canInlineTarget(target, callInfo)) {
             IonSpew(IonSpew_Inlining, "Decided not to inline");
             return false;
         }
-
-        // For fun.apply we need to make sure the types of the argument is a subset
-        // of the types used in the callee. Because adding a typeset in the callee,
-        // doesn't update the types in the "apply" function, resulting in missed types.
-        if (op == JSOP_FUNAPPLY) {
-            types::TypeSet *calleeType, *callerType;
-            size_t nargs = Min(target->nargs, inlinedArguments_.length());
-            for (size_t i = 0; i < nargs; i++) {
-                calleeType = types::TypeScript::ArgTypes(targetScript, i);
-                // The arguments to this function aren't always available in this script.
-                // We need to get them from the caller at the position where
-                // the function gets called.
-                callerType = oracle->getCallArg(callerBuilder_->script_.get(),
-                                                inlinedArguments_.length(),
-                                                i+1, callerBuilder_->pc);
-
-                if (!callerType->isSubset(calleeType)) {
-                    IonSpew(IonSpew_Inlining, "Funapply inlining failed due to wrong types");
-                    return false;
-                }
-            }
-            // Arguments that weren't provided will be Undefined
-            for (size_t i = nargs; i < target->nargs; i++) {
-                calleeType = types::TypeScript::ArgTypes(targetScript, i);
-                if (calleeType->unknown() ||
-                    !calleeType->hasType(types::Type::UndefinedType()))
-                {
-                    IonSpew(IonSpew_Inlining, "Funapply inlining failed due to wrong types");
-                    return false;
-                }
-            }
-        }
     }
 
     return true;
@@ -4054,7 +4044,11 @@ IonBuilder::jsop_funapplyarguments(uint32_t argc)
         return false;
     callInfo.setArgs(&args);
     RootedScript scriptRoot(cx, script());
-    if (!callInfo.initFunApplyArguments(oracle, scriptRoot, pc, info().nargs()))
+    RootedScript parentScriptRoot(cx, callerBuilder_->script());
+    Vector argTypes(cx);
+    if (!argTypes.append(inlinedArgumentTypes_.begin(), inlinedArgumentTypes_.end()))
+        return false;
+    if (!callInfo.initFunApplyArguments(oracle, scriptRoot, pc, &argTypes))
         return false;
 
     // This
@@ -4085,7 +4079,7 @@ IonBuilder::jsop_funapplyarguments(uint32_t argc)
         AutoObjectVector targets(cx);
         targets.append(target);
 
-        if (makeInliningDecision(targets))
+        if (makeInliningDecision(targets, callInfo))
             return inlineScriptedCall(target, callInfo);
     }
 
@@ -4149,7 +4143,7 @@ IonBuilder::jsop_call(uint32_t argc, bool constructing)
     // Inline scriped call(s).
     if (!callInfo.initCallType(oracle, scriptRoot, pc))
         return false;
-    if (inliningEnabled() && targets.length() > 0 && makeInliningDecision(targets))
+    if (inliningEnabled() && targets.length() > 0 && makeInliningDecision(targets, callInfo))
         return inlineScriptedCalls(targets, originals, callInfo);
 
     // No inline, just make the call.
diff --git a/js/src/ion/IonBuilder.h b/js/src/ion/IonBuilder.h
index e78360f798db..c5d26413ae0f 100644
--- a/js/src/ion/IonBuilder.h
+++ b/js/src/ion/IonBuilder.h
@@ -196,7 +196,7 @@ class IonBuilder : public MIRGenerator
     JSFunction *getSingleCallTarget(types::StackTypeSet *calleeTypes);
     bool getPolyCallTargets(types::StackTypeSet *calleeTypes,
                             AutoObjectVector &targets, uint32_t maxTargets);
-    bool canInlineTarget(JSFunction *target);
+    bool canInlineTarget(JSFunction *target, CallInfo &callInfo);
 
     void popCfgStack();
     bool processDeferredContinues(CFGState &state);
@@ -460,7 +460,7 @@ class IonBuilder : public MIRGenerator
     bool inlineScriptedCalls(AutoObjectVector &targets, AutoObjectVector &originals,
                              CallInfo &callInfo);
     bool inlineScriptedCall(HandleFunction target, CallInfo &callInfo);
-    bool makeInliningDecision(AutoObjectVector &targets);
+    bool makeInliningDecision(AutoObjectVector &targets, CallInfo &callInfo);
 
     bool anyFunctionIsCloneAtCallsite(types::StackTypeSet *funTypes);
     MDefinition *makeCallsiteClone(HandleFunction target, MDefinition *fun);
@@ -537,6 +537,7 @@ class IonBuilder : public MIRGenerator
 
     size_t inliningDepth_;
     Vector inlinedArguments_;
+    Vector inlinedArgumentTypes_;
 
     // True if script->failedBoundsCheck is set for the current script or
     // an outer script.
@@ -602,7 +603,7 @@ class CallInfo
         fun_ = callInfo.fun();
         thisArg_ = callInfo.thisArg();
 
-        if (!args_.append(callInfo.argv()->begin(), callInfo.argv()->end()))
+        if (!args_.append(callInfo.argv().begin(), callInfo.argv().end()))
             return false;
 
         if (callInfo.hasTypeInfo())
@@ -632,7 +633,7 @@ class CallInfo
 
     bool initCallType(TypeOracle *oracle, HandleScript script, jsbytecode *pc) {
         argsBarriers_ = oracle->callArgsBarrier(script, pc);
-        thisType_ = oracle->getCallTarget(script, argc(), pc);
+        thisType_ = oracle->getCallArg(script, argc(), 0, pc);
         if (!argsType_.reserve(argc()))
             return false;
         for (uint32_t i = 1; i <= argc(); i++)
@@ -640,13 +641,12 @@ class CallInfo
         return true;
     }
 
-    bool initFunApplyArguments(TypeOracle *oracle, HandleScript script, jsbytecode *pc, uint32_t nargs) {
+    bool initFunApplyArguments(TypeOracle *oracle, HandleScript script, jsbytecode *pc,
+                               Vector *types) {
         argsBarriers_ = oracle->callArgsBarrier(script, pc);
-        thisType_ = oracle->getCallArg(script, 2, 0, pc);
-        if (!argsType_.reserve(nargs))
+        thisType_ = oracle->getCallArg(script, 2, 1, pc);
+        if (!argsType_.append(types->begin(), types->end()))
             return false;
-        for (uint32_t i = 0; i < nargs; i++)
-            argsType_.infallibleAppend(oracle->parameterTypeSet(script, i));
         return true;
     }
 
@@ -691,8 +691,8 @@ class CallInfo
         args_.append(args->begin(), args->end());
     }
 
-    Vector *argv() {
-        return &args_;
+    Vector &argv() {
+        return args_;
     }
 
     Vector &argvType() {
diff --git a/js/src/ion/TypeOracle.cpp b/js/src/ion/TypeOracle.cpp
index e9fec71e0106..d7dfecc33f15 100644
--- a/js/src/ion/TypeOracle.cpp
+++ b/js/src/ion/TypeOracle.cpp
@@ -598,7 +598,7 @@ TypeInferenceOracle::callArgsBarrier(HandleScript caller, jsbytecode *pc)
 }
 
 bool
-TypeInferenceOracle::canEnterInlinedFunction(RawScript caller, jsbytecode *pc, RawFunction target)
+TypeInferenceOracle::canEnterInlinedFunction(RawFunction target)
 {
     RootedScript targetScript(cx, target->nonLazyScript());
 
@@ -631,9 +631,20 @@ TypeInferenceOracle::canEnterInlinedFunction(RawScript caller, jsbytecode *pc, R
     if (!targetType || targetType->unknownProperties())
         return false;
 
-    JSOp op = JSOp(*pc);
+    // TI calls ObjectStateChange to trigger invalidation of the caller.
+    HeapTypeSet::WatchObjectStateChange(cx, targetType);
+    return true;
+}
+
+bool
+TypeInferenceOracle::callReturnTypeSetMatches(RawScript callerScript, jsbytecode *callerPc,
+                                              RawFunction callee)
+{
+    RootedScript targetScript(cx, callee->nonLazyScript());
+
+    JSOp op = JSOp(*callerPc);
     TypeSet *returnTypes = TypeScript::ReturnTypes(targetScript);
-    TypeSet *callReturn = getCallReturn(caller, pc);
+    TypeSet *callReturn = getCallReturn(callerScript, callerPc);
     if (op == JSOP_NEW) {
         if (!returnTypes->isSubsetIgnorePrimitives(callReturn))
             return false;
@@ -642,8 +653,74 @@ TypeInferenceOracle::canEnterInlinedFunction(RawScript caller, jsbytecode *pc, R
             return false;
     }
 
-    // TI calls ObjectStateChange to trigger invalidation of the caller.
-    HeapTypeSet::WatchObjectStateChange(cx, targetType);
+    return true;
+}
+
+bool
+TypeInferenceOracle::callArgsTypeSetMatches(types::StackTypeSet *thisType, Vector &argvType, RawFunction callee)
+{
+    RootedScript targetScript(cx, callee->nonLazyScript());
+    types::TypeSet *calleeType;
+
+    size_t nargs = Min(callee->nargs, argvType.length());
+
+    // This
+    calleeType = types::TypeScript::ThisTypes(targetScript);
+    if (!thisType->isSubset(calleeType))
+        return false;
+
+    // Arguments
+    for (size_t i = 0; i < nargs; i++) {
+        calleeType = types::TypeScript::ArgTypes(targetScript, i);
+        if (!argvType[i]->isSubset(calleeType))
+            return false;
+    }
+
+    // Arguments that weren't provided will be Undefined
+    for (size_t i = nargs; i < callee->nargs; i++) {
+        calleeType = types::TypeScript::ArgTypes(targetScript, i);
+        if (calleeType->unknown() ||
+            !calleeType->hasType(types::Type::UndefinedType()))
+        {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+bool
+TypeInferenceOracle::callArgsTypeSetIntersects(types::StackTypeSet *thisType, Vector &argvType, RawFunction callee)
+{
+    RootedScript targetScript(cx, callee->nonLazyScript());
+    types::TypeSet *calleeType;
+
+    size_t nargs = Min(callee->nargs, argvType.length());
+
+    // This
+    if (thisType) {
+        calleeType = types::TypeScript::ThisTypes(targetScript);
+        if (thisType->intersectionEmpty(calleeType))
+            return false;
+    }
+
+    // Arguments
+    for (size_t i = 0; i < nargs; i++) {
+        calleeType = types::TypeScript::ArgTypes(targetScript, i);
+        if (argvType[i]->intersectionEmpty(calleeType))
+            return false;
+    }
+
+    // Arguments that weren't provided will be Undefined
+    for (size_t i = nargs; i < callee->nargs; i++) {
+        calleeType = types::TypeScript::ArgTypes(targetScript, i);
+        if (calleeType->unknown() ||
+            !calleeType->hasType(types::Type::UndefinedType()))
+        {
+            return false;
+        }
+    }
+
     return true;
 }
 
diff --git a/js/src/ion/TypeOracle.h b/js/src/ion/TypeOracle.h
index e85b36d81bb8..99c04cd08196 100644
--- a/js/src/ion/TypeOracle.h
+++ b/js/src/ion/TypeOracle.h
@@ -163,9 +163,27 @@ class TypeOracle
     virtual types::TypeBarrier *callArgsBarrier(HandleScript caller, jsbytecode *pc) {
         return NULL;
     }
-    virtual bool canEnterInlinedFunction(RawScript caller, jsbytecode *pc, RawFunction callee) {
+    virtual bool canEnterInlinedFunction(RawFunction callee) {
         return false;
     }
+    virtual bool callReturnTypeSetMatches(RawScript callerScript, jsbytecode *callerPc,
+                                     RawFunction callee)
+    {
+        return false;
+    }
+    virtual bool callArgsTypeSetIntersects(types::StackTypeSet *thisType, Vector &argvType, RawFunction callee)
+    {
+        return false;
+    }
+    virtual bool callArgsTypeSetMatches(types::StackTypeSet *thisType, Vector &argvType, RawFunction callee)
+    {
+        return false;
+    }
+    virtual types::StackTypeSet *aliasedVarBarrier(RawScript script, jsbytecode *pc,
+                                                   types::StackTypeSet **barrier)
+    {
+        return NULL;
+    }
 
     virtual LazyArgumentsType isArgumentObject(types::StackTypeSet *obj) {
         return MaybeArguments;
@@ -179,11 +197,6 @@ class TypeOracle
     virtual LazyArgumentsType elementWriteMagicArguments(RawScript script, jsbytecode *pc) {
         return MaybeArguments;
     }
-    virtual types::StackTypeSet *aliasedVarBarrier(RawScript script, jsbytecode *pc,
-                                                   types::StackTypeSet **barrier)
-    {
-        return NULL;
-    }
 };
 
 class DummyOracle : public TypeOracle
@@ -273,13 +286,17 @@ class TypeInferenceOracle : public TypeOracle
     MIRType elementWrite(RawScript script, jsbytecode *pc);
     bool canInlineCall(HandleScript caller, jsbytecode *pc);
     types::TypeBarrier *callArgsBarrier(HandleScript caller, jsbytecode *pc);
-    bool canEnterInlinedFunction(RawScript caller, jsbytecode *pc, RawFunction callee);
+    bool canEnterInlinedFunction(RawFunction callee);
+    bool callReturnTypeSetMatches(RawScript callerScript, jsbytecode *callerPc, RawFunction callee);
+    bool callArgsTypeSetIntersects(types::StackTypeSet *thisType, Vector &argvType, RawFunction callee);
+    bool callArgsTypeSetMatches(types::StackTypeSet *thisType, Vector &argvType, RawFunction callee);
     types::StackTypeSet *aliasedVarBarrier(RawScript script, jsbytecode *pc, types::StackTypeSet **barrier);
 
     LazyArgumentsType isArgumentObject(types::StackTypeSet *obj);
     LazyArgumentsType propertyReadMagicArguments(RawScript script, jsbytecode *pc);
     LazyArgumentsType elementReadMagicArguments(RawScript script, jsbytecode *pc);
     LazyArgumentsType elementWriteMagicArguments(RawScript script, jsbytecode *pc);
+
 };
 
 static inline MIRType
diff --git a/js/src/jit-test/tests/ion/bug849781-2.js b/js/src/jit-test/tests/ion/bug849781-2.js
new file mode 100644
index 000000000000..031ded4272cc
--- /dev/null
+++ b/js/src/jit-test/tests/ion/bug849781-2.js
@@ -0,0 +1,9 @@
+function assertArraysFirstEqual(a, b) {
+    if (a.length != b.length) {}
+}
+function check(b) {
+    var a = deserialize(serialize(b));
+    assertArraysFirstEqual(a, b);
+}
+check(new Int8Array(1));
+evaluate("check(['a', 'b']);");
diff --git a/js/src/jit-test/tests/ion/bug849781.js b/js/src/jit-test/tests/ion/bug849781.js
new file mode 100644
index 000000000000..3818b97ef965
--- /dev/null
+++ b/js/src/jit-test/tests/ion/bug849781.js
@@ -0,0 +1,8 @@
+function c0(i) { print(i) }
+function c1() { c0.apply({}, arguments); }
+function c2() { c1.apply({}, arguments); }
+function c3(a) { c2(a); }
+c3(1);
+c3(1);
+c3("");
+c3("");
diff --git a/js/src/jsinfer.cpp b/js/src/jsinfer.cpp
index bd87a3232595..991b26576a00 100644
--- a/js/src/jsinfer.cpp
+++ b/js/src/jsinfer.cpp
@@ -364,6 +364,40 @@ TypeSet::isSubsetIgnorePrimitives(TypeSet *other)
     return true;
 }
 
+bool
+TypeSet::intersectionEmpty(TypeSet *other)
+{
+    // For unknown/unknownObject there is no reason they couldn't intersect.
+    // I.e. we eagerly return their intersection isn't empty.
+    // That's ok, since we can't make predictions that can be checked to not hold.
+    if (unknown() || other->unknown())
+        return false;
+
+    if (unknownObject() && unknownObject())
+        return false;
+
+    if (unknownObject() && other->getObjectCount() > 0)
+        return false;
+
+    if (other->unknownObject() && getObjectCount() > 0)
+        return false;
+
+    // Test if there is an intersection in the baseFlags
+    if ((baseFlags() & other->baseFlags()) != 0)
+        return false;
+
+    // Test if there are object that are in both TypeSets
+    for (unsigned i = 0; i < getObjectCount(); i++) {
+        TypeObjectKey *obj = getObject(i);
+        if (!obj)
+            continue;
+        if (other->hasType(Type::ObjectType(obj)))
+            return false;
+    }
+
+    return true;
+}
+
 inline void
 TypeSet::addTypesToConstraint(JSContext *cx, TypeConstraint *constraint)
 {
diff --git a/js/src/jsinfer.h b/js/src/jsinfer.h
index 91383b2daa67..5cae580786ea 100644
--- a/js/src/jsinfer.h
+++ b/js/src/jsinfer.h
@@ -514,6 +514,7 @@ class TypeSet
      */
     bool isSubset(TypeSet *other);
     bool isSubsetIgnorePrimitives(TypeSet *other);
+    bool intersectionEmpty(TypeSet *other);
 
     inline StackTypeSet *toStackTypeSet();
     inline HeapTypeSet *toHeapTypeSet();

From 87626e74fa6456b6e63ebcb5830212dc347f390d Mon Sep 17 00:00:00 2001
From: David Zbarsky 
Date: Tue, 26 Mar 2013 19:43:32 -0400
Subject: [PATCH 089/129] Bug 847120: Move SVGFEMorphologyElement to its own
 file r=Ms2ger

--HG--
rename : content/svg/content/src/nsSVGFilters.cpp => content/svg/content/src/SVGFEMorphologyElement.cpp
rename : content/svg/content/src/nsSVGFilters.cpp => content/svg/content/src/SVGFEMorphologyElement.h
---
 content/svg/content/src/Makefile.in           |   2 +
 .../content/src/SVGFEMorphologyElement.cpp    | 254 ++++++++++++++
 .../svg/content/src/SVGFEMorphologyElement.h  |  85 +++++
 content/svg/content/src/nsSVGFilters.cpp      | 312 ------------------
 4 files changed, 341 insertions(+), 312 deletions(-)
 create mode 100644 content/svg/content/src/SVGFEMorphologyElement.cpp
 create mode 100644 content/svg/content/src/SVGFEMorphologyElement.h

diff --git a/content/svg/content/src/Makefile.in b/content/svg/content/src/Makefile.in
index f902f68a03da..18244ce3451a 100644
--- a/content/svg/content/src/Makefile.in
+++ b/content/svg/content/src/Makefile.in
@@ -89,6 +89,7 @@ CPPSRCS		= \
 		SVGFEImageElement.cpp \
 		SVGFEMergeElement.cpp \
 		SVGFEMergeNodeElement.cpp \
+		SVGFEMorphologyElement.cpp \
 		SVGFEOffsetElement.cpp \
 		SVGFEPointLightElement.cpp \
 		SVGFESpecularLightingElement.cpp \
@@ -201,6 +202,7 @@ EXPORTS_mozilla/dom = \
 	SVGFEImageElement.h \
 	SVGFEMergeElement.h \
 	SVGFEMergeNodeElement.h \
+	SVGFEMorphologyElement.h \
 	SVGFEOffsetElement.h \
 	SVGFEPointLightElement.h \
 	SVGFESpecularLightingElement.h \
diff --git a/content/svg/content/src/SVGFEMorphologyElement.cpp b/content/svg/content/src/SVGFEMorphologyElement.cpp
new file mode 100644
index 000000000000..d91e6a425b62
--- /dev/null
+++ b/content/svg/content/src/SVGFEMorphologyElement.cpp
@@ -0,0 +1,254 @@
+/* a*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/dom/SVGFEMorphologyElement.h"
+
+namespace mozilla {
+namespace dom {
+
+nsSVGElement::NumberPairInfo nsSVGFEMorphologyElement::sNumberPairInfo[1] =
+{
+  { &nsGkAtoms::radius, 0, 0 }
+};
+
+nsSVGEnumMapping nsSVGFEMorphologyElement::sOperatorMap[] = {
+  {&nsGkAtoms::erode, nsSVGFEMorphologyElement::SVG_OPERATOR_ERODE},
+  {&nsGkAtoms::dilate, nsSVGFEMorphologyElement::SVG_OPERATOR_DILATE},
+  {nullptr, 0}
+};
+
+nsSVGElement::EnumInfo nsSVGFEMorphologyElement::sEnumInfo[1] =
+{
+  { &nsGkAtoms::_operator,
+    sOperatorMap,
+    nsSVGFEMorphologyElement::SVG_OPERATOR_ERODE
+  }
+};
+
+nsSVGElement::StringInfo nsSVGFEMorphologyElement::sStringInfo[2] =
+{
+  { &nsGkAtoms::result, kNameSpaceID_None, true },
+  { &nsGkAtoms::in, kNameSpaceID_None, true }
+};
+
+NS_IMPL_NS_NEW_SVG_ELEMENT(FEMorphology)
+
+//----------------------------------------------------------------------
+// nsISupports methods
+
+NS_IMPL_ADDREF_INHERITED(nsSVGFEMorphologyElement,nsSVGFEMorphologyElementBase)
+NS_IMPL_RELEASE_INHERITED(nsSVGFEMorphologyElement,nsSVGFEMorphologyElementBase)
+
+DOMCI_NODE_DATA(SVGFEMorphologyElement, nsSVGFEMorphologyElement)
+
+NS_INTERFACE_TABLE_HEAD(nsSVGFEMorphologyElement)
+  NS_NODE_INTERFACE_TABLE5(nsSVGFEMorphologyElement, nsIDOMNode, nsIDOMElement,
+                           nsIDOMSVGElement,
+                           nsIDOMSVGFilterPrimitiveStandardAttributes,
+                           nsIDOMSVGFEMorphologyElement)
+  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGFEMorphologyElement)
+NS_INTERFACE_MAP_END_INHERITING(nsSVGFEMorphologyElementBase)
+
+//----------------------------------------------------------------------
+// nsIDOMNode methods
+
+
+NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGFEMorphologyElement)
+
+
+//----------------------------------------------------------------------
+// nsSVGFEMorphologyElement methods
+
+/* readonly attribute nsIDOMSVGAnimatedString in1; */
+NS_IMETHODIMP nsSVGFEMorphologyElement::GetIn1(nsIDOMSVGAnimatedString * *aIn)
+{
+  return mStringAttributes[IN1].ToDOMAnimatedString(aIn, this);
+}
+
+/* readonly attribute nsIDOMSVGAnimatedEnumeration operator; */
+NS_IMETHODIMP nsSVGFEMorphologyElement::GetOperator(nsIDOMSVGAnimatedEnumeration * *aOperator)
+{
+  return mEnumAttributes[OPERATOR].ToDOMAnimatedEnum(aOperator, this);
+}
+
+/* readonly attribute nsIDOMSVGAnimatedNumber radiusX; */
+NS_IMETHODIMP nsSVGFEMorphologyElement::GetRadiusX(nsIDOMSVGAnimatedNumber * *aX)
+{
+  return mNumberPairAttributes[RADIUS].ToDOMAnimatedNumber(aX, nsSVGNumberPair::eFirst, this);
+}
+
+/* readonly attribute nsIDOMSVGAnimatedNumber radiusY; */
+NS_IMETHODIMP nsSVGFEMorphologyElement::GetRadiusY(nsIDOMSVGAnimatedNumber * *aY)
+{
+  return mNumberPairAttributes[RADIUS].ToDOMAnimatedNumber(aY, nsSVGNumberPair::eSecond, this);
+}
+
+NS_IMETHODIMP
+nsSVGFEMorphologyElement::SetRadius(float rx, float ry)
+{
+  NS_ENSURE_FINITE2(rx, ry, NS_ERROR_ILLEGAL_VALUE);
+  mNumberPairAttributes[RADIUS].SetBaseValues(rx, ry, this);
+  return NS_OK;
+}
+
+void
+nsSVGFEMorphologyElement::GetSourceImageNames(nsTArray& aSources)
+{
+  aSources.AppendElement(nsSVGStringInfo(&mStringAttributes[IN1], this));
+}
+
+nsIntRect
+nsSVGFEMorphologyElement::InflateRect(const nsIntRect& aRect,
+                                      const nsSVGFilterInstance& aInstance)
+{
+  int32_t rx, ry;
+  GetRXY(&rx, &ry, aInstance);
+  nsIntRect result = aRect;
+  result.Inflate(std::max(0, rx), std::max(0, ry));
+  return result;
+}
+
+nsIntRect
+nsSVGFEMorphologyElement::ComputeTargetBBox(const nsTArray& aSourceBBoxes,
+        const nsSVGFilterInstance& aInstance)
+{
+  return InflateRect(aSourceBBoxes[0], aInstance);
+}
+
+void
+nsSVGFEMorphologyElement::ComputeNeededSourceBBoxes(const nsIntRect& aTargetBBox,
+          nsTArray& aSourceBBoxes, const nsSVGFilterInstance& aInstance)
+{
+  aSourceBBoxes[0] = InflateRect(aTargetBBox, aInstance);
+}
+
+nsIntRect
+nsSVGFEMorphologyElement::ComputeChangeBBox(const nsTArray& aSourceChangeBoxes,
+                                            const nsSVGFilterInstance& aInstance)
+{
+  return InflateRect(aSourceChangeBoxes[0], aInstance);
+}
+
+#define MORPHOLOGY_EPSILON 0.0001
+
+void
+nsSVGFEMorphologyElement::GetRXY(int32_t *aRX, int32_t *aRY,
+                                 const nsSVGFilterInstance& aInstance)
+{
+  // Subtract an epsilon here because we don't want a value that's just
+  // slightly larger than an integer to round up to the next integer; it's
+  // probably meant to be the integer it's close to, modulo machine precision
+  // issues.
+  *aRX = NSToIntCeil(aInstance.GetPrimitiveNumber(SVGContentUtils::X,
+                                                  &mNumberPairAttributes[RADIUS],
+                                                  nsSVGNumberPair::eFirst) -
+                     MORPHOLOGY_EPSILON);
+  *aRY = NSToIntCeil(aInstance.GetPrimitiveNumber(SVGContentUtils::Y,
+                                                  &mNumberPairAttributes[RADIUS],
+                                                  nsSVGNumberPair::eSecond) -
+                     MORPHOLOGY_EPSILON);
+}
+
+nsresult
+nsSVGFEMorphologyElement::Filter(nsSVGFilterInstance *instance,
+                                 const nsTArray& aSources,
+                                 const Image* aTarget,
+                                 const nsIntRect& rect)
+{
+  int32_t rx, ry;
+  GetRXY(&rx, &ry, *instance);
+
+  if (rx < 0 || ry < 0) {
+    // XXX SVGContentUtils::ReportToConsole()
+    return NS_OK;
+  }
+  if (rx == 0 && ry == 0) {
+    return NS_OK;
+  }
+
+  // Clamp radii to prevent completely insane values:
+  rx = std::min(rx, 100000);
+  ry = std::min(ry, 100000);
+
+  uint8_t* sourceData = aSources[0]->mImage->Data();
+  uint8_t* targetData = aTarget->mImage->Data();
+  int32_t stride = aTarget->mImage->Stride();
+  uint8_t extrema[4];         // RGBA magnitude of extrema
+  uint16_t op = mEnumAttributes[OPERATOR].GetAnimValue();
+
+  // Scan the kernel for each pixel to determine max/min RGBA values.
+  for (int32_t y = rect.y; y < rect.YMost(); y++) {
+    int32_t startY = std::max(0, y - ry);
+    // We need to read pixels not just in 'rect', which is limited to
+    // the dirty part of our filter primitive subregion, but all pixels in
+    // the given radii from the source surface, so use the surface size here.
+    int32_t endY = std::min(y + ry, instance->GetSurfaceHeight() - 1);
+    for (int32_t x = rect.x; x < rect.XMost(); x++) {
+      int32_t startX = std::max(0, x - rx);
+      int32_t endX = std::min(x + rx, instance->GetSurfaceWidth() - 1);
+      int32_t targIndex = y * stride + 4 * x;
+
+      for (int32_t i = 0; i < 4; i++) {
+        extrema[i] = sourceData[targIndex + i];
+      }
+      for (int32_t y1 = startY; y1 <= endY; y1++) {
+        for (int32_t x1 = startX; x1 <= endX; x1++) {
+          for (int32_t i = 0; i < 4; i++) {
+            uint8_t pixel = sourceData[y1 * stride + 4 * x1 + i];
+            if ((extrema[i] > pixel &&
+                 op == nsSVGFEMorphologyElement::SVG_OPERATOR_ERODE) ||
+                (extrema[i] < pixel &&
+                 op == nsSVGFEMorphologyElement::SVG_OPERATOR_DILATE)) {
+              extrema[i] = pixel;
+            }
+          }
+        }
+      }
+      targetData[targIndex  ] = extrema[0];
+      targetData[targIndex+1] = extrema[1];
+      targetData[targIndex+2] = extrema[2];
+      targetData[targIndex+3] = extrema[3];
+    }
+  }
+  return NS_OK;
+}
+
+bool
+nsSVGFEMorphologyElement::AttributeAffectsRendering(int32_t aNameSpaceID,
+                                                    nsIAtom* aAttribute) const
+{
+  return nsSVGFEMorphologyElementBase::AttributeAffectsRendering(aNameSpaceID, aAttribute) ||
+         (aNameSpaceID == kNameSpaceID_None &&
+          (aAttribute == nsGkAtoms::in ||
+           aAttribute == nsGkAtoms::radius ||
+           aAttribute == nsGkAtoms::_operator));
+}
+
+//----------------------------------------------------------------------
+// nsSVGElement methods
+
+nsSVGElement::NumberPairAttributesInfo
+nsSVGFEMorphologyElement::GetNumberPairInfo()
+{
+  return NumberPairAttributesInfo(mNumberPairAttributes, sNumberPairInfo,
+                                  ArrayLength(sNumberPairInfo));
+}
+
+nsSVGElement::EnumAttributesInfo
+nsSVGFEMorphologyElement::GetEnumInfo()
+{
+  return EnumAttributesInfo(mEnumAttributes, sEnumInfo,
+                            ArrayLength(sEnumInfo));
+}
+
+nsSVGElement::StringAttributesInfo
+nsSVGFEMorphologyElement::GetStringInfo()
+{
+  return StringAttributesInfo(mStringAttributes, sStringInfo,
+                              ArrayLength(sStringInfo));
+}
+
+} // namespace dom
+} // namespace mozilla
diff --git a/content/svg/content/src/SVGFEMorphologyElement.h b/content/svg/content/src/SVGFEMorphologyElement.h
new file mode 100644
index 000000000000..27fd0c911a0b
--- /dev/null
+++ b/content/svg/content/src/SVGFEMorphologyElement.h
@@ -0,0 +1,85 @@
+/* a*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_dom_SVGFEMorphologyElement_h
+#define mozilla_dom_SVGFEMorphologyElement_h
+
+#include "nsSVGFilters.h"
+
+namespace mozilla {
+namespace dom {
+
+typedef nsSVGFE nsSVGFEMorphologyElementBase;
+
+class nsSVGFEMorphologyElement : public nsSVGFEMorphologyElementBase,
+                                 public nsIDOMSVGFEMorphologyElement
+{
+  friend nsresult NS_NewSVGFEMorphologyElement(nsIContent **aResult,
+                                               already_AddRefed aNodeInfo);
+protected:
+  nsSVGFEMorphologyElement(already_AddRefed aNodeInfo)
+    : nsSVGFEMorphologyElementBase(aNodeInfo) {}
+
+public:
+  // interfaces:
+  NS_DECL_ISUPPORTS_INHERITED
+
+  // FE Base
+  NS_FORWARD_NSIDOMSVGFILTERPRIMITIVESTANDARDATTRIBUTES(nsSVGFEMorphologyElementBase::)
+
+  virtual nsresult Filter(nsSVGFilterInstance* aInstance,
+                          const nsTArray& aSources,
+                          const Image* aTarget,
+                          const nsIntRect& aDataRect);
+  virtual bool AttributeAffectsRendering(
+          int32_t aNameSpaceID, nsIAtom* aAttribute) const;
+  virtual nsSVGString& GetResultImageName() { return mStringAttributes[RESULT]; }
+  virtual void GetSourceImageNames(nsTArray& aSources);
+  virtual nsIntRect ComputeTargetBBox(const nsTArray& aSourceBBoxes,
+          const nsSVGFilterInstance& aInstance);
+  virtual void ComputeNeededSourceBBoxes(const nsIntRect& aTargetBBox,
+          nsTArray& aSourceBBoxes, const nsSVGFilterInstance& aInstance);
+  virtual nsIntRect ComputeChangeBBox(const nsTArray& aSourceChangeBoxes,
+          const nsSVGFilterInstance& aInstance);
+
+  // Morphology
+  NS_DECL_NSIDOMSVGFEMORPHOLOGYELEMENT
+
+  NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFEMorphologyElementBase::)
+
+  NS_FORWARD_NSIDOMNODE_TO_NSINODE
+  NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
+
+  virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
+
+  virtual nsXPCClassInfo* GetClassInfo();
+
+  virtual nsIDOMNode* AsDOMNode() { return this; }
+protected:
+  void GetRXY(int32_t *aRX, int32_t *aRY, const nsSVGFilterInstance& aInstance);
+  nsIntRect InflateRect(const nsIntRect& aRect, const nsSVGFilterInstance& aInstance);
+
+  virtual NumberPairAttributesInfo GetNumberPairInfo();
+  virtual EnumAttributesInfo GetEnumInfo();
+  virtual StringAttributesInfo GetStringInfo();
+
+  enum { RADIUS };
+  nsSVGNumberPair mNumberPairAttributes[1];
+  static NumberPairInfo sNumberPairInfo[1];
+
+  enum { OPERATOR };
+  nsSVGEnum mEnumAttributes[1];
+  static nsSVGEnumMapping sOperatorMap[];
+  static EnumInfo sEnumInfo[1];
+
+  enum { RESULT, IN1 };
+  nsSVGString mStringAttributes[2];
+  static StringInfo sStringInfo[2];
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_SVGFEMorphologyElement_h
diff --git a/content/svg/content/src/nsSVGFilters.cpp b/content/svg/content/src/nsSVGFilters.cpp
index 669c4a4e1d36..f0c209badf73 100644
--- a/content/svg/content/src/nsSVGFilters.cpp
+++ b/content/svg/content/src/nsSVGFilters.cpp
@@ -1206,318 +1206,6 @@ nsSVGFETurbulenceElement::GetStringInfo()
                               ArrayLength(sStringInfo));
 }
 
-//---------------------Morphology------------------------
-
-typedef nsSVGFE nsSVGFEMorphologyElementBase;
-
-class nsSVGFEMorphologyElement : public nsSVGFEMorphologyElementBase,
-                                 public nsIDOMSVGFEMorphologyElement
-{
-  friend nsresult NS_NewSVGFEMorphologyElement(nsIContent **aResult,
-                                               already_AddRefed aNodeInfo);
-protected:
-  nsSVGFEMorphologyElement(already_AddRefed aNodeInfo)
-    : nsSVGFEMorphologyElementBase(aNodeInfo) {}
-
-public:
-  // interfaces:
-  NS_DECL_ISUPPORTS_INHERITED
-
-  // FE Base
-  NS_FORWARD_NSIDOMSVGFILTERPRIMITIVESTANDARDATTRIBUTES(nsSVGFEMorphologyElementBase::)
-
-  virtual nsresult Filter(nsSVGFilterInstance* aInstance,
-                          const nsTArray& aSources,
-                          const Image* aTarget,
-                          const nsIntRect& aDataRect);
-  virtual bool AttributeAffectsRendering(
-          int32_t aNameSpaceID, nsIAtom* aAttribute) const;
-  virtual nsSVGString& GetResultImageName() { return mStringAttributes[RESULT]; }
-  virtual void GetSourceImageNames(nsTArray& aSources);
-  virtual nsIntRect ComputeTargetBBox(const nsTArray& aSourceBBoxes,
-          const nsSVGFilterInstance& aInstance);
-  virtual void ComputeNeededSourceBBoxes(const nsIntRect& aTargetBBox,
-          nsTArray& aSourceBBoxes, const nsSVGFilterInstance& aInstance);
-  virtual nsIntRect ComputeChangeBBox(const nsTArray& aSourceChangeBoxes,
-          const nsSVGFilterInstance& aInstance);
-
-  // Morphology
-  NS_DECL_NSIDOMSVGFEMORPHOLOGYELEMENT
-
-  NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFEMorphologyElementBase::)
-
-  NS_FORWARD_NSIDOMNODE_TO_NSINODE
-  NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
-
-  virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
-
-  virtual nsXPCClassInfo* GetClassInfo();
-
-  virtual nsIDOMNode* AsDOMNode() { return this; }
-protected:
-  void GetRXY(int32_t *aRX, int32_t *aRY, const nsSVGFilterInstance& aInstance);
-  nsIntRect InflateRect(const nsIntRect& aRect, const nsSVGFilterInstance& aInstance);
-
-  virtual NumberPairAttributesInfo GetNumberPairInfo();
-  virtual EnumAttributesInfo GetEnumInfo();
-  virtual StringAttributesInfo GetStringInfo();
-
-  enum { RADIUS };
-  nsSVGNumberPair mNumberPairAttributes[1];
-  static NumberPairInfo sNumberPairInfo[1];
-
-  enum { OPERATOR };
-  nsSVGEnum mEnumAttributes[1];
-  static nsSVGEnumMapping sOperatorMap[];
-  static EnumInfo sEnumInfo[1];
-
-  enum { RESULT, IN1 };
-  nsSVGString mStringAttributes[2];
-  static StringInfo sStringInfo[2];
-};
-
-nsSVGElement::NumberPairInfo nsSVGFEMorphologyElement::sNumberPairInfo[1] =
-{
-  { &nsGkAtoms::radius, 0, 0 }
-};
-
-nsSVGEnumMapping nsSVGFEMorphologyElement::sOperatorMap[] = {
-  {&nsGkAtoms::erode, nsSVGFEMorphologyElement::SVG_OPERATOR_ERODE},
-  {&nsGkAtoms::dilate, nsSVGFEMorphologyElement::SVG_OPERATOR_DILATE},
-  {nullptr, 0}
-};
-
-nsSVGElement::EnumInfo nsSVGFEMorphologyElement::sEnumInfo[1] =
-{
-  { &nsGkAtoms::_operator,
-    sOperatorMap,
-    nsSVGFEMorphologyElement::SVG_OPERATOR_ERODE
-  }
-};
-
-nsSVGElement::StringInfo nsSVGFEMorphologyElement::sStringInfo[2] =
-{
-  { &nsGkAtoms::result, kNameSpaceID_None, true },
-  { &nsGkAtoms::in, kNameSpaceID_None, true }
-};
-
-NS_IMPL_NS_NEW_SVG_ELEMENT(FEMorphology)
-
-//----------------------------------------------------------------------
-// nsISupports methods
-
-NS_IMPL_ADDREF_INHERITED(nsSVGFEMorphologyElement,nsSVGFEMorphologyElementBase)
-NS_IMPL_RELEASE_INHERITED(nsSVGFEMorphologyElement,nsSVGFEMorphologyElementBase)
-
-DOMCI_NODE_DATA(SVGFEMorphologyElement, nsSVGFEMorphologyElement)
-
-NS_INTERFACE_TABLE_HEAD(nsSVGFEMorphologyElement)
-  NS_NODE_INTERFACE_TABLE5(nsSVGFEMorphologyElement, nsIDOMNode, nsIDOMElement,
-                           nsIDOMSVGElement,
-                           nsIDOMSVGFilterPrimitiveStandardAttributes,
-                           nsIDOMSVGFEMorphologyElement)
-  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGFEMorphologyElement)
-NS_INTERFACE_MAP_END_INHERITING(nsSVGFEMorphologyElementBase)
-
-//----------------------------------------------------------------------
-// nsIDOMNode methods
-
-
-NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGFEMorphologyElement)
-
-
-//----------------------------------------------------------------------
-// nsSVGFEMorphologyElement methods
-
-/* readonly attribute nsIDOMSVGAnimatedString in1; */
-NS_IMETHODIMP nsSVGFEMorphologyElement::GetIn1(nsIDOMSVGAnimatedString * *aIn)
-{
-  return mStringAttributes[IN1].ToDOMAnimatedString(aIn, this);
-}
-
-/* readonly attribute nsIDOMSVGAnimatedEnumeration operator; */
-NS_IMETHODIMP nsSVGFEMorphologyElement::GetOperator(nsIDOMSVGAnimatedEnumeration * *aOperator)
-{
-  return mEnumAttributes[OPERATOR].ToDOMAnimatedEnum(aOperator, this);
-}
-
-/* readonly attribute nsIDOMSVGAnimatedNumber radiusX; */
-NS_IMETHODIMP nsSVGFEMorphologyElement::GetRadiusX(nsIDOMSVGAnimatedNumber * *aX)
-{
-  return mNumberPairAttributes[RADIUS].ToDOMAnimatedNumber(aX, nsSVGNumberPair::eFirst, this);
-}
-
-/* readonly attribute nsIDOMSVGAnimatedNumber radiusY; */
-NS_IMETHODIMP nsSVGFEMorphologyElement::GetRadiusY(nsIDOMSVGAnimatedNumber * *aY)
-{
-  return mNumberPairAttributes[RADIUS].ToDOMAnimatedNumber(aY, nsSVGNumberPair::eSecond, this);
-}
-
-NS_IMETHODIMP
-nsSVGFEMorphologyElement::SetRadius(float rx, float ry)
-{
-  NS_ENSURE_FINITE2(rx, ry, NS_ERROR_ILLEGAL_VALUE);
-  mNumberPairAttributes[RADIUS].SetBaseValues(rx, ry, this);
-  return NS_OK;
-}
-
-void
-nsSVGFEMorphologyElement::GetSourceImageNames(nsTArray& aSources)
-{
-  aSources.AppendElement(nsSVGStringInfo(&mStringAttributes[IN1], this));
-}
-
-nsIntRect
-nsSVGFEMorphologyElement::InflateRect(const nsIntRect& aRect,
-                                      const nsSVGFilterInstance& aInstance)
-{
-  int32_t rx, ry;
-  GetRXY(&rx, &ry, aInstance);
-  nsIntRect result = aRect;
-  result.Inflate(std::max(0, rx), std::max(0, ry));
-  return result;
-}
-
-nsIntRect
-nsSVGFEMorphologyElement::ComputeTargetBBox(const nsTArray& aSourceBBoxes,
-        const nsSVGFilterInstance& aInstance)
-{
-  return InflateRect(aSourceBBoxes[0], aInstance);
-}
-
-void
-nsSVGFEMorphologyElement::ComputeNeededSourceBBoxes(const nsIntRect& aTargetBBox,
-          nsTArray& aSourceBBoxes, const nsSVGFilterInstance& aInstance)
-{
-  aSourceBBoxes[0] = InflateRect(aTargetBBox, aInstance);
-}
-
-nsIntRect
-nsSVGFEMorphologyElement::ComputeChangeBBox(const nsTArray& aSourceChangeBoxes,
-                                            const nsSVGFilterInstance& aInstance)
-{
-  return InflateRect(aSourceChangeBoxes[0], aInstance);
-}
-
-#define MORPHOLOGY_EPSILON 0.0001
-
-void
-nsSVGFEMorphologyElement::GetRXY(int32_t *aRX, int32_t *aRY,
-                                 const nsSVGFilterInstance& aInstance)
-{
-  // Subtract an epsilon here because we don't want a value that's just
-  // slightly larger than an integer to round up to the next integer; it's
-  // probably meant to be the integer it's close to, modulo machine precision
-  // issues.
-  *aRX = NSToIntCeil(aInstance.GetPrimitiveNumber(SVGContentUtils::X,
-                                                  &mNumberPairAttributes[RADIUS],
-                                                  nsSVGNumberPair::eFirst) -
-                     MORPHOLOGY_EPSILON);
-  *aRY = NSToIntCeil(aInstance.GetPrimitiveNumber(SVGContentUtils::Y,
-                                                  &mNumberPairAttributes[RADIUS],
-                                                  nsSVGNumberPair::eSecond) -
-                     MORPHOLOGY_EPSILON);
-}
-
-nsresult
-nsSVGFEMorphologyElement::Filter(nsSVGFilterInstance *instance,
-                                 const nsTArray& aSources,
-                                 const Image* aTarget,
-                                 const nsIntRect& rect)
-{
-  int32_t rx, ry;
-  GetRXY(&rx, &ry, *instance);
-
-  if (rx < 0 || ry < 0) {
-    // XXX SVGContentUtils::ReportToConsole()
-    return NS_OK;
-  }
-  if (rx == 0 && ry == 0) {
-    return NS_OK;
-  }
-
-  // Clamp radii to prevent completely insane values:
-  rx = std::min(rx, 100000);
-  ry = std::min(ry, 100000);
-
-  uint8_t* sourceData = aSources[0]->mImage->Data();
-  uint8_t* targetData = aTarget->mImage->Data();
-  int32_t stride = aTarget->mImage->Stride();
-  uint8_t extrema[4];         // RGBA magnitude of extrema
-  uint16_t op = mEnumAttributes[OPERATOR].GetAnimValue();
-
-  // Scan the kernel for each pixel to determine max/min RGBA values.
-  for (int32_t y = rect.y; y < rect.YMost(); y++) {
-    int32_t startY = std::max(0, y - ry);
-    // We need to read pixels not just in 'rect', which is limited to
-    // the dirty part of our filter primitive subregion, but all pixels in
-    // the given radii from the source surface, so use the surface size here.
-    int32_t endY = std::min(y + ry, instance->GetSurfaceHeight() - 1);
-    for (int32_t x = rect.x; x < rect.XMost(); x++) {
-      int32_t startX = std::max(0, x - rx);
-      int32_t endX = std::min(x + rx, instance->GetSurfaceWidth() - 1);
-      int32_t targIndex = y * stride + 4 * x;
-
-      for (int32_t i = 0; i < 4; i++) {
-        extrema[i] = sourceData[targIndex + i];
-      }
-      for (int32_t y1 = startY; y1 <= endY; y1++) {
-        for (int32_t x1 = startX; x1 <= endX; x1++) {
-          for (int32_t i = 0; i < 4; i++) {
-            uint8_t pixel = sourceData[y1 * stride + 4 * x1 + i];
-            if ((extrema[i] > pixel &&
-                 op == nsSVGFEMorphologyElement::SVG_OPERATOR_ERODE) ||
-                (extrema[i] < pixel &&
-                 op == nsSVGFEMorphologyElement::SVG_OPERATOR_DILATE)) {
-              extrema[i] = pixel;
-            }
-          }
-        }
-      }
-      targetData[targIndex  ] = extrema[0];
-      targetData[targIndex+1] = extrema[1];
-      targetData[targIndex+2] = extrema[2];
-      targetData[targIndex+3] = extrema[3];
-    }
-  }
-  return NS_OK;
-}
-
-bool
-nsSVGFEMorphologyElement::AttributeAffectsRendering(int32_t aNameSpaceID,
-                                                    nsIAtom* aAttribute) const
-{
-  return nsSVGFEMorphologyElementBase::AttributeAffectsRendering(aNameSpaceID, aAttribute) ||
-         (aNameSpaceID == kNameSpaceID_None &&
-          (aAttribute == nsGkAtoms::in ||
-           aAttribute == nsGkAtoms::radius ||
-           aAttribute == nsGkAtoms::_operator));
-}
-
-//----------------------------------------------------------------------
-// nsSVGElement methods
-
-nsSVGElement::NumberPairAttributesInfo
-nsSVGFEMorphologyElement::GetNumberPairInfo()
-{
-  return NumberPairAttributesInfo(mNumberPairAttributes, sNumberPairInfo,
-                                  ArrayLength(sNumberPairInfo));
-}
-
-nsSVGElement::EnumAttributesInfo
-nsSVGFEMorphologyElement::GetEnumInfo()
-{
-  return EnumAttributesInfo(mEnumAttributes, sEnumInfo,
-                            ArrayLength(sEnumInfo));
-}
-
-nsSVGElement::StringAttributesInfo
-nsSVGFEMorphologyElement::GetStringInfo()
-{
-  return StringAttributesInfo(mStringAttributes, sStringInfo,
-                              ArrayLength(sStringInfo));
-}
-
 //--------------------------------------------------------------------
 //
 nsSVGElement::NumberInfo nsSVGFELightingElement::sNumberInfo[4] =

From 2077c75f8c67fc71a09c313113b4411a679b1079 Mon Sep 17 00:00:00 2001
From: David Zbarsky 
Date: Tue, 26 Mar 2013 19:43:33 -0400
Subject: [PATCH 090/129] Bug 847120: Convert SVGFEMorphologyElement to WebIDL
 r=Ms2ger

---
 .../content/src/SVGFEMorphologyElement.cpp    | 132 +++++++++---------
 .../svg/content/src/SVGFEMorphologyElement.h  |  42 +++---
 dom/base/nsDOMClassInfo.cpp                   |   8 --
 dom/base/nsDOMClassInfoClasses.h              |   1 -
 dom/interfaces/svg/nsIDOMSVGFilters.idl       |  16 ---
 dom/webidl/SVGFEMorphologyElement.webidl      |  30 ++++
 dom/webidl/WebIDL.mk                          |   1 +
 7 files changed, 126 insertions(+), 104 deletions(-)
 create mode 100644 dom/webidl/SVGFEMorphologyElement.webidl

diff --git a/content/svg/content/src/SVGFEMorphologyElement.cpp b/content/svg/content/src/SVGFEMorphologyElement.cpp
index d91e6a425b62..e1814ec65b49 100644
--- a/content/svg/content/src/SVGFEMorphologyElement.cpp
+++ b/content/svg/content/src/SVGFEMorphologyElement.cpp
@@ -4,104 +4,110 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/dom/SVGFEMorphologyElement.h"
+#include "mozilla/dom/SVGFEMorphologyElementBinding.h"
+#include "nsSVGFilterInstance.h"
+
+NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(FEMorphology)
 
 namespace mozilla {
 namespace dom {
 
-nsSVGElement::NumberPairInfo nsSVGFEMorphologyElement::sNumberPairInfo[1] =
+JSObject*
+SVGFEMorphologyElement::WrapNode(JSContext* aCx, JSObject* aScope)
+{
+  return SVGFEMorphologyElementBinding::Wrap(aCx, aScope, this);
+}
+
+// Morphology Operators
+static const unsigned short SVG_OPERATOR_UNKNOWN = 0;
+static const unsigned short SVG_OPERATOR_ERODE = 1;
+static const unsigned short SVG_OPERATOR_DILATE = 2;
+
+nsSVGElement::NumberPairInfo SVGFEMorphologyElement::sNumberPairInfo[1] =
 {
   { &nsGkAtoms::radius, 0, 0 }
 };
 
-nsSVGEnumMapping nsSVGFEMorphologyElement::sOperatorMap[] = {
-  {&nsGkAtoms::erode, nsSVGFEMorphologyElement::SVG_OPERATOR_ERODE},
-  {&nsGkAtoms::dilate, nsSVGFEMorphologyElement::SVG_OPERATOR_DILATE},
+nsSVGEnumMapping SVGFEMorphologyElement::sOperatorMap[] = {
+  {&nsGkAtoms::erode, SVG_OPERATOR_ERODE},
+  {&nsGkAtoms::dilate, SVG_OPERATOR_DILATE},
   {nullptr, 0}
 };
 
-nsSVGElement::EnumInfo nsSVGFEMorphologyElement::sEnumInfo[1] =
+nsSVGElement::EnumInfo SVGFEMorphologyElement::sEnumInfo[1] =
 {
   { &nsGkAtoms::_operator,
     sOperatorMap,
-    nsSVGFEMorphologyElement::SVG_OPERATOR_ERODE
+    SVG_OPERATOR_ERODE
   }
 };
 
-nsSVGElement::StringInfo nsSVGFEMorphologyElement::sStringInfo[2] =
+nsSVGElement::StringInfo SVGFEMorphologyElement::sStringInfo[2] =
 {
   { &nsGkAtoms::result, kNameSpaceID_None, true },
   { &nsGkAtoms::in, kNameSpaceID_None, true }
 };
 
-NS_IMPL_NS_NEW_SVG_ELEMENT(FEMorphology)
-
 //----------------------------------------------------------------------
 // nsISupports methods
 
-NS_IMPL_ADDREF_INHERITED(nsSVGFEMorphologyElement,nsSVGFEMorphologyElementBase)
-NS_IMPL_RELEASE_INHERITED(nsSVGFEMorphologyElement,nsSVGFEMorphologyElementBase)
+NS_IMPL_ADDREF_INHERITED(SVGFEMorphologyElement,SVGFEMorphologyElementBase)
+NS_IMPL_RELEASE_INHERITED(SVGFEMorphologyElement,SVGFEMorphologyElementBase)
 
-DOMCI_NODE_DATA(SVGFEMorphologyElement, nsSVGFEMorphologyElement)
-
-NS_INTERFACE_TABLE_HEAD(nsSVGFEMorphologyElement)
-  NS_NODE_INTERFACE_TABLE5(nsSVGFEMorphologyElement, nsIDOMNode, nsIDOMElement,
-                           nsIDOMSVGElement,
-                           nsIDOMSVGFilterPrimitiveStandardAttributes,
-                           nsIDOMSVGFEMorphologyElement)
-  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGFEMorphologyElement)
-NS_INTERFACE_MAP_END_INHERITING(nsSVGFEMorphologyElementBase)
+NS_INTERFACE_TABLE_HEAD(SVGFEMorphologyElement)
+  NS_NODE_INTERFACE_TABLE3(SVGFEMorphologyElement, nsIDOMNode, nsIDOMElement,
+                           nsIDOMSVGElement)
+NS_INTERFACE_MAP_END_INHERITING(SVGFEMorphologyElementBase)
 
 //----------------------------------------------------------------------
 // nsIDOMNode methods
 
 
-NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGFEMorphologyElement)
+NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGFEMorphologyElement)
 
 
 //----------------------------------------------------------------------
-// nsSVGFEMorphologyElement methods
+// SVGFEMorphologyElement methods
 
-/* readonly attribute nsIDOMSVGAnimatedString in1; */
-NS_IMETHODIMP nsSVGFEMorphologyElement::GetIn1(nsIDOMSVGAnimatedString * *aIn)
+already_AddRefed
+SVGFEMorphologyElement::In1()
 {
-  return mStringAttributes[IN1].ToDOMAnimatedString(aIn, this);
+  return mStringAttributes[IN1].ToDOMAnimatedString(this);
 }
 
-/* readonly attribute nsIDOMSVGAnimatedEnumeration operator; */
-NS_IMETHODIMP nsSVGFEMorphologyElement::GetOperator(nsIDOMSVGAnimatedEnumeration * *aOperator)
+already_AddRefed
+SVGFEMorphologyElement::Operator()
 {
-  return mEnumAttributes[OPERATOR].ToDOMAnimatedEnum(aOperator, this);
+  return mEnumAttributes[OPERATOR].ToDOMAnimatedEnum(this);
 }
 
-/* readonly attribute nsIDOMSVGAnimatedNumber radiusX; */
-NS_IMETHODIMP nsSVGFEMorphologyElement::GetRadiusX(nsIDOMSVGAnimatedNumber * *aX)
+already_AddRefed
+SVGFEMorphologyElement::RadiusX()
 {
-  return mNumberPairAttributes[RADIUS].ToDOMAnimatedNumber(aX, nsSVGNumberPair::eFirst, this);
+  return mNumberPairAttributes[RADIUS].ToDOMAnimatedNumber(nsSVGNumberPair::eFirst, this);
 }
 
-/* readonly attribute nsIDOMSVGAnimatedNumber radiusY; */
-NS_IMETHODIMP nsSVGFEMorphologyElement::GetRadiusY(nsIDOMSVGAnimatedNumber * *aY)
+already_AddRefed
+SVGFEMorphologyElement::RadiusY()
 {
-  return mNumberPairAttributes[RADIUS].ToDOMAnimatedNumber(aY, nsSVGNumberPair::eSecond, this);
-}
-
-NS_IMETHODIMP
-nsSVGFEMorphologyElement::SetRadius(float rx, float ry)
-{
-  NS_ENSURE_FINITE2(rx, ry, NS_ERROR_ILLEGAL_VALUE);
-  mNumberPairAttributes[RADIUS].SetBaseValues(rx, ry, this);
-  return NS_OK;
+  return mNumberPairAttributes[RADIUS].ToDOMAnimatedNumber(nsSVGNumberPair::eSecond, this);
 }
 
 void
-nsSVGFEMorphologyElement::GetSourceImageNames(nsTArray& aSources)
+SVGFEMorphologyElement::SetRadius(float rx, float ry)
+{
+  mNumberPairAttributes[RADIUS].SetBaseValues(rx, ry, this);
+}
+
+void
+SVGFEMorphologyElement::GetSourceImageNames(nsTArray& aSources)
 {
   aSources.AppendElement(nsSVGStringInfo(&mStringAttributes[IN1], this));
 }
 
 nsIntRect
-nsSVGFEMorphologyElement::InflateRect(const nsIntRect& aRect,
-                                      const nsSVGFilterInstance& aInstance)
+SVGFEMorphologyElement::InflateRect(const nsIntRect& aRect,
+                                    const nsSVGFilterInstance& aInstance)
 {
   int32_t rx, ry;
   GetRXY(&rx, &ry, aInstance);
@@ -111,22 +117,22 @@ nsSVGFEMorphologyElement::InflateRect(const nsIntRect& aRect,
 }
 
 nsIntRect
-nsSVGFEMorphologyElement::ComputeTargetBBox(const nsTArray& aSourceBBoxes,
+SVGFEMorphologyElement::ComputeTargetBBox(const nsTArray& aSourceBBoxes,
         const nsSVGFilterInstance& aInstance)
 {
   return InflateRect(aSourceBBoxes[0], aInstance);
 }
 
 void
-nsSVGFEMorphologyElement::ComputeNeededSourceBBoxes(const nsIntRect& aTargetBBox,
+SVGFEMorphologyElement::ComputeNeededSourceBBoxes(const nsIntRect& aTargetBBox,
           nsTArray& aSourceBBoxes, const nsSVGFilterInstance& aInstance)
 {
   aSourceBBoxes[0] = InflateRect(aTargetBBox, aInstance);
 }
 
 nsIntRect
-nsSVGFEMorphologyElement::ComputeChangeBBox(const nsTArray& aSourceChangeBoxes,
-                                            const nsSVGFilterInstance& aInstance)
+SVGFEMorphologyElement::ComputeChangeBBox(const nsTArray& aSourceChangeBoxes,
+                                          const nsSVGFilterInstance& aInstance)
 {
   return InflateRect(aSourceChangeBoxes[0], aInstance);
 }
@@ -134,8 +140,8 @@ nsSVGFEMorphologyElement::ComputeChangeBBox(const nsTArray& aSourceCh
 #define MORPHOLOGY_EPSILON 0.0001
 
 void
-nsSVGFEMorphologyElement::GetRXY(int32_t *aRX, int32_t *aRY,
-                                 const nsSVGFilterInstance& aInstance)
+SVGFEMorphologyElement::GetRXY(int32_t *aRX, int32_t *aRY,
+                               const nsSVGFilterInstance& aInstance)
 {
   // Subtract an epsilon here because we don't want a value that's just
   // slightly larger than an integer to round up to the next integer; it's
@@ -152,10 +158,10 @@ nsSVGFEMorphologyElement::GetRXY(int32_t *aRX, int32_t *aRY,
 }
 
 nsresult
-nsSVGFEMorphologyElement::Filter(nsSVGFilterInstance *instance,
-                                 const nsTArray& aSources,
-                                 const Image* aTarget,
-                                 const nsIntRect& rect)
+SVGFEMorphologyElement::Filter(nsSVGFilterInstance* instance,
+                               const nsTArray& aSources,
+                               const Image* aTarget,
+                               const nsIntRect& rect)
 {
   int32_t rx, ry;
   GetRXY(&rx, &ry, *instance);
@@ -198,9 +204,9 @@ nsSVGFEMorphologyElement::Filter(nsSVGFilterInstance *instance,
           for (int32_t i = 0; i < 4; i++) {
             uint8_t pixel = sourceData[y1 * stride + 4 * x1 + i];
             if ((extrema[i] > pixel &&
-                 op == nsSVGFEMorphologyElement::SVG_OPERATOR_ERODE) ||
+                 op == SVG_OPERATOR_ERODE) ||
                 (extrema[i] < pixel &&
-                 op == nsSVGFEMorphologyElement::SVG_OPERATOR_DILATE)) {
+                 op == SVG_OPERATOR_DILATE)) {
               extrema[i] = pixel;
             }
           }
@@ -216,10 +222,10 @@ nsSVGFEMorphologyElement::Filter(nsSVGFilterInstance *instance,
 }
 
 bool
-nsSVGFEMorphologyElement::AttributeAffectsRendering(int32_t aNameSpaceID,
-                                                    nsIAtom* aAttribute) const
+SVGFEMorphologyElement::AttributeAffectsRendering(int32_t aNameSpaceID,
+                                                  nsIAtom* aAttribute) const
 {
-  return nsSVGFEMorphologyElementBase::AttributeAffectsRendering(aNameSpaceID, aAttribute) ||
+  return SVGFEMorphologyElementBase::AttributeAffectsRendering(aNameSpaceID, aAttribute) ||
          (aNameSpaceID == kNameSpaceID_None &&
           (aAttribute == nsGkAtoms::in ||
            aAttribute == nsGkAtoms::radius ||
@@ -230,21 +236,21 @@ nsSVGFEMorphologyElement::AttributeAffectsRendering(int32_t aNameSpaceID,
 // nsSVGElement methods
 
 nsSVGElement::NumberPairAttributesInfo
-nsSVGFEMorphologyElement::GetNumberPairInfo()
+SVGFEMorphologyElement::GetNumberPairInfo()
 {
   return NumberPairAttributesInfo(mNumberPairAttributes, sNumberPairInfo,
                                   ArrayLength(sNumberPairInfo));
 }
 
 nsSVGElement::EnumAttributesInfo
-nsSVGFEMorphologyElement::GetEnumInfo()
+SVGFEMorphologyElement::GetEnumInfo()
 {
   return EnumAttributesInfo(mEnumAttributes, sEnumInfo,
                             ArrayLength(sEnumInfo));
 }
 
 nsSVGElement::StringAttributesInfo
-nsSVGFEMorphologyElement::GetStringInfo()
+SVGFEMorphologyElement::GetStringInfo()
 {
   return StringAttributesInfo(mStringAttributes, sStringInfo,
                               ArrayLength(sStringInfo));
diff --git a/content/svg/content/src/SVGFEMorphologyElement.h b/content/svg/content/src/SVGFEMorphologyElement.h
index 27fd0c911a0b..fc0c46893fff 100644
--- a/content/svg/content/src/SVGFEMorphologyElement.h
+++ b/content/svg/content/src/SVGFEMorphologyElement.h
@@ -6,29 +6,36 @@
 #ifndef mozilla_dom_SVGFEMorphologyElement_h
 #define mozilla_dom_SVGFEMorphologyElement_h
 
+#include "nsSVGEnum.h"
 #include "nsSVGFilters.h"
+#include "nsSVGNumberPair.h"
+#include "nsSVGString.h"
+
+nsresult NS_NewSVGFEMorphologyElement(nsIContent **aResult,
+                                      already_AddRefed aNodeInfo);
 
 namespace mozilla {
 namespace dom {
 
-typedef nsSVGFE nsSVGFEMorphologyElementBase;
+typedef nsSVGFE SVGFEMorphologyElementBase;
 
-class nsSVGFEMorphologyElement : public nsSVGFEMorphologyElementBase,
-                                 public nsIDOMSVGFEMorphologyElement
+class SVGFEMorphologyElement : public SVGFEMorphologyElementBase,
+                               public nsIDOMSVGElement
 {
-  friend nsresult NS_NewSVGFEMorphologyElement(nsIContent **aResult,
-                                               already_AddRefed aNodeInfo);
+  friend nsresult (::NS_NewSVGFEMorphologyElement(nsIContent **aResult,
+                                                  already_AddRefed aNodeInfo));
 protected:
-  nsSVGFEMorphologyElement(already_AddRefed aNodeInfo)
-    : nsSVGFEMorphologyElementBase(aNodeInfo) {}
+  SVGFEMorphologyElement(already_AddRefed aNodeInfo)
+    : SVGFEMorphologyElementBase(aNodeInfo)
+  {
+    SetIsDOMBinding();
+  }
+  virtual JSObject* WrapNode(JSContext* aCx, JSObject* aScope) MOZ_OVERRIDE;
 
 public:
   // interfaces:
   NS_DECL_ISUPPORTS_INHERITED
 
-  // FE Base
-  NS_FORWARD_NSIDOMSVGFILTERPRIMITIVESTANDARDATTRIBUTES(nsSVGFEMorphologyElementBase::)
-
   virtual nsresult Filter(nsSVGFilterInstance* aInstance,
                           const nsTArray& aSources,
                           const Image* aTarget,
@@ -44,19 +51,22 @@ public:
   virtual nsIntRect ComputeChangeBBox(const nsTArray& aSourceChangeBoxes,
           const nsSVGFilterInstance& aInstance);
 
-  // Morphology
-  NS_DECL_NSIDOMSVGFEMORPHOLOGYELEMENT
-
-  NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFEMorphologyElementBase::)
+  NS_FORWARD_NSIDOMSVGELEMENT(SVGFEMorphologyElementBase::)
 
   NS_FORWARD_NSIDOMNODE_TO_NSINODE
   NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
 
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
 
-  virtual nsXPCClassInfo* GetClassInfo();
-
   virtual nsIDOMNode* AsDOMNode() { return this; }
+
+  // WebIDL
+  already_AddRefed In1();
+  already_AddRefed Operator();
+  already_AddRefed RadiusX();
+  already_AddRefed RadiusY();
+  void SetRadius(float rx, float ry);
+
 protected:
   void GetRXY(int32_t *aRX, int32_t *aRY, const nsSVGFilterInstance& aInstance);
   nsIntRect InflateRect(const nsIntRect& aRect, const nsSVGFilterInstance& aInstance);
diff --git a/dom/base/nsDOMClassInfo.cpp b/dom/base/nsDOMClassInfo.cpp
index f2d4b96ba317..0f25aa4b4f87 100644
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -812,8 +812,6 @@ static nsDOMClassInfoData sClassInfoData[] = {
   // SVG element classes
   NS_DEFINE_CLASSINFO_DATA(TimeEvent, nsEventSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
-  NS_DEFINE_CLASSINFO_DATA(SVGFEMorphologyElement, nsElementSH,
-                           ELEMENT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(SVGFETurbulenceElement, nsElementSH,
                            ELEMENT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA_WITH_NAME(SVGUnknownElement, SVGElement, nsElementSH,
@@ -2225,12 +2223,6 @@ nsDOMClassInfo::Init()
     DOM_CLASSINFO_EVENT_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
-  DOM_CLASSINFO_MAP_BEGIN(SVGFEMorphologyElement, nsIDOMSVGFEMorphologyElement)
-    DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGFEMorphologyElement)
-    DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGFilterPrimitiveStandardAttributes)
-    DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES
-  DOM_CLASSINFO_MAP_END
-
   DOM_CLASSINFO_MAP_BEGIN(SVGFETurbulenceElement, nsIDOMSVGFETurbulenceElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGFETurbulenceElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGFilterPrimitiveStandardAttributes)
diff --git a/dom/base/nsDOMClassInfoClasses.h b/dom/base/nsDOMClassInfoClasses.h
index e84bb04c0376..0163b37df793 100644
--- a/dom/base/nsDOMClassInfoClasses.h
+++ b/dom/base/nsDOMClassInfoClasses.h
@@ -122,7 +122,6 @@ DOMCI_CLASS(SVGDocument)
 
 // SVG element classes
 DOMCI_CLASS(TimeEvent)
-DOMCI_CLASS(SVGFEMorphologyElement)
 DOMCI_CLASS(SVGFETurbulenceElement)
 DOMCI_CLASS(SVGUnknownElement)
 
diff --git a/dom/interfaces/svg/nsIDOMSVGFilters.idl b/dom/interfaces/svg/nsIDOMSVGFilters.idl
index 7b3d75f8ae5b..bdd158247189 100644
--- a/dom/interfaces/svg/nsIDOMSVGFilters.idl
+++ b/dom/interfaces/svg/nsIDOMSVGFilters.idl
@@ -40,19 +40,3 @@ interface nsIDOMSVGFETurbulenceElement : nsIDOMSVGFilterPrimitiveStandardAttribu
     readonly attribute nsIDOMSVGAnimatedEnumeration stitchTiles;
     readonly attribute nsIDOMSVGAnimatedEnumeration type;
 };
-
-[scriptable, uuid(053c0aec-30df-48e9-9059-53f43b5261bb)]
-interface nsIDOMSVGFEMorphologyElement : nsIDOMSVGFilterPrimitiveStandardAttributes
-{ 
-    // Operator Types
-    const unsigned short SVG_OPERATOR_UNKNOWN  = 0;
-    const unsigned short SVG_OPERATOR_ERODE    = 1;
-    const unsigned short SVG_OPERATOR_DILATE   = 2;
-
-    readonly attribute nsIDOMSVGAnimatedString      in1;
-    readonly attribute nsIDOMSVGAnimatedNumber      radiusX;
-    readonly attribute nsIDOMSVGAnimatedNumber      radiusY;
-    readonly attribute nsIDOMSVGAnimatedEnumeration operator;
-    
-    void setRadius ( in float rx, in float ry );
-};
diff --git a/dom/webidl/SVGFEMorphologyElement.webidl b/dom/webidl/SVGFEMorphologyElement.webidl
new file mode 100644
index 000000000000..28c27730cbed
--- /dev/null
+++ b/dom/webidl/SVGFEMorphologyElement.webidl
@@ -0,0 +1,30 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * The origin of this IDL file is
+ * http://www.w3.org/TR/SVG2/
+ *
+ * Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
+ * liability, trademark and document use rules apply.
+ */
+
+interface SVGAnimatedEnumeration;
+interface SVGAnimatedNumber;
+interface SVGAnimatedString;
+
+interface SVGFEMorphologyElement : SVGElement {
+
+  // Morphology Operators
+  const unsigned short SVG_MORPHOLOGY_OPERATOR_UNKNOWN = 0;
+  const unsigned short SVG_MORPHOLOGY_OPERATOR_ERODE = 1;
+  const unsigned short SVG_MORPHOLOGY_OPERATOR_DILATE = 2;
+
+  readonly attribute SVGAnimatedString in1;
+  readonly attribute SVGAnimatedEnumeration operator;
+  readonly attribute SVGAnimatedNumber radiusX;
+  readonly attribute SVGAnimatedNumber radiusY;
+};
+
+SVGFEMorphologyElement implements SVGFilterPrimitiveStandardAttributes;
diff --git a/dom/webidl/WebIDL.mk b/dom/webidl/WebIDL.mk
index 0963f11ba400..5b9a6431107f 100644
--- a/dom/webidl/WebIDL.mk
+++ b/dom/webidl/WebIDL.mk
@@ -206,6 +206,7 @@ webidl_files = \
   SVGFEImageElement.webidl \
   SVGFEMergeElement.webidl \
   SVGFEMergeNodeElement.webidl \
+  SVGFEMorphologyElement.webidl \
   SVGFEOffsetElement.webidl \
   SVGFEPointLightElement.webidl \
   SVGFESpecularLightingElement.webidl \

From 84fe1989bfff5c89ccf849147c092b5548964ac9 Mon Sep 17 00:00:00 2001
From: David Zbarsky 
Date: Tue, 26 Mar 2013 19:43:33 -0400
Subject: [PATCH 091/129] Bug 847120: Move SVGFETurbulenceElement to its own
 file r=Ms2ger

--HG--
rename : content/svg/content/src/nsSVGFilters.cpp => content/svg/content/src/SVGFETurbulenceElement.cpp
rename : content/svg/content/src/nsSVGFilters.cpp => content/svg/content/src/SVGFETurbulenceElement.h
---
 content/svg/content/src/Makefile.in           |   2 +
 .../content/src/SVGFETurbulenceElement.cpp    | 422 ++++++++++++++
 .../svg/content/src/SVGFETurbulenceElement.h  | 151 +++++
 content/svg/content/src/nsSVGFilters.cpp      | 546 ------------------
 4 files changed, 575 insertions(+), 546 deletions(-)
 create mode 100644 content/svg/content/src/SVGFETurbulenceElement.cpp
 create mode 100644 content/svg/content/src/SVGFETurbulenceElement.h

diff --git a/content/svg/content/src/Makefile.in b/content/svg/content/src/Makefile.in
index 18244ce3451a..3db9c5731488 100644
--- a/content/svg/content/src/Makefile.in
+++ b/content/svg/content/src/Makefile.in
@@ -95,6 +95,7 @@ CPPSRCS		= \
 		SVGFESpecularLightingElement.cpp \
 		SVGFESpotLightElement.cpp \
 		SVGFETileElement.cpp \
+		SVGFETurbulenceElement.cpp \
 		SVGFilterElement.cpp \
 		SVGForeignObjectElement.cpp \
 		SVGFragmentIdentifier.cpp \
@@ -208,6 +209,7 @@ EXPORTS_mozilla/dom = \
 	SVGFESpecularLightingElement.h \
 	SVGFESpotLightElement.h \
 	SVGFETileElement.h \
+	SVGFETurbulenceElement.h \
 	SVGFilterElement.h \
 	SVGForeignObjectElement.h \
 	SVGGElement.h \
diff --git a/content/svg/content/src/SVGFETurbulenceElement.cpp b/content/svg/content/src/SVGFETurbulenceElement.cpp
new file mode 100644
index 000000000000..92bf61f41126
--- /dev/null
+++ b/content/svg/content/src/SVGFETurbulenceElement.cpp
@@ -0,0 +1,422 @@
+/* a*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/dom/SVGFETurbulenceElement.h"
+
+namespace mozilla {
+namespace dom {
+
+nsSVGElement::NumberInfo nsSVGFETurbulenceElement::sNumberInfo[1] =
+{
+  { &nsGkAtoms::seed, 0, false }
+};
+
+nsSVGElement::NumberPairInfo nsSVGFETurbulenceElement::sNumberPairInfo[1] =
+{
+  { &nsGkAtoms::baseFrequency, 0, 0 }
+};
+
+nsSVGElement::IntegerInfo nsSVGFETurbulenceElement::sIntegerInfo[1] =
+{
+  { &nsGkAtoms::numOctaves, 1 }
+};
+
+nsSVGEnumMapping nsSVGFETurbulenceElement::sTypeMap[] = {
+  {&nsGkAtoms::fractalNoise,
+   nsIDOMSVGFETurbulenceElement::SVG_TURBULENCE_TYPE_FRACTALNOISE},
+  {&nsGkAtoms::turbulence,
+   nsIDOMSVGFETurbulenceElement::SVG_TURBULENCE_TYPE_TURBULENCE},
+  {nullptr, 0}
+};
+
+nsSVGEnumMapping nsSVGFETurbulenceElement::sStitchTilesMap[] = {
+  {&nsGkAtoms::stitch,
+   nsIDOMSVGFETurbulenceElement::SVG_STITCHTYPE_STITCH},
+  {&nsGkAtoms::noStitch,
+   nsIDOMSVGFETurbulenceElement::SVG_STITCHTYPE_NOSTITCH},
+  {nullptr, 0}
+};
+
+nsSVGElement::EnumInfo nsSVGFETurbulenceElement::sEnumInfo[2] =
+{
+  { &nsGkAtoms::type,
+    sTypeMap,
+    nsIDOMSVGFETurbulenceElement::SVG_TURBULENCE_TYPE_TURBULENCE
+  },
+  { &nsGkAtoms::stitchTiles,
+    sStitchTilesMap,
+    nsIDOMSVGFETurbulenceElement::SVG_STITCHTYPE_NOSTITCH
+  }
+};
+
+nsSVGElement::StringInfo nsSVGFETurbulenceElement::sStringInfo[1] =
+{
+  { &nsGkAtoms::result, kNameSpaceID_None, true }
+};
+
+NS_IMPL_NS_NEW_SVG_ELEMENT(FETurbulence)
+
+//----------------------------------------------------------------------
+// nsISupports methods
+
+NS_IMPL_ADDREF_INHERITED(nsSVGFETurbulenceElement,nsSVGFETurbulenceElementBase)
+NS_IMPL_RELEASE_INHERITED(nsSVGFETurbulenceElement,nsSVGFETurbulenceElementBase)
+
+DOMCI_NODE_DATA(SVGFETurbulenceElement, nsSVGFETurbulenceElement)
+
+NS_INTERFACE_TABLE_HEAD(nsSVGFETurbulenceElement)
+  NS_NODE_INTERFACE_TABLE5(nsSVGFETurbulenceElement, nsIDOMNode, nsIDOMElement,
+                           nsIDOMSVGElement,
+                           nsIDOMSVGFilterPrimitiveStandardAttributes,
+                           nsIDOMSVGFETurbulenceElement)
+  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGFETurbulenceElement)
+NS_INTERFACE_MAP_END_INHERITING(nsSVGFETurbulenceElementBase)
+
+//----------------------------------------------------------------------
+// nsIDOMNode methods
+
+NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGFETurbulenceElement)
+
+//----------------------------------------------------------------------
+// nsIDOMSVGFETurbulenceElement methods
+
+/* readonly attribute nsIDOMSVGAnimatedNumber baseFrequencyX; */
+NS_IMETHODIMP nsSVGFETurbulenceElement::GetBaseFrequencyX(nsIDOMSVGAnimatedNumber * *aX)
+{
+  return mNumberPairAttributes[BASE_FREQ].ToDOMAnimatedNumber(aX, nsSVGNumberPair::eFirst, this);
+}
+
+/* readonly attribute nsIDOMSVGAnimatedNumber baseFrequencyY; */
+NS_IMETHODIMP nsSVGFETurbulenceElement::GetBaseFrequencyY(nsIDOMSVGAnimatedNumber * *aY)
+{
+  return mNumberPairAttributes[BASE_FREQ].ToDOMAnimatedNumber(aY, nsSVGNumberPair::eSecond, this);
+}
+
+/* readonly attribute nsIDOMSVGAnimatedInteger numOctaves; */
+NS_IMETHODIMP nsSVGFETurbulenceElement::GetNumOctaves(nsIDOMSVGAnimatedInteger * *aNum)
+{
+  return mIntegerAttributes[OCTAVES].ToDOMAnimatedInteger(aNum, this);
+}
+
+/* readonly attribute nsIDOMSVGAnimatedNumber seed; */
+NS_IMETHODIMP nsSVGFETurbulenceElement::GetSeed(nsIDOMSVGAnimatedNumber * *aSeed)
+{
+  return mNumberAttributes[SEED].ToDOMAnimatedNumber(aSeed, this);
+}
+
+/* readonly attribute nsIDOMSVGAnimatedEnumeration stitchTiles; */
+NS_IMETHODIMP nsSVGFETurbulenceElement::GetStitchTiles(nsIDOMSVGAnimatedEnumeration * *aStitch)
+{
+  return mEnumAttributes[STITCHTILES].ToDOMAnimatedEnum(aStitch, this);
+}
+
+/* readonly attribute nsIDOMSVGAnimatedEnumeration type; */
+NS_IMETHODIMP nsSVGFETurbulenceElement::GetType(nsIDOMSVGAnimatedEnumeration * *aType)
+{
+  return mEnumAttributes[TYPE].ToDOMAnimatedEnum(aType, this);
+}
+
+nsresult
+nsSVGFETurbulenceElement::Filter(nsSVGFilterInstance *instance,
+                                 const nsTArray& aSources,
+                                 const Image* aTarget,
+                                 const nsIntRect& rect)
+{
+  uint8_t* targetData = aTarget->mImage->Data();
+  uint32_t stride = aTarget->mImage->Stride();
+
+  nsIntRect filterSubregion(int32_t(aTarget->mFilterPrimitiveSubregion.X()),
+                            int32_t(aTarget->mFilterPrimitiveSubregion.Y()),
+                            int32_t(aTarget->mFilterPrimitiveSubregion.Width()),
+                            int32_t(aTarget->mFilterPrimitiveSubregion.Height()));
+
+  float fX = mNumberPairAttributes[BASE_FREQ].GetAnimValue(nsSVGNumberPair::eFirst);
+  float fY = mNumberPairAttributes[BASE_FREQ].GetAnimValue(nsSVGNumberPair::eSecond);
+  float seed = mNumberAttributes[OCTAVES].GetAnimValue();
+  int32_t octaves = mIntegerAttributes[OCTAVES].GetAnimValue();
+  uint16_t type = mEnumAttributes[TYPE].GetAnimValue();
+  uint16_t stitch = mEnumAttributes[STITCHTILES].GetAnimValue();
+
+  InitSeed((int32_t)seed);
+
+  // XXXroc this makes absolutely no sense to me.
+  float filterX = instance->GetFilterRegion().X();
+  float filterY = instance->GetFilterRegion().Y();
+  float filterWidth = instance->GetFilterRegion().Width();
+  float filterHeight = instance->GetFilterRegion().Height();
+
+  bool doStitch = false;
+  if (stitch == nsIDOMSVGFETurbulenceElement::SVG_STITCHTYPE_STITCH) {
+    doStitch = true;
+
+    float lowFreq, hiFreq;
+
+    lowFreq = floor(filterWidth * fX) / filterWidth;
+    hiFreq = ceil(filterWidth * fX) / filterWidth;
+    if (fX / lowFreq < hiFreq / fX)
+      fX = lowFreq;
+    else
+      fX = hiFreq;
+
+    lowFreq = floor(filterHeight * fY) / filterHeight;
+    hiFreq = ceil(filterHeight * fY) / filterHeight;
+    if (fY / lowFreq < hiFreq / fY)
+      fY = lowFreq;
+    else
+      fY = hiFreq;
+  }
+  for (int32_t y = rect.y; y < rect.YMost(); y++) {
+    for (int32_t x = rect.x; x < rect.XMost(); x++) {
+      int32_t targIndex = y * stride + x * 4;
+      double point[2];
+      point[0] = filterX + (filterWidth * (x + instance->GetSurfaceRect().x)) / (filterSubregion.width - 1);
+      point[1] = filterY + (filterHeight * (y + instance->GetSurfaceRect().y)) / (filterSubregion.height - 1);
+
+      float col[4];
+      if (type == nsIDOMSVGFETurbulenceElement::SVG_TURBULENCE_TYPE_TURBULENCE) {
+        for (int i = 0; i < 4; i++)
+          col[i] = Turbulence(i, point, fX, fY, octaves, false,
+                              doStitch, filterX, filterY, filterWidth, filterHeight) * 255;
+      } else {
+        for (int i = 0; i < 4; i++)
+          col[i] = (Turbulence(i, point, fX, fY, octaves, true,
+                               doStitch, filterX, filterY, filterWidth, filterHeight) * 255 + 255) / 2;
+      }
+      for (int i = 0; i < 4; i++) {
+        col[i] = std::min(col[i], 255.f);
+        col[i] = std::max(col[i], 0.f);
+      }
+
+      uint8_t r, g, b, a;
+      a = uint8_t(col[3]);
+      FAST_DIVIDE_BY_255(r, unsigned(col[0]) * a);
+      FAST_DIVIDE_BY_255(g, unsigned(col[1]) * a);
+      FAST_DIVIDE_BY_255(b, unsigned(col[2]) * a);
+
+      targetData[targIndex + GFX_ARGB32_OFFSET_B] = b;
+      targetData[targIndex + GFX_ARGB32_OFFSET_G] = g;
+      targetData[targIndex + GFX_ARGB32_OFFSET_R] = r;
+      targetData[targIndex + GFX_ARGB32_OFFSET_A] = a;
+    }
+  }
+
+  return NS_OK;
+}
+
+bool
+nsSVGFETurbulenceElement::AttributeAffectsRendering(int32_t aNameSpaceID,
+                                                    nsIAtom* aAttribute) const
+{
+  return nsSVGFETurbulenceElementBase::AttributeAffectsRendering(aNameSpaceID, aAttribute) ||
+         (aNameSpaceID == kNameSpaceID_None &&
+          (aAttribute == nsGkAtoms::seed ||
+           aAttribute == nsGkAtoms::baseFrequency ||
+           aAttribute == nsGkAtoms::numOctaves ||
+           aAttribute == nsGkAtoms::type ||
+           aAttribute == nsGkAtoms::stitchTiles));
+}
+
+void
+nsSVGFETurbulenceElement::InitSeed(int32_t aSeed)
+{
+  double s;
+  int i, j, k;
+  aSeed = SetupSeed(aSeed);
+  for (k = 0; k < 4; k++) {
+    for (i = 0; i < sBSize; i++) {
+      mLatticeSelector[i] = i;
+      for (j = 0; j < 2; j++) {
+        mGradient[k][i][j] =
+          (double) (((aSeed =
+                      Random(aSeed)) % (sBSize + sBSize)) - sBSize) / sBSize;
+      }
+      s = double (sqrt
+                  (mGradient[k][i][0] * mGradient[k][i][0] +
+                   mGradient[k][i][1] * mGradient[k][i][1]));
+      mGradient[k][i][0] /= s;
+      mGradient[k][i][1] /= s;
+    }
+  }
+  while (--i) {
+    k = mLatticeSelector[i];
+    mLatticeSelector[i] = mLatticeSelector[j =
+                                           (aSeed =
+                                            Random(aSeed)) % sBSize];
+    mLatticeSelector[j] = k;
+  }
+  for (i = 0; i < sBSize + 2; i++) {
+    mLatticeSelector[sBSize + i] = mLatticeSelector[i];
+    for (k = 0; k < 4; k++)
+      for (j = 0; j < 2; j++)
+        mGradient[k][sBSize + i][j] = mGradient[k][i][j];
+  }
+}
+
+#define S_CURVE(t) ( t * t * (3. - 2. * t) )
+#define LERP(t, a, b) ( a + t * (b - a) )
+double
+nsSVGFETurbulenceElement::Noise2(int aColorChannel, double aVec[2],
+                                 StitchInfo *aStitchInfo)
+{
+  int bx0, bx1, by0, by1, b00, b10, b01, b11;
+  double rx0, rx1, ry0, ry1, *q, sx, sy, a, b, t, u, v;
+  register long i, j;
+  t = aVec[0] + sPerlinN;
+  bx0 = (int) t;
+  bx1 = bx0 + 1;
+  rx0 = t - (int) t;
+  rx1 = rx0 - 1.0f;
+  t = aVec[1] + sPerlinN;
+  by0 = (int) t;
+  by1 = by0 + 1;
+  ry0 = t - (int) t;
+  ry1 = ry0 - 1.0f;
+  // If stitching, adjust lattice points accordingly.
+  if (aStitchInfo != NULL) {
+    if (bx0 >= aStitchInfo->mWrapX)
+      bx0 -= aStitchInfo->mWidth;
+    if (bx1 >= aStitchInfo->mWrapX)
+      bx1 -= aStitchInfo->mWidth;
+    if (by0 >= aStitchInfo->mWrapY)
+      by0 -= aStitchInfo->mHeight;
+    if (by1 >= aStitchInfo->mWrapY)
+      by1 -= aStitchInfo->mHeight;
+  }
+  bx0 &= sBM;
+  bx1 &= sBM;
+  by0 &= sBM;
+  by1 &= sBM;
+  i = mLatticeSelector[bx0];
+  j = mLatticeSelector[bx1];
+  b00 = mLatticeSelector[i + by0];
+  b10 = mLatticeSelector[j + by0];
+  b01 = mLatticeSelector[i + by1];
+  b11 = mLatticeSelector[j + by1];
+  sx = double (S_CURVE(rx0));
+  sy = double (S_CURVE(ry0));
+  q = mGradient[aColorChannel][b00];
+  u = rx0 * q[0] + ry0 * q[1];
+  q = mGradient[aColorChannel][b10];
+  v = rx1 * q[0] + ry0 * q[1];
+  a = LERP(sx, u, v);
+  q = mGradient[aColorChannel][b01];
+  u = rx0 * q[0] + ry1 * q[1];
+  q = mGradient[aColorChannel][b11];
+  v = rx1 * q[0] + ry1 * q[1];
+  b = LERP(sx, u, v);
+  return LERP(sy, a, b);
+}
+#undef S_CURVE
+#undef LERP
+
+double
+nsSVGFETurbulenceElement::Turbulence(int aColorChannel, double *aPoint,
+                                     double aBaseFreqX, double aBaseFreqY,
+                                     int aNumOctaves, bool aFractalSum,
+                                     bool aDoStitching,
+                                     double aTileX, double aTileY,
+                                     double aTileWidth, double aTileHeight)
+{
+  StitchInfo stitch;
+  StitchInfo *stitchInfo = NULL; // Not stitching when NULL.
+  // Adjust the base frequencies if necessary for stitching.
+  if (aDoStitching) {
+    // When stitching tiled turbulence, the frequencies must be adjusted
+    // so that the tile borders will be continuous.
+    if (aBaseFreqX != 0.0) {
+      double loFreq = double (floor(aTileWidth * aBaseFreqX)) / aTileWidth;
+      double hiFreq = double (ceil(aTileWidth * aBaseFreqX)) / aTileWidth;
+      if (aBaseFreqX / loFreq < hiFreq / aBaseFreqX)
+        aBaseFreqX = loFreq;
+      else
+        aBaseFreqX = hiFreq;
+    }
+    if (aBaseFreqY != 0.0) {
+      double loFreq = double (floor(aTileHeight * aBaseFreqY)) / aTileHeight;
+      double hiFreq = double (ceil(aTileHeight * aBaseFreqY)) / aTileHeight;
+      if (aBaseFreqY / loFreq < hiFreq / aBaseFreqY)
+        aBaseFreqY = loFreq;
+      else
+        aBaseFreqY = hiFreq;
+    }
+    // Set up initial stitch values.
+    stitchInfo = &stitch;
+    stitch.mWidth = int (aTileWidth * aBaseFreqX + 0.5f);
+    stitch.mWrapX = int (aTileX * aBaseFreqX + sPerlinN + stitch.mWidth);
+    stitch.mHeight = int (aTileHeight * aBaseFreqY + 0.5f);
+    stitch.mWrapY = int (aTileY * aBaseFreqY + sPerlinN + stitch.mHeight);
+  }
+  double sum = 0.0f;
+  double vec[2];
+  vec[0] = aPoint[0] * aBaseFreqX;
+  vec[1] = aPoint[1] * aBaseFreqY;
+  double ratio = 1;
+  for (int octave = 0; octave < aNumOctaves; octave++) {
+    if (aFractalSum)
+      sum += double (Noise2(aColorChannel, vec, stitchInfo) / ratio);
+    else
+      sum += double (fabs(Noise2(aColorChannel, vec, stitchInfo)) / ratio);
+    vec[0] *= 2;
+    vec[1] *= 2;
+    ratio *= 2;
+    if (stitchInfo != NULL) {
+      // Update stitch values. Subtracting sPerlinN before the multiplication
+      // and adding it afterward simplifies to subtracting it once.
+      stitch.mWidth *= 2;
+      stitch.mWrapX = 2 * stitch.mWrapX - sPerlinN;
+      stitch.mHeight *= 2;
+      stitch.mWrapY = 2 * stitch.mWrapY - sPerlinN;
+    }
+  }
+  return sum;
+}
+
+nsIntRect
+nsSVGFETurbulenceElement::ComputeTargetBBox(const nsTArray& aSourceBBoxes,
+        const nsSVGFilterInstance& aInstance)
+{
+  return GetMaxRect();
+}
+
+//----------------------------------------------------------------------
+// nsSVGElement methods
+
+nsSVGElement::NumberAttributesInfo
+nsSVGFETurbulenceElement::GetNumberInfo()
+{
+  return NumberAttributesInfo(mNumberAttributes, sNumberInfo,
+                              ArrayLength(sNumberInfo));
+}
+
+nsSVGElement::NumberPairAttributesInfo
+nsSVGFETurbulenceElement::GetNumberPairInfo()
+{
+  return NumberPairAttributesInfo(mNumberPairAttributes, sNumberPairInfo,
+                                 ArrayLength(sNumberPairInfo));
+}
+
+nsSVGElement::IntegerAttributesInfo
+nsSVGFETurbulenceElement::GetIntegerInfo()
+{
+  return IntegerAttributesInfo(mIntegerAttributes, sIntegerInfo,
+                               ArrayLength(sIntegerInfo));
+}
+
+nsSVGElement::EnumAttributesInfo
+nsSVGFETurbulenceElement::GetEnumInfo()
+{
+  return EnumAttributesInfo(mEnumAttributes, sEnumInfo,
+                            ArrayLength(sEnumInfo));
+}
+
+nsSVGElement::StringAttributesInfo
+nsSVGFETurbulenceElement::GetStringInfo()
+{
+  return StringAttributesInfo(mStringAttributes, sStringInfo,
+                              ArrayLength(sStringInfo));
+}
+
+} // namespace dom
+} // namespace mozilla
diff --git a/content/svg/content/src/SVGFETurbulenceElement.h b/content/svg/content/src/SVGFETurbulenceElement.h
new file mode 100644
index 000000000000..0322b473a658
--- /dev/null
+++ b/content/svg/content/src/SVGFETurbulenceElement.h
@@ -0,0 +1,151 @@
+/* a*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_dom_SVGFETurbulenceElement_h
+#define mozilla_dom_SVGFETurbulenceElement_h
+
+#include "nsSVGFilters.h"
+
+namespace mozilla {
+namespace dom {
+
+typedef nsSVGFE nsSVGFETurbulenceElementBase;
+
+class nsSVGFETurbulenceElement : public nsSVGFETurbulenceElementBase,
+                                 public nsIDOMSVGFETurbulenceElement
+{
+  friend nsresult NS_NewSVGFETurbulenceElement(nsIContent **aResult,
+                                               already_AddRefed aNodeInfo);
+protected:
+  nsSVGFETurbulenceElement(already_AddRefed aNodeInfo)
+    : nsSVGFETurbulenceElementBase(aNodeInfo) {}
+
+public:
+  virtual bool SubregionIsUnionOfRegions() { return false; }
+
+  // interfaces:
+  NS_DECL_ISUPPORTS_INHERITED
+
+  // FE Base
+  NS_FORWARD_NSIDOMSVGFILTERPRIMITIVESTANDARDATTRIBUTES(nsSVGFETurbulenceElementBase::)
+
+  virtual nsresult Filter(nsSVGFilterInstance* aInstance,
+                          const nsTArray& aSources,
+                          const Image* aTarget,
+                          const nsIntRect& aDataRect);
+  virtual bool AttributeAffectsRendering(
+          int32_t aNameSpaceID, nsIAtom* aAttribute) const;
+  virtual nsSVGString& GetResultImageName() { return mStringAttributes[RESULT]; }
+  virtual nsIntRect ComputeTargetBBox(const nsTArray& aSourceBBoxes,
+          const nsSVGFilterInstance& aInstance);
+
+  // Turbulence
+  NS_DECL_NSIDOMSVGFETURBULENCEELEMENT
+
+  NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFETurbulenceElementBase::)
+
+  NS_FORWARD_NSIDOMNODE_TO_NSINODE
+  NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
+
+  virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
+
+  virtual nsXPCClassInfo* GetClassInfo();
+
+  virtual nsIDOMNode* AsDOMNode() { return this; }
+protected:
+  virtual NumberAttributesInfo GetNumberInfo();
+  virtual NumberPairAttributesInfo GetNumberPairInfo();
+  virtual IntegerAttributesInfo GetIntegerInfo();
+  virtual EnumAttributesInfo GetEnumInfo();
+  virtual StringAttributesInfo GetStringInfo();
+
+  enum { SEED }; // floating point seed?!
+  nsSVGNumber2 mNumberAttributes[1];
+  static NumberInfo sNumberInfo[1];
+
+  enum { BASE_FREQ };
+  nsSVGNumberPair mNumberPairAttributes[1];
+  static NumberPairInfo sNumberPairInfo[1];
+
+  enum { OCTAVES };
+  nsSVGInteger mIntegerAttributes[1];
+  static IntegerInfo sIntegerInfo[1];
+
+  enum { TYPE, STITCHTILES };
+  nsSVGEnum mEnumAttributes[2];
+  static nsSVGEnumMapping sTypeMap[];
+  static nsSVGEnumMapping sStitchTilesMap[];
+  static EnumInfo sEnumInfo[2];
+
+  enum { RESULT };
+  nsSVGString mStringAttributes[1];
+  static StringInfo sStringInfo[1];
+
+private:
+
+  /* The turbulence calculation code is an adapted version of what
+     appears in the SVG 1.1 specification:
+         http://www.w3.org/TR/SVG11/filters.html#feTurbulence
+  */
+
+  /* Produces results in the range [1, 2**31 - 2].
+     Algorithm is: r = (a * r) mod m
+     where a = 16807 and m = 2**31 - 1 = 2147483647
+     See [Park & Miller], CACM vol. 31 no. 10 p. 1195, Oct. 1988
+     To test: the algorithm should produce the result 1043618065
+     as the 10,000th generated number if the original seed is 1.
+  */
+#define RAND_M 2147483647	/* 2**31 - 1 */
+#define RAND_A 16807		/* 7**5; primitive root of m */
+#define RAND_Q 127773		/* m / a */
+#define RAND_R 2836		/* m % a */
+
+  int32_t SetupSeed(int32_t aSeed) {
+    if (aSeed <= 0)
+      aSeed = -(aSeed % (RAND_M - 1)) + 1;
+    if (aSeed > RAND_M - 1)
+      aSeed = RAND_M - 1;
+    return aSeed;
+  }
+
+  uint32_t Random(uint32_t aSeed) {
+    int32_t result = RAND_A * (aSeed % RAND_Q) - RAND_R * (aSeed / RAND_Q);
+    if (result <= 0)
+      result += RAND_M;
+    return result;
+  }
+#undef RAND_M
+#undef RAND_A
+#undef RAND_Q
+#undef RAND_R
+
+  const static int sBSize = 0x100;
+  const static int sBM = 0xff;
+  const static int sPerlinN = 0x1000;
+  const static int sNP = 12;			/* 2^PerlinN */
+  const static int sNM = 0xfff;
+
+  int32_t mLatticeSelector[sBSize + sBSize + 2];
+  double mGradient[4][sBSize + sBSize + 2][2];
+  struct StitchInfo {
+    int mWidth;			// How much to subtract to wrap for stitching.
+    int mHeight;
+    int mWrapX;			// Minimum value to wrap.
+    int mWrapY;
+  };
+
+  void InitSeed(int32_t aSeed);
+  double Noise2(int aColorChannel, double aVec[2], StitchInfo *aStitchInfo);
+  double
+  Turbulence(int aColorChannel, double *aPoint, double aBaseFreqX,
+             double aBaseFreqY, int aNumOctaves, bool aFractalSum,
+             bool aDoStitching, double aTileX, double aTileY,
+             double aTileWidth, double aTileHeight);
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_SVGFETurbulenceElement_h
diff --git a/content/svg/content/src/nsSVGFilters.cpp b/content/svg/content/src/nsSVGFilters.cpp
index f0c209badf73..c81a2bd224bc 100644
--- a/content/svg/content/src/nsSVGFilters.cpp
+++ b/content/svg/content/src/nsSVGFilters.cpp
@@ -660,552 +660,6 @@ NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGFEFuncAElement)
 } // namespace dom
 } // namespace mozilla
 
-//---------------------Turbulence------------------------
-
-typedef nsSVGFE nsSVGFETurbulenceElementBase;
-
-class nsSVGFETurbulenceElement : public nsSVGFETurbulenceElementBase,
-                                 public nsIDOMSVGFETurbulenceElement
-{
-  friend nsresult NS_NewSVGFETurbulenceElement(nsIContent **aResult,
-                                               already_AddRefed aNodeInfo);
-protected:
-  nsSVGFETurbulenceElement(already_AddRefed aNodeInfo)
-    : nsSVGFETurbulenceElementBase(aNodeInfo) {}
-
-public:
-  virtual bool SubregionIsUnionOfRegions() { return false; }
-
-  // interfaces:
-  NS_DECL_ISUPPORTS_INHERITED
-
-  // FE Base
-  NS_FORWARD_NSIDOMSVGFILTERPRIMITIVESTANDARDATTRIBUTES(nsSVGFETurbulenceElementBase::)
-
-  virtual nsresult Filter(nsSVGFilterInstance* aInstance,
-                          const nsTArray& aSources,
-                          const Image* aTarget,
-                          const nsIntRect& aDataRect);
-  virtual bool AttributeAffectsRendering(
-          int32_t aNameSpaceID, nsIAtom* aAttribute) const;
-  virtual nsSVGString& GetResultImageName() { return mStringAttributes[RESULT]; }
-  virtual nsIntRect ComputeTargetBBox(const nsTArray& aSourceBBoxes,
-          const nsSVGFilterInstance& aInstance);
-
-  // Turbulence
-  NS_DECL_NSIDOMSVGFETURBULENCEELEMENT
-
-  NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFETurbulenceElementBase::)
-
-  NS_FORWARD_NSIDOMNODE_TO_NSINODE
-  NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
-
-  virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
-
-  virtual nsXPCClassInfo* GetClassInfo();
-
-  virtual nsIDOMNode* AsDOMNode() { return this; }
-protected:
-  virtual NumberAttributesInfo GetNumberInfo();
-  virtual NumberPairAttributesInfo GetNumberPairInfo();
-  virtual IntegerAttributesInfo GetIntegerInfo();
-  virtual EnumAttributesInfo GetEnumInfo();
-  virtual StringAttributesInfo GetStringInfo();
-
-  enum { SEED }; // floating point seed?!
-  nsSVGNumber2 mNumberAttributes[1];
-  static NumberInfo sNumberInfo[1];
-
-  enum { BASE_FREQ };
-  nsSVGNumberPair mNumberPairAttributes[1];
-  static NumberPairInfo sNumberPairInfo[1];
-
-  enum { OCTAVES };
-  nsSVGInteger mIntegerAttributes[1];
-  static IntegerInfo sIntegerInfo[1];
-
-  enum { TYPE, STITCHTILES };
-  nsSVGEnum mEnumAttributes[2];
-  static nsSVGEnumMapping sTypeMap[];
-  static nsSVGEnumMapping sStitchTilesMap[];
-  static EnumInfo sEnumInfo[2];
-
-  enum { RESULT };
-  nsSVGString mStringAttributes[1];
-  static StringInfo sStringInfo[1];
-
-private:
-
-  /* The turbulence calculation code is an adapted version of what
-     appears in the SVG 1.1 specification:
-         http://www.w3.org/TR/SVG11/filters.html#feTurbulence
-  */
-
-  /* Produces results in the range [1, 2**31 - 2].
-     Algorithm is: r = (a * r) mod m
-     where a = 16807 and m = 2**31 - 1 = 2147483647
-     See [Park & Miller], CACM vol. 31 no. 10 p. 1195, Oct. 1988
-     To test: the algorithm should produce the result 1043618065
-     as the 10,000th generated number if the original seed is 1.
-  */
-#define RAND_M 2147483647	/* 2**31 - 1 */
-#define RAND_A 16807		/* 7**5; primitive root of m */
-#define RAND_Q 127773		/* m / a */
-#define RAND_R 2836		/* m % a */
-
-  int32_t SetupSeed(int32_t aSeed) {
-    if (aSeed <= 0)
-      aSeed = -(aSeed % (RAND_M - 1)) + 1;
-    if (aSeed > RAND_M - 1)
-      aSeed = RAND_M - 1;
-    return aSeed;
-  }
-
-  uint32_t Random(uint32_t aSeed) {
-    int32_t result = RAND_A * (aSeed % RAND_Q) - RAND_R * (aSeed / RAND_Q);
-    if (result <= 0)
-      result += RAND_M;
-    return result;
-  }
-#undef RAND_M
-#undef RAND_A
-#undef RAND_Q
-#undef RAND_R
-
-  const static int sBSize = 0x100;
-  const static int sBM = 0xff;
-  const static int sPerlinN = 0x1000;
-  const static int sNP = 12;			/* 2^PerlinN */
-  const static int sNM = 0xfff;
-
-  int32_t mLatticeSelector[sBSize + sBSize + 2];
-  double mGradient[4][sBSize + sBSize + 2][2];
-  struct StitchInfo {
-    int mWidth;			// How much to subtract to wrap for stitching.
-    int mHeight;
-    int mWrapX;			// Minimum value to wrap.
-    int mWrapY;
-  };
-
-  void InitSeed(int32_t aSeed);
-  double Noise2(int aColorChannel, double aVec[2], StitchInfo *aStitchInfo);
-  double
-  Turbulence(int aColorChannel, double *aPoint, double aBaseFreqX,
-             double aBaseFreqY, int aNumOctaves, bool aFractalSum,
-             bool aDoStitching, double aTileX, double aTileY,
-             double aTileWidth, double aTileHeight);
-};
-
-nsSVGElement::NumberInfo nsSVGFETurbulenceElement::sNumberInfo[1] =
-{
-  { &nsGkAtoms::seed, 0, false }
-};
-
-nsSVGElement::NumberPairInfo nsSVGFETurbulenceElement::sNumberPairInfo[1] =
-{
-  { &nsGkAtoms::baseFrequency, 0, 0 }
-};
-
-nsSVGElement::IntegerInfo nsSVGFETurbulenceElement::sIntegerInfo[1] =
-{
-  { &nsGkAtoms::numOctaves, 1 }
-};
-
-nsSVGEnumMapping nsSVGFETurbulenceElement::sTypeMap[] = {
-  {&nsGkAtoms::fractalNoise,
-   nsIDOMSVGFETurbulenceElement::SVG_TURBULENCE_TYPE_FRACTALNOISE},
-  {&nsGkAtoms::turbulence,
-   nsIDOMSVGFETurbulenceElement::SVG_TURBULENCE_TYPE_TURBULENCE},
-  {nullptr, 0}
-};
-
-nsSVGEnumMapping nsSVGFETurbulenceElement::sStitchTilesMap[] = {
-  {&nsGkAtoms::stitch,
-   nsIDOMSVGFETurbulenceElement::SVG_STITCHTYPE_STITCH},
-  {&nsGkAtoms::noStitch,
-   nsIDOMSVGFETurbulenceElement::SVG_STITCHTYPE_NOSTITCH},
-  {nullptr, 0}
-};
-
-nsSVGElement::EnumInfo nsSVGFETurbulenceElement::sEnumInfo[2] =
-{
-  { &nsGkAtoms::type,
-    sTypeMap,
-    nsIDOMSVGFETurbulenceElement::SVG_TURBULENCE_TYPE_TURBULENCE
-  },
-  { &nsGkAtoms::stitchTiles,
-    sStitchTilesMap,
-    nsIDOMSVGFETurbulenceElement::SVG_STITCHTYPE_NOSTITCH
-  }
-};
-
-nsSVGElement::StringInfo nsSVGFETurbulenceElement::sStringInfo[1] =
-{
-  { &nsGkAtoms::result, kNameSpaceID_None, true }
-};
-
-NS_IMPL_NS_NEW_SVG_ELEMENT(FETurbulence)
-
-//----------------------------------------------------------------------
-// nsISupports methods
-
-NS_IMPL_ADDREF_INHERITED(nsSVGFETurbulenceElement,nsSVGFETurbulenceElementBase)
-NS_IMPL_RELEASE_INHERITED(nsSVGFETurbulenceElement,nsSVGFETurbulenceElementBase)
-
-DOMCI_NODE_DATA(SVGFETurbulenceElement, nsSVGFETurbulenceElement)
-
-NS_INTERFACE_TABLE_HEAD(nsSVGFETurbulenceElement)
-  NS_NODE_INTERFACE_TABLE5(nsSVGFETurbulenceElement, nsIDOMNode, nsIDOMElement,
-                           nsIDOMSVGElement,
-                           nsIDOMSVGFilterPrimitiveStandardAttributes,
-                           nsIDOMSVGFETurbulenceElement)
-  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGFETurbulenceElement)
-NS_INTERFACE_MAP_END_INHERITING(nsSVGFETurbulenceElementBase)
-
-//----------------------------------------------------------------------
-// nsIDOMNode methods
-
-NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGFETurbulenceElement)
-
-//----------------------------------------------------------------------
-// nsIDOMSVGFETurbulenceElement methods
-
-/* readonly attribute nsIDOMSVGAnimatedNumber baseFrequencyX; */
-NS_IMETHODIMP nsSVGFETurbulenceElement::GetBaseFrequencyX(nsIDOMSVGAnimatedNumber * *aX)
-{
-  return mNumberPairAttributes[BASE_FREQ].ToDOMAnimatedNumber(aX, nsSVGNumberPair::eFirst, this);
-}
-
-/* readonly attribute nsIDOMSVGAnimatedNumber baseFrequencyY; */
-NS_IMETHODIMP nsSVGFETurbulenceElement::GetBaseFrequencyY(nsIDOMSVGAnimatedNumber * *aY)
-{
-  return mNumberPairAttributes[BASE_FREQ].ToDOMAnimatedNumber(aY, nsSVGNumberPair::eSecond, this);
-}
-
-/* readonly attribute nsIDOMSVGAnimatedInteger numOctaves; */
-NS_IMETHODIMP nsSVGFETurbulenceElement::GetNumOctaves(nsIDOMSVGAnimatedInteger * *aNum)
-{
-  return mIntegerAttributes[OCTAVES].ToDOMAnimatedInteger(aNum, this);
-}
-
-/* readonly attribute nsIDOMSVGAnimatedNumber seed; */
-NS_IMETHODIMP nsSVGFETurbulenceElement::GetSeed(nsIDOMSVGAnimatedNumber * *aSeed)
-{
-  return mNumberAttributes[SEED].ToDOMAnimatedNumber(aSeed, this);
-}
-
-/* readonly attribute nsIDOMSVGAnimatedEnumeration stitchTiles; */
-NS_IMETHODIMP nsSVGFETurbulenceElement::GetStitchTiles(nsIDOMSVGAnimatedEnumeration * *aStitch)
-{
-  return mEnumAttributes[STITCHTILES].ToDOMAnimatedEnum(aStitch, this);
-}
-
-/* readonly attribute nsIDOMSVGAnimatedEnumeration type; */
-NS_IMETHODIMP nsSVGFETurbulenceElement::GetType(nsIDOMSVGAnimatedEnumeration * *aType)
-{
-  return mEnumAttributes[TYPE].ToDOMAnimatedEnum(aType, this);
-}
-
-nsresult
-nsSVGFETurbulenceElement::Filter(nsSVGFilterInstance *instance,
-                                 const nsTArray& aSources,
-                                 const Image* aTarget,
-                                 const nsIntRect& rect)
-{
-  uint8_t* targetData = aTarget->mImage->Data();
-  uint32_t stride = aTarget->mImage->Stride();
-
-  nsIntRect filterSubregion(int32_t(aTarget->mFilterPrimitiveSubregion.X()),
-                            int32_t(aTarget->mFilterPrimitiveSubregion.Y()),
-                            int32_t(aTarget->mFilterPrimitiveSubregion.Width()),
-                            int32_t(aTarget->mFilterPrimitiveSubregion.Height()));
-
-  float fX = mNumberPairAttributes[BASE_FREQ].GetAnimValue(nsSVGNumberPair::eFirst);
-  float fY = mNumberPairAttributes[BASE_FREQ].GetAnimValue(nsSVGNumberPair::eSecond);
-  float seed = mNumberAttributes[OCTAVES].GetAnimValue();
-  int32_t octaves = mIntegerAttributes[OCTAVES].GetAnimValue();
-  uint16_t type = mEnumAttributes[TYPE].GetAnimValue();
-  uint16_t stitch = mEnumAttributes[STITCHTILES].GetAnimValue();
-
-  InitSeed((int32_t)seed);
-
-  // XXXroc this makes absolutely no sense to me.
-  float filterX = instance->GetFilterRegion().X();
-  float filterY = instance->GetFilterRegion().Y();
-  float filterWidth = instance->GetFilterRegion().Width();
-  float filterHeight = instance->GetFilterRegion().Height();
-
-  bool doStitch = false;
-  if (stitch == nsIDOMSVGFETurbulenceElement::SVG_STITCHTYPE_STITCH) {
-    doStitch = true;
-
-    float lowFreq, hiFreq;
-
-    lowFreq = floor(filterWidth * fX) / filterWidth;
-    hiFreq = ceil(filterWidth * fX) / filterWidth;
-    if (fX / lowFreq < hiFreq / fX)
-      fX = lowFreq;
-    else
-      fX = hiFreq;
-
-    lowFreq = floor(filterHeight * fY) / filterHeight;
-    hiFreq = ceil(filterHeight * fY) / filterHeight;
-    if (fY / lowFreq < hiFreq / fY)
-      fY = lowFreq;
-    else
-      fY = hiFreq;
-  }
-  for (int32_t y = rect.y; y < rect.YMost(); y++) {
-    for (int32_t x = rect.x; x < rect.XMost(); x++) {
-      int32_t targIndex = y * stride + x * 4;
-      double point[2];
-      point[0] = filterX + (filterWidth * (x + instance->GetSurfaceRect().x)) / (filterSubregion.width - 1);
-      point[1] = filterY + (filterHeight * (y + instance->GetSurfaceRect().y)) / (filterSubregion.height - 1);
-
-      float col[4];
-      if (type == nsIDOMSVGFETurbulenceElement::SVG_TURBULENCE_TYPE_TURBULENCE) {
-        for (int i = 0; i < 4; i++)
-          col[i] = Turbulence(i, point, fX, fY, octaves, false,
-                              doStitch, filterX, filterY, filterWidth, filterHeight) * 255;
-      } else {
-        for (int i = 0; i < 4; i++)
-          col[i] = (Turbulence(i, point, fX, fY, octaves, true,
-                               doStitch, filterX, filterY, filterWidth, filterHeight) * 255 + 255) / 2;
-      }
-      for (int i = 0; i < 4; i++) {
-        col[i] = std::min(col[i], 255.f);
-        col[i] = std::max(col[i], 0.f);
-      }
-
-      uint8_t r, g, b, a;
-      a = uint8_t(col[3]);
-      FAST_DIVIDE_BY_255(r, unsigned(col[0]) * a);
-      FAST_DIVIDE_BY_255(g, unsigned(col[1]) * a);
-      FAST_DIVIDE_BY_255(b, unsigned(col[2]) * a);
-
-      targetData[targIndex + GFX_ARGB32_OFFSET_B] = b;
-      targetData[targIndex + GFX_ARGB32_OFFSET_G] = g;
-      targetData[targIndex + GFX_ARGB32_OFFSET_R] = r;
-      targetData[targIndex + GFX_ARGB32_OFFSET_A] = a;
-    }
-  }
-
-  return NS_OK;
-}
-
-bool
-nsSVGFETurbulenceElement::AttributeAffectsRendering(int32_t aNameSpaceID,
-                                                    nsIAtom* aAttribute) const
-{
-  return nsSVGFETurbulenceElementBase::AttributeAffectsRendering(aNameSpaceID, aAttribute) ||
-         (aNameSpaceID == kNameSpaceID_None &&
-          (aAttribute == nsGkAtoms::seed ||
-           aAttribute == nsGkAtoms::baseFrequency ||
-           aAttribute == nsGkAtoms::numOctaves ||
-           aAttribute == nsGkAtoms::type ||
-           aAttribute == nsGkAtoms::stitchTiles));
-}
-
-void
-nsSVGFETurbulenceElement::InitSeed(int32_t aSeed)
-{
-  double s;
-  int i, j, k;
-  aSeed = SetupSeed(aSeed);
-  for (k = 0; k < 4; k++) {
-    for (i = 0; i < sBSize; i++) {
-      mLatticeSelector[i] = i;
-      for (j = 0; j < 2; j++) {
-        mGradient[k][i][j] =
-          (double) (((aSeed =
-                      Random(aSeed)) % (sBSize + sBSize)) - sBSize) / sBSize;
-      }
-      s = double (sqrt
-                  (mGradient[k][i][0] * mGradient[k][i][0] +
-                   mGradient[k][i][1] * mGradient[k][i][1]));
-      mGradient[k][i][0] /= s;
-      mGradient[k][i][1] /= s;
-    }
-  }
-  while (--i) {
-    k = mLatticeSelector[i];
-    mLatticeSelector[i] = mLatticeSelector[j =
-                                           (aSeed =
-                                            Random(aSeed)) % sBSize];
-    mLatticeSelector[j] = k;
-  }
-  for (i = 0; i < sBSize + 2; i++) {
-    mLatticeSelector[sBSize + i] = mLatticeSelector[i];
-    for (k = 0; k < 4; k++)
-      for (j = 0; j < 2; j++)
-        mGradient[k][sBSize + i][j] = mGradient[k][i][j];
-  }
-}
-
-#define S_CURVE(t) ( t * t * (3. - 2. * t) )
-#define LERP(t, a, b) ( a + t * (b - a) )
-double
-nsSVGFETurbulenceElement::Noise2(int aColorChannel, double aVec[2],
-                                 StitchInfo *aStitchInfo)
-{
-  int bx0, bx1, by0, by1, b00, b10, b01, b11;
-  double rx0, rx1, ry0, ry1, *q, sx, sy, a, b, t, u, v;
-  register long i, j;
-  t = aVec[0] + sPerlinN;
-  bx0 = (int) t;
-  bx1 = bx0 + 1;
-  rx0 = t - (int) t;
-  rx1 = rx0 - 1.0f;
-  t = aVec[1] + sPerlinN;
-  by0 = (int) t;
-  by1 = by0 + 1;
-  ry0 = t - (int) t;
-  ry1 = ry0 - 1.0f;
-  // If stitching, adjust lattice points accordingly.
-  if (aStitchInfo != NULL) {
-    if (bx0 >= aStitchInfo->mWrapX)
-      bx0 -= aStitchInfo->mWidth;
-    if (bx1 >= aStitchInfo->mWrapX)
-      bx1 -= aStitchInfo->mWidth;
-    if (by0 >= aStitchInfo->mWrapY)
-      by0 -= aStitchInfo->mHeight;
-    if (by1 >= aStitchInfo->mWrapY)
-      by1 -= aStitchInfo->mHeight;
-  }
-  bx0 &= sBM;
-  bx1 &= sBM;
-  by0 &= sBM;
-  by1 &= sBM;
-  i = mLatticeSelector[bx0];
-  j = mLatticeSelector[bx1];
-  b00 = mLatticeSelector[i + by0];
-  b10 = mLatticeSelector[j + by0];
-  b01 = mLatticeSelector[i + by1];
-  b11 = mLatticeSelector[j + by1];
-  sx = double (S_CURVE(rx0));
-  sy = double (S_CURVE(ry0));
-  q = mGradient[aColorChannel][b00];
-  u = rx0 * q[0] + ry0 * q[1];
-  q = mGradient[aColorChannel][b10];
-  v = rx1 * q[0] + ry0 * q[1];
-  a = LERP(sx, u, v);
-  q = mGradient[aColorChannel][b01];
-  u = rx0 * q[0] + ry1 * q[1];
-  q = mGradient[aColorChannel][b11];
-  v = rx1 * q[0] + ry1 * q[1];
-  b = LERP(sx, u, v);
-  return LERP(sy, a, b);
-}
-#undef S_CURVE
-#undef LERP
-
-double
-nsSVGFETurbulenceElement::Turbulence(int aColorChannel, double *aPoint,
-                                     double aBaseFreqX, double aBaseFreqY,
-                                     int aNumOctaves, bool aFractalSum,
-                                     bool aDoStitching,
-                                     double aTileX, double aTileY,
-                                     double aTileWidth, double aTileHeight)
-{
-  StitchInfo stitch;
-  StitchInfo *stitchInfo = NULL; // Not stitching when NULL.
-  // Adjust the base frequencies if necessary for stitching.
-  if (aDoStitching) {
-    // When stitching tiled turbulence, the frequencies must be adjusted
-    // so that the tile borders will be continuous.
-    if (aBaseFreqX != 0.0) {
-      double loFreq = double (floor(aTileWidth * aBaseFreqX)) / aTileWidth;
-      double hiFreq = double (ceil(aTileWidth * aBaseFreqX)) / aTileWidth;
-      if (aBaseFreqX / loFreq < hiFreq / aBaseFreqX)
-        aBaseFreqX = loFreq;
-      else
-        aBaseFreqX = hiFreq;
-    }
-    if (aBaseFreqY != 0.0) {
-      double loFreq = double (floor(aTileHeight * aBaseFreqY)) / aTileHeight;
-      double hiFreq = double (ceil(aTileHeight * aBaseFreqY)) / aTileHeight;
-      if (aBaseFreqY / loFreq < hiFreq / aBaseFreqY)
-        aBaseFreqY = loFreq;
-      else
-        aBaseFreqY = hiFreq;
-    }
-    // Set up initial stitch values.
-    stitchInfo = &stitch;
-    stitch.mWidth = int (aTileWidth * aBaseFreqX + 0.5f);
-    stitch.mWrapX = int (aTileX * aBaseFreqX + sPerlinN + stitch.mWidth);
-    stitch.mHeight = int (aTileHeight * aBaseFreqY + 0.5f);
-    stitch.mWrapY = int (aTileY * aBaseFreqY + sPerlinN + stitch.mHeight);
-  }
-  double sum = 0.0f;
-  double vec[2];
-  vec[0] = aPoint[0] * aBaseFreqX;
-  vec[1] = aPoint[1] * aBaseFreqY;
-  double ratio = 1;
-  for (int octave = 0; octave < aNumOctaves; octave++) {
-    if (aFractalSum)
-      sum += double (Noise2(aColorChannel, vec, stitchInfo) / ratio);
-    else
-      sum += double (fabs(Noise2(aColorChannel, vec, stitchInfo)) / ratio);
-    vec[0] *= 2;
-    vec[1] *= 2;
-    ratio *= 2;
-    if (stitchInfo != NULL) {
-      // Update stitch values. Subtracting sPerlinN before the multiplication
-      // and adding it afterward simplifies to subtracting it once.
-      stitch.mWidth *= 2;
-      stitch.mWrapX = 2 * stitch.mWrapX - sPerlinN;
-      stitch.mHeight *= 2;
-      stitch.mWrapY = 2 * stitch.mWrapY - sPerlinN;
-    }
-  }
-  return sum;
-}
-
-nsIntRect
-nsSVGFETurbulenceElement::ComputeTargetBBox(const nsTArray& aSourceBBoxes,
-        const nsSVGFilterInstance& aInstance)
-{
-  return GetMaxRect();
-}
-
-//----------------------------------------------------------------------
-// nsSVGElement methods
-
-nsSVGElement::NumberAttributesInfo
-nsSVGFETurbulenceElement::GetNumberInfo()
-{
-  return NumberAttributesInfo(mNumberAttributes, sNumberInfo,
-                              ArrayLength(sNumberInfo));
-}
-
-nsSVGElement::NumberPairAttributesInfo
-nsSVGFETurbulenceElement::GetNumberPairInfo()
-{
-  return NumberPairAttributesInfo(mNumberPairAttributes, sNumberPairInfo,
-                                 ArrayLength(sNumberPairInfo));
-}
-
-nsSVGElement::IntegerAttributesInfo
-nsSVGFETurbulenceElement::GetIntegerInfo()
-{
-  return IntegerAttributesInfo(mIntegerAttributes, sIntegerInfo,
-                               ArrayLength(sIntegerInfo));
-}
-
-nsSVGElement::EnumAttributesInfo
-nsSVGFETurbulenceElement::GetEnumInfo()
-{
-  return EnumAttributesInfo(mEnumAttributes, sEnumInfo,
-                            ArrayLength(sEnumInfo));
-}
-
-nsSVGElement::StringAttributesInfo
-nsSVGFETurbulenceElement::GetStringInfo()
-{
-  return StringAttributesInfo(mStringAttributes, sStringInfo,
-                              ArrayLength(sStringInfo));
-}
-
 //--------------------------------------------------------------------
 //
 nsSVGElement::NumberInfo nsSVGFELightingElement::sNumberInfo[4] =

From 747eeafd7568a98b07db3dd261030d4fa44ac9ad Mon Sep 17 00:00:00 2001
From: David Zbarsky 
Date: Tue, 26 Mar 2013 19:43:33 -0400
Subject: [PATCH 092/129] Bug 847120: Convert SVGFETurbulenceElement to WebIDL
 r=Ms2ger

---
 .../content/src/SVGFETurbulenceElement.cpp    | 151 ++++++++++--------
 .../svg/content/src/SVGFETurbulenceElement.h  |  44 +++--
 dom/base/nsDOMClassInfo.cpp                   |   8 -
 dom/base/nsDOMClassInfoClasses.h              |   1 -
 dom/interfaces/svg/nsIDOMSVGFilters.idl       |  20 ---
 dom/webidl/SVGFETurbulenceElement.webidl      |  38 +++++
 dom/webidl/WebIDL.mk                          |   1 +
 7 files changed, 149 insertions(+), 114 deletions(-)
 create mode 100644 dom/webidl/SVGFETurbulenceElement.webidl

diff --git a/content/svg/content/src/SVGFETurbulenceElement.cpp b/content/svg/content/src/SVGFETurbulenceElement.cpp
index 92bf61f41126..ebd39a46f04a 100644
--- a/content/svg/content/src/SVGFETurbulenceElement.cpp
+++ b/content/svg/content/src/SVGFETurbulenceElement.cpp
@@ -4,125 +4,138 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/dom/SVGFETurbulenceElement.h"
+#include "mozilla/dom/SVGFETurbulenceElementBinding.h"
+#include "nsSVGFilterInstance.h"
+#include "nsSVGUtils.h"
+
+NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(FETurbulence)
 
 namespace mozilla {
 namespace dom {
 
-nsSVGElement::NumberInfo nsSVGFETurbulenceElement::sNumberInfo[1] =
+// Turbulence Types
+static const unsigned short SVG_TURBULENCE_TYPE_UNKNOWN = 0;
+static const unsigned short SVG_TURBULENCE_TYPE_FRACTALNOISE = 1;
+static const unsigned short SVG_TURBULENCE_TYPE_TURBULENCE = 2;
+
+// Stitch Options
+static const unsigned short SVG_STITCHTYPE_UNKNOWN = 0;
+static const unsigned short SVG_STITCHTYPE_STITCH = 1;
+static const unsigned short SVG_STITCHTYPE_NOSTITCH = 2;
+
+JSObject*
+SVGFETurbulenceElement::WrapNode(JSContext* aCx, JSObject* aScope)
+{
+  return SVGFETurbulenceElementBinding::Wrap(aCx, aScope, this);
+}
+
+nsSVGElement::NumberInfo SVGFETurbulenceElement::sNumberInfo[1] =
 {
   { &nsGkAtoms::seed, 0, false }
 };
 
-nsSVGElement::NumberPairInfo nsSVGFETurbulenceElement::sNumberPairInfo[1] =
+nsSVGElement::NumberPairInfo SVGFETurbulenceElement::sNumberPairInfo[1] =
 {
   { &nsGkAtoms::baseFrequency, 0, 0 }
 };
 
-nsSVGElement::IntegerInfo nsSVGFETurbulenceElement::sIntegerInfo[1] =
+nsSVGElement::IntegerInfo SVGFETurbulenceElement::sIntegerInfo[1] =
 {
   { &nsGkAtoms::numOctaves, 1 }
 };
 
-nsSVGEnumMapping nsSVGFETurbulenceElement::sTypeMap[] = {
+nsSVGEnumMapping SVGFETurbulenceElement::sTypeMap[] = {
   {&nsGkAtoms::fractalNoise,
-   nsIDOMSVGFETurbulenceElement::SVG_TURBULENCE_TYPE_FRACTALNOISE},
+   SVG_TURBULENCE_TYPE_FRACTALNOISE},
   {&nsGkAtoms::turbulence,
-   nsIDOMSVGFETurbulenceElement::SVG_TURBULENCE_TYPE_TURBULENCE},
+   SVG_TURBULENCE_TYPE_TURBULENCE},
   {nullptr, 0}
 };
 
-nsSVGEnumMapping nsSVGFETurbulenceElement::sStitchTilesMap[] = {
+nsSVGEnumMapping SVGFETurbulenceElement::sStitchTilesMap[] = {
   {&nsGkAtoms::stitch,
-   nsIDOMSVGFETurbulenceElement::SVG_STITCHTYPE_STITCH},
+   SVG_STITCHTYPE_STITCH},
   {&nsGkAtoms::noStitch,
-   nsIDOMSVGFETurbulenceElement::SVG_STITCHTYPE_NOSTITCH},
+   SVG_STITCHTYPE_NOSTITCH},
   {nullptr, 0}
 };
 
-nsSVGElement::EnumInfo nsSVGFETurbulenceElement::sEnumInfo[2] =
+nsSVGElement::EnumInfo SVGFETurbulenceElement::sEnumInfo[2] =
 {
   { &nsGkAtoms::type,
     sTypeMap,
-    nsIDOMSVGFETurbulenceElement::SVG_TURBULENCE_TYPE_TURBULENCE
+    SVG_TURBULENCE_TYPE_TURBULENCE
   },
   { &nsGkAtoms::stitchTiles,
     sStitchTilesMap,
-    nsIDOMSVGFETurbulenceElement::SVG_STITCHTYPE_NOSTITCH
+    SVG_STITCHTYPE_NOSTITCH
   }
 };
 
-nsSVGElement::StringInfo nsSVGFETurbulenceElement::sStringInfo[1] =
+nsSVGElement::StringInfo SVGFETurbulenceElement::sStringInfo[1] =
 {
   { &nsGkAtoms::result, kNameSpaceID_None, true }
 };
 
-NS_IMPL_NS_NEW_SVG_ELEMENT(FETurbulence)
-
 //----------------------------------------------------------------------
 // nsISupports methods
 
-NS_IMPL_ADDREF_INHERITED(nsSVGFETurbulenceElement,nsSVGFETurbulenceElementBase)
-NS_IMPL_RELEASE_INHERITED(nsSVGFETurbulenceElement,nsSVGFETurbulenceElementBase)
+NS_IMPL_ADDREF_INHERITED(SVGFETurbulenceElement,SVGFETurbulenceElementBase)
+NS_IMPL_RELEASE_INHERITED(SVGFETurbulenceElement,SVGFETurbulenceElementBase)
 
-DOMCI_NODE_DATA(SVGFETurbulenceElement, nsSVGFETurbulenceElement)
-
-NS_INTERFACE_TABLE_HEAD(nsSVGFETurbulenceElement)
-  NS_NODE_INTERFACE_TABLE5(nsSVGFETurbulenceElement, nsIDOMNode, nsIDOMElement,
-                           nsIDOMSVGElement,
-                           nsIDOMSVGFilterPrimitiveStandardAttributes,
-                           nsIDOMSVGFETurbulenceElement)
-  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(SVGFETurbulenceElement)
-NS_INTERFACE_MAP_END_INHERITING(nsSVGFETurbulenceElementBase)
+NS_INTERFACE_TABLE_HEAD(SVGFETurbulenceElement)
+  NS_NODE_INTERFACE_TABLE3(SVGFETurbulenceElement, nsIDOMNode, nsIDOMElement,
+                           nsIDOMSVGElement)
+NS_INTERFACE_MAP_END_INHERITING(SVGFETurbulenceElementBase)
 
 //----------------------------------------------------------------------
 // nsIDOMNode methods
 
-NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGFETurbulenceElement)
+NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGFETurbulenceElement)
 
 //----------------------------------------------------------------------
-// nsIDOMSVGFETurbulenceElement methods
 
-/* readonly attribute nsIDOMSVGAnimatedNumber baseFrequencyX; */
-NS_IMETHODIMP nsSVGFETurbulenceElement::GetBaseFrequencyX(nsIDOMSVGAnimatedNumber * *aX)
+already_AddRefed
+SVGFETurbulenceElement::BaseFrequencyX()
 {
-  return mNumberPairAttributes[BASE_FREQ].ToDOMAnimatedNumber(aX, nsSVGNumberPair::eFirst, this);
+  return mNumberPairAttributes[BASE_FREQ].ToDOMAnimatedNumber(nsSVGNumberPair::eFirst, this);
 }
 
-/* readonly attribute nsIDOMSVGAnimatedNumber baseFrequencyY; */
-NS_IMETHODIMP nsSVGFETurbulenceElement::GetBaseFrequencyY(nsIDOMSVGAnimatedNumber * *aY)
+already_AddRefed
+SVGFETurbulenceElement::BaseFrequencyY()
 {
-  return mNumberPairAttributes[BASE_FREQ].ToDOMAnimatedNumber(aY, nsSVGNumberPair::eSecond, this);
+  return mNumberPairAttributes[BASE_FREQ].ToDOMAnimatedNumber(nsSVGNumberPair::eSecond, this);
 }
 
-/* readonly attribute nsIDOMSVGAnimatedInteger numOctaves; */
-NS_IMETHODIMP nsSVGFETurbulenceElement::GetNumOctaves(nsIDOMSVGAnimatedInteger * *aNum)
+already_AddRefed
+SVGFETurbulenceElement::NumOctaves()
 {
-  return mIntegerAttributes[OCTAVES].ToDOMAnimatedInteger(aNum, this);
+  return mIntegerAttributes[OCTAVES].ToDOMAnimatedInteger(this);
 }
 
-/* readonly attribute nsIDOMSVGAnimatedNumber seed; */
-NS_IMETHODIMP nsSVGFETurbulenceElement::GetSeed(nsIDOMSVGAnimatedNumber * *aSeed)
+already_AddRefed
+SVGFETurbulenceElement::Seed()
 {
-  return mNumberAttributes[SEED].ToDOMAnimatedNumber(aSeed, this);
+  return mNumberAttributes[SEED].ToDOMAnimatedNumber(this);
 }
 
-/* readonly attribute nsIDOMSVGAnimatedEnumeration stitchTiles; */
-NS_IMETHODIMP nsSVGFETurbulenceElement::GetStitchTiles(nsIDOMSVGAnimatedEnumeration * *aStitch)
+already_AddRefed
+SVGFETurbulenceElement::StitchTiles()
 {
-  return mEnumAttributes[STITCHTILES].ToDOMAnimatedEnum(aStitch, this);
+  return mEnumAttributes[STITCHTILES].ToDOMAnimatedEnum(this);
 }
 
-/* readonly attribute nsIDOMSVGAnimatedEnumeration type; */
-NS_IMETHODIMP nsSVGFETurbulenceElement::GetType(nsIDOMSVGAnimatedEnumeration * *aType)
+already_AddRefed
+SVGFETurbulenceElement::Type()
 {
-  return mEnumAttributes[TYPE].ToDOMAnimatedEnum(aType, this);
+  return mEnumAttributes[TYPE].ToDOMAnimatedEnum(this);
 }
 
 nsresult
-nsSVGFETurbulenceElement::Filter(nsSVGFilterInstance *instance,
-                                 const nsTArray& aSources,
-                                 const Image* aTarget,
-                                 const nsIntRect& rect)
+SVGFETurbulenceElement::Filter(nsSVGFilterInstance* instance,
+                               const nsTArray& aSources,
+                               const Image* aTarget,
+                               const nsIntRect& rect)
 {
   uint8_t* targetData = aTarget->mImage->Data();
   uint32_t stride = aTarget->mImage->Stride();
@@ -148,7 +161,7 @@ nsSVGFETurbulenceElement::Filter(nsSVGFilterInstance *instance,
   float filterHeight = instance->GetFilterRegion().Height();
 
   bool doStitch = false;
-  if (stitch == nsIDOMSVGFETurbulenceElement::SVG_STITCHTYPE_STITCH) {
+  if (stitch == SVG_STITCHTYPE_STITCH) {
     doStitch = true;
 
     float lowFreq, hiFreq;
@@ -175,7 +188,7 @@ nsSVGFETurbulenceElement::Filter(nsSVGFilterInstance *instance,
       point[1] = filterY + (filterHeight * (y + instance->GetSurfaceRect().y)) / (filterSubregion.height - 1);
 
       float col[4];
-      if (type == nsIDOMSVGFETurbulenceElement::SVG_TURBULENCE_TYPE_TURBULENCE) {
+      if (type == SVG_TURBULENCE_TYPE_TURBULENCE) {
         for (int i = 0; i < 4; i++)
           col[i] = Turbulence(i, point, fX, fY, octaves, false,
                               doStitch, filterX, filterY, filterWidth, filterHeight) * 255;
@@ -206,10 +219,10 @@ nsSVGFETurbulenceElement::Filter(nsSVGFilterInstance *instance,
 }
 
 bool
-nsSVGFETurbulenceElement::AttributeAffectsRendering(int32_t aNameSpaceID,
+SVGFETurbulenceElement::AttributeAffectsRendering(int32_t aNameSpaceID,
                                                     nsIAtom* aAttribute) const
 {
-  return nsSVGFETurbulenceElementBase::AttributeAffectsRendering(aNameSpaceID, aAttribute) ||
+  return SVGFETurbulenceElementBase::AttributeAffectsRendering(aNameSpaceID, aAttribute) ||
          (aNameSpaceID == kNameSpaceID_None &&
           (aAttribute == nsGkAtoms::seed ||
            aAttribute == nsGkAtoms::baseFrequency ||
@@ -219,7 +232,7 @@ nsSVGFETurbulenceElement::AttributeAffectsRendering(int32_t aNameSpaceID,
 }
 
 void
-nsSVGFETurbulenceElement::InitSeed(int32_t aSeed)
+SVGFETurbulenceElement::InitSeed(int32_t aSeed)
 {
   double s;
   int i, j, k;
@@ -257,8 +270,8 @@ nsSVGFETurbulenceElement::InitSeed(int32_t aSeed)
 #define S_CURVE(t) ( t * t * (3. - 2. * t) )
 #define LERP(t, a, b) ( a + t * (b - a) )
 double
-nsSVGFETurbulenceElement::Noise2(int aColorChannel, double aVec[2],
-                                 StitchInfo *aStitchInfo)
+SVGFETurbulenceElement::Noise2(int aColorChannel, double aVec[2],
+                               StitchInfo *aStitchInfo)
 {
   int bx0, bx1, by0, by1, b00, b10, b01, b11;
   double rx0, rx1, ry0, ry1, *q, sx, sy, a, b, t, u, v;
@@ -312,12 +325,12 @@ nsSVGFETurbulenceElement::Noise2(int aColorChannel, double aVec[2],
 #undef LERP
 
 double
-nsSVGFETurbulenceElement::Turbulence(int aColorChannel, double *aPoint,
-                                     double aBaseFreqX, double aBaseFreqY,
-                                     int aNumOctaves, bool aFractalSum,
-                                     bool aDoStitching,
-                                     double aTileX, double aTileY,
-                                     double aTileWidth, double aTileHeight)
+SVGFETurbulenceElement::Turbulence(int aColorChannel, double* aPoint,
+                                   double aBaseFreqX, double aBaseFreqY,
+                                   int aNumOctaves, bool aFractalSum,
+                                   bool aDoStitching,
+                                   double aTileX, double aTileY,
+                                   double aTileWidth, double aTileHeight)
 {
   StitchInfo stitch;
   StitchInfo *stitchInfo = NULL; // Not stitching when NULL.
@@ -374,7 +387,7 @@ nsSVGFETurbulenceElement::Turbulence(int aColorChannel, double *aPoint,
 }
 
 nsIntRect
-nsSVGFETurbulenceElement::ComputeTargetBBox(const nsTArray& aSourceBBoxes,
+SVGFETurbulenceElement::ComputeTargetBBox(const nsTArray& aSourceBBoxes,
         const nsSVGFilterInstance& aInstance)
 {
   return GetMaxRect();
@@ -384,35 +397,35 @@ nsSVGFETurbulenceElement::ComputeTargetBBox(const nsTArray& aSourceBB
 // nsSVGElement methods
 
 nsSVGElement::NumberAttributesInfo
-nsSVGFETurbulenceElement::GetNumberInfo()
+SVGFETurbulenceElement::GetNumberInfo()
 {
   return NumberAttributesInfo(mNumberAttributes, sNumberInfo,
                               ArrayLength(sNumberInfo));
 }
 
 nsSVGElement::NumberPairAttributesInfo
-nsSVGFETurbulenceElement::GetNumberPairInfo()
+SVGFETurbulenceElement::GetNumberPairInfo()
 {
   return NumberPairAttributesInfo(mNumberPairAttributes, sNumberPairInfo,
                                  ArrayLength(sNumberPairInfo));
 }
 
 nsSVGElement::IntegerAttributesInfo
-nsSVGFETurbulenceElement::GetIntegerInfo()
+SVGFETurbulenceElement::GetIntegerInfo()
 {
   return IntegerAttributesInfo(mIntegerAttributes, sIntegerInfo,
                                ArrayLength(sIntegerInfo));
 }
 
 nsSVGElement::EnumAttributesInfo
-nsSVGFETurbulenceElement::GetEnumInfo()
+SVGFETurbulenceElement::GetEnumInfo()
 {
   return EnumAttributesInfo(mEnumAttributes, sEnumInfo,
                             ArrayLength(sEnumInfo));
 }
 
 nsSVGElement::StringAttributesInfo
-nsSVGFETurbulenceElement::GetStringInfo()
+SVGFETurbulenceElement::GetStringInfo()
 {
   return StringAttributesInfo(mStringAttributes, sStringInfo,
                               ArrayLength(sStringInfo));
diff --git a/content/svg/content/src/SVGFETurbulenceElement.h b/content/svg/content/src/SVGFETurbulenceElement.h
index 0322b473a658..1edb9bace274 100644
--- a/content/svg/content/src/SVGFETurbulenceElement.h
+++ b/content/svg/content/src/SVGFETurbulenceElement.h
@@ -6,21 +6,32 @@
 #ifndef mozilla_dom_SVGFETurbulenceElement_h
 #define mozilla_dom_SVGFETurbulenceElement_h
 
+#include "nsSVGEnum.h"
 #include "nsSVGFilters.h"
+#include "nsSVGNumber2.h"
+#include "nsSVGInteger.h"
+#include "nsSVGString.h"
+
+nsresult NS_NewSVGFETurbulenceElement(nsIContent **aResult,
+                                      already_AddRefed aNodeInfo);
 
 namespace mozilla {
 namespace dom {
 
-typedef nsSVGFE nsSVGFETurbulenceElementBase;
+typedef nsSVGFE SVGFETurbulenceElementBase;
 
-class nsSVGFETurbulenceElement : public nsSVGFETurbulenceElementBase,
-                                 public nsIDOMSVGFETurbulenceElement
+class SVGFETurbulenceElement : public SVGFETurbulenceElementBase,
+                               public nsIDOMSVGElement
 {
-  friend nsresult NS_NewSVGFETurbulenceElement(nsIContent **aResult,
-                                               already_AddRefed aNodeInfo);
+  friend nsresult (::NS_NewSVGFETurbulenceElement(nsIContent **aResult,
+                                                  already_AddRefed aNodeInfo));
 protected:
-  nsSVGFETurbulenceElement(already_AddRefed aNodeInfo)
-    : nsSVGFETurbulenceElementBase(aNodeInfo) {}
+  SVGFETurbulenceElement(already_AddRefed aNodeInfo)
+    : SVGFETurbulenceElementBase(aNodeInfo)
+  {
+    SetIsDOMBinding();
+  }
+  virtual JSObject* WrapNode(JSContext* aCx, JSObject* aScope) MOZ_OVERRIDE;
 
 public:
   virtual bool SubregionIsUnionOfRegions() { return false; }
@@ -28,9 +39,6 @@ public:
   // interfaces:
   NS_DECL_ISUPPORTS_INHERITED
 
-  // FE Base
-  NS_FORWARD_NSIDOMSVGFILTERPRIMITIVESTANDARDATTRIBUTES(nsSVGFETurbulenceElementBase::)
-
   virtual nsresult Filter(nsSVGFilterInstance* aInstance,
                           const nsTArray& aSources,
                           const Image* aTarget,
@@ -41,19 +49,23 @@ public:
   virtual nsIntRect ComputeTargetBBox(const nsTArray& aSourceBBoxes,
           const nsSVGFilterInstance& aInstance);
 
-  // Turbulence
-  NS_DECL_NSIDOMSVGFETURBULENCEELEMENT
-
-  NS_FORWARD_NSIDOMSVGELEMENT(nsSVGFETurbulenceElementBase::)
+  NS_FORWARD_NSIDOMSVGELEMENT(SVGFETurbulenceElementBase::)
 
   NS_FORWARD_NSIDOMNODE_TO_NSINODE
   NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
 
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
 
-  virtual nsXPCClassInfo* GetClassInfo();
-
   virtual nsIDOMNode* AsDOMNode() { return this; }
+
+  // WebIDL
+  already_AddRefed BaseFrequencyX();
+  already_AddRefed BaseFrequencyY();
+  already_AddRefed NumOctaves();
+  already_AddRefed Seed();
+  already_AddRefed StitchTiles();
+  already_AddRefed Type();
+
 protected:
   virtual NumberAttributesInfo GetNumberInfo();
   virtual NumberPairAttributesInfo GetNumberPairInfo();
diff --git a/dom/base/nsDOMClassInfo.cpp b/dom/base/nsDOMClassInfo.cpp
index 0f25aa4b4f87..33b2fcaa6a26 100644
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -812,8 +812,6 @@ static nsDOMClassInfoData sClassInfoData[] = {
   // SVG element classes
   NS_DEFINE_CLASSINFO_DATA(TimeEvent, nsEventSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
-  NS_DEFINE_CLASSINFO_DATA(SVGFETurbulenceElement, nsElementSH,
-                           ELEMENT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA_WITH_NAME(SVGUnknownElement, SVGElement, nsElementSH,
                                      ELEMENT_SCRIPTABLE_FLAGS)
 
@@ -2223,12 +2221,6 @@ nsDOMClassInfo::Init()
     DOM_CLASSINFO_EVENT_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
-  DOM_CLASSINFO_MAP_BEGIN(SVGFETurbulenceElement, nsIDOMSVGFETurbulenceElement)
-    DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGFETurbulenceElement)
-    DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGFilterPrimitiveStandardAttributes)
-    DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES
-  DOM_CLASSINFO_MAP_END
-
   DOM_CLASSINFO_MAP_BEGIN(SVGUnknownElement, nsIDOMSVGElement)
     DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
diff --git a/dom/base/nsDOMClassInfoClasses.h b/dom/base/nsDOMClassInfoClasses.h
index 0163b37df793..8ccd34275e96 100644
--- a/dom/base/nsDOMClassInfoClasses.h
+++ b/dom/base/nsDOMClassInfoClasses.h
@@ -122,7 +122,6 @@ DOMCI_CLASS(SVGDocument)
 
 // SVG element classes
 DOMCI_CLASS(TimeEvent)
-DOMCI_CLASS(SVGFETurbulenceElement)
 DOMCI_CLASS(SVGUnknownElement)
 
 // other SVG classes
diff --git a/dom/interfaces/svg/nsIDOMSVGFilters.idl b/dom/interfaces/svg/nsIDOMSVGFilters.idl
index bdd158247189..90007261043a 100644
--- a/dom/interfaces/svg/nsIDOMSVGFilters.idl
+++ b/dom/interfaces/svg/nsIDOMSVGFilters.idl
@@ -20,23 +20,3 @@ interface nsIDOMSVGFilterPrimitiveStandardAttributes : nsIDOMSVGElement
     readonly attribute nsIDOMSVGAnimatedLength      height;
     readonly attribute nsIDOMSVGAnimatedString      result;
 };
-
-[scriptable, uuid(14eb581d-0e54-42b5-a595-5db6c9490277)]
-interface nsIDOMSVGFETurbulenceElement : nsIDOMSVGFilterPrimitiveStandardAttributes
-{ 
-    // Turbulence Types
-    const unsigned short SVG_TURBULENCE_TYPE_UNKNOWN      = 0;
-    const unsigned short SVG_TURBULENCE_TYPE_FRACTALNOISE = 1;
-    const unsigned short SVG_TURBULENCE_TYPE_TURBULENCE   = 2;
-    // Stitch Options
-    const unsigned short SVG_STITCHTYPE_UNKNOWN  = 0;
-    const unsigned short SVG_STITCHTYPE_STITCH   = 1;
-    const unsigned short SVG_STITCHTYPE_NOSTITCH = 2;
-
-    readonly attribute nsIDOMSVGAnimatedNumber      baseFrequencyX;
-    readonly attribute nsIDOMSVGAnimatedNumber      baseFrequencyY;
-    readonly attribute nsIDOMSVGAnimatedInteger     numOctaves;
-    readonly attribute nsIDOMSVGAnimatedNumber      seed;
-    readonly attribute nsIDOMSVGAnimatedEnumeration stitchTiles;
-    readonly attribute nsIDOMSVGAnimatedEnumeration type;
-};
diff --git a/dom/webidl/SVGFETurbulenceElement.webidl b/dom/webidl/SVGFETurbulenceElement.webidl
new file mode 100644
index 000000000000..dc531aa6dcbe
--- /dev/null
+++ b/dom/webidl/SVGFETurbulenceElement.webidl
@@ -0,0 +1,38 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * The origin of this IDL file is
+ * http://www.w3.org/TR/SVG2/
+ *
+ * Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
+ * liability, trademark and document use rules apply.
+ */
+
+interface SVGAnimatedEnumeration;
+interface SVGAnimatedInteger;
+interface SVGAnimatedNumber;
+interface SVGAnimatedString;
+
+interface SVGFETurbulenceElement : SVGElement {
+
+  // Turbulence Types
+  const unsigned short SVG_TURBULENCE_TYPE_UNKNOWN = 0;
+  const unsigned short SVG_TURBULENCE_TYPE_FRACTALNOISE = 1;
+  const unsigned short SVG_TURBULENCE_TYPE_TURBULENCE = 2;
+
+  // Stitch Options
+  const unsigned short SVG_STITCHTYPE_UNKNOWN = 0;
+  const unsigned short SVG_STITCHTYPE_STITCH = 1;
+  const unsigned short SVG_STITCHTYPE_NOSTITCH = 2;
+
+  readonly attribute SVGAnimatedNumber baseFrequencyX;
+  readonly attribute SVGAnimatedNumber baseFrequencyY;
+  readonly attribute SVGAnimatedInteger numOctaves;
+  readonly attribute SVGAnimatedNumber seed;
+  readonly attribute SVGAnimatedEnumeration stitchTiles;
+  readonly attribute SVGAnimatedEnumeration type;
+};
+
+SVGFETurbulenceElement implements SVGFilterPrimitiveStandardAttributes;
diff --git a/dom/webidl/WebIDL.mk b/dom/webidl/WebIDL.mk
index 5b9a6431107f..4edaa91d12a3 100644
--- a/dom/webidl/WebIDL.mk
+++ b/dom/webidl/WebIDL.mk
@@ -212,6 +212,7 @@ webidl_files = \
   SVGFESpecularLightingElement.webidl \
   SVGFESpotLightElement.webidl \
   SVGFETileElement.webidl \
+  SVGFETurbulenceElement.webidl \
   SVGFitToViewBox.webidl \
   SVGForeignObjectElement.webidl \
   SVGGElement.webidl \

From 3b43d6003c59623ca2899bfcd3efcea34b882db5 Mon Sep 17 00:00:00 2001
From: Reuben Morais 
Date: Tue, 26 Mar 2013 16:49:12 -0700
Subject: [PATCH 093/129] Bug 854514 - Don't import SettingsChangeNotifier.jsm
 if the mozSettings pref is enabled. r=gwagner

---
 dom/settings/tests/test_settings_basics.html         |  8 +++++---
 dom/settings/tests/test_settings_blobs.html          | 10 ++++++----
 .../tests/test_settings_onsettingchange.html         |  9 ++++++---
 testing/mochitest/b2g.json                           | 12 +++++-------
 4 files changed, 22 insertions(+), 17 deletions(-)

diff --git a/dom/settings/tests/test_settings_basics.html b/dom/settings/tests/test_settings_basics.html
index 2ead7344b164..b8c1492dcefb 100644
--- a/dom/settings/tests/test_settings_basics.html
+++ b/dom/settings/tests/test_settings_basics.html
@@ -21,9 +21,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id={678695}
 
 "use strict";
 
-var comp = SpecialPowers.wrap(SpecialPowers.Components);
-comp.utils.import("resource://gre/modules/SettingsChangeNotifier.jsm");
-SpecialPowers.setBoolPref("dom.mozSettings.enabled", true);
+if (!SpecialPowers.getBoolPref("dom.mozSettings.enabled")) {
+  SpecialPowers.Cu.import("resource://gre/modules/SettingsChangeNotifier.jsm");
+  SpecialPowers.setBoolPref("dom.mozSettings.enabled", true);
+}
+
 SpecialPowers.addPermission("settings-read", true, document);
 SpecialPowers.addPermission("settings-write", true, document);
 
diff --git a/dom/settings/tests/test_settings_blobs.html b/dom/settings/tests/test_settings_blobs.html
index 78fd92420ae7..ffb6a27f71f1 100644
--- a/dom/settings/tests/test_settings_blobs.html
+++ b/dom/settings/tests/test_settings_blobs.html
@@ -17,13 +17,15 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=821630
 
 
 
-
-
-
diff --git a/content/base/test/file_mixed_content_frameNavigation_grandchild.html b/content/base/test/file_mixed_content_frameNavigation_grandchild.html
deleted file mode 100644
index eb49f78073b1..000000000000
--- a/content/base/test/file_mixed_content_frameNavigation_grandchild.html
+++ /dev/null
@@ -1,54 +0,0 @@
-
-
-
-
-  
-  Tests for Mixed Content Frame Navigation
-
-
-
-
-
-
-
diff --git a/content/base/test/file_mixed_content_frameNavigation_innermost.html b/content/base/test/file_mixed_content_frameNavigation_innermost.html
deleted file mode 100644
index 4fbdd0356580..000000000000
--- a/content/base/test/file_mixed_content_frameNavigation_innermost.html
+++ /dev/null
@@ -1,61 +0,0 @@
-
-
-
-
- - - diff --git a/content/base/test/file_mixed_content_frameNavigation_secure.html b/content/base/test/file_mixed_content_frameNavigation_secure.html deleted file mode 100644 index 786bfd7c7cad..000000000000 --- a/content/base/test/file_mixed_content_frameNavigation_secure.html +++ /dev/null @@ -1,75 +0,0 @@ - - - - - - Tests for Mixed Content Frame Navigation - - -
- - - - diff --git a/content/base/test/file_mixed_content_frameNavigation_secure_grandchild.html b/content/base/test/file_mixed_content_frameNavigation_secure_grandchild.html deleted file mode 100644 index dbe264ba4346..000000000000 --- a/content/base/test/file_mixed_content_frameNavigation_secure_grandchild.html +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - Tests for Mixed Content Frame Navigation - - - - - - - diff --git a/content/base/test/test_mixed_content_blocker_frameNavigation.html b/content/base/test/test_mixed_content_blocker_frameNavigation.html deleted file mode 100644 index 188db64e784f..000000000000 --- a/content/base/test/test_mixed_content_blocker_frameNavigation.html +++ /dev/null @@ -1,111 +0,0 @@ - - - - - - Tests for Bug 840388 - - - - - - - -
- -
-
- -
- -

-
-

From e51447822ae048355e6d4113497fbf452eae984f Mon Sep 17 00:00:00 2001
From: Phil Ringnalda 
Date: Tue, 26 Mar 2013 20:34:02 -0700
Subject: [PATCH 101/129] Back out bd91df842f2f (bug 840388) CLOSED TREE

---
 content/base/src/nsMixedContentBlocker.cpp | 51 ++--------------------
 1 file changed, 4 insertions(+), 47 deletions(-)

diff --git a/content/base/src/nsMixedContentBlocker.cpp b/content/base/src/nsMixedContentBlocker.cpp
index 416c495a97c4..f869b5ce0501 100644
--- a/content/base/src/nsMixedContentBlocker.cpp
+++ b/content/base/src/nsMixedContentBlocker.cpp
@@ -23,7 +23,6 @@
 #include "nsIScriptObjectPrincipal.h"
 #include "nsISecureBrowserUI.h"
 #include "nsIDocumentLoader.h"
-#include "nsIWebNavigation.h"
 #include "nsLoadGroup.h"
 
 #include "prlog.h"
@@ -354,6 +353,8 @@ nsMixedContentBlocker::ShouldLoad(uint32_t aContentType,
     return NS_OK;
   }
 
+  // If we are here we have mixed content.
+
   // Determine if the rootDoc is https and if the user decided to allow Mixed Content
   nsCOMPtr docShell = NS_CP_GetDocShellFromContext(aRequestingContext);
   NS_ENSURE_TRUE(docShell, NS_OK);
@@ -365,54 +366,10 @@ nsMixedContentBlocker::ShouldLoad(uint32_t aContentType,
      return rv;
   }
 
-
-  // Get the sameTypeRoot tree item from the docshell
+  // Get the root document from the docshell
   nsCOMPtr sameTypeRoot;
   docShell->GetSameTypeRootTreeItem(getter_AddRefs(sameTypeRoot));
-  NS_ASSERTION(sameTypeRoot, "No root tree item from docshell!");
-
-  // When navigating an iframe, the iframe may be https
-  // but its parents may not be.  Check the parents to see if any of them are https.
-  // If none of the parents are https, allow the load.
-  if (aContentType == TYPE_SUBDOCUMENT && !rootHasSecureConnection) {
-
-    bool httpsParentExists = false;
-    bool chromeParent = false;
-
-    nsCOMPtr parentTreeItem;
-    parentTreeItem = docShell;
-
-    while(!httpsParentExists && parentTreeItem) {
-      nsCOMPtr parentAsNav(do_QueryInterface(parentTreeItem));
-      NS_ASSERTION(parentAsNav, "No web navigation object from parent's docshell tree item");
-      nsCOMPtr parentURI;
-
-      parentAsNav->GetCurrentURI(getter_AddRefs(parentURI));
-      if (!parentURI || NS_FAILED(parentURI->SchemeIs("https", &httpsParentExists))) {
-        // if getting the URI or the scheme fails, assume there is a https parent and break.
-        httpsParentExists = true;
-        break;
-      }
-
-      // When the parent and the root are the same, we have traversed all the way up
-      // the same type docshell tree.  Break out of the while loop.
-      if(sameTypeRoot == parentTreeItem) {
-        break;
-      }
-
-      // update the parent to the grandparent.
-      nsCOMPtr newParentTreeItem;
-      parentTreeItem->GetSameTypeParent(getter_AddRefs(newParentTreeItem));
-      parentTreeItem = newParentTreeItem;
-    } // end while loop.
-
-    if (!httpsParentExists) {
-      *aDecision = nsIContentPolicy::ACCEPT;
-      return NS_OK;
-    }
-  }
-
-  // Get the root document from the sameTypeRoot
+  NS_ASSERTION(sameTypeRoot, "No document shell root tree item from document shell tree item!");
   nsCOMPtr rootDoc = do_GetInterface(sameTypeRoot);
   NS_ASSERTION(rootDoc, "No root document from document shell root tree item.");
 

From eb903ad1daaf06ddce5210fff5c07908170a516e Mon Sep 17 00:00:00 2001
From: Cameron McCormack 
Date: Wed, 27 Mar 2013 15:49:56 +1100
Subject: [PATCH 102/129] Bug 848973 - Document what aFrame means in
 nsStyleDisplay::IsBlockInside() and friends. r=roc

---
 layout/base/nsCSSFrameConstructor.cpp | 19 +++----
 layout/generic/nsFrame.cpp            |  2 +-
 layout/style/nsStyleStruct.h          | 43 +++++++++-----
 layout/style/nsStyleStructInlines.h   | 82 ++++++++++++++++-----------
 4 files changed, 86 insertions(+), 60 deletions(-)

diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp
index ca48f22e5cd6..54f8ab37ad1e 100644
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -1956,7 +1956,7 @@ nsCSSFrameConstructor::ConstructTable(nsFrameConstructorState& aState,
 
   // Mark the table frame as an absolute container if needed
   newFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
-  if (display->IsPositioned(aParentFrame)) {
+  if (display->IsPositionedStyle() && !aParentFrame->IsSVGText()) {
     aState.PushAbsoluteContainingBlock(newFrame, absoluteSaveState);
   }
   if (aItem.mFCData->mBits & FCDATA_USE_CHILD_ITEMS) {
@@ -3623,7 +3623,8 @@ nsCSSFrameConstructor::ConstructFrameFromItemInternal(FrameConstructionItem& aIt
     } else if (!(bits & FCDATA_SKIP_ABSPOS_PUSH)) {
       nsIFrame* cb = maybeAbsoluteContainingBlock;
       cb->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
-      if (maybeAbsoluteContainingBlockDisplay->IsPositioned(cb)) {
+      if (maybeAbsoluteContainingBlockDisplay->IsPositionedStyle()) {
+        NS_ASSERTION(!cb->IsSVGText(), "SVG text cannot have abspos children");
         aState.PushAbsoluteContainingBlock(cb, absoluteSaveState);
       }
     }
@@ -4241,8 +4242,7 @@ nsCSSFrameConstructor::FindDisplayData(const nsStyleDisplay* aDisplay,
   // XXX Ignore tables for the time being
   // XXXbz it would be nice to combine this with the other block
   // case... Think about how do do this?
-  if ((aParentFrame ? aDisplay->IsBlockInside(aParentFrame) :
-                      aDisplay->IsBlockInsideStyle()) &&
+  if (aDisplay->IsBlockInsideStyle() &&
       aDisplay->IsScrollableOverflow() &&
       !propagatedScrollToViewport) {
     // Except we don't want to do that for paginated contexts for
@@ -4263,8 +4263,7 @@ nsCSSFrameConstructor::FindDisplayData(const nsStyleDisplay* aDisplay,
   }
 
   // Handle various non-scrollable blocks
-  if ((aParentFrame ? aDisplay->IsBlockInside(aParentFrame) :
-                      aDisplay->IsBlockInsideStyle())) {
+  if (aDisplay->IsBlockInsideStyle()) {
     static const FrameConstructionData sNonScrollableBlockData =
       FULL_CTOR_FCDATA(0, &nsCSSFrameConstructor::ConstructNonScrollableBlock);
     return &sNonScrollableBlockData;
@@ -4330,8 +4329,7 @@ nsCSSFrameConstructor::FindDisplayData(const nsStyleDisplay* aDisplay,
                        &nsCSSFrameConstructor::ConstructTableCell) }
   };
 
-  return FindDataByInt((aParentFrame ? aDisplay->GetDisplay(aParentFrame) :
-                                       aDisplay->mDisplay),
+  return FindDataByInt(aDisplay->mDisplay,
                        aElement, aStyleContext, sDisplayData,
                        ArrayLength(sDisplayData));
 }
@@ -5293,8 +5291,7 @@ nsCSSFrameConstructor::AddFrameConstructionItemsInternal(nsFrameConstructorState
        (!aParentFrame || // No aParentFrame means inline
         aParentFrame->StyleDisplay()->mDisplay == NS_STYLE_DISPLAY_INLINE)) ||
       // Things that are inline-outside but aren't inline frames are inline
-      (aParentFrame ? display->IsInlineOutside(aParentFrame) :
-                      display->IsInlineOutsideStyle()) ||
+      display->IsInlineOutsideStyle() ||
       // Popups that are certainly out of flow.
       isPopup;
 
@@ -10454,7 +10451,7 @@ nsCSSFrameConstructor::CreateLetterFrame(nsIFrame* aBlockFrame,
 
     // Create the right type of first-letter frame
     const nsStyleDisplay* display = sc->StyleDisplay();
-    if (display->IsFloating(aParentFrame)) {
+    if (display->IsFloatingStyle() && !aParentFrame->IsSVGText()) {
       // Make a floating first-letter frame
       CreateFloatingLetterFrame(state, aBlockFrame, aTextContent, textFrame,
                                 blockContent, aParentFrame, sc, aResult);
diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp
index f3aac706f4f1..391280763168 100644
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -2187,7 +2187,7 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder*   aBuilder,
     || child->IsTransformed()
     || nsSVGIntegrationUtils::UsingEffectsForFrame(child);
 
-  bool isPositioned = !isSVG && disp->IsPositioned(child);
+  bool isPositioned = !isSVG && disp->IsPositionedStyle();
   if (isVisuallyAtomic || isPositioned || (!isSVG && disp->IsFloating(child)) ||
       ((disp->mClipFlags & NS_STYLE_CLIP_RECT) &&
        IsSVGContentWithCSSClip(child)) ||
diff --git a/layout/style/nsStyleStruct.h b/layout/style/nsStyleStruct.h
index c6380a53f6a2..ed7c87d6cc14 100644
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -1348,10 +1348,15 @@ struct nsStyleText {
   }
 
   // These are defined in nsStyleStructInlines.h.
-  inline bool HasTextShadow(const nsIFrame* aFrame) const;
-  inline nsCSSShadowArray* GetTextShadow(const nsIFrame* aFrame) const;
-  inline bool WhiteSpaceCanWrap(const nsIFrame* aFrame) const;
-  inline bool WordCanWrap(const nsIFrame* aFrame) const;
+
+  // The aContextFrame argument on each of these is the frame this
+  // style struct is for.  If the frame is for SVG text, the return
+  // value will be massaged to be something that makes sense for
+  // SVG text.
+  inline bool HasTextShadow(const nsIFrame* aContextFrame) const;
+  inline nsCSSShadowArray* GetTextShadow(const nsIFrame* aContextFrame) const;
+  inline bool WhiteSpaceCanWrap(const nsIFrame* aContextFrame) const;
+  inline bool WordCanWrap(const nsIFrame* aContextFrame) const;
 };
 
 struct nsStyleVisibility {
@@ -1685,6 +1690,10 @@ struct nsStyleDisplay {
     return mPosition == NS_STYLE_POSITION_RELATIVE;
   }
 
+  bool IsPositionedStyle() const {
+    return IsAbsolutelyPositionedStyle() || IsRelativelyPositionedStyle();
+  }
+
   bool IsScrollableOverflow() const {
     // mOverflowX and mOverflowY always match when one of them is
     // NS_STYLE_OVERFLOW_VISIBLE or NS_STYLE_OVERFLOW_CLIP.
@@ -1701,18 +1710,24 @@ struct nsStyleDisplay {
   }
 
   // These are defined in nsStyleStructInlines.h.
-  inline bool IsBlockInside(const nsIFrame* aFrame) const;
-  inline bool IsBlockOutside(const nsIFrame* aFrame) const;
-  inline bool IsInlineOutside(const nsIFrame* aFrame) const;
-  inline bool IsOriginalDisplayInlineOutside(const nsIFrame* aFrame) const;
-  inline uint8_t GetDisplay(const nsIFrame* aFrame) const;
-  inline bool IsFloating(const nsIFrame* aFrame) const;
-  inline bool IsPositioned(const nsIFrame* aFrame) const;
-  inline bool IsRelativelyPositioned(const nsIFrame* aFrame) const;
-  inline bool IsAbsolutelyPositioned(const nsIFrame* aFrame) const;
+
+  // The aContextFrame argument on each of these is the frame this
+  // style struct is for.  If the frame is for SVG text, the return
+  // value will be massaged to be something that makes sense for
+  // SVG text.
+  inline bool IsBlockInside(const nsIFrame* aContextFrame) const;
+  inline bool IsBlockOutside(const nsIFrame* aContextFrame) const;
+  inline bool IsInlineOutside(const nsIFrame* aContextFrame) const;
+  inline bool IsOriginalDisplayInlineOutside(const nsIFrame* aContextFrame) const;
+  inline uint8_t GetDisplay(const nsIFrame* aContextFrame) const;
+  inline bool IsFloating(const nsIFrame* aContextFrame) const;
+  inline bool IsPositioned(const nsIFrame* aContextFrame) const;
+  inline bool IsRelativelyPositioned(const nsIFrame* aContextFrame) const;
+  inline bool IsAbsolutelyPositioned(const nsIFrame* aContextFrame) const;
+
   /* Returns whether the element has the -moz-transform property
    * or a related property, and supports CSS transforms. */
-  inline bool HasTransform(const nsIFrame* aFrame) const;
+  inline bool HasTransform(const nsIFrame* aContextFrame) const;
 };
 
 struct nsStyleTable {
diff --git a/layout/style/nsStyleStructInlines.h b/layout/style/nsStyleStructInlines.h
index 5964acdca305..f9349b904706 100644
--- a/layout/style/nsStyleStructInlines.h
+++ b/layout/style/nsStyleStructInlines.h
@@ -56,74 +56,83 @@ nsStyleBorder::GetSubImage(uint8_t aIndex) const
 }
 
 bool
-nsStyleText::HasTextShadow(const nsIFrame* aFrame) const
+nsStyleText::HasTextShadow(const nsIFrame* aContextFrame) const
 {
-  return mTextShadow && !aFrame->IsSVGText();
+  NS_ASSERTION(aContextFrame->StyleText() == this, "unexpected aContextFrame");
+  return mTextShadow && !aContextFrame->IsSVGText();
 }
 
 nsCSSShadowArray*
-nsStyleText::GetTextShadow(const nsIFrame* aFrame) const
+nsStyleText::GetTextShadow(const nsIFrame* aContextFrame) const
 {
-  if (aFrame->IsSVGText()) {
+  NS_ASSERTION(aContextFrame->StyleText() == this, "unexpected aContextFrame");
+  if (aContextFrame->IsSVGText()) {
     return nullptr;
   }
   return mTextShadow;
 }
 
 bool
-nsStyleText::WhiteSpaceCanWrap(const nsIFrame* aFrame) const
+nsStyleText::WhiteSpaceCanWrap(const nsIFrame* aContextFrame) const
 {
-  return WhiteSpaceCanWrapStyle() && !aFrame->IsSVGText();
+  NS_ASSERTION(aContextFrame->StyleText() == this, "unexpected aContextFrame");
+  return WhiteSpaceCanWrapStyle() && !aContextFrame->IsSVGText();
 }
 
 bool
-nsStyleText::WordCanWrap(const nsIFrame* aFrame) const
+nsStyleText::WordCanWrap(const nsIFrame* aContextFrame) const
 {
-  return WordCanWrapStyle() && !aFrame->IsSVGText();
+  NS_ASSERTION(aContextFrame->StyleText() == this, "unexpected aContextFrame");
+  return WordCanWrapStyle() && !aContextFrame->IsSVGText();
 }
 
 bool
-nsStyleDisplay::IsBlockInside(const nsIFrame* aFrame) const
+nsStyleDisplay::IsBlockInside(const nsIFrame* aContextFrame) const
 {
-  if (aFrame->IsSVGText()) {
-    return aFrame->GetType() == nsGkAtoms::blockFrame;
+  NS_ASSERTION(aContextFrame->StyleDisplay() == this, "unexpected aContextFrame");
+  if (aContextFrame->IsSVGText()) {
+    return aContextFrame->GetType() == nsGkAtoms::blockFrame;
   }
   return IsBlockInsideStyle();
 }
 
 bool
-nsStyleDisplay::IsBlockOutside(const nsIFrame* aFrame) const
+nsStyleDisplay::IsBlockOutside(const nsIFrame* aContextFrame) const
 {
-  if (aFrame->IsSVGText()) {
-    return aFrame->GetType() == nsGkAtoms::blockFrame;
+  NS_ASSERTION(aContextFrame->StyleDisplay() == this, "unexpected aContextFrame");
+  if (aContextFrame->IsSVGText()) {
+    return aContextFrame->GetType() == nsGkAtoms::blockFrame;
   }
   return IsBlockOutsideStyle();
 }
 
 bool
-nsStyleDisplay::IsInlineOutside(const nsIFrame* aFrame) const
+nsStyleDisplay::IsInlineOutside(const nsIFrame* aContextFrame) const
 {
-  if (aFrame->IsSVGText()) {
-    return aFrame->GetType() != nsGkAtoms::blockFrame;
+  NS_ASSERTION(aContextFrame->StyleDisplay() == this, "unexpected aContextFrame");
+  if (aContextFrame->IsSVGText()) {
+    return aContextFrame->GetType() != nsGkAtoms::blockFrame;
   }
   return IsInlineOutsideStyle();
 }
 
 bool
-nsStyleDisplay::IsOriginalDisplayInlineOutside(const nsIFrame* aFrame) const
+nsStyleDisplay::IsOriginalDisplayInlineOutside(const nsIFrame* aContextFrame) const
 {
-  if (aFrame->IsSVGText()) {
-    return aFrame->GetType() != nsGkAtoms::blockFrame;
+  NS_ASSERTION(aContextFrame->StyleDisplay() == this, "unexpected aContextFrame");
+  if (aContextFrame->IsSVGText()) {
+    return aContextFrame->GetType() != nsGkAtoms::blockFrame;
   }
   return IsOriginalDisplayInlineOutsideStyle();
 }
 
 uint8_t
-nsStyleDisplay::GetDisplay(const nsIFrame* aFrame) const
+nsStyleDisplay::GetDisplay(const nsIFrame* aContextFrame) const
 {
-  if (aFrame->IsSVGText() &&
+  NS_ASSERTION(aContextFrame->StyleDisplay() == this, "unexpected aContextFrame");
+  if (aContextFrame->IsSVGText() &&
       mDisplay != NS_STYLE_DISPLAY_NONE) {
-    return aFrame->GetType() == nsGkAtoms::blockFrame ?
+    return aContextFrame->GetType() == nsGkAtoms::blockFrame ?
              NS_STYLE_DISPLAY_BLOCK :
              NS_STYLE_DISPLAY_INLINE;
   }
@@ -131,36 +140,41 @@ nsStyleDisplay::GetDisplay(const nsIFrame* aFrame) const
 }
 
 bool
-nsStyleDisplay::IsFloating(const nsIFrame* aFrame) const
+nsStyleDisplay::IsFloating(const nsIFrame* aContextFrame) const
 {
-  return IsFloatingStyle() && !aFrame->IsSVGText();
+  NS_ASSERTION(aContextFrame->StyleDisplay() == this, "unexpected aContextFrame");
+  return IsFloatingStyle() && !aContextFrame->IsSVGText();
 }
 
 bool
-nsStyleDisplay::HasTransform(const nsIFrame* aFrame) const
+nsStyleDisplay::HasTransform(const nsIFrame* aContextFrame) const
 {
-  return HasTransformStyle() && aFrame->IsFrameOfType(nsIFrame::eSupportsCSSTransforms);
+  NS_ASSERTION(aContextFrame->StyleDisplay() == this, "unexpected aContextFrame");
+  return HasTransformStyle() && aContextFrame->IsFrameOfType(nsIFrame::eSupportsCSSTransforms);
 }
 
 bool
-nsStyleDisplay::IsPositioned(const nsIFrame* aFrame) const
+nsStyleDisplay::IsPositioned(const nsIFrame* aContextFrame) const
 {
+  NS_ASSERTION(aContextFrame->StyleDisplay() == this, "unexpected aContextFrame");
   return (IsAbsolutelyPositionedStyle() ||
           IsRelativelyPositionedStyle() ||
-          HasTransform(aFrame)) &&
-         !aFrame->IsSVGText();
+          HasTransform(aContextFrame)) &&
+         !aContextFrame->IsSVGText();
 }
 
 bool
-nsStyleDisplay::IsRelativelyPositioned(const nsIFrame* aFrame) const
+nsStyleDisplay::IsRelativelyPositioned(const nsIFrame* aContextFrame) const
 {
-  return IsRelativelyPositionedStyle() && !aFrame->IsSVGText();
+  NS_ASSERTION(aContextFrame->StyleDisplay() == this, "unexpected aContextFrame");
+  return IsRelativelyPositionedStyle() && !aContextFrame->IsSVGText();
 }
 
 bool
-nsStyleDisplay::IsAbsolutelyPositioned(const nsIFrame* aFrame) const
+nsStyleDisplay::IsAbsolutelyPositioned(const nsIFrame* aContextFrame) const
 {
-  return IsAbsolutelyPositionedStyle() && !aFrame->IsSVGText();
+  NS_ASSERTION(aContextFrame->StyleDisplay() == this, "unexpected aContextFrame");
+  return IsAbsolutelyPositionedStyle() && !aContextFrame->IsSVGText();
 }
 
 uint8_t

From a55cc2028d4d28cd838e4b9a26a272d571c9f0e9 Mon Sep 17 00:00:00 2001
From: Mark Finkle 
Date: Wed, 27 Mar 2013 00:53:24 -0400
Subject: [PATCH 103/129] Bug 854340 - Firefox for Android cannot against loop
 + alert attack r=wesj

---
 mobile/android/components/PromptService.js | 17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/mobile/android/components/PromptService.js b/mobile/android/components/PromptService.js
index 727804a0fc55..14757a1b8070 100644
--- a/mobile/android/components/PromptService.js
+++ b/mobile/android/components/PromptService.js
@@ -127,8 +127,12 @@ Prompt.prototype = {
     if (aCheckMsg)
       aInputs.push({ type: "checkbox", label: PromptUtils.cleanUpLabel(aCheckMsg), checked: aCheckState.value });
 
-    if (this._domWin)
+    let callerWin;
+    if (this._domWin) {
       PromptUtils.fireDialogEvent(this._domWin, "DOMWillOpenModalDialog");
+      let winUtils = this._domWin.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
+      callerWin = winUtils.enterModalStateWithWindow();
+    }
 
     let msg = { type: "Prompt:Show" };
     if (aTitle) msg.title = aTitle;
@@ -138,7 +142,16 @@ Prompt.prototype = {
       PromptUtils.getLocaleString("Cancel")
     ];
     msg.inputs = aInputs;
-    return PromptUtils.sendMessageToJava(msg);
+
+    let retval = PromptUtils.sendMessageToJava(msg);
+
+    if (this._domWin) {
+      let winUtils = this._domWin.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
+      winUtils.leaveModalStateWithWindow(callerWin);
+      PromptUtils.fireDialogEvent(this._domWin, "DOMModalDialogClosed");
+    }
+
+    return retval;
   },
 
   /*

From c8ed26cbac903b263ba5c3467ab2822146722767 Mon Sep 17 00:00:00 2001
From: Randell Jesup 
Date: Wed, 27 Mar 2013 01:01:23 -0400
Subject: [PATCH 104/129] Bug 839650: proxy AddTrack() to MSG thread via a
 custom command so we can get access to the current stream time r=ekr

---
 media/webrtc/signaling/signaling.gyp          |   1 +
 .../src/mediapipeline/MediaPipeline.cpp       | 163 ++++++++++++++----
 .../src/mediapipeline/MediaPipeline.h         |  87 ++++++++--
 .../webrtc/signaling/test/FakeMediaStreams.h  |   6 +-
 4 files changed, 202 insertions(+), 55 deletions(-)

diff --git a/media/webrtc/signaling/signaling.gyp b/media/webrtc/signaling/signaling.gyp
index b8b7742c3591..44b3bbc3a605 100644
--- a/media/webrtc/signaling/signaling.gyp
+++ b/media/webrtc/signaling/signaling.gyp
@@ -54,6 +54,7 @@
         '../../../xpcom/base',
         '$(DEPTH)/dist/include',
         '../../../dom/base',
+        '../../../content/media',
         '../../../media/mtransport',
         '../trunk/webrtc',
         '../trunk/webrtc/video_engine/include',
diff --git a/media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp b/media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp
index 02840805fb1d..14ec1357e532 100644
--- a/media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp
+++ b/media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp
@@ -4,10 +4,12 @@
 
 // Original author: ekr@rtfm.com
 
-#include "CSFLog.h"
-
 #include "MediaPipeline.h"
 
+#ifndef USE_FAKE_MEDIA_STREAMS
+#include "MediaStreamGraphImpl.h"
+#endif
+
 #include 
 
 #include "nspr.h"
@@ -59,7 +61,7 @@ nsresult MediaPipeline::Init() {
                     nsRefPtr(this),
                     &MediaPipeline::Init_s),
                 NS_DISPATCH_NORMAL);
-  
+
   return NS_OK;
 }
 
@@ -842,22 +844,89 @@ nsresult MediaPipelineReceiveAudio::Init() {
   description_ += track_id_string;
   description_ += "]";
 
-  stream_->AddListener(listener_);
+  listener_->AddSelf(new AudioSegment());
 
   return MediaPipelineReceive::Init();
 }
 
 
+void GenericReceiveListener::AddSelf(MediaSegment* segment) {
+  RefPtr callback = new GenericReceiveCallback(this);
+  AddTrackAndListener(source_, track_id_, track_rate_, this, segment, callback);
+}
+
+// Add a track and listener on the MSG thread using the MSG command queue
+static void AddTrackAndListener(MediaStream* source,
+                                TrackID track_id, TrackRate track_rate,
+                                MediaStreamListener* listener, MediaSegment* segment,
+                                const RefPtr& completed) {
+  // This both adds the listener and the track
+#ifdef MOZILLA_INTERNAL_API
+  class Message : public ControlMessage {
+   public:
+    Message(MediaStream* stream, TrackID track, TrackRate rate,
+            MediaSegment* segment, MediaStreamListener* listener,
+            const RefPtr& completed)
+      : ControlMessage(stream),
+        track_id_(track),
+        track_rate_(rate),
+        segment_(segment),
+        listener_(listener),
+        completed_(completed) {}
+
+    virtual void Run() MOZ_OVERRIDE {
+      StreamTime current_end = mStream->GetBufferEnd();
+      TrackTicks current_ticks = TimeToTicksRoundUp(track_rate_, current_end);
+
+      mStream->AddListenerImpl(listener_.forget());
+
+      // Add a track 'now' to avoid possible underrun, especially if we add
+      // a track "later".
+
+      if (current_end != 0L) {
+        MOZ_MTLOG(MP_LOG_INFO, "added track @ " << current_end <<
+                  " -> " << MediaTimeToSeconds(current_end));
+      }
+
+      // To avoid assertions, we need to insert a dummy segment that covers up
+      // to the "start" time for the track
+      segment_->AppendNullData(current_ticks);
+      mStream->AsSourceStream()->AddTrack(track_id_, track_rate_,
+                                          current_ticks, segment_);
+      // AdvanceKnownTracksTicksTime(HEAT_DEATH_OF_UNIVERSE) means that in
+      // theory per the API, we can't add more tracks before that
+      // time. However, the impl actually allows it, and it avoids a whole
+      // bunch of locking that would be required (and potential blocking)
+      // if we used smaller values and updated them on each NotifyPull.
+      mStream->AsSourceStream()->AdvanceKnownTracksTime(STREAM_TIME_MAX);
+
+      // We need to know how much has been "inserted" because we're given absolute
+      // times in NotifyPull.
+      completed_->TrackAdded(current_ticks);
+    }
+   private:
+    TrackID track_id_;
+    TrackRate track_rate_;
+    MediaSegment* segment_;
+    nsRefPtr listener_;
+    const RefPtr completed_;
+  };
+
+  MOZ_ASSERT(listener);
+
+  source->GraphImpl()->AppendMessage(new Message(source, track_id, track_rate, segment, listener, completed));
+#else
+  source->AsSourceStream()->AddTrack(track_id, track_rate, 0, segment);
+#endif
+}
+
 MediaPipelineReceiveAudio::PipelineListener::PipelineListener(
     SourceMediaStream * source, TrackID track_id,
     const RefPtr& conduit)
-    : source_(source),
-      track_id_(track_id),
-      conduit_(conduit),
-      played_(0) {
-  mozilla::AudioSegment *segment = new mozilla::AudioSegment();
-  source_->AddTrack(track_id_, 16000, 0, segment);
-  source_->AdvanceKnownTracksTime(STREAM_TIME_MAX);
+  : GenericReceiveListener(source, track_id, 16000), // XXX rate assumption
+    conduit_(conduit)
+{
+  MOZ_ASSERT(track_rate_%100 == 0);
 }
 
 void MediaPipelineReceiveAudio::PipelineListener::
@@ -869,21 +938,33 @@ NotifyPull(MediaStreamGraph* graph, StreamTime desired_time) {
   }
 
   // This comparison is done in total time to avoid accumulated roundoff errors.
-  while (MillisecondsToMediaTime(played_) < desired_time) {
-    // TODO(ekr@rtfm.com): Is there a way to avoid mallocating here?
-    nsRefPtr samples = SharedBuffer::Create(1000);
+  while (TicksToTimeRoundDown(track_rate_, played_ticks_) < desired_time) {
+    // TODO(ekr@rtfm.com): Is there a way to avoid mallocating here?  Or reduce the size?
+    // Max size given mono is 480*2*1 = 960 (48KHz)
+#define AUDIO_SAMPLE_BUFFER_MAX 1000
+    MOZ_ASSERT((track_rate_/100)*sizeof(uint16_t) <= AUDIO_SAMPLE_BUFFER_MAX);
+
+    nsRefPtr samples = SharedBuffer::Create(AUDIO_SAMPLE_BUFFER_MAX);
     int16_t *samples_data = static_cast(samples->Data());
     int samples_length;
 
+    // This fetches 10ms of data
     MediaConduitErrorCode err =
         static_cast(conduit_.get())->GetAudioFrame(
             samples_data,
-            16000,  // Sampling rate fixed at 16 kHz for now
-            0,  // TODO(ekr@rtfm.com): better estimate of capture delay
+            track_rate_,
+            0,  // TODO(ekr@rtfm.com): better estimate of "capture" (really playout) delay
             samples_length);
+    MOZ_ASSERT(samples_length < AUDIO_SAMPLE_BUFFER_MAX);
 
-    if (err != kMediaConduitNoError)
-      return;
+    if (err != kMediaConduitNoError) {
+      // Insert silence on conduit/GIPS failure (extremely unlikely)
+      MOZ_MTLOG(PR_LOG_ERROR, "Audio conduit failed (" << err << ") to return data @ " << played_ticks_ <<
+                " (desired " << desired_time << " -> " << MediaTimeToSeconds(desired_time) << ")");
+      MOZ_ASSERT(err == kMediaConduitNoError);
+      samples_length = (track_rate_/100)*sizeof(uint16_t); // if this is not enough we'll loop and provide more
+      memset(samples_data, '\0', samples_length);
+    }
 
     MOZ_MTLOG(PR_LOG_DEBUG, "Audio conduit returned buffer of length " << samples_length);
 
@@ -892,9 +973,15 @@ NotifyPull(MediaStreamGraph* graph, StreamTime desired_time) {
     channels.AppendElement(samples_data);
     segment.AppendFrames(samples.forget(), channels, samples_length);
 
-    source_->AppendToTrack(track_id_, &segment);
-
-    played_ += 10;
+    // Handle track not actually added yet or removed/finished
+    if (source_->AppendToTrack(track_id_, &segment)) {
+      played_ticks_ += track_rate_/100; // 10ms in TrackTicks
+    } else {
+      MOZ_MTLOG(PR_LOG_ERROR, "AppendToTrack failed");
+      // we can't un-read the data, but that's ok since we don't want to
+      // buffer - but don't i-loop!
+      return;
+    }
   }
 }
 
@@ -910,7 +997,9 @@ nsresult MediaPipelineReceiveVideo::Init() {
   description_ += track_id_string;
   description_ += "]";
 
-  stream_->AddListener(listener_);
+#ifdef MOZILLA_INTERNAL_API
+  listener_->AddSelf(new VideoSegment());
+#endif
 
   static_cast(conduit_.get())->
       AttachRenderer(renderer_);
@@ -920,22 +1009,16 @@ nsresult MediaPipelineReceiveVideo::Init() {
 
 MediaPipelineReceiveVideo::PipelineListener::PipelineListener(
   SourceMediaStream* source, TrackID track_id)
-    : source_(source),
-      track_id_(track_id),
+  : GenericReceiveListener(source, track_id, USECS_PER_S),
+    width_(640),
+    height_(480),
 #ifdef MOZILLA_INTERNAL_API
-      played_(0),
+    image_container_(),
+    image_(),
 #endif
-      width_(640),
-      height_(480),
-#ifdef MOZILLA_INTERNAL_API
-      image_container_(),
-      image_(),
-#endif
-      monitor_("Video PipelineListener") {
+    monitor_("Video PipelineListener") {
 #ifdef MOZILLA_INTERNAL_API
   image_container_ = layers::LayerManager::CreateImageContainer();
-  source_->AddTrack(track_id_, USECS_PER_S, 0, new VideoSegment());
-  source_->AdvanceKnownTracksTime(STREAM_TIME_MAX);
 #endif
 }
 
@@ -982,7 +1065,7 @@ NotifyPull(MediaStreamGraph* graph, StreamTime desired_time) {
 #ifdef MOZILLA_INTERNAL_API
   nsRefPtr image = image_;
   TrackTicks target = TimeToTicksRoundUp(USECS_PER_S, desired_time);
-  TrackTicks delta = target - played_;
+  TrackTicks delta = target - played_ticks_;
 
   // Don't append if we've already provided a frame that supposedly
   // goes past the current aDesiredTime Doing so means a negative
@@ -991,9 +1074,13 @@ NotifyPull(MediaStreamGraph* graph, StreamTime desired_time) {
     VideoSegment segment;
     segment.AppendFrame(image ? image.forget() : nullptr, delta,
                         gfxIntSize(width_, height_));
-    source_->AppendToTrack(track_id_, &(segment));
-
-    played_ = target;
+    // Handle track not actually added yet or removed/finished
+    if (source_->AppendToTrack(track_id_, &segment)) {
+      played_ticks_ = target;
+    } else {
+      MOZ_MTLOG(PR_LOG_ERROR, "AppendToTrack failed");
+      return;
+    }
   }
 #endif
 }
diff --git a/media/webrtc/signaling/src/mediapipeline/MediaPipeline.h b/media/webrtc/signaling/src/mediapipeline/MediaPipeline.h
index e1e0ff5027cc..d4aa9d2e673a 100644
--- a/media/webrtc/signaling/src/mediapipeline/MediaPipeline.h
+++ b/media/webrtc/signaling/src/mediapipeline/MediaPipeline.h
@@ -14,6 +14,7 @@
 #else
 #include "DOMMediaStream.h"
 #include "MediaStreamGraph.h"
+#include "VideoUtils.h"
 #endif
 #include "MediaConduitInterface.h"
 #include "AudioSegment.h"
@@ -226,6 +227,66 @@ class MediaPipeline : public sigslot::has_slots<> {
   bool IsRtp(const unsigned char *data, size_t len);
 };
 
+class GenericReceiveListener : public MediaStreamListener
+{
+ public:
+  GenericReceiveListener(SourceMediaStream *source, TrackID track_id,
+                         TrackRate track_rate)
+    : source_(source),
+      track_id_(track_id),
+      track_rate_(track_rate),
+      played_ticks_(0) {}
+
+  virtual ~GenericReceiveListener() {}
+
+  void AddSelf(MediaSegment* segment);
+
+  void SetPlayedTicks(TrackTicks time) {
+    played_ticks_ = time;
+  }
+
+  void EndTrack() {
+    source_->EndTrack(track_id_);
+  }
+
+ protected:
+  SourceMediaStream *source_;
+  TrackID track_id_;
+  TrackRate track_rate_;
+  TrackTicks played_ticks_;
+};
+
+class TrackAddedCallback {
+ public:
+  virtual void TrackAdded(TrackTicks current_ticks) = 0;
+
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TrackAddedCallback);
+
+ protected:
+  virtual ~TrackAddedCallback() {}
+};
+
+class GenericReceiveListener;
+
+class GenericReceiveCallback : public TrackAddedCallback
+{
+ public:
+  GenericReceiveCallback(GenericReceiveListener* listener)
+    : listener_(listener) {}
+
+  void TrackAdded(TrackTicks time) {
+    listener_->SetPlayedTicks(time);
+  }
+
+ private:
+  RefPtr listener_;
+};
+
+// Add a track and listener on the MSG thread using the MSG command queue
+static void AddTrackAndListener(MediaStream* source,
+                                TrackID track_id, TrackRate track_rate,
+                                MediaStreamListener* listener, MediaSegment* segment,
+                                const RefPtr& completed);
 
 class ConduitDeleteEvent: public nsRunnable
 {
@@ -320,8 +381,7 @@ class MediaPipelineTransmit : public MediaPipeline {
   };
 
  private:
-RefPtr listener_;
-
+  RefPtr listener_;
 };
 
 
@@ -373,6 +433,7 @@ class MediaPipelineReceiveAudio : public MediaPipelineReceive {
 
   virtual void DetachMediaStream() {
     ASSERT_ON_THREAD(main_thread_);
+    listener_->EndTrack();
     stream_->RemoveListener(listener_);
     // Remove our reference so that when the MediaStreamGraph
     // releases the listener, it will be destroyed.
@@ -384,7 +445,7 @@ class MediaPipelineReceiveAudio : public MediaPipelineReceive {
 
  private:
   // Separate class to allow ref counting
-  class PipelineListener : public MediaStreamListener {
+  class PipelineListener : public GenericReceiveListener {
    public:
     PipelineListener(SourceMediaStream * source, TrackID track_id,
                      const RefPtr& conduit);
@@ -401,13 +462,10 @@ class MediaPipelineReceiveAudio : public MediaPipelineReceive {
                                           TrackTicks offset,
                                           uint32_t events,
                                           const MediaSegment& queued_media) MOZ_OVERRIDE {}
-    virtual void NotifyPull(MediaStreamGraph* aGraph, StreamTime aDesiredTime) MOZ_OVERRIDE;
+    virtual void NotifyPull(MediaStreamGraph* graph, StreamTime desired_time) MOZ_OVERRIDE;
 
    private:
-    SourceMediaStream *source_;
-    TrackID track_id_;
     RefPtr conduit_;
-    uint64_t played_;  // Amount of media played in milliseconds.
   };
 
   RefPtr listener_;
@@ -437,6 +495,8 @@ class MediaPipelineReceiveVideo : public MediaPipelineReceive {
   virtual void DetachMediaStream() {
     ASSERT_ON_THREAD(main_thread_);
 
+    listener_->EndTrack();
+
     conduit_ = nullptr;  // Force synchronous destruction so we
                          // stop generating video.
 
@@ -478,17 +538,17 @@ class MediaPipelineReceiveVideo : public MediaPipelineReceive {
   };
 
   // Separate class to allow ref counting
-  class PipelineListener : public MediaStreamListener {
+  class PipelineListener : public GenericReceiveListener {
    public:
     PipelineListener(SourceMediaStream * source, TrackID track_id);
 
-    // Implement MediaStreamListenerb
+    // Implement MediaStreamListener
     virtual void NotifyQueuedTrackChanges(MediaStreamGraph* graph, TrackID tid,
                                           TrackRate rate,
                                           TrackTicks offset,
                                           uint32_t events,
-                                          const MediaSegment& queued_media) {}
-    virtual void NotifyPull(MediaStreamGraph* aGraph, StreamTime aDesiredTime);
+                                          const MediaSegment& queued_media) MOZ_OVERRIDE {}
+    virtual void NotifyPull(MediaStreamGraph* graph, StreamTime desired_time) MOZ_OVERRIDE;
 
     // Accessors for external writes from the renderer
     void FrameSizeChange(unsigned int width,
@@ -507,11 +567,6 @@ class MediaPipelineReceiveVideo : public MediaPipelineReceive {
 
 
    private:
-    SourceMediaStream *source_;
-    TrackID track_id_;
-#ifdef MOZILLA_INTERNAL_API
-    TrackTicks played_;  // Amount of media played.
-#endif
     int width_;
     int height_;
 #ifdef MOZILLA_INTERNAL_API
diff --git a/media/webrtc/signaling/test/FakeMediaStreams.h b/media/webrtc/signaling/test/FakeMediaStreams.h
index 1064a250ae17..69c25033158a 100644
--- a/media/webrtc/signaling/test/FakeMediaStreams.h
+++ b/media/webrtc/signaling/test/FakeMediaStreams.h
@@ -32,6 +32,8 @@ namespace mozilla {
 
 class Fake_SourceMediaStream;
 
+static const int64_t USECS_PER_S = 1000000;
+
 class Fake_MediaStreamListener
 {
  public:
@@ -108,8 +110,9 @@ class Fake_SourceMediaStream : public Fake_MediaStream {
 
   void AddTrack(mozilla::TrackID aID, mozilla::TrackRate aRate, mozilla::TrackTicks aStart,
                 mozilla::MediaSegment* aSegment) {}
+  void EndTrack(mozilla::TrackID aID) {}
 
-  void AppendToTrack(mozilla::TrackID aID, mozilla::MediaSegment* aSegment) {
+  bool AppendToTrack(mozilla::TrackID aID, mozilla::MediaSegment* aSegment) {
     bool nonZeroSample = false;
     MOZ_ASSERT(aSegment);
     if(aSegment->GetType() == mozilla::MediaSegment::AUDIO) {
@@ -143,6 +146,7 @@ class Fake_SourceMediaStream : public Fake_MediaStream {
       //segment count.
       ++mSegmentsAdded;
     }
+    return true;
   }
 
   void AdvanceKnownTracksTime(mozilla::StreamTime aKnownTime) {}

From 03a817207120f006f2ea46976e4207ff3e1c0a62 Mon Sep 17 00:00:00 2001
From: Mark Finkle 
Date: Wed, 27 Mar 2013 01:06:11 -0400
Subject: [PATCH 105/129] Bug 854107 - Lazy load more normal JS objects
 r=margaret

---
 .../android/chrome/content/MasterPassword.js  |  82 ++++
 mobile/android/chrome/content/OfflineApps.js  |  75 +++
 mobile/android/chrome/content/PluginHelper.js | 282 +++++++++++
 mobile/android/chrome/content/browser.js      | 456 +-----------------
 mobile/android/chrome/jar.mn                  |   3 +
 5 files changed, 455 insertions(+), 443 deletions(-)
 create mode 100644 mobile/android/chrome/content/MasterPassword.js
 create mode 100644 mobile/android/chrome/content/OfflineApps.js
 create mode 100644 mobile/android/chrome/content/PluginHelper.js

diff --git a/mobile/android/chrome/content/MasterPassword.js b/mobile/android/chrome/content/MasterPassword.js
new file mode 100644
index 000000000000..62c53f6bdd18
--- /dev/null
+++ b/mobile/android/chrome/content/MasterPassword.js
@@ -0,0 +1,82 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+"use strict";
+
+var MasterPassword = {
+  pref: "privacy.masterpassword.enabled",
+  _tokenName: "",
+
+  get _secModuleDB() {
+    delete this._secModuleDB;
+    return this._secModuleDB = Cc["@mozilla.org/security/pkcs11moduledb;1"].getService(Ci.nsIPKCS11ModuleDB);
+  },
+
+  get _pk11DB() {
+    delete this._pk11DB;
+    return this._pk11DB = Cc["@mozilla.org/security/pk11tokendb;1"].getService(Ci.nsIPK11TokenDB);
+  },
+
+  get enabled() {
+    let slot = this._secModuleDB.findSlotByName(this._tokenName);
+    if (slot) {
+      let status = slot.status;
+      return status != Ci.nsIPKCS11Slot.SLOT_UNINITIALIZED && status != Ci.nsIPKCS11Slot.SLOT_READY;
+    }
+    return false;
+  },
+
+  setPassword: function setPassword(aPassword) {
+    try {
+      let status;
+      let slot = this._secModuleDB.findSlotByName(this._tokenName);
+      if (slot)
+        status = slot.status;
+      else
+        return false;
+
+      let token = this._pk11DB.findTokenByName(this._tokenName);
+
+      if (status == Ci.nsIPKCS11Slot.SLOT_UNINITIALIZED)
+        token.initPassword(aPassword);
+      else if (status == Ci.nsIPKCS11Slot.SLOT_READY)
+        token.changePassword("", aPassword);
+
+      this.updatePref();
+      return true;
+    } catch(e) {
+      dump("MasterPassword.setPassword: " + e);
+    }
+    return false;
+  },
+
+  removePassword: function removePassword(aOldPassword) {
+    try {
+      let token = this._pk11DB.getInternalKeyToken();
+      if (token.checkPassword(aOldPassword)) {
+        token.changePassword(aOldPassword, "");
+        this.updatePref();
+        return true;
+      }
+    } catch(e) {
+      dump("MasterPassword.removePassword: " + e + "\n");
+    }
+    NativeWindow.toast.show(Strings.browser.GetStringFromName("masterPassword.incorrect"), "short");
+    return false;
+  },
+
+  updatePref: function() {
+    var prefs = [];
+    let pref = {
+      name: this.pref,
+      type: "bool",
+      value: this.enabled
+    };
+    prefs.push(pref);
+
+    sendMessageToJava({
+      type: "Preferences:Data",
+      preferences: prefs
+    });
+  }
+};
diff --git a/mobile/android/chrome/content/OfflineApps.js b/mobile/android/chrome/content/OfflineApps.js
new file mode 100644
index 000000000000..b45167f2aa0c
--- /dev/null
+++ b/mobile/android/chrome/content/OfflineApps.js
@@ -0,0 +1,75 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+"use strict";
+
+var OfflineApps = {
+  offlineAppRequested: function(aContentWindow) {
+    if (!Services.prefs.getBoolPref("browser.offline-apps.notify"))
+      return;
+
+    let tab = BrowserApp.getTabForWindow(aContentWindow);
+    let currentURI = aContentWindow.document.documentURIObject;
+
+    // Don't bother showing UI if the user has already made a decision
+    if (Services.perms.testExactPermission(currentURI, "offline-app") != Services.perms.UNKNOWN_ACTION)
+      return;
+
+    try {
+      if (Services.prefs.getBoolPref("offline-apps.allow_by_default")) {
+        // All pages can use offline capabilities, no need to ask the user
+        return;
+      }
+    } catch(e) {
+      // This pref isn't set by default, ignore failures
+    }
+
+    let host = currentURI.asciiHost;
+    let notificationID = "offline-app-requested-" + host;
+
+    let strings = Strings.browser;
+    let buttons = [{
+      label: strings.GetStringFromName("offlineApps.allow"),
+      callback: function() {
+        OfflineApps.allowSite(aContentWindow.document);
+      }
+    },
+    {
+      label: strings.GetStringFromName("offlineApps.dontAllow2"),
+      callback: function(aChecked) {
+        if (aChecked)
+          OfflineApps.disallowSite(aContentWindow.document);
+      }
+    }];
+
+    let message = strings.formatStringFromName("offlineApps.ask", [host], 1);
+    let options = { checkbox: Strings.browser.GetStringFromName("offlineApps.dontAskAgain") };
+    NativeWindow.doorhanger.show(message, notificationID, buttons, tab.id, options);
+  },
+
+  allowSite: function(aDocument) {
+    Services.perms.add(aDocument.documentURIObject, "offline-app", Services.perms.ALLOW_ACTION);
+
+    // When a site is enabled while loading, manifest resources will
+    // start fetching immediately.  This one time we need to do it
+    // ourselves.
+    this._startFetching(aDocument);
+  },
+
+  disallowSite: function(aDocument) {
+    Services.perms.add(aDocument.documentURIObject, "offline-app", Services.perms.DENY_ACTION);
+  },
+
+  _startFetching: function(aDocument) {
+    if (!aDocument.documentElement)
+      return;
+
+    let manifest = aDocument.documentElement.getAttribute("manifest");
+    if (!manifest)
+      return;
+
+    let manifestURI = Services.io.newURI(manifest, aDocument.characterSet, aDocument.documentURIObject);
+    let updateService = Cc["@mozilla.org/offlinecacheupdate-service;1"].getService(Ci.nsIOfflineCacheUpdateService);
+    updateService.scheduleUpdate(manifestURI, aDocument.documentURIObject, window);
+  }
+};
diff --git a/mobile/android/chrome/content/PluginHelper.js b/mobile/android/chrome/content/PluginHelper.js
new file mode 100644
index 000000000000..b9451c30c456
--- /dev/null
+++ b/mobile/android/chrome/content/PluginHelper.js
@@ -0,0 +1,282 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+"use strict";
+
+var PluginHelper = {
+  showDoorHanger: function(aTab) {
+    if (!aTab.browser)
+      return;
+
+    // Even though we may not end up showing a doorhanger, this flag
+    // lets us know that we've tried to show a doorhanger.
+    aTab.shouldShowPluginDoorhanger = false;
+
+    let uri = aTab.browser.currentURI;
+
+    // If the user has previously set a plugins permission for this website,
+    // either play or don't play the plugins instead of showing a doorhanger.
+    let permValue = Services.perms.testPermission(uri, "plugins");
+    if (permValue != Services.perms.UNKNOWN_ACTION) {
+      if (permValue == Services.perms.ALLOW_ACTION)
+        PluginHelper.playAllPlugins(aTab.browser.contentWindow);
+
+      return;
+    }
+
+    let message = Strings.browser.formatStringFromName("clickToPlayPlugins.message2",
+                                                       [uri.host], 1);
+    let buttons = [
+      {
+        label: Strings.browser.GetStringFromName("clickToPlayPlugins.activate"),
+        callback: function(aChecked) {
+          // If the user checked "Don't ask again", make a permanent exception
+          if (aChecked)
+            Services.perms.add(uri, "plugins", Ci.nsIPermissionManager.ALLOW_ACTION);
+
+          PluginHelper.playAllPlugins(aTab.browser.contentWindow);
+        }
+      },
+      {
+        label: Strings.browser.GetStringFromName("clickToPlayPlugins.dontActivate"),
+        callback: function(aChecked) {
+          // If the user checked "Don't ask again", make a permanent exception
+          if (aChecked)
+            Services.perms.add(uri, "plugins", Ci.nsIPermissionManager.DENY_ACTION);
+
+          // Other than that, do nothing
+        }
+      }
+    ];
+
+    // Add a checkbox with a "Don't ask again" message if the uri contains a
+    // host. Adding a permanent exception will fail if host is not present.
+    let options = uri.host ? { checkbox: Strings.browser.GetStringFromName("clickToPlayPlugins.dontAskAgain") } : {};
+
+    NativeWindow.doorhanger.show(message, "ask-to-play-plugins", buttons, aTab.id, options);
+  },
+
+  delayAndShowDoorHanger: function(aTab) {
+    // To avoid showing the doorhanger if there are also visible plugin
+    // overlays on the page, delay showing the doorhanger to check if
+    // visible plugins get added in the near future.
+    if (!aTab.pluginDoorhangerTimeout) {
+      aTab.pluginDoorhangerTimeout = setTimeout(function() {
+        if (this.shouldShowPluginDoorhanger) {
+          PluginHelper.showDoorHanger(this);
+        }
+      }.bind(aTab), 500);
+    }
+  },
+
+  playAllPlugins: function(aContentWindow) {
+    let cwu = aContentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
+                            .getInterface(Ci.nsIDOMWindowUtils);
+    // XXX not sure if we should enable plugins for the parent documents...
+    let plugins = cwu.plugins;
+    if (!plugins || !plugins.length)
+      return;
+
+    plugins.forEach(this.playPlugin);
+  },
+
+  playPlugin: function(plugin) {
+    let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
+    if (!objLoadingContent.activated)
+      objLoadingContent.playPlugin();
+  },
+
+  stopPlayPreview: function(plugin, playPlugin) {
+    let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
+    if (objLoadingContent.activated)
+      return;
+
+    if (playPlugin)
+      objLoadingContent.playPlugin();
+    else
+      objLoadingContent.cancelPlayPreview();
+  },
+
+  getPluginPreference: function getPluginPreference() {
+    let pluginDisable = Services.prefs.getBoolPref("plugin.disable");
+    if (pluginDisable)
+      return "0";
+
+    let clickToPlay = Services.prefs.getBoolPref("plugins.click_to_play");
+    return clickToPlay ? "2" : "1";
+  },
+
+  setPluginPreference: function setPluginPreference(aValue) {
+    switch (aValue) {
+      case "0": // Enable Plugins = No
+        Services.prefs.setBoolPref("plugin.disable", true);
+        Services.prefs.clearUserPref("plugins.click_to_play");
+        break;
+      case "1": // Enable Plugins = Yes
+        Services.prefs.clearUserPref("plugin.disable");
+        Services.prefs.setBoolPref("plugins.click_to_play", false);
+        break;
+      case "2": // Enable Plugins = Tap to Play (default)
+        Services.prefs.clearUserPref("plugin.disable");
+        Services.prefs.clearUserPref("plugins.click_to_play");
+        break;
+    }
+  },
+
+  // Copied from /browser/base/content/browser.js
+  isTooSmall : function (plugin, overlay) {
+    // Is the 's size too small to hold what we want to show?
+    let pluginRect = plugin.getBoundingClientRect();
+    // XXX bug 446693. The text-shadow on the submitted-report text at
+    //     the bottom causes scrollHeight to be larger than it should be.
+    let overflows = (overlay.scrollWidth > pluginRect.width) ||
+                    (overlay.scrollHeight - 5 > pluginRect.height);
+
+    return overflows;
+  },
+
+  getPluginMimeType: function (plugin) {
+    var tagMimetype;
+    if (plugin instanceof HTMLAppletElement) {
+      tagMimetype = "application/x-java-vm";
+    } else {
+      tagMimetype = plugin.QueryInterface(Components.interfaces.nsIObjectLoadingContent)
+                          .actualType;
+
+      if (tagMimetype == "") {
+        tagMimetype = plugin.type;
+      }
+    }
+
+    return tagMimetype;
+  },
+
+  handlePluginBindingAttached: function (aTab, aEvent) {
+    let plugin = aEvent.target;
+    let doc = plugin.ownerDocument;
+    let overlay = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox");
+    if (!overlay || overlay._bindingHandled) {
+      return;
+    }
+    overlay._bindingHandled = true;
+
+    let eventType = PluginHelper._getBindingType(plugin);
+    if (!eventType) {
+      // Not all bindings have handlers
+      return;
+    }
+
+    switch  (eventType) {
+      case "PluginClickToPlay": {
+        // Check if plugins have already been activated for this page, or if
+        // the user has set a permission to always play plugins on the site
+        if (aTab.clickToPlayPluginsActivated ||
+            Services.perms.testPermission(aTab.browser.currentURI, "plugins") ==
+            Services.perms.ALLOW_ACTION) {
+          PluginHelper.playPlugin(plugin);
+          return;
+        }
+
+        // If the plugin is hidden, or if the overlay is too small, show a 
+        // doorhanger notification
+        if (PluginHelper.isTooSmall(plugin, overlay)) {
+          PluginHelper.delayAndShowDoorHanger(aTab);
+        } else {
+          // There's a large enough visible overlay that we don't need to show
+          // the doorhanger.
+          aTab.shouldShowPluginDoorhanger = false;
+        }
+
+        // Add click to play listener to the overlay
+        overlay.addEventListener("click", function(e) {
+          if (!e.isTrusted)
+            return;
+          e.preventDefault();
+          let win = e.target.ownerDocument.defaultView.top;
+          let tab = BrowserApp.getTabForWindow(win);
+          tab.clickToPlayPluginsActivated = true;
+          PluginHelper.playAllPlugins(win);
+
+          NativeWindow.doorhanger.hide("ask-to-play-plugins", tab.id);
+        }, true);
+        break;
+      }
+
+      case "PluginPlayPreview": {
+        let previewContent = doc.getAnonymousElementByAttribute(plugin, "class", "previewPluginContent");
+        let pluginHost = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
+        let mimeType = PluginHelper.getPluginMimeType(plugin);
+        let playPreviewInfo = pluginHost.getPlayPreviewInfo(mimeType);
+
+        if (!playPreviewInfo.ignoreCTP) {
+          // Check if plugins have already been activated for this page, or if
+          // the user has set a permission to always play plugins on the site
+          if (aTab.clickToPlayPluginsActivated ||
+              Services.perms.testPermission(aTab.browser.currentURI, "plugins") ==
+              Services.perms.ALLOW_ACTION) {
+            PluginHelper.playPlugin(plugin);
+            return;
+          }
+
+          // Always show door hanger for play preview plugins
+          PluginHelper.delayAndShowDoorHanger(aTab);
+        }
+
+        let iframe = previewContent.getElementsByClassName("previewPluginContentFrame")[0];
+        if (!iframe) {
+          // lazy initialization of the iframe
+          iframe = doc.createElementNS("http://www.w3.org/1999/xhtml", "iframe");
+          iframe.className = "previewPluginContentFrame";
+          previewContent.appendChild(iframe);
+        }
+        iframe.src = playPreviewInfo.redirectURL;
+
+        // MozPlayPlugin event can be dispatched from the extension chrome
+        // code to replace the preview content with the native plugin
+        previewContent.addEventListener("MozPlayPlugin", function playPluginHandler(e) {
+          if (!e.isTrusted)
+            return;
+
+          previewContent.removeEventListener("MozPlayPlugin", playPluginHandler, true);
+
+          let playPlugin = !aEvent.detail;
+          PluginHelper.stopPlayPreview(plugin, playPlugin);
+
+          // cleaning up: removes overlay iframe from the DOM
+          let iframe = previewContent.getElementsByClassName("previewPluginContentFrame")[0];
+          if (iframe)
+            previewContent.removeChild(iframe);
+        }, true);
+        break;
+      }
+
+      case "PluginNotFound": {
+        // On devices where we don't support Flash, there will be a
+        // "Learn More..." link in the missing plugin error message.
+        let learnMoreLink = doc.getAnonymousElementByAttribute(plugin, "class", "unsupportedLearnMoreLink");
+        let learnMoreUrl = Services.urlFormatter.formatURLPref("app.support.baseURL");
+        learnMoreUrl += "why-cant-firefox-mobile-play-flash-on-my-device";
+        learnMoreLink.href = learnMoreUrl;
+        break;
+      }
+    }
+  },
+
+  // Helper to get the binding handler type from a plugin object
+  _getBindingType: function(plugin) {
+    if (!(plugin instanceof Ci.nsIObjectLoadingContent))
+      return null;
+
+    switch (plugin.pluginFallbackType) {
+      case Ci.nsIObjectLoadingContent.PLUGIN_UNSUPPORTED:
+        return "PluginNotFound";
+      case Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY:
+        return "PluginClickToPlay";
+      case Ci.nsIObjectLoadingContent.PLUGIN_PLAY_PREVIEW:
+        return "PluginPlayPreview";
+      default:
+        // Not all states map to a handler
+        return null;
+    }
+  }
+};
diff --git a/mobile/android/chrome/content/browser.js b/mobile/android/chrome/content/browser.js
index 83298788c80d..00fa890fc576 100644
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -64,6 +64,9 @@ XPCOMUtils.defineLazyGetter(this, "Sanitizer", function() {
   ["InputWidgetHelper", "chrome://browser/content/InputWidgetHelper.js"],
   ["AboutReader", "chrome://browser/content/aboutReader.js"],
   ["WebAppRT", "chrome://browser/content/WebAppRT.js"],
+  ["MasterPassword", "chrome://browser/content/MasterPassword.js"],
+  ["PluginHelper", "chrome://browser/content/PluginHelper.js"],
+  ["OfflineApps", "chrome://browser/content/OfflineApps.js"],
 ].forEach(function (aScript) {
   let [name, script] = aScript;
   XPCOMUtils.defineLazyGetter(window, name, function() {
@@ -267,7 +270,6 @@ var BrowserApp = {
     Downloads.init();
     FindHelper.init();
     FormAssistant.init();
-    OfflineApps.init();
     IndexedDB.init();
     XPInstallObserver.init();
     ClipboardHelper.init();
@@ -554,7 +556,6 @@ var BrowserApp = {
     LightWeightThemeWebInstaller.uninit();
     FormAssistant.uninit();
     FindHelper.uninit();
-    OfflineApps.uninit();
     IndexedDB.uninit();
     ViewportHandler.uninit();
     XPInstallObserver.uninit();
@@ -924,7 +925,7 @@ var BrowserApp = {
           pref.value = PluginHelper.getPluginPreference();
           prefs.push(pref);
           continue;
-        } else if (prefName == MasterPassword.pref) {
+        } else if (prefName == "privacy.masterpassword.enabled") {
           // Master password is not a "real" pref
           pref.type = "bool";
           pref.value = MasterPassword.enabled;
@@ -1016,7 +1017,8 @@ var BrowserApp = {
       // we need to handle it differently
       PluginHelper.setPluginPreference(json.value);
       return;
-    } else if (json.name == MasterPassword.pref) {
+    } else if (json.name == "privacy.masterpassword.enabled") {
+      // MasterPassword pref is not real, we just need take action and leave
       // MasterPassword pref is not real, we just need take action and leave
       if (MasterPassword.enabled)
         MasterPassword.removePassword(json.value);
@@ -2416,6 +2418,7 @@ Tab.prototype = {
     // Note that the XBL binding is untrusted
     this.browser.addEventListener("PluginBindingAttached", this, true, true);
     this.browser.addEventListener("pageshow", this, true);
+    this.browser.addEventListener("MozApplicationManifest", this, true);
 
     Services.obs.addObserver(this, "before-first-paint", false);
     Services.prefs.addObserver("browser.ui.zoom.force-user-scalable", this, false);
@@ -2527,6 +2530,7 @@ Tab.prototype = {
     this.browser.removeEventListener("MozScrolledAreaChanged", this, true);
     this.browser.removeEventListener("PluginBindingAttached", this, true);
     this.browser.removeEventListener("pageshow", this, true);
+    this.browser.removeEventListener("MozApplicationManifest", this, true);
 
     Services.obs.removeObserver(this, "before-first-paint");
     Services.prefs.removeObserver("browser.ui.zoom.force-user-scalable", this);
@@ -3135,6 +3139,11 @@ Tab.prototype = {
         break;
       }
 
+      case "MozApplicationManifest": {
+        OfflineApps.offlineAppRequested(aEvent.originalTarget.defaultView);
+        break;
+      }
+
       case "pageshow": {
         // only send pageshow for the top-level document
         if (aEvent.originalTarget.defaultView != this.browser.contentWindow)
@@ -5252,90 +5261,6 @@ var PopupBlockerObserver = {
 };
 
 
-var OfflineApps = {
-  init: function() {
-    BrowserApp.deck.addEventListener("MozApplicationManifest", this, false);
-  },
-
-  uninit: function() {
-    BrowserApp.deck.removeEventListener("MozApplicationManifest", this, false);
-  },
-
-  handleEvent: function(aEvent) {
-    if (aEvent.type == "MozApplicationManifest")
-      this.offlineAppRequested(aEvent.originalTarget.defaultView);
-  },
-
-  offlineAppRequested: function(aContentWindow) {
-    if (!Services.prefs.getBoolPref("browser.offline-apps.notify"))
-      return;
-
-    let tab = BrowserApp.getTabForWindow(aContentWindow);
-    let currentURI = aContentWindow.document.documentURIObject;
-
-    // Don't bother showing UI if the user has already made a decision
-    if (Services.perms.testExactPermission(currentURI, "offline-app") != Services.perms.UNKNOWN_ACTION)
-      return;
-
-    try {
-      if (Services.prefs.getBoolPref("offline-apps.allow_by_default")) {
-        // All pages can use offline capabilities, no need to ask the user
-        return;
-      }
-    } catch(e) {
-      // This pref isn't set by default, ignore failures
-    }
-
-    let host = currentURI.asciiHost;
-    let notificationID = "offline-app-requested-" + host;
-
-    let strings = Strings.browser;
-    let buttons = [{
-      label: strings.GetStringFromName("offlineApps.allow"),
-      callback: function() {
-        OfflineApps.allowSite(aContentWindow.document);
-      }
-    },
-    {
-      label: strings.GetStringFromName("offlineApps.dontAllow2"),
-      callback: function(aChecked) {
-        if (aChecked)
-          OfflineApps.disallowSite(aContentWindow.document);
-      }
-    }];
-
-    let message = strings.formatStringFromName("offlineApps.ask", [host], 1);
-    let options = { checkbox: Strings.browser.GetStringFromName("offlineApps.dontAskAgain") };
-    NativeWindow.doorhanger.show(message, notificationID, buttons, tab.id, options);
-  },
-
-  allowSite: function(aDocument) {
-    Services.perms.add(aDocument.documentURIObject, "offline-app", Services.perms.ALLOW_ACTION);
-
-    // When a site is enabled while loading, manifest resources will
-    // start fetching immediately.  This one time we need to do it
-    // ourselves.
-    this._startFetching(aDocument);
-  },
-
-  disallowSite: function(aDocument) {
-    Services.perms.add(aDocument.documentURIObject, "offline-app", Services.perms.DENY_ACTION);
-  },
-
-  _startFetching: function(aDocument) {
-    if (!aDocument.documentElement)
-      return;
-
-    let manifest = aDocument.documentElement.getAttribute("manifest");
-    if (!manifest)
-      return;
-
-    let manifestURI = Services.io.newURI(manifest, aDocument.characterSet, aDocument.documentURIObject);
-    let updateService = Cc["@mozilla.org/offlinecacheupdate-service;1"].getService(Ci.nsIOfflineCacheUpdateService);
-    updateService.scheduleUpdate(manifestURI, aDocument.documentURIObject, window);
-  }
-};
-
 var IndexedDB = {
   _permissionsPrompt: "indexedDB-permissions-prompt",
   _permissionsResponse: "indexedDB-permissions-response",
@@ -5568,284 +5493,6 @@ var ClipboardHelper = {
   }
 };
 
-var PluginHelper = {
-  showDoorHanger: function(aTab) {
-    if (!aTab.browser)
-      return;
-
-    // Even though we may not end up showing a doorhanger, this flag
-    // lets us know that we've tried to show a doorhanger.
-    aTab.shouldShowPluginDoorhanger = false;
-
-    let uri = aTab.browser.currentURI;
-
-    // If the user has previously set a plugins permission for this website,
-    // either play or don't play the plugins instead of showing a doorhanger.
-    let permValue = Services.perms.testPermission(uri, "plugins");
-    if (permValue != Services.perms.UNKNOWN_ACTION) {
-      if (permValue == Services.perms.ALLOW_ACTION)
-        PluginHelper.playAllPlugins(aTab.browser.contentWindow);
-
-      return;
-    }
-
-    let message = Strings.browser.formatStringFromName("clickToPlayPlugins.message2",
-                                                       [uri.host], 1);
-    let buttons = [
-      {
-        label: Strings.browser.GetStringFromName("clickToPlayPlugins.activate"),
-        callback: function(aChecked) {
-          // If the user checked "Don't ask again", make a permanent exception
-          if (aChecked)
-            Services.perms.add(uri, "plugins", Ci.nsIPermissionManager.ALLOW_ACTION);
-
-          PluginHelper.playAllPlugins(aTab.browser.contentWindow);
-        }
-      },
-      {
-        label: Strings.browser.GetStringFromName("clickToPlayPlugins.dontActivate"),
-        callback: function(aChecked) {
-          // If the user checked "Don't ask again", make a permanent exception
-          if (aChecked)
-            Services.perms.add(uri, "plugins", Ci.nsIPermissionManager.DENY_ACTION);
-
-          // Other than that, do nothing
-        }
-      }
-    ];
-
-    // Add a checkbox with a "Don't ask again" message if the uri contains a
-    // host. Adding a permanent exception will fail if host is not present.
-    let options = uri.host ? { checkbox: Strings.browser.GetStringFromName("clickToPlayPlugins.dontAskAgain") } : {};
-
-    NativeWindow.doorhanger.show(message, "ask-to-play-plugins", buttons, aTab.id, options);
-  },
-
-  delayAndShowDoorHanger: function(aTab) {
-    // To avoid showing the doorhanger if there are also visible plugin
-    // overlays on the page, delay showing the doorhanger to check if
-    // visible plugins get added in the near future.
-    if (!aTab.pluginDoorhangerTimeout) {
-      aTab.pluginDoorhangerTimeout = setTimeout(function() {
-        if (this.shouldShowPluginDoorhanger) {
-          PluginHelper.showDoorHanger(this);
-        }
-      }.bind(aTab), 500);
-    }
-  },
-
-  playAllPlugins: function(aContentWindow) {
-    let cwu = aContentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
-                            .getInterface(Ci.nsIDOMWindowUtils);
-    // XXX not sure if we should enable plugins for the parent documents...
-    let plugins = cwu.plugins;
-    if (!plugins || !plugins.length)
-      return;
-
-    plugins.forEach(this.playPlugin);
-  },
-
-  playPlugin: function(plugin) {
-    let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
-    if (!objLoadingContent.activated)
-      objLoadingContent.playPlugin();
-  },
-
-  stopPlayPreview: function(plugin, playPlugin) {
-    let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
-    if (objLoadingContent.activated)
-      return;
-
-    if (playPlugin)
-      objLoadingContent.playPlugin();
-    else
-      objLoadingContent.cancelPlayPreview();
-  },
-
-  getPluginPreference: function getPluginPreference() {
-    let pluginDisable = Services.prefs.getBoolPref("plugin.disable");
-    if (pluginDisable)
-      return "0";
-
-    let clickToPlay = Services.prefs.getBoolPref("plugins.click_to_play");
-    return clickToPlay ? "2" : "1";
-  },
-
-  setPluginPreference: function setPluginPreference(aValue) {
-    switch (aValue) {
-      case "0": // Enable Plugins = No
-        Services.prefs.setBoolPref("plugin.disable", true);
-        Services.prefs.clearUserPref("plugins.click_to_play");
-        break;
-      case "1": // Enable Plugins = Yes
-        Services.prefs.clearUserPref("plugin.disable");
-        Services.prefs.setBoolPref("plugins.click_to_play", false);
-        break;
-      case "2": // Enable Plugins = Tap to Play (default)
-        Services.prefs.clearUserPref("plugin.disable");
-        Services.prefs.clearUserPref("plugins.click_to_play");
-        break;
-    }
-  },
-
-  // Copied from /browser/base/content/browser.js
-  isTooSmall : function (plugin, overlay) {
-    // Is the 's size too small to hold what we want to show?
-    let pluginRect = plugin.getBoundingClientRect();
-    // XXX bug 446693. The text-shadow on the submitted-report text at
-    //     the bottom causes scrollHeight to be larger than it should be.
-    let overflows = (overlay.scrollWidth > pluginRect.width) ||
-                    (overlay.scrollHeight - 5 > pluginRect.height);
-
-    return overflows;
-  },
-
-  getPluginMimeType: function (plugin) {
-    var tagMimetype;
-    if (plugin instanceof HTMLAppletElement) {
-      tagMimetype = "application/x-java-vm";
-    } else {
-      tagMimetype = plugin.QueryInterface(Components.interfaces.nsIObjectLoadingContent)
-                          .actualType;
-
-      if (tagMimetype == "") {
-        tagMimetype = plugin.type;
-      }
-    }
-
-    return tagMimetype;
-  },
-
-  handlePluginBindingAttached: function (aTab, aEvent) {
-    let plugin = aEvent.target;
-    let doc = plugin.ownerDocument;
-    let overlay = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox");
-    if (!overlay || overlay._bindingHandled) {
-      return;
-    }
-    overlay._bindingHandled = true;
-
-    let eventType = PluginHelper._getBindingType(plugin);
-    if (!eventType) {
-      // Not all bindings have handlers
-      return;
-    }
-
-    switch  (eventType) {
-      case "PluginClickToPlay": {
-        // Check if plugins have already been activated for this page, or if
-        // the user has set a permission to always play plugins on the site
-        if (aTab.clickToPlayPluginsActivated ||
-            Services.perms.testPermission(aTab.browser.currentURI, "plugins") ==
-            Services.perms.ALLOW_ACTION) {
-          PluginHelper.playPlugin(plugin);
-          return;
-        }
-
-        // If the plugin is hidden, or if the overlay is too small, show a 
-        // doorhanger notification
-        if (PluginHelper.isTooSmall(plugin, overlay)) {
-          PluginHelper.delayAndShowDoorHanger(aTab);
-        } else {
-          // There's a large enough visible overlay that we don't need to show
-          // the doorhanger.
-          aTab.shouldShowPluginDoorhanger = false;
-        }
-
-        // Add click to play listener to the overlay
-        overlay.addEventListener("click", function(e) {
-          if (!e.isTrusted)
-            return;
-          e.preventDefault();
-          let win = e.target.ownerDocument.defaultView.top;
-          let tab = BrowserApp.getTabForWindow(win);
-          tab.clickToPlayPluginsActivated = true;
-          PluginHelper.playAllPlugins(win);
-
-          NativeWindow.doorhanger.hide("ask-to-play-plugins", tab.id);
-        }, true);
-        break;
-      }
-
-      case "PluginPlayPreview": {
-        let previewContent = doc.getAnonymousElementByAttribute(plugin, "class", "previewPluginContent");
-        let pluginHost = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
-        let mimeType = PluginHelper.getPluginMimeType(plugin);
-        let playPreviewInfo = pluginHost.getPlayPreviewInfo(mimeType);
-
-        if (!playPreviewInfo.ignoreCTP) {
-          // Check if plugins have already been activated for this page, or if
-          // the user has set a permission to always play plugins on the site
-          if (aTab.clickToPlayPluginsActivated ||
-              Services.perms.testPermission(aTab.browser.currentURI, "plugins") ==
-              Services.perms.ALLOW_ACTION) {
-            PluginHelper.playPlugin(plugin);
-            return;
-          }
-
-          // Always show door hanger for play preview plugins
-          PluginHelper.delayAndShowDoorHanger(aTab);
-        }
-
-        let iframe = previewContent.getElementsByClassName("previewPluginContentFrame")[0];
-        if (!iframe) {
-          // lazy initialization of the iframe
-          iframe = doc.createElementNS("http://www.w3.org/1999/xhtml", "iframe");
-          iframe.className = "previewPluginContentFrame";
-          previewContent.appendChild(iframe);
-        }
-        iframe.src = playPreviewInfo.redirectURL;
-
-        // MozPlayPlugin event can be dispatched from the extension chrome
-        // code to replace the preview content with the native plugin
-        previewContent.addEventListener("MozPlayPlugin", function playPluginHandler(e) {
-          if (!e.isTrusted)
-            return;
-
-          previewContent.removeEventListener("MozPlayPlugin", playPluginHandler, true);
-
-          let playPlugin = !aEvent.detail;
-          PluginHelper.stopPlayPreview(plugin, playPlugin);
-
-          // cleaning up: removes overlay iframe from the DOM
-          let iframe = previewContent.getElementsByClassName("previewPluginContentFrame")[0];
-          if (iframe)
-            previewContent.removeChild(iframe);
-        }, true);
-        break;
-      }
-
-      case "PluginNotFound": {
-        // On devices where we don't support Flash, there will be a
-        // "Learn More..." link in the missing plugin error message.
-        let learnMoreLink = doc.getAnonymousElementByAttribute(plugin, "class", "unsupportedLearnMoreLink");
-        let learnMoreUrl = Services.urlFormatter.formatURLPref("app.support.baseURL");
-        learnMoreUrl += "why-cant-firefox-mobile-play-flash-on-my-device";
-        learnMoreLink.href = learnMoreUrl;
-        break;
-      }
-    }
-  },
-
-  // Helper to get the binding handler type from a plugin object
-  _getBindingType: function(plugin) {
-    if (!(plugin instanceof Ci.nsIObjectLoadingContent))
-      return null;
-
-    switch (plugin.pluginFallbackType) {
-      case Ci.nsIObjectLoadingContent.PLUGIN_UNSUPPORTED:
-        return "PluginNotFound";
-      case Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY:
-        return "PluginClickToPlay";
-      case Ci.nsIObjectLoadingContent.PLUGIN_PLAY_PREVIEW:
-        return "PluginPlayPreview";
-      default:
-        // Not all states map to a handler
-        return null;
-    }
-  },
-
-};
 
 var PermissionsHelper = {
 
@@ -6018,83 +5665,6 @@ var PermissionsHelper = {
   }
 };
 
-var MasterPassword = {
-  pref: "privacy.masterpassword.enabled",
-  _tokenName: "",
-
-  get _secModuleDB() {
-    delete this._secModuleDB;
-    return this._secModuleDB = Cc["@mozilla.org/security/pkcs11moduledb;1"].getService(Ci.nsIPKCS11ModuleDB);
-  },
-
-  get _pk11DB() {
-    delete this._pk11DB;
-    return this._pk11DB = Cc["@mozilla.org/security/pk11tokendb;1"].getService(Ci.nsIPK11TokenDB);
-  },
-
-  get enabled() {
-    let slot = this._secModuleDB.findSlotByName(this._tokenName);
-    if (slot) {
-      let status = slot.status;
-      return status != Ci.nsIPKCS11Slot.SLOT_UNINITIALIZED && status != Ci.nsIPKCS11Slot.SLOT_READY;
-    }
-    return false;
-  },
-
-  setPassword: function setPassword(aPassword) {
-    try {
-      let status;
-      let slot = this._secModuleDB.findSlotByName(this._tokenName);
-      if (slot)
-        status = slot.status;
-      else
-        return false;
-
-      let token = this._pk11DB.findTokenByName(this._tokenName);
-
-      if (status == Ci.nsIPKCS11Slot.SLOT_UNINITIALIZED)
-        token.initPassword(aPassword);
-      else if (status == Ci.nsIPKCS11Slot.SLOT_READY)
-        token.changePassword("", aPassword);
-
-      this.updatePref();
-      return true;
-    } catch(e) {
-      dump("MasterPassword.setPassword: " + e);
-    }
-    return false;
-  },
-
-  removePassword: function removePassword(aOldPassword) {
-    try {
-      let token = this._pk11DB.getInternalKeyToken();
-      if (token.checkPassword(aOldPassword)) {
-        token.changePassword(aOldPassword, "");
-        this.updatePref();
-        return true;
-      }
-    } catch(e) {
-      dump("MasterPassword.removePassword: " + e + "\n");
-    }
-    NativeWindow.toast.show(Strings.browser.GetStringFromName("masterPassword.incorrect"), "short");
-    return false;
-  },
-
-  updatePref: function() {
-    var prefs = [];
-    let pref = {
-      name: this.pref,
-      type: "bool",
-      value: this.enabled
-    };
-    prefs.push(pref);
-
-    sendMessageToJava({
-      type: "Preferences:Data",
-      preferences: prefs
-    });
-  }
-};
 
 var CharacterEncoding = {
   _charsets: [],
diff --git a/mobile/android/chrome/jar.mn b/mobile/android/chrome/jar.mn
index 3adb4c6f8bfd..883f6b904797 100644
--- a/mobile/android/chrome/jar.mn
+++ b/mobile/android/chrome/jar.mn
@@ -43,6 +43,9 @@ chrome.jar:
   content/WebrtcUI.js                  (content/WebrtcUI.js)
   content/MemoryObserver.js            (content/MemoryObserver.js)
   content/ConsoleAPI.js                (content/ConsoleAPI.js)
+  content/PluginHelper.js              (content/PluginHelper.js)
+  content/OfflineApps.js               (content/OfflineApps.js)
+  content/MasterPassword.js            (content/MasterPassword.js)
 
 % content branding %content/branding/
 

From 043e016d9cb68b85435fd4ed5ab6304bf3f14cb2 Mon Sep 17 00:00:00 2001
From: Mark Finkle 
Date: Wed, 27 Mar 2013 01:06:14 -0400
Subject: [PATCH 106/129] Bug 854107 - Lazy load more notification-based
 objects r=margaret

---
 mobile/android/chrome/content/FindHelper.js   |  83 ++++++
 .../chrome/content/PermissionsHelper.js       | 169 +++++++++++
 mobile/android/chrome/content/browser.js      | 273 +-----------------
 mobile/android/chrome/jar.mn                  |   2 +
 4 files changed, 256 insertions(+), 271 deletions(-)
 create mode 100644 mobile/android/chrome/content/FindHelper.js
 create mode 100644 mobile/android/chrome/content/PermissionsHelper.js

diff --git a/mobile/android/chrome/content/FindHelper.js b/mobile/android/chrome/content/FindHelper.js
new file mode 100644
index 000000000000..617e904d7e80
--- /dev/null
+++ b/mobile/android/chrome/content/FindHelper.js
@@ -0,0 +1,83 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+"use strict";
+
+var FindHelper = {
+  _fastFind: null,
+  _targetTab: null,
+  _initialViewport: null,
+  _viewportChanged: false,
+
+  observe: function(aMessage, aTopic, aData) {
+    switch(aTopic) {
+      case "FindInPage:Find":
+        this.doFind(aData);
+        break;
+
+      case "FindInPage:Prev":
+        this.findAgain(aData, true);
+        break;
+
+      case "FindInPage:Next":
+        this.findAgain(aData, false);
+        break;
+
+      case "Tab:Selected":
+      case "FindInPage:Closed":
+        this.findClosed();
+        break;
+    }
+  },
+
+  doFind: function(aSearchString) {
+    if (!this._fastFind) {
+      this._targetTab = BrowserApp.selectedTab;
+      this._fastFind = this._targetTab.browser.fastFind;
+      this._initialViewport = JSON.stringify(this._targetTab.getViewport());
+      this._viewportChanged = false;
+    }
+
+    let result = this._fastFind.find(aSearchString, false);
+    this.handleResult(result);
+  },
+
+  findAgain: function(aString, aFindBackwards) {
+    // This can happen if the user taps next/previous after re-opening the search bar
+    if (!this._fastFind) {
+      this.doFind(aString);
+      return;
+    }
+
+    let result = this._fastFind.findAgain(aFindBackwards, false);
+    this.handleResult(result);
+  },
+
+  findClosed: function() {
+    // If there's no find in progress, there's nothing to clean up
+    if (!this._fastFind)
+      return;
+
+    this._fastFind.collapseSelection();
+    this._fastFind = null;
+    this._targetTab = null;
+    this._initialViewport = null;
+    this._viewportChanged = false;
+  },
+
+  handleResult: function(aResult) {
+    if (aResult == Ci.nsITypeAheadFind.FIND_NOTFOUND) {
+      if (this._viewportChanged) {
+        if (this._targetTab != BrowserApp.selectedTab) {
+          // this should never happen
+          Cu.reportError("Warning: selected tab changed during find!");
+          // fall through and restore viewport on the initial tab anyway
+        }
+        this._targetTab.setViewport(JSON.parse(this._initialViewport));
+        this._targetTab.sendViewportUpdate();
+      }
+    } else {
+      this._viewportChanged = true;
+    }
+  }
+};
diff --git a/mobile/android/chrome/content/PermissionsHelper.js b/mobile/android/chrome/content/PermissionsHelper.js
new file mode 100644
index 000000000000..6d5b37969a64
--- /dev/null
+++ b/mobile/android/chrome/content/PermissionsHelper.js
@@ -0,0 +1,169 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+"use strict";
+
+var PermissionsHelper = {
+  _permissonTypes: ["password", "geolocation", "popup", "indexedDB",
+                    "offline-app", "desktop-notification", "plugins", "native-intent"],
+  _permissionStrings: {
+    "password": {
+      label: "password.savePassword",
+      allowed: "password.save",
+      denied: "password.dontSave"
+    },
+    "geolocation": {
+      label: "geolocation.shareLocation",
+      allowed: "geolocation.allow",
+      denied: "geolocation.dontAllow"
+    },
+    "popup": {
+      label: "blockPopups.label",
+      allowed: "popup.show",
+      denied: "popup.dontShow"
+    },
+    "indexedDB": {
+      label: "offlineApps.storeOfflineData",
+      allowed: "offlineApps.allow",
+      denied: "offlineApps.dontAllow2"
+    },
+    "offline-app": {
+      label: "offlineApps.storeOfflineData",
+      allowed: "offlineApps.allow",
+      denied: "offlineApps.dontAllow2"
+    },
+    "desktop-notification": {
+      label: "desktopNotification.useNotifications",
+      allowed: "desktopNotification.allow",
+      denied: "desktopNotification.dontAllow"
+    },
+    "plugins": {
+      label: "clickToPlayPlugins.activatePlugins",
+      allowed: "clickToPlayPlugins.activate",
+      denied: "clickToPlayPlugins.dontActivate"
+    },
+    "native-intent": {
+      label: "helperapps.openWithList2",
+      allowed: "helperapps.always",
+      denied: "helperapps.never"
+    }
+  },
+
+  observe: function observe(aSubject, aTopic, aData) {
+    let uri = BrowserApp.selectedBrowser.currentURI;
+
+    switch (aTopic) {
+      case "Permissions:Get":
+        let permissions = [];
+        for (let i = 0; i < this._permissonTypes.length; i++) {
+          let type = this._permissonTypes[i];
+          let value = this.getPermission(uri, type);
+
+          // Only add the permission if it was set by the user
+          if (value == Services.perms.UNKNOWN_ACTION)
+            continue;
+
+          // Get the strings that correspond to the permission type
+          let typeStrings = this._permissionStrings[type];
+          let label = Strings.browser.GetStringFromName(typeStrings["label"]);
+
+          // Get the key to look up the appropriate string entity
+          let valueKey = value == Services.perms.ALLOW_ACTION ?
+                         "allowed" : "denied";
+          let valueString = Strings.browser.GetStringFromName(typeStrings[valueKey]);
+
+          permissions.push({
+            type: type,
+            setting: label,
+            value: valueString
+          });
+        }
+
+        // Keep track of permissions, so we know which ones to clear
+        this._currentPermissions = permissions;
+
+        let host;
+        try {
+          host = uri.host;
+        } catch(e) {
+          host = uri.spec;
+        }
+        sendMessageToJava({
+          type: "Permissions:Data",
+          host: host,
+          permissions: permissions
+        });
+        break;
+ 
+      case "Permissions:Clear":
+        // An array of the indices of the permissions we want to clear
+        let permissionsToClear = JSON.parse(aData);
+        let privacyContext = BrowserApp.selectedBrowser.docShell
+                               .QueryInterface(Ci.nsILoadContext);
+
+        for (let i = 0; i < permissionsToClear.length; i++) {
+          let indexToClear = permissionsToClear[i];
+          let permissionType = this._currentPermissions[indexToClear]["type"];
+          this.clearPermission(uri, permissionType, privacyContext);
+        }
+        break;
+    }
+  },
+
+  /**
+   * Gets the permission value stored for a specified permission type.
+   *
+   * @param aType
+   *        The permission type string stored in permission manager.
+   *        e.g. "geolocation", "indexedDB", "popup"
+   *
+   * @return A permission value defined in nsIPermissionManager.
+   */
+  getPermission: function getPermission(aURI, aType) {
+    // Password saving isn't a nsIPermissionManager permission type, so handle
+    // it seperately.
+    if (aType == "password") {
+      // By default, login saving is enabled, so if it is disabled, the
+      // user selected the never remember option
+      if (!Services.logins.getLoginSavingEnabled(aURI.prePath))
+        return Services.perms.DENY_ACTION;
+
+      // Check to see if the user ever actually saved a login
+      if (Services.logins.countLogins(aURI.prePath, "", ""))
+        return Services.perms.ALLOW_ACTION;
+
+      return Services.perms.UNKNOWN_ACTION;
+    }
+
+    // Geolocation consumers use testExactPermission
+    if (aType == "geolocation")
+      return Services.perms.testExactPermission(aURI, aType);
+
+    return Services.perms.testPermission(aURI, aType);
+  },
+
+  /**
+   * Clears a user-set permission value for the site given a permission type.
+   *
+   * @param aType
+   *        The permission type string stored in permission manager.
+   *        e.g. "geolocation", "indexedDB", "popup"
+   */
+  clearPermission: function clearPermission(aURI, aType, aContext) {
+    // Password saving isn't a nsIPermissionManager permission type, so handle
+    // it seperately.
+    if (aType == "password") {
+      // Get rid of exisiting stored logings
+      let logins = Services.logins.findLogins({}, aURI.prePath, "", "");
+      for (let i = 0; i < logins.length; i++) {
+        Services.logins.removeLogin(logins[i]);
+      }
+      // Re-set login saving to enabled
+      Services.logins.setLoginSavingEnabled(aURI.prePath, true);
+    } else {
+      Services.perms.remove(aURI.host, aType);
+      // Clear content prefs set in ContentPermissionPrompt.js
+      Services.contentPrefs.removePref(aURI, aType + ".request.remember", aContext);
+    }
+  }
+};
diff --git a/mobile/android/chrome/content/browser.js b/mobile/android/chrome/content/browser.js
index 00fa890fc576..d91cf2f550f5 100644
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -93,6 +93,8 @@ var LazyNotificationGetter = {
 #endif
   ["MemoryObserver", ["memory-pressure", "Memory:Dump"], "chrome://browser/content/MemoryObserver.js"],
   ["ConsoleAPI", ["console-api-log-event"], "chrome://browser/content/ConsoleAPI.js"],
+  ["FindHelper", ["FindInPage:Find", "FindInPage:Prev", "FindInPage:Next", "FindInPage:Closed", "Tab:Selected"], "chrome://browser/content/FindHelper.js"],
+  ["PermissionsHelper", ["Permissions:Get", "Permissions:Clear"], "chrome://browser/content/PermissionsHelper.js"],
 ].forEach(function (aScript) {
   let [name, notifications, script] = aScript;
   XPCOMUtils.defineLazyGetter(window, name, function() {
@@ -268,12 +270,10 @@ var BrowserApp = {
     NativeWindow.init();
     LightWeightThemeWebInstaller.init();
     Downloads.init();
-    FindHelper.init();
     FormAssistant.init();
     IndexedDB.init();
     XPInstallObserver.init();
     ClipboardHelper.init();
-    PermissionsHelper.init();
     CharacterEncoding.init();
     ActivityObserver.init();
     WebappsUI.init();
@@ -555,7 +555,6 @@ var BrowserApp = {
     NativeWindow.uninit();
     LightWeightThemeWebInstaller.uninit();
     FormAssistant.uninit();
-    FindHelper.uninit();
     IndexedDB.uninit();
     ViewportHandler.uninit();
     XPInstallObserver.uninit();
@@ -4445,101 +4444,6 @@ var ErrorPageEventHandler = {
   }
 };
 
-var FindHelper = {
-  _fastFind: null,
-  _targetTab: null,
-  _initialViewport: null,
-  _viewportChanged: false,
-
-  init: function() {
-    Services.obs.addObserver(this, "FindInPage:Find", false);
-    Services.obs.addObserver(this, "FindInPage:Prev", false);
-    Services.obs.addObserver(this, "FindInPage:Next", false);
-    Services.obs.addObserver(this, "FindInPage:Closed", false);
-    Services.obs.addObserver(this, "Tab:Selected", false);
-  },
-
-  uninit: function() {
-    Services.obs.removeObserver(this, "FindInPage:Find");
-    Services.obs.removeObserver(this, "FindInPage:Prev");
-    Services.obs.removeObserver(this, "FindInPage:Next");
-    Services.obs.removeObserver(this, "FindInPage:Closed");
-    Services.obs.removeObserver(this, "Tab:Selected");
-  },
-
-  observe: function(aMessage, aTopic, aData) {
-    switch(aTopic) {
-      case "FindInPage:Find":
-        this.doFind(aData);
-        break;
-
-      case "FindInPage:Prev":
-        this.findAgain(aData, true);
-        break;
-
-      case "FindInPage:Next":
-        this.findAgain(aData, false);
-        break;
-
-      case "Tab:Selected":
-      case "FindInPage:Closed":
-        this.findClosed();
-        break;
-    }
-  },
-
-  doFind: function(aSearchString) {
-    if (!this._fastFind) {
-      this._targetTab = BrowserApp.selectedTab;
-      this._fastFind = this._targetTab.browser.fastFind;
-      this._initialViewport = JSON.stringify(this._targetTab.getViewport());
-      this._viewportChanged = false;
-    }
-
-    let result = this._fastFind.find(aSearchString, false);
-    this.handleResult(result);
-  },
-
-  findAgain: function(aString, aFindBackwards) {
-    // This can happen if the user taps next/previous after re-opening the search bar
-    if (!this._fastFind) {
-      this.doFind(aString);
-      return;
-    }
-
-    let result = this._fastFind.findAgain(aFindBackwards, false);
-    this.handleResult(result);
-  },
-
-  findClosed: function() {
-    // If there's no find in progress, there's nothing to clean up
-    if (!this._fastFind)
-      return;
-
-    this._fastFind.collapseSelection();
-    this._fastFind = null;
-    this._targetTab = null;
-    this._initialViewport = null;
-    this._viewportChanged = false;
-  },
-
-  handleResult: function(aResult) {
-    if (aResult == Ci.nsITypeAheadFind.FIND_NOTFOUND) {
-      if (this._viewportChanged) {
-        if (this._targetTab != BrowserApp.selectedTab) {
-          // this should never happen
-          Cu.reportError("Warning: selected tab changed during find!");
-          // fall through and restore viewport on the initial tab anyway
-        }
-        this._targetTab.setViewport(JSON.parse(this._initialViewport));
-        this._targetTab.sendViewportUpdate();
-      }
-    } else {
-      this._viewportChanged = true;
-    }
-  }
-};
-
 var FormAssistant = {
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIFormSubmitObserver]),
 
@@ -5493,179 +5397,6 @@ var ClipboardHelper = {
   }
 };
 
-
-var PermissionsHelper = {
-
-  _permissonTypes: ["password", "geolocation", "popup", "indexedDB",
-                    "offline-app", "desktop-notification", "plugins", "native-intent"],
-  _permissionStrings: {
-    "password": {
-      label: "password.savePassword",
-      allowed: "password.save",
-      denied: "password.dontSave"
-    },
-    "geolocation": {
-      label: "geolocation.shareLocation",
-      allowed: "geolocation.allow",
-      denied: "geolocation.dontAllow"
-    },
-    "popup": {
-      label: "blockPopups.label",
-      allowed: "popup.show",
-      denied: "popup.dontShow"
-    },
-    "indexedDB": {
-      label: "offlineApps.storeOfflineData",
-      allowed: "offlineApps.allow",
-      denied: "offlineApps.dontAllow2"
-    },
-    "offline-app": {
-      label: "offlineApps.storeOfflineData",
-      allowed: "offlineApps.allow",
-      denied: "offlineApps.dontAllow2"
-    },
-    "desktop-notification": {
-      label: "desktopNotification.useNotifications",
-      allowed: "desktopNotification.allow",
-      denied: "desktopNotification.dontAllow"
-    },
-    "plugins": {
-      label: "clickToPlayPlugins.activatePlugins",
-      allowed: "clickToPlayPlugins.activate",
-      denied: "clickToPlayPlugins.dontActivate"
-    },
-    "native-intent": {
-      label: "helperapps.openWithList2",
-      allowed: "helperapps.always",
-      denied: "helperapps.never"
-    }
-  },
-
-  init: function init() {
-    Services.obs.addObserver(this, "Permissions:Get", false);
-    Services.obs.addObserver(this, "Permissions:Clear", false);
-  },
-
-  observe: function observe(aSubject, aTopic, aData) {
-    let uri = BrowserApp.selectedBrowser.currentURI;
-
-    switch (aTopic) {
-      case "Permissions:Get":
-        let permissions = [];
-        for (let i = 0; i < this._permissonTypes.length; i++) {
-          let type = this._permissonTypes[i];
-          let value = this.getPermission(uri, type);
-
-          // Only add the permission if it was set by the user
-          if (value == Services.perms.UNKNOWN_ACTION)
-            continue;
-
-          // Get the strings that correspond to the permission type
-          let typeStrings = this._permissionStrings[type];
-          let label = Strings.browser.GetStringFromName(typeStrings["label"]);
-
-          // Get the key to look up the appropriate string entity
-          let valueKey = value == Services.perms.ALLOW_ACTION ?
-                         "allowed" : "denied";
-          let valueString = Strings.browser.GetStringFromName(typeStrings[valueKey]);
-
-          permissions.push({
-            type: type,
-            setting: label,
-            value: valueString
-          });
-        }
-
-        // Keep track of permissions, so we know which ones to clear
-        this._currentPermissions = permissions;
-
-        let host;
-        try {
-          host = uri.host;
-        } catch(e) {
-          host = uri.spec;
-        }
-        sendMessageToJava({
-          type: "Permissions:Data",
-          host: host,
-          permissions: permissions
-        });
-        break;
- 
-      case "Permissions:Clear":
-        // An array of the indices of the permissions we want to clear
-        let permissionsToClear = JSON.parse(aData);
-        let privacyContext = BrowserApp.selectedBrowser.docShell
-                               .QueryInterface(Ci.nsILoadContext);
-
-        for (let i = 0; i < permissionsToClear.length; i++) {
-          let indexToClear = permissionsToClear[i];
-          let permissionType = this._currentPermissions[indexToClear]["type"];
-          this.clearPermission(uri, permissionType, privacyContext);
-        }
-        break;
-    }
-  },
-
-  /**
-   * Gets the permission value stored for a specified permission type.
-   *
-   * @param aType
-   *        The permission type string stored in permission manager.
-   *        e.g. "geolocation", "indexedDB", "popup"
-   *
-   * @return A permission value defined in nsIPermissionManager.
-   */
-  getPermission: function getPermission(aURI, aType) {
-    // Password saving isn't a nsIPermissionManager permission type, so handle
-    // it seperately.
-    if (aType == "password") {
-      // By default, login saving is enabled, so if it is disabled, the
-      // user selected the never remember option
-      if (!Services.logins.getLoginSavingEnabled(aURI.prePath))
-        return Services.perms.DENY_ACTION;
-
-      // Check to see if the user ever actually saved a login
-      if (Services.logins.countLogins(aURI.prePath, "", ""))
-        return Services.perms.ALLOW_ACTION;
-
-      return Services.perms.UNKNOWN_ACTION;
-    }
-
-    // Geolocation consumers use testExactPermission
-    if (aType == "geolocation")
-      return Services.perms.testExactPermission(aURI, aType);
-
-    return Services.perms.testPermission(aURI, aType);
-  },
-
-  /**
-   * Clears a user-set permission value for the site given a permission type.
-   *
-   * @param aType
-   *        The permission type string stored in permission manager.
-   *        e.g. "geolocation", "indexedDB", "popup"
-   */
-  clearPermission: function clearPermission(aURI, aType, aContext) {
-    // Password saving isn't a nsIPermissionManager permission type, so handle
-    // it seperately.
-    if (aType == "password") {
-      // Get rid of exisiting stored logings
-      let logins = Services.logins.findLogins({}, aURI.prePath, "", "");
-      for (let i = 0; i < logins.length; i++) {
-        Services.logins.removeLogin(logins[i]);
-      }
-      // Re-set login saving to enabled
-      Services.logins.setLoginSavingEnabled(aURI.prePath, true);
-    } else {
-      Services.perms.remove(aURI.host, aType);
-      // Clear content prefs set in ContentPermissionPrompt.js
-      Services.contentPrefs.removePref(aURI, aType + ".request.remember", aContext);
-    }
-  }
-};
-
-
 var CharacterEncoding = {
   _charsets: [],
 
diff --git a/mobile/android/chrome/jar.mn b/mobile/android/chrome/jar.mn
index 883f6b904797..055cbbbf3a8e 100644
--- a/mobile/android/chrome/jar.mn
+++ b/mobile/android/chrome/jar.mn
@@ -46,6 +46,8 @@ chrome.jar:
   content/PluginHelper.js              (content/PluginHelper.js)
   content/OfflineApps.js               (content/OfflineApps.js)
   content/MasterPassword.js            (content/MasterPassword.js)
+  content/FindHelper.js                (content/FindHelper.js)
+  content/PermissionsHelper.js         (content/PermissionsHelper.js)
 
 % content branding %content/branding/
 

From 9c783dca75344eb352b8b52266609b62ebaada8b Mon Sep 17 00:00:00 2001
From: Alexander Surkov 
Date: Wed, 27 Mar 2013 09:57:29 +0900
Subject: [PATCH 107/129] Bug 853361 - moving by words is inconsistent, r=roc

---
 .../tests/mochitest/text/test_multiline.html  | 24 ++++++-------------
 layout/generic/nsTextFrameThebes.cpp          |  3 ++-
 .../generic/test/test_movement_by_words.html  |  4 ----
 3 files changed, 9 insertions(+), 22 deletions(-)

diff --git a/accessible/tests/mochitest/text/test_multiline.html b/accessible/tests/mochitest/text/test_multiline.html
index b09a7f0f8235..4d8e826c7d28 100644
--- a/accessible/tests/mochitest/text/test_multiline.html
+++ b/accessible/tests/mochitest/text/test_multiline.html
@@ -66,9 +66,9 @@
                           "textarea", kTodo, kTodo, kTodo);
       testTextAfterOffset(8, BOUNDARY_WORD_START, "two ", 9, 13,
                           "div", kTodo, kTodo, kTodo,
-                          "divbr", kTodo, kTodo, kTodo,
+                          "divbr", kTodo, kTodo, kOk,
                           "editable", kTodo, kTodo, kTodo,
-                          "editablebr", kTodo, kTodo, kTodo,
+                          "editablebr", kTodo, kTodo, kOk,
                           "textarea", kTodo, kTodo, kTodo);
       testTextAfterOffset(9, BOUNDARY_WORD_START, "words\n", 13, 19,
                           "div", kTodo, kTodo, kTodo,
@@ -384,12 +384,7 @@
                        "textarea", kOk, kOk, kOk);
 
       // BOUNDARY_WORD_START
-      testTextAtOffset(0, BOUNDARY_WORD_START, "oneword\n\n", 0, 9,
-                       "div", kTodo, kOk, kTodo,
-                       "divbr", kOk, kOk, kOk,
-                       "editable", kTodo, kOk, kTodo,
-                       "editablebr", kOk, kOk, kOk,
-                       "textarea", kTodo, kOk, kTodo);
+      testTextAtOffset(0, BOUNDARY_WORD_START, "oneword\n\n", 0, 9, IDs);
       testTextAtOffset(8, BOUNDARY_WORD_START, "oneword\n\n", 0, 9,
                        "div", kOk, kOk, kOk,
                        "divbr", kTodo, kTodo, kTodo,
@@ -413,17 +408,12 @@
                        "editablebr", kTodo, kTodo, kTodo,
                        "textarea", kOk, kOk, kOk);
       testTextAtOffset(9, BOUNDARY_WORD_END, "\n\ntwo", 7, 12,
-                       "div", kTodo, kTodo, kOk,
+                       "div", kOk, kOk, kOk,
                        "divbr", kTodo, kTodo, kTodo,
-                       "editable", kTodo, kTodo, kOk,
+                       "editable", kOk, kOk, kOk,
                        "editablebr", kTodo, kTodo, kTodo,
-                       "textarea", kTodo, kTodo, kOk);
-      testTextAtOffset(12, BOUNDARY_WORD_END, "\n\ntwo", 7, 12,
-                       "div", kTodo, kTodo, kOk,
-                       "divbr", kOk, kOk, kOk,
-                       "editable", kTodo, kTodo, kOk,
-                       "editablebr", kOk, kOk, kOk,
-                       "textarea", kTodo, kTodo, kOk);
+                       "textarea", kOk, kOk, kOk);
+      testTextAtOffset(12, BOUNDARY_WORD_END, "\n\ntwo", 7, 12, IDs);
       testTextAtOffset(13, BOUNDARY_WORD_END, " words", 12, 18,
                        "div", kOk, kOk, kOk,
                        "divbr", kOk, kOk, kOk,
diff --git a/layout/generic/nsTextFrameThebes.cpp b/layout/generic/nsTextFrameThebes.cpp
index 218a4b38e127..1a0b1747d25c 100644
--- a/layout/generic/nsTextFrameThebes.cpp
+++ b/layout/generic/nsTextFrameThebes.cpp
@@ -6827,7 +6827,8 @@ nsTextFrame::PeekOffsetWord(bool aForward, bool aWordSelectEatSpace, bool aIsKey
         // Japanese and Chinese.
         canBreak = true;
       } else {
-        canBreak = isWordBreakBefore && aState->mSawBeforeType;
+        canBreak = isWordBreakBefore && aState->mSawBeforeType &&
+          (aWordSelectEatSpace != isWhitespace);
       }
       if (canBreak) {
         *aOffset = cIter.GetBeforeOffset() - mContentOffset;
diff --git a/layout/generic/test/test_movement_by_words.html b/layout/generic/test/test_movement_by_words.html
index 8bb34de56e40..dbbb154de1ad 100644
--- a/layout/generic/test/test_movement_by_words.html
+++ b/layout/generic/test/test_movement_by_words.html
@@ -123,10 +123,8 @@ function test() {
   testRight(editor.firstChild, 10);
   testRight(editor.firstChild.nextSibling.nextSibling, 5);
   testLeft(editor.firstChild.nextSibling.firstChild, 1);
-  testLeft(editor.firstChild, 10);
   testLeft(editor.firstChild, 8);
   testLeft(editor.firstChild, 5);
-  testLeft(editor.firstChild, 3);
   testLeft(editor.firstChild, 0);
 
   var ChineseChars = "漢字";
@@ -239,10 +237,8 @@ function test() {
   testRight(editor.firstChild.nextSibling.firstChild, 0);
   testRight(editor.firstChild.nextSibling.nextSibling, 5);
   testLeft(editor.firstChild.nextSibling.firstChild, 1);
-  testLeft(editor.firstChild, 10);
   testLeft(editor.firstChild, 8);
   testLeft(editor.firstChild, 5);
-  testLeft(editor.firstChild, 3);
   testLeft(editor.firstChild, 0);
 
   editor.innerHTML = ChineseChars + HiraganaChars + ChineseChars;

From 53b9848aa465b6b3bef169ff259f8452734526a3 Mon Sep 17 00:00:00 2001
From: Bobby Holley 
Date: Tue, 26 Mar 2013 22:08:10 -0700
Subject: [PATCH 108/129] Bug 854604 - Null-check funobj. r=mrbkap

I've audited all the places where we instantiate an XPCCallContext with more
than just (cx, {NATIVE,JS}_CALLER), and the toString hook is the only place
where we don't check IsValid() or something that depends on it.
---
 js/xpconnect/crashtests/854604.html        | 10 ++++++++++
 js/xpconnect/crashtests/crashtests.list    |  1 +
 js/xpconnect/src/XPCCallContext.cpp        |  4 ++++
 js/xpconnect/src/XPCWrappedNativeJSOps.cpp |  2 ++
 4 files changed, 17 insertions(+)
 create mode 100644 js/xpconnect/crashtests/854604.html

diff --git a/js/xpconnect/crashtests/854604.html b/js/xpconnect/crashtests/854604.html
new file mode 100644
index 000000000000..41c028bc2d5f
--- /dev/null
+++ b/js/xpconnect/crashtests/854604.html
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
diff --git a/js/xpconnect/crashtests/crashtests.list b/js/xpconnect/crashtests/crashtests.list
index 96ded50251cc..ecc817ef1783 100644
--- a/js/xpconnect/crashtests/crashtests.list
+++ b/js/xpconnect/crashtests/crashtests.list
@@ -50,3 +50,4 @@ load 791845.html
 load 797583.html
 load 806751.html
 load 833856.html
+load 854604.html
diff --git a/js/xpconnect/src/XPCCallContext.cpp b/js/xpconnect/src/XPCCallContext.cpp
index 7e1be739eb9d..619bf601027a 100644
--- a/js/xpconnect/src/XPCCallContext.cpp
+++ b/js/xpconnect/src/XPCCallContext.cpp
@@ -462,6 +462,10 @@ XPCCallContext::UnwrapThisIfAllowed(JSObject *object, JSObject *fun, unsigned ar
     MOZ_ASSERT(!js::UnwrapObjectChecked(obj));
     MOZ_ASSERT(js::IsObjectInContextCompartment(obj, mJSContext));
 
+    // We can't do anything here without a function.
+    if (!fun)
+        return nullptr;
+
     // Determine if we're allowed to unwrap the security wrapper to invoke the
     // method.
     //
diff --git a/js/xpconnect/src/XPCWrappedNativeJSOps.cpp b/js/xpconnect/src/XPCWrappedNativeJSOps.cpp
index 8f77a4b836fb..f2acb306086e 100644
--- a/js/xpconnect/src/XPCWrappedNativeJSOps.cpp
+++ b/js/xpconnect/src/XPCWrappedNativeJSOps.cpp
@@ -106,6 +106,8 @@ XPC_WN_Shared_ToString(JSContext *cx, unsigned argc, jsval *vp)
     }
 
     XPCCallContext ccx(JS_CALLER, cx, obj);
+    if (!ccx.IsValid())
+        return Throw(NS_ERROR_XPC_BAD_OP_ON_WN_PROTO, cx);
     ccx.SetName(ccx.GetRuntime()->GetStringID(XPCJSRuntime::IDX_TO_STRING));
     ccx.SetArgsAndResultPtr(argc, JS_ARGV(cx, vp), vp);
     return ToStringGuts(ccx);

From ca50f252f0dfac56fd02dad32b582d5bc6e12d20 Mon Sep 17 00:00:00 2001
From: Bobby Holley 
Date: Tue, 26 Mar 2013 22:18:54 -0700
Subject: [PATCH 109/129] Bug 790732 - Fix two more toolkit tests. r=me

Not sure why these didn't appear on earlier try runs, but they're trivial.
---
 toolkit/components/passwordmgr/test/test_prompt.html | 12 +++++-------
 .../satchel/test/test_form_autocomplete.html         |  2 +-
 2 files changed, 6 insertions(+), 8 deletions(-)

diff --git a/toolkit/components/passwordmgr/test/test_prompt.html b/toolkit/components/passwordmgr/test/test_prompt.html
index bc1f8424987b..31f85d153b8b 100644
--- a/toolkit/components/passwordmgr/test/test_prompt.html
+++ b/toolkit/components/passwordmgr/test/test_prompt.html
@@ -138,7 +138,7 @@ var resolveCallback = {
     const interfaces = [Ci.nsIProtocolProxyCallback, Ci.nsISupports];
 
     if (!interfaces.some( function(v) { return iid.equals(v) } ))
-      throw Components.results.NS_ERROR_NO_INTERFACE;
+      throw SpecialPowers.Cr.NS_ERROR_NO_INTERFACE;
     return this;
   },
 
@@ -160,12 +160,10 @@ var resolveCallback = {
 
 function startup() {
   //need to allow for arbitrary network servers defined in PAC instead of a hardcoded moz-proxy.
-  var ios = SpecialPowers.wrap(Components).
-    classes["@mozilla.org/network/io-service;1"].
-    getService(Components.interfaces.nsIIOService);
+  var ios = SpecialPowers.Cc["@mozilla.org/network/io-service;1"].
+    getService(SpecialPowers.Ci.nsIIOService);
 
-  var pps = SpecialPowers.wrap(Components).
-    classes["@mozilla.org/network/protocol-proxy-service;1"].getService();
+  var pps = SpecialPowers.Cc["@mozilla.org/network/protocol-proxy-service;1"].getService();
 
   var uri = ios.newURI("http://example.com", null, null);
   pps.asyncResolve(uri, 0, resolveCallback);
@@ -183,7 +181,7 @@ var storageObserver = {
                         Ci.nsISupports, Ci.nsISupportsWeakReference];
 
     if (!interfaces.some( function(v) { return iid.equals(v) } ))
-      throw SpecialPowers.Components.results.NS_ERROR_NO_INTERFACE;
+      throw SpecialPowers.Cr.NS_ERROR_NO_INTERFACE;
     return this;
   },
 
diff --git a/toolkit/components/satchel/test/test_form_autocomplete.html b/toolkit/components/satchel/test/test_form_autocomplete.html
index e18b860cf0a1..03142d3529c7 100644
--- a/toolkit/components/satchel/test/test_form_autocomplete.html
+++ b/toolkit/components/satchel/test/test_form_autocomplete.html
@@ -122,7 +122,7 @@ const shiftModifier = Event.SHIFT_MASK;
 
 // Get the form history service
 var fh = SpecialPowers.Cc["@mozilla.org/satchel/form-history;1"].
-         getService(Components.interfaces.nsIFormHistory2);
+         getService(SpecialPowers.Ci.nsIFormHistory2);
 ok(fh != null, "got form history service");
 
 fh.removeAllEntries();

From c980e62926d7433f13c3af06cbcffae8e104f7c8 Mon Sep 17 00:00:00 2001
From: Bobby Holley 
Date: Tue, 26 Mar 2013 22:18:55 -0700
Subject: [PATCH 110/129] Bug 790732 - Remove the aTarget parameter from
 AttachComponentsObject. r=mrbkap

I added this when I thought we'd be defining Components on an object on the XBL
scope chain. At this point, it's not necessary anymore.
---
 js/xpconnect/src/XPCComponents.cpp | 7 ++-----
 js/xpconnect/src/xpcprivate.h      | 6 +-----
 2 files changed, 3 insertions(+), 10 deletions(-)

diff --git a/js/xpconnect/src/XPCComponents.cpp b/js/xpconnect/src/XPCComponents.cpp
index 6153f8ab579d..bf1c0d110f5a 100644
--- a/js/xpconnect/src/XPCComponents.cpp
+++ b/js/xpconnect/src/XPCComponents.cpp
@@ -4880,8 +4880,7 @@ ContentComponentsGetterOp(JSContext *cx, JSHandleObject obj, JSHandleId id,
 // static
 JSBool
 nsXPCComponents::AttachComponentsObject(XPCCallContext& ccx,
-                                        XPCWrappedNativeScope* aScope,
-                                        JSObject* aTarget)
+                                        XPCWrappedNativeScope* aScope)
 {
     JSObject *components = aScope->GetComponentsJSObject(ccx);
     if (!components)
@@ -4889,13 +4888,11 @@ nsXPCComponents::AttachComponentsObject(XPCCallContext& ccx,
 
     JSObject *global = aScope->GetGlobalJSObject();
     MOZ_ASSERT(js::IsObjectInContextCompartment(global, ccx));
-    if (!aTarget)
-        aTarget = global;
 
     jsid id = ccx.GetRuntime()->GetStringID(XPCJSRuntime::IDX_COMPONENTS);
     JSPropertyOp getter = AccessCheck::isChrome(global) ? nullptr
                                                         : &ContentComponentsGetterOp;
-    return JS_DefinePropertyById(ccx, aTarget, id, js::ObjectValue(*components),
+    return JS_DefinePropertyById(ccx, global, id, js::ObjectValue(*components),
                                  getter, nullptr, JSPROP_PERMANENT | JSPROP_READONLY);
 }
 
diff --git a/js/xpconnect/src/xpcprivate.h b/js/xpconnect/src/xpcprivate.h
index 7f9752fb08e1..80f6916c1dce 100644
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -3722,13 +3722,9 @@ public:
     NS_DECL_NSISECURITYCHECKEDCOMPONENT
 
 public:
-    // The target is the object upon which |Components| will be defined. If
-    // aTarget is left null, a default object will be computed. This is usually
-    // the right thing to do.
     static JSBool
     AttachComponentsObject(XPCCallContext& ccx,
-                           XPCWrappedNativeScope* aScope,
-                           JSObject* aTarget = NULL);
+                           XPCWrappedNativeScope* aScope);
 
     void SystemIsBeingShutDown() {ClearMembers();}
 

From 77fb834b208fc684118e803d52f193139594d4cb Mon Sep 17 00:00:00 2001
From: Bobby Holley 
Date: Tue, 26 Mar 2013 22:18:55 -0700
Subject: [PATCH 111/129] Bug 790732 - Stop attaching Components in
 InitClasses. r=mrbkap

This method is larely deprecated. The only two consumers are JSD and the setup
for the safe JSContext, neither of which use system principal and thus neither
of which should have |Components|.
---
 js/xpconnect/src/nsXPConnect.cpp | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/js/xpconnect/src/nsXPConnect.cpp b/js/xpconnect/src/nsXPConnect.cpp
index f667c7cf260e..2e8e89876c09 100644
--- a/js/xpconnect/src/nsXPConnect.cpp
+++ b/js/xpconnect/src/nsXPConnect.cpp
@@ -946,9 +946,6 @@ nsXPConnect::InitClasses(JSContext * aJSContext, JSObject * aGlobalJSObj)
 
     scope->RemoveWrappedNativeProtos();
 
-    if (!nsXPCComponents::AttachComponentsObject(ccx, scope))
-        return UnexpectedFailure(NS_ERROR_FAILURE);
-
     if (!XPCNativeWrapper::AttachNewConstructorObject(ccx, aGlobalJSObj))
         return UnexpectedFailure(NS_ERROR_FAILURE);
 

From 89264d7aee7febfc443396525086d6a75c18fb21 Mon Sep 17 00:00:00 2001
From: Bobby Holley 
Date: Tue, 26 Mar 2013 22:18:55 -0700
Subject: [PATCH 112/129] Bug 790732 - Make Components console warning test
 pref-aware. r=mrbkap

---
 js/xpconnect/tests/chrome/test_bug795275.xul | 18 +++++++++++++-----
 1 file changed, 13 insertions(+), 5 deletions(-)

diff --git a/js/xpconnect/tests/chrome/test_bug795275.xul b/js/xpconnect/tests/chrome/test_bug795275.xul
index e752b4ed07f3..816013f491a0 100644
--- a/js/xpconnect/tests/chrome/test_bug795275.xul
+++ b/js/xpconnect/tests/chrome/test_bug795275.xul
@@ -20,6 +20,14 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=795275
   /** Test for Warning in content scopes about Components. **/
 
   SimpleTest.waitForExplicitFinish();
+  SpecialPowers.pushPrefEnv({set: [['dom.omit_components_in_content', false]]}, startLoad);
+  function startLoad() {
+    for (var i = 1; i <= document.getElementsByTagName('iframe').length; ++i) {
+      var frame = document.getElementById('frame' + i);
+      frame.contentWindow.location = 'http://mochi.test:8888/tests/js/xpconnect/tests/mochitest/file_bug795275.html';
+      frame.onload = frameLoaded;
+    }
+  }
 
   // Set up our console listener.
   var gWarnings = 0;
@@ -73,10 +81,10 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=795275
   ]]>
 
   
-  
+
+

From 3961c780967b83dc0d45abe16109b5287216568d Mon Sep 17 00:00:00 2001
From: Nicholas Nethercote 
Date: Tue, 26 Mar 2013 15:07:33 -0700
Subject: [PATCH 117/129] Bug 831588 - Don't measure decommitted GC arenas in
 the "explicit" tree.  r=terrence,jlebar.

--HG--
extra : rebase_source : a35d978b8884e25169cca8ffc93f96e532e82320
---
 js/src/ds/BitArray.h                          | 17 ++++++---
 js/src/jsmemorymetrics.cpp                    | 36 ++++++++++++-------
 js/xpconnect/src/XPCJSRuntime.cpp             | 29 ++++++++-------
 .../aboutmemory/content/aboutMemory.js        |  3 +-
 4 files changed, 52 insertions(+), 33 deletions(-)

diff --git a/js/src/ds/BitArray.h b/js/src/ds/BitArray.h
index 1be12fc88127..4d0d0e64bb63 100644
--- a/js/src/ds/BitArray.h
+++ b/js/src/ds/BitArray.h
@@ -17,14 +17,13 @@ namespace js {
 template 
 class BitArray {
   private:
-    uintptr_t map[nbits / JS_BITS_PER_WORD + (nbits % JS_BITS_PER_WORD == 0 ? 0 : 1)];
+    static const size_t numSlots =
+        nbits / JS_BITS_PER_WORD + (nbits % JS_BITS_PER_WORD == 0 ? 0 : 1);
+    uintptr_t map[numSlots];
 
   public:
     void clear(bool value) {
-        if (value)
-            memset(map, 0xFF, sizeof(map));
-        else
-            memset(map, 0, sizeof(map));
+        memset(map, value ? 0xFF : 0, sizeof(map));
     }
 
     inline bool get(size_t offset) const {
@@ -45,6 +44,14 @@ class BitArray {
         map[index] &= ~mask;
     }
 
+    bool isAllClear() const {
+        for (size_t i = 0; i < numSlots; i++) {
+            if (map[i])
+                return false;
+        }
+        return true;
+    }
+
   private:
     inline void getMarkWordAndMask(size_t offset,
                                    uintptr_t *indexp, uintptr_t *maskp) const {
diff --git a/js/src/jsmemorymetrics.cpp b/js/src/jsmemorymetrics.cpp
index 1ab7b5ae36ed..f8b52f435511 100644
--- a/js/src/jsmemorymetrics.cpp
+++ b/js/src/jsmemorymetrics.cpp
@@ -83,6 +83,22 @@ CompartmentStats::GCHeapThingsSize()
     return n;
 }
 
+static void
+DecommittedArenasChunkCallback(JSRuntime *rt, void *data, gc::Chunk *chunk)
+{
+    // This case is common and fast to check.  Do it first.
+    if (chunk->decommittedArenas.isAllClear())
+        return;
+
+    size_t n = 0;
+    for (size_t i = 0; i < gc::ArenasPerChunk; i++) {
+        if (chunk->decommittedArenas.get(i))
+            n += gc::ArenaSize;
+    }
+    JS_ASSERT(n > 0);
+    *static_cast(data) += n;
+}
+
 static void
 StatsCompartmentCallback(JSRuntime *rt, void *data, JSCompartment *compartment)
 {
@@ -122,15 +138,6 @@ StatsZoneCallback(JSRuntime *rt, void *data, Zone *zone)
                               &zStats.typePool);
 }
 
-static void
-StatsChunkCallback(JSRuntime *rt, void *data, gc::Chunk *chunk)
-{
-    RuntimeStats *rtStats = static_cast(data);
-    for (size_t i = 0; i < gc::ArenasPerChunk; i++)
-        if (chunk->decommittedArenas.get(i))
-            rtStats->gcHeapDecommittedArenas += gc::ArenaSize;
-}
-
 static void
 StatsArenaCallback(JSRuntime *rt, void *data, gc::Arena *arena,
                    JSGCTraceKind traceKind, size_t thingSize)
@@ -300,8 +307,8 @@ JS::CollectRuntimeStats(JSRuntime *rt, RuntimeStats *rtStats, ObjectPrivateVisit
     rtStats->gcHeapUnusedChunks =
         size_t(JS_GetGCParameter(rt, JSGC_UNUSED_CHUNKS)) * gc::ChunkSize;
 
-    // This just computes rtStats->gcHeapDecommittedArenas.
-    IterateChunks(rt, rtStats, StatsChunkCallback);
+    IterateChunks(rt, &rtStats->gcHeapDecommittedArenas,
+                  DecommittedArenasChunkCallback);
 
     // Take the per-compartment measurements.
     IteratorClosure closure(rtStats, opv);
@@ -364,9 +371,14 @@ JS::CollectRuntimeStats(JSRuntime *rt, RuntimeStats *rtStats, ObjectPrivateVisit
 JS_PUBLIC_API(int64_t)
 JS::GetExplicitNonHeapForRuntime(JSRuntime *rt, JSMallocSizeOfFun mallocSizeOf)
 {
-    // explicit//gc-heap/*
+    // explicit/*/gc-heap/*
     size_t n = size_t(JS_GetGCParameter(rt, JSGC_TOTAL_CHUNKS)) * gc::ChunkSize;
 
+    // Subtract decommitted arenas, which aren't included in "explicit".
+    size_t decommittedArenas = 0;
+    IterateChunks(rt, &decommittedArenas, DecommittedArenasChunkCallback);
+    n -= decommittedArenas;
+
     // explicit/runtime/mjit-code
     // explicit/runtime/regexp-code
     // explicit/runtime/stack-committed
diff --git a/js/xpconnect/src/XPCJSRuntime.cpp b/js/xpconnect/src/XPCJSRuntime.cpp
index d84f89e5a821..535a55de9ece 100644
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -2045,10 +2045,16 @@ ReportJSRuntimeExplicitTreeStats(const JS::RuntimeStats &rtStats,
 
     // Report GC numbers that don't belong to a compartment.
 
-    REPORT_GC_BYTES(rtPath + NS_LITERAL_CSTRING("gc-heap/unused-arenas"),
-                    rtStats.gcHeapUnusedArenas,
-                    "Memory on the garbage-collected JavaScript heap taken by "
-                    "empty arenas within non-empty chunks.");
+    // We don't want to report decommitted memory in "explicit", so we just
+    // change the leading "explicit/" to "decommitted/".
+    nsCString rtPath2(rtPath);
+    rtPath2.Replace(0, strlen("explicit"), NS_LITERAL_CSTRING("decommitted"));
+    REPORT_GC_BYTES(rtPath2 + NS_LITERAL_CSTRING("gc-heap/decommitted-arenas"),
+                    rtStats.gcHeapDecommittedArenas,
+                    "Memory on the garbage-collected JavaScript heap, in "
+                    "arenas in non-empty chunks, that is returned to the OS. "
+                    "This means it takes up address space but no physical "
+                    "memory or swap space.");
 
     REPORT_GC_BYTES(rtPath + NS_LITERAL_CSTRING("gc-heap/unused-chunks"),
                     rtStats.gcHeapUnusedChunks,
@@ -2056,12 +2062,10 @@ ReportJSRuntimeExplicitTreeStats(const JS::RuntimeStats &rtStats,
                     "empty chunks, which will soon be released unless claimed "
                     "for new allocations.");
 
-    REPORT_GC_BYTES(rtPath + NS_LITERAL_CSTRING("gc-heap/decommitted-arenas"),
-                    rtStats.gcHeapDecommittedArenas,
-                    "Memory on the garbage-collected JavaScript heap, "
-                    "in arenas in non-empty chunks, that is returned to the OS. "
-                    "This means it takes up address space but no physical "
-                    "memory or swap space.");
+    REPORT_GC_BYTES(rtPath + NS_LITERAL_CSTRING("gc-heap/unused-arenas"),
+                    rtStats.gcHeapUnusedArenas,
+                    "Memory on the garbage-collected JavaScript heap taken by "
+                    "empty arenas within non-empty chunks.");
 
     REPORT_GC_BYTES(rtPath + NS_LITERAL_CSTRING("gc-heap/chunk-admin"),
                     rtStats.gcHeapChunkAdmin,
@@ -2339,11 +2343,6 @@ JSMemoryMultiReporter::CollectReports(WindowPaths *windowPaths,
 
     // Report the numbers for memory outside of compartments.
 
-    REPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime/gc-heap/decommitted-arenas"),
-                 nsIMemoryReporter::KIND_OTHER,
-                 rtStats.gcHeapDecommittedArenas,
-                 "The same as 'explicit/js-non-window/gc-heap/decommitted-arenas'.");
-
     REPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime/gc-heap/unused-chunks"),
                  nsIMemoryReporter::KIND_OTHER,
                  rtStats.gcHeapUnusedChunks,
diff --git a/toolkit/components/aboutmemory/content/aboutMemory.js b/toolkit/components/aboutmemory/content/aboutMemory.js
index 96840c6f9dcb..97e982c39a70 100644
--- a/toolkit/components/aboutmemory/content/aboutMemory.js
+++ b/toolkit/components/aboutmemory/content/aboutMemory.js
@@ -289,7 +289,8 @@ const kTreeDescriptions = {
 "This tree covers explicit memory allocations by the application, both at the \
 operating system level (via calls to functions such as VirtualAlloc, \
 vm_allocate, and mmap), and at the heap allocation level (via functions such \
-as malloc, calloc, realloc, memalign, operator new, and operator new[]).\
+as malloc, calloc, realloc, memalign, operator new, and operator new[]) that \
+have not been explicitly decommitted (i.e. evicted from memory and swap). \
 \n\n\
 It excludes memory that is mapped implicitly such as code and data segments, \
 and thread stacks.  It also excludes heap memory that has been freed by the \

From acb75a7a40fa440a4e6ff2ceacf812b339801a3c Mon Sep 17 00:00:00 2001
From: Jeff Muizelaar 
Date: Tue, 26 Mar 2013 22:29:07 -0700
Subject: [PATCH 118/129] Bug 855178. Use WaitSync instead of ClientWaitSync in
 SharedSurfaceGL. r=jgilbert

This is better than waiting/spinning. WaitSync will make the GPU do the
waiting for us and we can continue on.
---
 gfx/gl/SharedSurfaceGL.cpp | 19 +++++--------------
 1 file changed, 5 insertions(+), 14 deletions(-)

diff --git a/gfx/gl/SharedSurfaceGL.cpp b/gfx/gl/SharedSurfaceGL.cpp
index 7a96ef14cfc2..51a79c71fd51 100644
--- a/gfx/gl/SharedSurfaceGL.cpp
+++ b/gfx/gl/SharedSurfaceGL.cpp
@@ -365,22 +365,13 @@ SharedSurface_GLTexture::WaitSync()
         // We must have used glFinish instead of glFenceSync.
         return true;
     }
-    MOZ_ASSERT(mGL->IsExtensionSupported(GLContext::ARB_sync));
+    MOZ_ASSERT(mConsGL->IsExtensionSupported(GLContext::ARB_sync));
 
-    GLuint64 waitMS = 500;
-    const GLuint64 nsPerMS = 1000 * 1000;
-    GLuint64 waitNS = waitMS * nsPerMS;
-    GLenum status = mGL->fClientWaitSync(mSync,
-                                         0,
-                                         waitNS);
+    mConsGL->fWaitSync(mSync,
+                       0,
+                       LOCAL_GL_TIMEOUT_IGNORED);
 
-    if (status != LOCAL_GL_CONDITION_SATISFIED &&
-        status != LOCAL_GL_ALREADY_SIGNALED)
-    {
-        return false;
-    }
-
-    mGL->fDeleteSync(mSync);
+    mConsGL->fDeleteSync(mSync);
     mSync = 0;
 
     return true;

From 0ecf218a040ec9038b627d62cc2ef7a9428235f8 Mon Sep 17 00:00:00 2001
From: Phil Ringnalda 
Date: Tue, 26 Mar 2013 23:31:57 -0700
Subject: [PATCH 119/129] Back out c04824522d46 (bug 848973) for (at least)
 10.8 and Android reftest failures CLOSED TREE

---
 layout/base/nsCSSFrameConstructor.cpp | 19 ++++---
 layout/generic/nsFrame.cpp            |  2 +-
 layout/style/nsStyleStruct.h          | 43 +++++---------
 layout/style/nsStyleStructInlines.h   | 82 +++++++++++----------------
 4 files changed, 60 insertions(+), 86 deletions(-)

diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp
index 54f8ab37ad1e..ca48f22e5cd6 100644
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -1956,7 +1956,7 @@ nsCSSFrameConstructor::ConstructTable(nsFrameConstructorState& aState,
 
   // Mark the table frame as an absolute container if needed
   newFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
-  if (display->IsPositionedStyle() && !aParentFrame->IsSVGText()) {
+  if (display->IsPositioned(aParentFrame)) {
     aState.PushAbsoluteContainingBlock(newFrame, absoluteSaveState);
   }
   if (aItem.mFCData->mBits & FCDATA_USE_CHILD_ITEMS) {
@@ -3623,8 +3623,7 @@ nsCSSFrameConstructor::ConstructFrameFromItemInternal(FrameConstructionItem& aIt
     } else if (!(bits & FCDATA_SKIP_ABSPOS_PUSH)) {
       nsIFrame* cb = maybeAbsoluteContainingBlock;
       cb->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
-      if (maybeAbsoluteContainingBlockDisplay->IsPositionedStyle()) {
-        NS_ASSERTION(!cb->IsSVGText(), "SVG text cannot have abspos children");
+      if (maybeAbsoluteContainingBlockDisplay->IsPositioned(cb)) {
         aState.PushAbsoluteContainingBlock(cb, absoluteSaveState);
       }
     }
@@ -4242,7 +4241,8 @@ nsCSSFrameConstructor::FindDisplayData(const nsStyleDisplay* aDisplay,
   // XXX Ignore tables for the time being
   // XXXbz it would be nice to combine this with the other block
   // case... Think about how do do this?
-  if (aDisplay->IsBlockInsideStyle() &&
+  if ((aParentFrame ? aDisplay->IsBlockInside(aParentFrame) :
+                      aDisplay->IsBlockInsideStyle()) &&
       aDisplay->IsScrollableOverflow() &&
       !propagatedScrollToViewport) {
     // Except we don't want to do that for paginated contexts for
@@ -4263,7 +4263,8 @@ nsCSSFrameConstructor::FindDisplayData(const nsStyleDisplay* aDisplay,
   }
 
   // Handle various non-scrollable blocks
-  if (aDisplay->IsBlockInsideStyle()) {
+  if ((aParentFrame ? aDisplay->IsBlockInside(aParentFrame) :
+                      aDisplay->IsBlockInsideStyle())) {
     static const FrameConstructionData sNonScrollableBlockData =
       FULL_CTOR_FCDATA(0, &nsCSSFrameConstructor::ConstructNonScrollableBlock);
     return &sNonScrollableBlockData;
@@ -4329,7 +4330,8 @@ nsCSSFrameConstructor::FindDisplayData(const nsStyleDisplay* aDisplay,
                        &nsCSSFrameConstructor::ConstructTableCell) }
   };
 
-  return FindDataByInt(aDisplay->mDisplay,
+  return FindDataByInt((aParentFrame ? aDisplay->GetDisplay(aParentFrame) :
+                                       aDisplay->mDisplay),
                        aElement, aStyleContext, sDisplayData,
                        ArrayLength(sDisplayData));
 }
@@ -5291,7 +5293,8 @@ nsCSSFrameConstructor::AddFrameConstructionItemsInternal(nsFrameConstructorState
        (!aParentFrame || // No aParentFrame means inline
         aParentFrame->StyleDisplay()->mDisplay == NS_STYLE_DISPLAY_INLINE)) ||
       // Things that are inline-outside but aren't inline frames are inline
-      display->IsInlineOutsideStyle() ||
+      (aParentFrame ? display->IsInlineOutside(aParentFrame) :
+                      display->IsInlineOutsideStyle()) ||
       // Popups that are certainly out of flow.
       isPopup;
 
@@ -10451,7 +10454,7 @@ nsCSSFrameConstructor::CreateLetterFrame(nsIFrame* aBlockFrame,
 
     // Create the right type of first-letter frame
     const nsStyleDisplay* display = sc->StyleDisplay();
-    if (display->IsFloatingStyle() && !aParentFrame->IsSVGText()) {
+    if (display->IsFloating(aParentFrame)) {
       // Make a floating first-letter frame
       CreateFloatingLetterFrame(state, aBlockFrame, aTextContent, textFrame,
                                 blockContent, aParentFrame, sc, aResult);
diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp
index 391280763168..f3aac706f4f1 100644
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -2187,7 +2187,7 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder*   aBuilder,
     || child->IsTransformed()
     || nsSVGIntegrationUtils::UsingEffectsForFrame(child);
 
-  bool isPositioned = !isSVG && disp->IsPositionedStyle();
+  bool isPositioned = !isSVG && disp->IsPositioned(child);
   if (isVisuallyAtomic || isPositioned || (!isSVG && disp->IsFloating(child)) ||
       ((disp->mClipFlags & NS_STYLE_CLIP_RECT) &&
        IsSVGContentWithCSSClip(child)) ||
diff --git a/layout/style/nsStyleStruct.h b/layout/style/nsStyleStruct.h
index ed7c87d6cc14..c6380a53f6a2 100644
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -1348,15 +1348,10 @@ struct nsStyleText {
   }
 
   // These are defined in nsStyleStructInlines.h.
-
-  // The aContextFrame argument on each of these is the frame this
-  // style struct is for.  If the frame is for SVG text, the return
-  // value will be massaged to be something that makes sense for
-  // SVG text.
-  inline bool HasTextShadow(const nsIFrame* aContextFrame) const;
-  inline nsCSSShadowArray* GetTextShadow(const nsIFrame* aContextFrame) const;
-  inline bool WhiteSpaceCanWrap(const nsIFrame* aContextFrame) const;
-  inline bool WordCanWrap(const nsIFrame* aContextFrame) const;
+  inline bool HasTextShadow(const nsIFrame* aFrame) const;
+  inline nsCSSShadowArray* GetTextShadow(const nsIFrame* aFrame) const;
+  inline bool WhiteSpaceCanWrap(const nsIFrame* aFrame) const;
+  inline bool WordCanWrap(const nsIFrame* aFrame) const;
 };
 
 struct nsStyleVisibility {
@@ -1690,10 +1685,6 @@ struct nsStyleDisplay {
     return mPosition == NS_STYLE_POSITION_RELATIVE;
   }
 
-  bool IsPositionedStyle() const {
-    return IsAbsolutelyPositionedStyle() || IsRelativelyPositionedStyle();
-  }
-
   bool IsScrollableOverflow() const {
     // mOverflowX and mOverflowY always match when one of them is
     // NS_STYLE_OVERFLOW_VISIBLE or NS_STYLE_OVERFLOW_CLIP.
@@ -1710,24 +1701,18 @@ struct nsStyleDisplay {
   }
 
   // These are defined in nsStyleStructInlines.h.
-
-  // The aContextFrame argument on each of these is the frame this
-  // style struct is for.  If the frame is for SVG text, the return
-  // value will be massaged to be something that makes sense for
-  // SVG text.
-  inline bool IsBlockInside(const nsIFrame* aContextFrame) const;
-  inline bool IsBlockOutside(const nsIFrame* aContextFrame) const;
-  inline bool IsInlineOutside(const nsIFrame* aContextFrame) const;
-  inline bool IsOriginalDisplayInlineOutside(const nsIFrame* aContextFrame) const;
-  inline uint8_t GetDisplay(const nsIFrame* aContextFrame) const;
-  inline bool IsFloating(const nsIFrame* aContextFrame) const;
-  inline bool IsPositioned(const nsIFrame* aContextFrame) const;
-  inline bool IsRelativelyPositioned(const nsIFrame* aContextFrame) const;
-  inline bool IsAbsolutelyPositioned(const nsIFrame* aContextFrame) const;
-
+  inline bool IsBlockInside(const nsIFrame* aFrame) const;
+  inline bool IsBlockOutside(const nsIFrame* aFrame) const;
+  inline bool IsInlineOutside(const nsIFrame* aFrame) const;
+  inline bool IsOriginalDisplayInlineOutside(const nsIFrame* aFrame) const;
+  inline uint8_t GetDisplay(const nsIFrame* aFrame) const;
+  inline bool IsFloating(const nsIFrame* aFrame) const;
+  inline bool IsPositioned(const nsIFrame* aFrame) const;
+  inline bool IsRelativelyPositioned(const nsIFrame* aFrame) const;
+  inline bool IsAbsolutelyPositioned(const nsIFrame* aFrame) const;
   /* Returns whether the element has the -moz-transform property
    * or a related property, and supports CSS transforms. */
-  inline bool HasTransform(const nsIFrame* aContextFrame) const;
+  inline bool HasTransform(const nsIFrame* aFrame) const;
 };
 
 struct nsStyleTable {
diff --git a/layout/style/nsStyleStructInlines.h b/layout/style/nsStyleStructInlines.h
index f9349b904706..5964acdca305 100644
--- a/layout/style/nsStyleStructInlines.h
+++ b/layout/style/nsStyleStructInlines.h
@@ -56,83 +56,74 @@ nsStyleBorder::GetSubImage(uint8_t aIndex) const
 }
 
 bool
-nsStyleText::HasTextShadow(const nsIFrame* aContextFrame) const
+nsStyleText::HasTextShadow(const nsIFrame* aFrame) const
 {
-  NS_ASSERTION(aContextFrame->StyleText() == this, "unexpected aContextFrame");
-  return mTextShadow && !aContextFrame->IsSVGText();
+  return mTextShadow && !aFrame->IsSVGText();
 }
 
 nsCSSShadowArray*
-nsStyleText::GetTextShadow(const nsIFrame* aContextFrame) const
+nsStyleText::GetTextShadow(const nsIFrame* aFrame) const
 {
-  NS_ASSERTION(aContextFrame->StyleText() == this, "unexpected aContextFrame");
-  if (aContextFrame->IsSVGText()) {
+  if (aFrame->IsSVGText()) {
     return nullptr;
   }
   return mTextShadow;
 }
 
 bool
-nsStyleText::WhiteSpaceCanWrap(const nsIFrame* aContextFrame) const
+nsStyleText::WhiteSpaceCanWrap(const nsIFrame* aFrame) const
 {
-  NS_ASSERTION(aContextFrame->StyleText() == this, "unexpected aContextFrame");
-  return WhiteSpaceCanWrapStyle() && !aContextFrame->IsSVGText();
+  return WhiteSpaceCanWrapStyle() && !aFrame->IsSVGText();
 }
 
 bool
-nsStyleText::WordCanWrap(const nsIFrame* aContextFrame) const
+nsStyleText::WordCanWrap(const nsIFrame* aFrame) const
 {
-  NS_ASSERTION(aContextFrame->StyleText() == this, "unexpected aContextFrame");
-  return WordCanWrapStyle() && !aContextFrame->IsSVGText();
+  return WordCanWrapStyle() && !aFrame->IsSVGText();
 }
 
 bool
-nsStyleDisplay::IsBlockInside(const nsIFrame* aContextFrame) const
+nsStyleDisplay::IsBlockInside(const nsIFrame* aFrame) const
 {
-  NS_ASSERTION(aContextFrame->StyleDisplay() == this, "unexpected aContextFrame");
-  if (aContextFrame->IsSVGText()) {
-    return aContextFrame->GetType() == nsGkAtoms::blockFrame;
+  if (aFrame->IsSVGText()) {
+    return aFrame->GetType() == nsGkAtoms::blockFrame;
   }
   return IsBlockInsideStyle();
 }
 
 bool
-nsStyleDisplay::IsBlockOutside(const nsIFrame* aContextFrame) const
+nsStyleDisplay::IsBlockOutside(const nsIFrame* aFrame) const
 {
-  NS_ASSERTION(aContextFrame->StyleDisplay() == this, "unexpected aContextFrame");
-  if (aContextFrame->IsSVGText()) {
-    return aContextFrame->GetType() == nsGkAtoms::blockFrame;
+  if (aFrame->IsSVGText()) {
+    return aFrame->GetType() == nsGkAtoms::blockFrame;
   }
   return IsBlockOutsideStyle();
 }
 
 bool
-nsStyleDisplay::IsInlineOutside(const nsIFrame* aContextFrame) const
+nsStyleDisplay::IsInlineOutside(const nsIFrame* aFrame) const
 {
-  NS_ASSERTION(aContextFrame->StyleDisplay() == this, "unexpected aContextFrame");
-  if (aContextFrame->IsSVGText()) {
-    return aContextFrame->GetType() != nsGkAtoms::blockFrame;
+  if (aFrame->IsSVGText()) {
+    return aFrame->GetType() != nsGkAtoms::blockFrame;
   }
   return IsInlineOutsideStyle();
 }
 
 bool
-nsStyleDisplay::IsOriginalDisplayInlineOutside(const nsIFrame* aContextFrame) const
+nsStyleDisplay::IsOriginalDisplayInlineOutside(const nsIFrame* aFrame) const
 {
-  NS_ASSERTION(aContextFrame->StyleDisplay() == this, "unexpected aContextFrame");
-  if (aContextFrame->IsSVGText()) {
-    return aContextFrame->GetType() != nsGkAtoms::blockFrame;
+  if (aFrame->IsSVGText()) {
+    return aFrame->GetType() != nsGkAtoms::blockFrame;
   }
   return IsOriginalDisplayInlineOutsideStyle();
 }
 
 uint8_t
-nsStyleDisplay::GetDisplay(const nsIFrame* aContextFrame) const
+nsStyleDisplay::GetDisplay(const nsIFrame* aFrame) const
 {
-  NS_ASSERTION(aContextFrame->StyleDisplay() == this, "unexpected aContextFrame");
-  if (aContextFrame->IsSVGText() &&
+  if (aFrame->IsSVGText() &&
       mDisplay != NS_STYLE_DISPLAY_NONE) {
-    return aContextFrame->GetType() == nsGkAtoms::blockFrame ?
+    return aFrame->GetType() == nsGkAtoms::blockFrame ?
              NS_STYLE_DISPLAY_BLOCK :
              NS_STYLE_DISPLAY_INLINE;
   }
@@ -140,41 +131,36 @@ nsStyleDisplay::GetDisplay(const nsIFrame* aContextFrame) const
 }
 
 bool
-nsStyleDisplay::IsFloating(const nsIFrame* aContextFrame) const
+nsStyleDisplay::IsFloating(const nsIFrame* aFrame) const
 {
-  NS_ASSERTION(aContextFrame->StyleDisplay() == this, "unexpected aContextFrame");
-  return IsFloatingStyle() && !aContextFrame->IsSVGText();
+  return IsFloatingStyle() && !aFrame->IsSVGText();
 }
 
 bool
-nsStyleDisplay::HasTransform(const nsIFrame* aContextFrame) const
+nsStyleDisplay::HasTransform(const nsIFrame* aFrame) const
 {
-  NS_ASSERTION(aContextFrame->StyleDisplay() == this, "unexpected aContextFrame");
-  return HasTransformStyle() && aContextFrame->IsFrameOfType(nsIFrame::eSupportsCSSTransforms);
+  return HasTransformStyle() && aFrame->IsFrameOfType(nsIFrame::eSupportsCSSTransforms);
 }
 
 bool
-nsStyleDisplay::IsPositioned(const nsIFrame* aContextFrame) const
+nsStyleDisplay::IsPositioned(const nsIFrame* aFrame) const
 {
-  NS_ASSERTION(aContextFrame->StyleDisplay() == this, "unexpected aContextFrame");
   return (IsAbsolutelyPositionedStyle() ||
           IsRelativelyPositionedStyle() ||
-          HasTransform(aContextFrame)) &&
-         !aContextFrame->IsSVGText();
+          HasTransform(aFrame)) &&
+         !aFrame->IsSVGText();
 }
 
 bool
-nsStyleDisplay::IsRelativelyPositioned(const nsIFrame* aContextFrame) const
+nsStyleDisplay::IsRelativelyPositioned(const nsIFrame* aFrame) const
 {
-  NS_ASSERTION(aContextFrame->StyleDisplay() == this, "unexpected aContextFrame");
-  return IsRelativelyPositionedStyle() && !aContextFrame->IsSVGText();
+  return IsRelativelyPositionedStyle() && !aFrame->IsSVGText();
 }
 
 bool
-nsStyleDisplay::IsAbsolutelyPositioned(const nsIFrame* aContextFrame) const
+nsStyleDisplay::IsAbsolutelyPositioned(const nsIFrame* aFrame) const
 {
-  NS_ASSERTION(aContextFrame->StyleDisplay() == this, "unexpected aContextFrame");
-  return IsAbsolutelyPositionedStyle() && !aContextFrame->IsSVGText();
+  return IsAbsolutelyPositionedStyle() && !aFrame->IsSVGText();
 }
 
 uint8_t

From 6463b16c2580b8762a2a681d7106eabc70724a01 Mon Sep 17 00:00:00 2001
From: Phil Ringnalda 
Date: Tue, 26 Mar 2013 23:40:45 -0700
Subject: [PATCH 120/129] Back out 8e59146e161e:29acf1494fed (bug 790732) for
 failing in exactly the same way it failed on the tryserver CLOSED TREE

---
 dom/base/nsDOMClassInfo.cpp                   | 98 -------------------
 dom/base/nsGlobalWindow.cpp                   | 22 +----
 js/xpconnect/src/XPCComponents.cpp            |  7 +-
 js/xpconnect/src/XPCJSRuntime.cpp             | 14 +--
 js/xpconnect/src/nsXPConnect.cpp              |  3 +
 js/xpconnect/src/xpcprivate.h                 |  6 +-
 js/xpconnect/tests/chrome/test_bug795275.xul  | 18 +---
 js/xpconnect/tests/mochitest/Makefile.in      |  2 -
 .../tests/mochitest/file_bug790732.html       | 56 -----------
 .../tests/mochitest/test_bug790732.html       | 46 ---------
 modules/libpref/src/init/all.js               |  3 -
 .../passwordmgr/test/test_prompt.html         | 12 ++-
 .../satchel/test/test_form_autocomplete.html  |  2 +-
 toolkit/components/telemetry/Histograms.json  |  4 -
 14 files changed, 29 insertions(+), 264 deletions(-)
 delete mode 100644 js/xpconnect/tests/mochitest/file_bug790732.html
 delete mode 100644 js/xpconnect/tests/mochitest/test_bug790732.html

diff --git a/dom/base/nsDOMClassInfo.cpp b/dom/base/nsDOMClassInfo.cpp
index 6dfc8380a433..33b2fcaa6a26 100644
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -5162,98 +5162,6 @@ LocationSetterUnwrapper(JSContext *cx, JSHandleObject obj_, JSHandleId id, JSBoo
   return LocationSetter(cx, obj, id, strict, vp);
 }
 
-struct InterfaceShimEntry {
-  const char *geckoName;
-  const char *domName;
-};
-
-// We add shims from Components.interfaces.nsIDOMFoo to window.Foo for each
-// interface that has interface constants that sites might be getting off
-// of Ci.
-const InterfaceShimEntry kInterfaceShimMap[] =
-{ { "nsIDOMFileReader", "FileReader" },
-  { "nsIXMLHttpRequest", "XMLHttpRequest" },
-  { "nsIDOMDOMException", "DOMException" },
-  { "nsIDOMNode", "Node" },
-  { "nsIDOMUserDataHandler", "UserDataHandler" },
-  { "nsIDOMCSSPrimitiveValue", "CSSPrimitiveValue" },
-  { "nsIDOMCSSRule", "CSSRule" },
-  { "nsIDOMCSSValue", "CSSValue" },
-  { "nsIDOMEvent", "Event" },
-  { "nsIDOMNSEvent", "Event" },
-  { "nsIDOMKeyEvent", "KeyEvent" },
-  { "nsIDOMMouseEvent", "MouseEvent" },
-  { "nsIDOMMouseScrollEvent", "MouseScrollEvent" },
-  { "nsIDOMMutationEvent", "MutationEvent" },
-  { "nsIDOMSimpleGestureEvent", "SimpleGestureEvent" },
-  { "nsIDOMUIEvent", "UIEvent" },
-  { "nsIDOMGeoPositionError", "GeoPositionError" },
-  { "nsIDOMHTMLMediaElement", "HTMLMediaElement" },
-  { "nsIDOMMediaError", "MediaError" },
-  { "nsIDOMLoadStatus", "LoadStatus" },
-  { "nsIDOMOfflineResourceList", "OfflineResourceList" },
-  { "nsIDOMRange", "Range" },
-  { "nsIDOMSVGFETurbulenceElement", "SVGFETurbulenceElement" },
-  { "nsIDOMSVGFEMorphologyElement", "SVGFEMorphologyElement" },
-  { "nsIDOMSVGFEConvolveMatrixElement", "SVGFEConvolveMatrixElement" },
-  { "nsIDOMSVGFEDisplacementMapElement", "SVGFEDisplacementMapElement" },
-  { "nsIDOMSVGLength", "SVGLength" },
-  { "nsIDOMSVGUnitTypes", "SVGUnitTypes" },
-  { "nsIDOMNodeFilter", "NodeFilter" },
-  { "nsIDOMXPathNamespace", "XPathNamespace" },
-  { "nsIDOMXPathResult", "XPathResult" },
-  { "nsIDOMXULButtonElement", "XULButtonElement" },
-  { "nsIDOMXULCheckboxElement", "XULCheckboxElement" },
-  { "nsIDOMXULPopupElement", "XULPopupElement" } };
-
-static nsresult
-DefineComponentsShim(JSContext *cx, JS::HandleObject global)
-{
-  // Keep track of how often this happens.
-  Telemetry::Accumulate(Telemetry::COMPONENTS_SHIM_ACCESSED_BY_CONTENT, true);
-
-  // Create a fake Components object.
-  JSObject *components = JS_NewObject(cx, nullptr, nullptr, global);
-  NS_ENSURE_TRUE(components, NS_ERROR_OUT_OF_MEMORY);
-  bool ok = JS_DefineProperty(cx, global, "Components", JS::ObjectValue(*components),
-                              JS_PropertyStub, JS_StrictPropertyStub, JSPROP_ENUMERATE);
-  NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY);
-
-  // Create a fake interfaces object.
-  JSObject *interfaces = JS_NewObject(cx, nullptr, nullptr, global);
-  NS_ENSURE_TRUE(interfaces, NS_ERROR_OUT_OF_MEMORY);
-  ok = JS_DefineProperty(cx, components, "interfaces", JS::ObjectValue(*interfaces),
-                         JS_PropertyStub, JS_StrictPropertyStub,
-                         JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_READONLY);
-  NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY);
-
-  // Define a bunch of shims from the Ci.nsIDOMFoo to window.Foo for DOM
-  // interfaces with constants.
-  for (uint32_t i = 0; i < ArrayLength(kInterfaceShimMap); ++i) {
-
-    // Grab the names from the table.
-    const char *geckoName = kInterfaceShimMap[i].geckoName;
-    const char *domName = kInterfaceShimMap[i].domName;
-
-    // Look up the appopriate interface object on the global.
-    JS::Value v = JS::UndefinedValue();
-    ok = JS_GetProperty(cx, global, domName, &v);
-    NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY);
-    if (!v.isObject()) {
-      NS_WARNING("Unable to find interface object on global");
-      continue;
-    }
-
-    // Define the shim on the interfaces object.
-    ok = JS_DefineProperty(cx, interfaces, geckoName, v,
-                           JS_PropertyStub, JS_StrictPropertyStub,
-                           JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_READONLY);
-    NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY);
-  }
-
-  return NS_OK;
-}
-
 NS_IMETHODIMP
 nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
                        JSObject *obj_, jsid id_, uint32_t flags,
@@ -5266,12 +5174,6 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
     return NS_OK;
   }
 
-  MOZ_ASSERT(*_retval == true); // guaranteed by XPC_WN_Helper_NewResolve
-  if (id == XPCJSRuntime::Get()->GetStringID(XPCJSRuntime::IDX_COMPONENTS)) {
-    *objp = obj;
-    return DefineComponentsShim(cx, obj);
-  }
-
   nsGlobalWindow *win = nsGlobalWindow::FromWrapper(wrapper);
   MOZ_ASSERT(win->IsInnerWindow());
 
diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp
index b25a59b46e1b..faba920f3359 100644
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -1971,17 +1971,6 @@ nsGlobalWindow::SetOuterObject(JSContext* aCx, JSObject* aOuterObject)
   return NS_OK;
 }
 
-// We need certain special behavior for remote XUL whitelisted domains, but we
-// don't want that behavior to take effect in automation, because we whitelist
-// all the mochitest domains. So we need to check a pref here.
-static bool
-TreatAsRemoteXUL(nsIPrincipal* aPrincipal)
-{
-  MOZ_ASSERT(!nsContentUtils::IsSystemPrincipal(aPrincipal));
-  return nsContentUtils::AllowXULXBLForPrincipal(aPrincipal) &&
-         !Preferences::GetBool("dom.use_xbl_scopes_for_remote_xul", false);
-}
-
 /**
  * Create a new global object that will be used for an inner window.
  * Return the native global and an nsISupports 'holder' that can be used
@@ -2015,19 +2004,10 @@ CreateNativeGlobalForInner(JSContext* aCx,
 
   nsIXPConnect* xpc = nsContentUtils::XPConnect();
 
-  // Determine if we need the Components object.
-  bool componentsInContent =
-    !Preferences::GetBool("dom.omit_components_in_content", true) ||
-    !Preferences::GetBool("dom.xbl_scopes", true);
-  bool needComponents = componentsInContent ||
-                        nsContentUtils::IsSystemPrincipal(aPrincipal) ||
-                        TreatAsRemoteXUL(aPrincipal);
-  uint32_t flags = needComponents ? 0 : nsIXPConnect::OMIT_COMPONENTS_OBJECT;
-
   nsRefPtr jsholder;
   nsresult rv = xpc->InitClassesWithNewWrappedGlobal(
     aCx, ToSupports(aNewInner),
-    aPrincipal, flags, zoneSpec, getter_AddRefs(jsholder));
+    aPrincipal, 0, zoneSpec, getter_AddRefs(jsholder));
   NS_ENSURE_SUCCESS(rv, rv);
 
   MOZ_ASSERT(jsholder);
diff --git a/js/xpconnect/src/XPCComponents.cpp b/js/xpconnect/src/XPCComponents.cpp
index bf1c0d110f5a..6153f8ab579d 100644
--- a/js/xpconnect/src/XPCComponents.cpp
+++ b/js/xpconnect/src/XPCComponents.cpp
@@ -4880,7 +4880,8 @@ ContentComponentsGetterOp(JSContext *cx, JSHandleObject obj, JSHandleId id,
 // static
 JSBool
 nsXPCComponents::AttachComponentsObject(XPCCallContext& ccx,
-                                        XPCWrappedNativeScope* aScope)
+                                        XPCWrappedNativeScope* aScope,
+                                        JSObject* aTarget)
 {
     JSObject *components = aScope->GetComponentsJSObject(ccx);
     if (!components)
@@ -4888,11 +4889,13 @@ nsXPCComponents::AttachComponentsObject(XPCCallContext& ccx,
 
     JSObject *global = aScope->GetGlobalJSObject();
     MOZ_ASSERT(js::IsObjectInContextCompartment(global, ccx));
+    if (!aTarget)
+        aTarget = global;
 
     jsid id = ccx.GetRuntime()->GetStringID(XPCJSRuntime::IDX_COMPONENTS);
     JSPropertyOp getter = AccessCheck::isChrome(global) ? nullptr
                                                         : &ContentComponentsGetterOp;
-    return JS_DefinePropertyById(ccx, global, id, js::ObjectValue(*components),
+    return JS_DefinePropertyById(ccx, aTarget, id, js::ObjectValue(*components),
                                  getter, nullptr, JSPROP_PERMANENT | JSPROP_READONLY);
 }
 
diff --git a/js/xpconnect/src/XPCJSRuntime.cpp b/js/xpconnect/src/XPCJSRuntime.cpp
index 535a55de9ece..5e7413cca5b4 100644
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -282,18 +282,8 @@ EnableUniversalXPConnect(JSContext *cx)
 
     // Recompute all the cross-compartment wrappers leaving the newly-privileged
     // compartment.
-    bool ok = js::RecomputeWrappers(cx, js::SingleCompartment(compartment),
-                                    js::AllCompartments());
-    NS_ENSURE_TRUE(ok, false);
-
-    // The Components object normally isn't defined for unprivileged web content,
-    // but we define it when UniversalXPConnect is enabled to support legacy
-    // tests.
-    XPCWrappedNativeScope *scope = priv->scope;
-    if (!scope)
-        return true;
-    XPCCallContext ccx(NATIVE_CALLER, cx);
-    return nsXPCComponents::AttachComponentsObject(ccx, scope);
+    return js::RecomputeWrappers(cx, js::SingleCompartment(compartment),
+                                 js::AllCompartments());
 }
 
 }
diff --git a/js/xpconnect/src/nsXPConnect.cpp b/js/xpconnect/src/nsXPConnect.cpp
index 2e8e89876c09..f667c7cf260e 100644
--- a/js/xpconnect/src/nsXPConnect.cpp
+++ b/js/xpconnect/src/nsXPConnect.cpp
@@ -946,6 +946,9 @@ nsXPConnect::InitClasses(JSContext * aJSContext, JSObject * aGlobalJSObj)
 
     scope->RemoveWrappedNativeProtos();
 
+    if (!nsXPCComponents::AttachComponentsObject(ccx, scope))
+        return UnexpectedFailure(NS_ERROR_FAILURE);
+
     if (!XPCNativeWrapper::AttachNewConstructorObject(ccx, aGlobalJSObj))
         return UnexpectedFailure(NS_ERROR_FAILURE);
 
diff --git a/js/xpconnect/src/xpcprivate.h b/js/xpconnect/src/xpcprivate.h
index 80f6916c1dce..7f9752fb08e1 100644
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -3722,9 +3722,13 @@ public:
     NS_DECL_NSISECURITYCHECKEDCOMPONENT
 
 public:
+    // The target is the object upon which |Components| will be defined. If
+    // aTarget is left null, a default object will be computed. This is usually
+    // the right thing to do.
     static JSBool
     AttachComponentsObject(XPCCallContext& ccx,
-                           XPCWrappedNativeScope* aScope);
+                           XPCWrappedNativeScope* aScope,
+                           JSObject* aTarget = NULL);
 
     void SystemIsBeingShutDown() {ClearMembers();}
 
diff --git a/js/xpconnect/tests/chrome/test_bug795275.xul b/js/xpconnect/tests/chrome/test_bug795275.xul
index 816013f491a0..e752b4ed07f3 100644
--- a/js/xpconnect/tests/chrome/test_bug795275.xul
+++ b/js/xpconnect/tests/chrome/test_bug795275.xul
@@ -20,14 +20,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=795275
   /** Test for Warning in content scopes about Components. **/
 
   SimpleTest.waitForExplicitFinish();
-  SpecialPowers.pushPrefEnv({set: [['dom.omit_components_in_content', false]]}, startLoad);
-  function startLoad() {
-    for (var i = 1; i <= document.getElementsByTagName('iframe').length; ++i) {
-      var frame = document.getElementById('frame' + i);
-      frame.contentWindow.location = 'http://mochi.test:8888/tests/js/xpconnect/tests/mochitest/file_bug795275.html';
-      frame.onload = frameLoaded;
-    }
-  }
 
   // Set up our console listener.
   var gWarnings = 0;
@@ -81,10 +73,10 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=795275
   ]]>
 
   
-  
-
-
diff --git a/modules/libpref/src/init/all.js b/modules/libpref/src/init/all.js
index 5a3f213174d5..46c10df52794 100644
--- a/modules/libpref/src/init/all.js
+++ b/modules/libpref/src/init/all.js
@@ -715,9 +715,6 @@ pref("dom.min_background_timeout_value", 1000);
 // Run content XBL in a separate scope.
 pref("dom.xbl_scopes", true);
 
-// Stop defining the Components object in content.
-pref("dom.omit_components_in_content", false);
-
 // Don't use new input types
 pref("dom.experimental_forms", false);
 
diff --git a/toolkit/components/passwordmgr/test/test_prompt.html b/toolkit/components/passwordmgr/test/test_prompt.html
index 31f85d153b8b..bc1f8424987b 100644
--- a/toolkit/components/passwordmgr/test/test_prompt.html
+++ b/toolkit/components/passwordmgr/test/test_prompt.html
@@ -138,7 +138,7 @@ var resolveCallback = {
     const interfaces = [Ci.nsIProtocolProxyCallback, Ci.nsISupports];
 
     if (!interfaces.some( function(v) { return iid.equals(v) } ))
-      throw SpecialPowers.Cr.NS_ERROR_NO_INTERFACE;
+      throw Components.results.NS_ERROR_NO_INTERFACE;
     return this;
   },
 
@@ -160,10 +160,12 @@ var resolveCallback = {
 
 function startup() {
   //need to allow for arbitrary network servers defined in PAC instead of a hardcoded moz-proxy.
-  var ios = SpecialPowers.Cc["@mozilla.org/network/io-service;1"].
-    getService(SpecialPowers.Ci.nsIIOService);
+  var ios = SpecialPowers.wrap(Components).
+    classes["@mozilla.org/network/io-service;1"].
+    getService(Components.interfaces.nsIIOService);
 
-  var pps = SpecialPowers.Cc["@mozilla.org/network/protocol-proxy-service;1"].getService();
+  var pps = SpecialPowers.wrap(Components).
+    classes["@mozilla.org/network/protocol-proxy-service;1"].getService();
 
   var uri = ios.newURI("http://example.com", null, null);
   pps.asyncResolve(uri, 0, resolveCallback);
@@ -181,7 +183,7 @@ var storageObserver = {
                         Ci.nsISupports, Ci.nsISupportsWeakReference];
 
     if (!interfaces.some( function(v) { return iid.equals(v) } ))
-      throw SpecialPowers.Cr.NS_ERROR_NO_INTERFACE;
+      throw SpecialPowers.Components.results.NS_ERROR_NO_INTERFACE;
     return this;
   },
 
diff --git a/toolkit/components/satchel/test/test_form_autocomplete.html b/toolkit/components/satchel/test/test_form_autocomplete.html
index 03142d3529c7..e18b860cf0a1 100644
--- a/toolkit/components/satchel/test/test_form_autocomplete.html
+++ b/toolkit/components/satchel/test/test_form_autocomplete.html
@@ -122,7 +122,7 @@ const shiftModifier = Event.SHIFT_MASK;
 
 // Get the form history service
 var fh = SpecialPowers.Cc["@mozilla.org/satchel/form-history;1"].
-         getService(SpecialPowers.Ci.nsIFormHistory2);
+         getService(Components.interfaces.nsIFormHistory2);
 ok(fh != null, "got form history service");
 
 fh.removeAllEntries();
diff --git a/toolkit/components/telemetry/Histograms.json b/toolkit/components/telemetry/Histograms.json
index f4101c8de78d..bf03877c3675 100644
--- a/toolkit/components/telemetry/Histograms.json
+++ b/toolkit/components/telemetry/Histograms.json
@@ -2895,10 +2895,6 @@
     "kind": "flag",
     "description": "Whether content ever accesed Components.interfaces in this session"
   },
-  "COMPONENTS_SHIM_ACCESSED_BY_CONTENT": {
-    "kind": "flag",
-    "description": "Whether content ever accesed the Components shim in this session"
-  },
   "CHECK_ADDONS_MODIFIED_MS": {
     "kind": "exponential",
     "high": "5000",

From 8376bad5ebff490917944ff1c648bf3ef673b619 Mon Sep 17 00:00:00 2001
From: Mike Hommey 
Date: Wed, 27 Mar 2013 07:51:14 +0100
Subject: [PATCH 121/129] Bug 854914 - Allow clang to build in C++11 mode by
 working around http://llvm.org/bugs/show_bug.cgi?id=13530. r=ted

---
 build/unix/headers/bits/c++config.h |  2 ++
 configure.in                        | 17 ++++++++++++++---
 2 files changed, 16 insertions(+), 3 deletions(-)
 create mode 100644 build/unix/headers/bits/c++config.h

diff --git a/build/unix/headers/bits/c++config.h b/build/unix/headers/bits/c++config.h
new file mode 100644
index 000000000000..c0182c12858f
--- /dev/null
+++ b/build/unix/headers/bits/c++config.h
@@ -0,0 +1,2 @@
+#include_next 
+#undef _GLIBCXX_USE_FLOAT128
diff --git a/configure.in b/configure.in
index 335132c99e73..7eaab05cdab3 100644
--- a/configure.in
+++ b/configure.in
@@ -2715,9 +2715,20 @@ if test "$GNU_CXX"; then
         [AC_TRY_COMPILE([#include ], [],
                         ac_cv_cxx0x_headers_bug="no",
                         ac_cv_cxx0x_headers_bug="yes")])
-    CXXFLAGS="$_SAVE_CXXFLAGS"
-    if test "$ac_cv_cxx0x_headers_bug" = "no"; then
-        CXXFLAGS="$CXXFLAGS -std=gnu++0x"
+
+    if test "$CLANG_CXX" -a "$ac_cv_cxx0x_headers_bug" = "yes"; then
+        CXXFLAGS="$CXXFLAGS -I$_topsrcdir/build/unix/headers"
+        AC_CACHE_CHECK(whether workaround for gcc c++0x headers conflict with clang works,
+            ac_cv_cxx0x_clang_workaround,
+            [AC_TRY_COMPILE([#include ], [],
+                            ac_cv_cxx0x_clang_workaround="yes",
+                            ac_cv_cxx0x_clang_workaround="no")])
+
+        if test "ac_cv_cxx0x_clang_workaround" = "no"; then
+            CXXFLAGS="$_SAVE_CXXFLAGS"
+        fi
+    elif test "$ac_cv_cxx0x_headers_bug" = "yes"; then
+        CXXFLAGS="$_SAVE_CXXFLAGS"
     fi
 fi
 

From 347a7c2d09c35eeeba440a2b48f1c0e37e23a305 Mon Sep 17 00:00:00 2001
From: Mike Hommey 
Date: Wed, 20 Mar 2013 14:56:41 +0100
Subject: [PATCH 122/129] Bug 852950 - Kill libxpcom. r=bsmedberg

Also refactored the xpcom standalone glue to reside in a single file and
removed its use of realpath().

--HG--
rename : xpcom/stub/dependentlibs.py => toolkit/library/dependentlibs.py
rename : xpcom/stub/nsXPComStub.cpp => xpcom/build/FrozenFunctions.cpp
---
 b2g/installer/package-manifest.in             |   1 -
 b2g/installer/removed-files.in                |   1 +
 browser/installer/package-manifest.in         |   1 -
 browser/installer/removed-files.in            |   1 +
 configure.in                                  |  26 +-
 mobile/android/installer/package-manifest.in  |   1 -
 mozglue/android/APKOpen.cpp                   |   8 +-
 toolkit/library/Makefile.in                   |   5 +
 .../stub => toolkit/library}/dependentlibs.py |   6 +-
 toolkit/toolkit.mozbuild                      |   1 -
 xpcom/build/FrozenFunctions.cpp               | 131 +++++
 xpcom/build/Makefile.in                       |   1 +
 xpcom/build/nsXPCOM.h                         |  28 -
 xpcom/build/nsXPCOMPrivate.h                  |   6 +-
 xpcom/glue/nsCycleCollectorUtils.h            |   1 -
 xpcom/glue/nsThreadUtils.h                    |  17 -
 xpcom/glue/standalone/Makefile.in             |  23 -
 xpcom/glue/standalone/nsGlueLinking.h         |  23 -
 xpcom/glue/standalone/nsGlueLinkingDlopen.cpp | 248 ---------
 xpcom/glue/standalone/nsGlueLinkingNull.cpp   |  23 -
 xpcom/glue/standalone/nsGlueLinkingOS2.cpp    | 156 ------
 xpcom/glue/standalone/nsGlueLinkingOSX.cpp    | 124 -----
 xpcom/glue/standalone/nsGlueLinkingWin.cpp    | 216 --------
 xpcom/glue/standalone/nsXPCOMGlue.cpp         | 512 +++++++++++++++--
 .../glue/standalone/staticruntime/Makefile.in |  28 +-
 xpcom/reflect/xptcall/public/xptcall.h        |   6 -
 .../src/md/unix/xptcinvoke_alpha_openbsd.cpp  |  14 +-
 .../src/md/unix/xptcinvoke_amd64_openbsd.cpp  |   2 +-
 .../src/md/unix/xptcinvoke_asm_ipf32.s        |  12 +-
 .../src/md/unix/xptcinvoke_asm_ipf64.s        |  10 +-
 .../xptcall/src/md/unix/xptcinvoke_asm_mips.s |  12 +-
 .../src/md/unix/xptcinvoke_asm_mips64.s       |   8 +-
 .../src/md/unix/xptcinvoke_asm_parisc_linux.s |   8 +-
 .../src/md/unix/xptcinvoke_asm_ppc64_linux.s  |  14 +-
 .../src/md/unix/xptcinvoke_asm_ppc_aix.s      |  20 +-
 .../src/md/unix/xptcinvoke_asm_ppc_aix64.s    |  20 +-
 .../md/unix/xptcinvoke_asm_ppc_ibmobj_aix.s   |  20 +-
 .../src/md/unix/xptcinvoke_asm_ppc_linux.s    |   8 +-
 .../src/md/unix/xptcinvoke_asm_ppc_openbsd.s  |   8 +-
 .../src/md/unix/xptcinvoke_asm_ppc_rhapsody.s |   6 +-
 .../md/unix/xptcinvoke_asm_sparc64_openbsd.s  |  10 +-
 .../md/unix/xptcinvoke_asm_sparc_linux_GCC3.s |   4 +-
 .../unix/xptcinvoke_asm_sparc_solaris_GCC3.s  |   6 +-
 .../unix/xptcinvoke_asm_sparc_solaris_SUNW.s  |  10 +-
 .../xptcinvoke_asm_sparcv9_solaris_SUNW.s     |  10 +-
 .../md/unix/xptcinvoke_asm_x86_solaris_SUNW.s |   8 +-
 .../src/md/unix/xptcinvoke_gcc_x86_unix.cpp   |  10 +-
 .../src/md/unix/xptcinvoke_linux_alpha.cpp    |  14 +-
 .../src/md/unix/xptcinvoke_linux_m68k.cpp     |   2 +-
 .../xptcall/src/md/unix/xptcinvoke_mips.cpp   |   6 +-
 .../xptcall/src/md/unix/xptcinvoke_mips64.cpp |   6 +-
 .../src/md/unix/xptcinvoke_ppc64_linux.cpp    |   6 +-
 .../src/md/unix/xptcinvoke_ppc_linux.cpp      |   6 +-
 .../src/md/unix/xptcinvoke_ppc_openbsd.cpp    |   6 +-
 .../src/md/unix/xptcinvoke_ppc_rhapsody.cpp   |   6 +-
 .../src/md/unix/xptcinvoke_x86_64_solaris.cpp |   2 +-
 .../src/md/unix/xptcinvoke_x86_64_unix.cpp    |   2 +-
 .../xptcall/src/md/win32/xptcinvoke.cpp       |   2 +-
 .../src/md/win32/xptcinvoke_x86_64.cpp        |   2 +-
 .../src/md/win32/xptcinvoke_x86_gnu.cpp       |   8 +-
 xpcom/string/public/nsXPCOMStrings.h          |  28 -
 xpcom/stub/Makefile.in                        |  58 --
 xpcom/stub/moz.build                          |   7 -
 xpcom/stub/nsXPComStub.cpp                    | 514 ------------------
 64 files changed, 768 insertions(+), 1721 deletions(-)
 rename {xpcom/stub => toolkit/library}/dependentlibs.py (95%)
 create mode 100644 xpcom/build/FrozenFunctions.cpp
 delete mode 100644 xpcom/glue/standalone/nsGlueLinking.h
 delete mode 100644 xpcom/glue/standalone/nsGlueLinkingDlopen.cpp
 delete mode 100644 xpcom/glue/standalone/nsGlueLinkingNull.cpp
 delete mode 100644 xpcom/glue/standalone/nsGlueLinkingOS2.cpp
 delete mode 100644 xpcom/glue/standalone/nsGlueLinkingOSX.cpp
 delete mode 100644 xpcom/glue/standalone/nsGlueLinkingWin.cpp
 delete mode 100644 xpcom/stub/Makefile.in
 delete mode 100644 xpcom/stub/moz.build
 delete mode 100644 xpcom/stub/nsXPComStub.cpp

diff --git a/b2g/installer/package-manifest.in b/b2g/installer/package-manifest.in
index dd46c7a9cfd0..782cb35f93a8 100644
--- a/b2g/installer/package-manifest.in
+++ b/b2g/installer/package-manifest.in
@@ -54,7 +54,6 @@
 @BINPATH@/@DLL_PREFIX@plds4@DLL_SUFFIX@
 @BINPATH@/@DLL_PREFIX@nspr4@DLL_SUFFIX@
 #endif
-@BINPATH@/@DLL_PREFIX@xpcom@DLL_SUFFIX@
 @BINPATH@/@DLL_PREFIX@mozalloc@DLL_SUFFIX@
 #ifdef MOZ_DMD
 @BINPATH@/@DLL_PREFIX@dmd@DLL_SUFFIX@
diff --git a/b2g/installer/removed-files.in b/b2g/installer/removed-files.in
index 10652dbdcf36..019fae2bd961 100644
--- a/b2g/installer/removed-files.in
+++ b/b2g/installer/removed-files.in
@@ -20,3 +20,4 @@ components/dom_sms.xpt
 @DLL_PREFIX@nssutil3@DLL_SUFFIX@
 @DLL_PREFIX@mozsqlite3@DLL_SUFFIX@
 #endif
+@DLL_PREFIX@xpcom@DLL_SUFFIX@
diff --git a/browser/installer/package-manifest.in b/browser/installer/package-manifest.in
index 22524369ede9..d6b630861a17 100644
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -69,7 +69,6 @@
 @BINPATH@/@DLL_PREFIX@plds4@DLL_SUFFIX@
 #endif
 #endif
-@BINPATH@/@DLL_PREFIX@xpcom@DLL_SUFFIX@
 #ifdef XP_MACOSX
 @BINPATH@/XUL
 #else
diff --git a/browser/installer/removed-files.in b/browser/installer/removed-files.in
index 41f74da1417e..87a956a0b376 100644
--- a/browser/installer/removed-files.in
+++ b/browser/installer/removed-files.in
@@ -26,6 +26,7 @@
 @DLL_PREFIX@nssutil3@DLL_SUFFIX@
 @DLL_PREFIX@mozsqlite3@DLL_SUFFIX@
 #endif
+@DLL_PREFIX@xpcom@DLL_SUFFIX@
 LICENSE
 browserconfig.properties
 chrome/US.jar
diff --git a/configure.in b/configure.in
index 7eaab05cdab3..1a4ff62c2a6c 100644
--- a/configure.in
+++ b/configure.in
@@ -1019,10 +1019,10 @@ MOZ_PNG_LIBS='$(call EXPAND_LIBNAME_PATH,mozpng,$(DEPTH)/media/libpng)'
 
 MOZ_JS_STATIC_LIBS='$(call EXPAND_LIBNAME_PATH,js_static,$(LIBXUL_DIST)/lib)'
 MOZ_JS_SHARED_LIBS='$(call EXPAND_LIBNAME_PATH,mozjs,$(LIBXUL_DIST)/lib)'
-DYNAMIC_XPCOM_LIBS='-L$(LIBXUL_DIST)/bin -lxpcom -lxpcom_core -lmozalloc'
+DYNAMIC_XPCOM_LIBS='-L$(LIBXUL_DIST)/bin -lxul -lxpcom_core -lmozalloc'
 MOZ_FIX_LINK_PATHS='-Wl,-rpath-link,$(LIBXUL_DIST)/bin -Wl,-rpath-link,$(prefix)/lib'
-XPCOM_FROZEN_LDOPTS='-L$(LIBXUL_DIST)/bin -lxpcom -lmozalloc'
-LIBXUL_LIBS='$(XPCOM_FROZEN_LDOPTS) -lxul'
+XPCOM_FROZEN_LDOPTS='-L$(LIBXUL_DIST)/bin -lxul -lmozalloc'
+LIBXUL_LIBS='$(XPCOM_FROZEN_LDOPTS)'
 XPCOM_GLUE_LDOPTS='$(LIBXUL_DIST)/lib/$(LIB_PREFIX)xpcomglue_s.$(LIB_SUFFIX) $(XPCOM_FROZEN_LDOPTS)'
 XPCOM_STANDALONE_GLUE_LDOPTS='$(LIBXUL_DIST)/lib/$(LIB_PREFIX)xpcomglue.$(LIB_SUFFIX)'
 
@@ -2116,8 +2116,8 @@ ia64*-hpux*)
         # mingw doesn't require kernel32, user32, and advapi32 explicitly
         LIBS="$LIBS -luuid -lgdi32 -lwinmm -lwsock32 -luserenv -lsecur32 -lnetapi32"
         MOZ_FIX_LINK_PATHS=
-        DYNAMIC_XPCOM_LIBS='-L$(LIBXUL_DIST)/lib -lxpcom -lxpcom_core -lmozalloc'
-        XPCOM_FROZEN_LDOPTS='-L$(LIBXUL_DIST)/lib -lxpcom -lmozalloc'
+        DYNAMIC_XPCOM_LIBS='-L$(LIBXUL_DIST)/lib -lxul -lxpcom_core -lmozalloc'
+        XPCOM_FROZEN_LDOPTS='-L$(LIBXUL_DIST)/lib -lxul -lmozalloc'
         DLL_PREFIX=
         IMPORT_LIB_SUFFIX=dll.a
 
@@ -2182,9 +2182,9 @@ ia64*-hpux*)
         WARNINGS_AS_ERRORS='-WX'
         MOZ_OPTIMIZE_FLAGS='-O1'
         MOZ_FIX_LINK_PATHS=
-        DYNAMIC_XPCOM_LIBS='$(LIBXUL_DIST)/lib/xpcom.lib $(LIBXUL_DIST)/lib/xpcom_core.lib $(LIBXUL_DIST)/lib/mozalloc.lib'
-        XPCOM_FROZEN_LDOPTS='$(LIBXUL_DIST)/lib/xpcom.lib $(LIBXUL_DIST)/lib/mozalloc.lib'
-        LIBXUL_LIBS='$(LIBXUL_DIST)/lib/xpcom.lib $(LIBXUL_DIST)/lib/xul.lib $(LIBXUL_DIST)/lib/mozalloc.lib'
+        DYNAMIC_XPCOM_LIBS='$(LIBXUL_DIST)/lib/xul.lib $(LIBXUL_DIST)/lib/xpcom_core.lib $(LIBXUL_DIST)/lib/mozalloc.lib'
+        XPCOM_FROZEN_LDOPTS='$(LIBXUL_DIST)/lib/xul.lib $(LIBXUL_DIST)/lib/mozalloc.lib'
+        LIBXUL_LIBS='$(LIBXUL_DIST)/lib/xul.lib $(LIBXUL_DIST)/lib/mozalloc.lib'
         MOZ_COMPONENT_NSPR_LIBS='$(NSPR_LIBS)'
         LDFLAGS="$LDFLAGS -LARGEADDRESSAWARE -NXCOMPAT"
         dnl For profile-guided optimization
@@ -2360,8 +2360,8 @@ ia64*-hpux*)
     MOZ_DEBUG_FLAGS="-g -fno-inline"
     MOZ_OPTIMIZE_FLAGS="-O2"
     MOZ_OPTIMIZE_LDFLAGS="-s -Zlinker /EXEPACK:2 -Zlinker /PACKCODE -Zlinker /PACKDATA"
-    DYNAMIC_XPCOM_LIBS='-L$(LIBXUL_DIST)/lib $(LIBXUL_DIST)/lib/xpcom.lib $(LIBXUL_DIST)/lib/xpcom_core.lib $(LIBXUL_DIST)/lib/mozalloc.lib'
-    LIBXUL_LIBS='-L$(LIBXUL_DIST)/lib $(LIBXUL_DIST)/lib/xpcom.lib $(LIBXUL_DIST)/lib/xul.lib $(LIBXUL_DIST)/lib/mozalloc.lib'
+    DYNAMIC_XPCOM_LIBS='-L$(LIBXUL_DIST)/lib $(LIBXUL_DIST)/lib/xul.lib $(LIBXUL_DIST)/lib/xpcom_core.lib $(LIBXUL_DIST)/lib/mozalloc.lib'
+    LIBXUL_LIBS='-L$(LIBXUL_DIST)/lib $(LIBXUL_DIST)/lib/xul.lib $(LIBXUL_DIST)/lib/mozalloc.lib'
     TARGET_MD_ARCH=os2
     _PLATFORM_DEFAULT_TOOLKIT="cairo-os2"
     RC=rc.exe
@@ -4596,7 +4596,8 @@ cairo-cocoa)
     TK_CFLAGS="-DNO_X11"
     CFLAGS="$CFLAGS $TK_CFLAGS"
     CXXFLAGS="$CXXFLAGS $TK_CFLAGS"
-    LIBXUL_LIBS='$(XPCOM_FROZEN_LDOPTS) $(LIBXUL_DIST)/bin/XUL'
+    DYNAMIC_XPCOM_LIBS='$(LIBXUL_DIST)/bin/XUL -lxpcom_core -lmozalloc'
+    XPCOM_FROZEN_LDOPTS='$(LIBXUL_DIST)/bin/XUL -lmozalloc'
     MOZ_USER_DIR="Mozilla"
     MOZ_FS_LAYOUT=bundle
     MOZ_WEBGL=1
@@ -4611,7 +4612,8 @@ cairo-uikit)
     TK_LIBS='-framework Foundation -framework CoreFoundation -framework CoreGraphics -framework CoreText'
     CFLAGS="$CFLAGS $TK_CFLAGS"
     CXXFLAGS="$CXXFLAGS $TK_CFLAGS"
-    LIBXUL_LIBS='$(XPCOM_FROZEN_LDOPTS) $(LIBXUL_DIST)/bin/XUL'
+    DYNAMIC_XPCOM_LIBS='$(LIBXUL_DIST)/bin/XUL -lxpcom_core -lmozalloc'
+    XPCOM_FROZEN_LDOPTS='$(LIBXUL_DIST)/bin/XUL -lmozalloc'
     MOZ_USER_DIR="Mozilla"
     MOZ_FS_LAYOUT=bundle
     ;;
diff --git a/mobile/android/installer/package-manifest.in b/mobile/android/installer/package-manifest.in
index 2068dde29680..e35c69795ccf 100644
--- a/mobile/android/installer/package-manifest.in
+++ b/mobile/android/installer/package-manifest.in
@@ -40,7 +40,6 @@
 @BINPATH@/@DLL_PREFIX@plds4@DLL_SUFFIX@
 @BINPATH@/@DLL_PREFIX@nspr4@DLL_SUFFIX@
 #endif
-@BINPATH@/@DLL_PREFIX@xpcom@DLL_SUFFIX@
 @BINPATH@/@DLL_PREFIX@mozalloc@DLL_SUFFIX@
 @BINPATH@/@DLL_PREFIX@mozglue@DLL_SUFFIX@
 @BINPATH@/@DLL_PREFIX@omxplugin@DLL_SUFFIX@
diff --git a/mozglue/android/APKOpen.cpp b/mozglue/android/APKOpen.cpp
index 11ec545c7d23..81bb05cd2c68 100644
--- a/mozglue/android/APKOpen.cpp
+++ b/mozglue/android/APKOpen.cpp
@@ -224,11 +224,9 @@ loadGeckoLibs(const char *apkName)
   file_ids = (char *)extractBuf("lib.id", zip);
 #endif
 
-  char *file = new char[strlen(apkName) + sizeof("!/libxpcom.so")];
-  sprintf(file, "%s!/libxpcom.so", apkName);
-  __wrap_dlopen(file, RTLD_GLOBAL | RTLD_LAZY);
-  // libxul.so is pulled from libxpcom.so, so we don't need to give the full path
-  xul_handle = __wrap_dlopen("libxul.so", RTLD_GLOBAL | RTLD_LAZY);
+  char *file = new char[strlen(apkName) + sizeof("!/libxul.so")];
+  sprintf(file, "%s!/libxul.so", apkName);
+  xul_handle = __wrap_dlopen(file, RTLD_GLOBAL | RTLD_LAZY);
   delete[] file;
 
 #ifdef MOZ_CRASHREPORTER
diff --git a/toolkit/library/Makefile.in b/toolkit/library/Makefile.in
index 11b754aee9cf..ecbacabca4ea 100644
--- a/toolkit/library/Makefile.in
+++ b/toolkit/library/Makefile.in
@@ -689,3 +689,8 @@ ifeq (WINNT_1,$(OS_TARGET)_$(MOZ_PROFILE_USE))
 # Wrap linker to measure peak virtual memory usage.
 LD := $(PYTHON) $(topsrcdir)/build/link.py $(CURDIR)/linker-vsize $(LD)
 endif
+
+libs:: $(FINAL_TARGET)/dependentlibs.list
+
+$(FINAL_TARGET)/dependentlibs.list: dependentlibs.py $(SHARED_LIBRARY) $(wildcard $(if $(wildcard $(FINAL_TARGET)/dependentlibs.list),$(addprefix $(FINAL_TARGET)/,$(shell cat $(FINAL_TARGET)/dependentlibs.list))))
+	$(PYTHON) $< $(SHARED_LIBRARY) -L $(FINAL_TARGET) $(if $(TOOLCHAIN_PREFIX),$(addprefix -p ,$(TOOLCHAIN_PREFIX))) > $@
diff --git a/xpcom/stub/dependentlibs.py b/toolkit/library/dependentlibs.py
similarity index 95%
rename from xpcom/stub/dependentlibs.py
rename to toolkit/library/dependentlibs.py
index 1534b3065706..54e2b86c08c1 100644
--- a/xpcom/stub/dependentlibs.py
+++ b/toolkit/library/dependentlibs.py
@@ -3,7 +3,7 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 '''Given a library, dependentlibs.py prints the list of libraries it depends
-upon that are in the same directory.
+upon that are in the same directory, followed by the library itself.
 '''
 
 from optparse import OptionParser
@@ -92,7 +92,7 @@ def dependentlibs_otool(lib):
 
 def dependentlibs(lib, libpaths, func):
     '''For a given library, returns the list of recursive dependencies that can
-    be found in the given list of paths'''
+    be found in the given list of paths, followed by the library itself.'''
     assert(libpaths)
     assert(isinstance(libpaths, list))
     deps = []
@@ -129,7 +129,7 @@ def main():
     if not options.libpaths:
         options.libpaths = [os.path.dirname(lib)]
 
-    print '\n'.join(dependentlibs(lib, options.libpaths, func))
+    print '\n'.join(dependentlibs(lib, options.libpaths, func) + [lib])
 
 if __name__ == '__main__':
     main()
diff --git a/toolkit/toolkit.mozbuild b/toolkit/toolkit.mozbuild
index d6382addecb7..053c7ccf550f 100644
--- a/toolkit/toolkit.mozbuild
+++ b/toolkit/toolkit.mozbuild
@@ -207,7 +207,6 @@ add_tier_dir('platform', app_libxul_dirs)
 add_tier_dir('platform', app_libxul_static_dirs, static=True)
 
 add_tier_dir('platform', 'toolkit/library')
-add_tier_dir('platform', 'xpcom/stub')
 
 if CONFIG['MOZ_REPLACE_MALLOC']:
     add_tier_dir('platform', 'memory/replace')
diff --git a/xpcom/build/FrozenFunctions.cpp b/xpcom/build/FrozenFunctions.cpp
new file mode 100644
index 000000000000..bf81ae5a0e3e
--- /dev/null
+++ b/xpcom/build/FrozenFunctions.cpp
@@ -0,0 +1,131 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsXPCOM.h"
+#include "nsXPCOMPrivate.h"
+#include "nsXPCOMStrings.h"
+#include "xptcall.h"
+
+#include 
+
+/**
+ * Private Method to register an exit routine.  This method
+ * used to allow you to setup a callback that will be called from 
+ * the NS_ShutdownXPCOM function after all services and 
+ * components have gone away. It was fatally flawed in that the component
+ * DLL could be released before the exit function was called; it is now a
+ * stub implementation that does nothing.
+ */
+XPCOM_API(nsresult)
+NS_RegisterXPCOMExitRoutine(XPCOMExitRoutine exitRoutine, uint32_t priority);
+
+XPCOM_API(nsresult)
+NS_UnregisterXPCOMExitRoutine(XPCOMExitRoutine exitRoutine);
+
+static const XPCOMFunctions kFrozenFunctions = {
+    XPCOM_GLUE_VERSION,
+    sizeof(XPCOMFunctions),
+    &NS_InitXPCOM2,
+    &NS_ShutdownXPCOM,
+    &NS_GetServiceManager,
+    &NS_GetComponentManager,
+    &NS_GetComponentRegistrar,
+    &NS_GetMemoryManager,
+    &NS_NewLocalFile,
+    &NS_NewNativeLocalFile,
+    &NS_RegisterXPCOMExitRoutine,
+    &NS_UnregisterXPCOMExitRoutine,
+
+    // these functions were added post 1.4
+    &NS_GetDebug,
+    &NS_GetTraceRefcnt,
+
+    // these functions were added post 1.6
+    &NS_StringContainerInit,
+    &NS_StringContainerFinish,
+    &NS_StringGetData,
+    &NS_StringSetData,
+    &NS_StringSetDataRange,
+    &NS_StringCopy,
+    &NS_CStringContainerInit,
+    &NS_CStringContainerFinish,
+    &NS_CStringGetData,
+    &NS_CStringSetData,
+    &NS_CStringSetDataRange,
+    &NS_CStringCopy,
+    &NS_CStringToUTF16,
+    &NS_UTF16ToCString,
+    &NS_StringCloneData,
+    &NS_CStringCloneData,
+
+    // these functions were added post 1.7 (post Firefox 1.0)
+    &NS_Alloc,
+    &NS_Realloc,
+    &NS_Free,
+    &NS_StringContainerInit2,
+    &NS_CStringContainerInit2,
+    &NS_StringGetMutableData,
+    &NS_CStringGetMutableData,
+    NULL,
+
+    // these functions were added post 1.8
+    &NS_DebugBreak,
+    &NS_LogInit,
+    &NS_LogTerm,
+    &NS_LogAddRef,
+    &NS_LogRelease,
+    &NS_LogCtor,
+    &NS_LogDtor,
+    &NS_LogCOMPtrAddRef,
+    &NS_LogCOMPtrRelease,
+    &NS_GetXPTCallStub,
+    &NS_DestroyXPTCallStub,
+    &NS_InvokeByIndex,
+    nullptr,
+    nullptr,
+    &NS_StringSetIsVoid,
+    &NS_StringGetIsVoid,
+    &NS_CStringSetIsVoid,
+    &NS_CStringGetIsVoid,
+
+    // these functions were added post 1.9
+    &NS_CycleCollectorSuspect2,
+    &NS_CycleCollectorForget2
+};
+
+EXPORT_XPCOM_API(nsresult)
+NS_GetFrozenFunctions(XPCOMFunctions *functions, const char* /* libraryPath */)
+{
+    if (!functions)
+        return NS_ERROR_OUT_OF_MEMORY;
+
+    if (functions->version != XPCOM_GLUE_VERSION)
+        return NS_ERROR_FAILURE;
+
+    uint32_t size = functions->size;
+    if (size > sizeof(XPCOMFunctions))
+        size = sizeof(XPCOMFunctions);
+
+    size -= offsetof(XPCOMFunctions, init);
+
+    memcpy(&functions->init, &kFrozenFunctions.init, size);
+
+    return NS_OK;
+}
+
+/*
+ * Stubs for nsXPCOMPrivate.h
+ */
+
+EXPORT_XPCOM_API(nsresult)
+NS_RegisterXPCOMExitRoutine(XPCOMExitRoutine exitRoutine, uint32_t priority)
+{
+  return NS_OK;
+}
+
+EXPORT_XPCOM_API(nsresult)
+NS_UnregisterXPCOMExitRoutine(XPCOMExitRoutine exitRoutine)
+{
+  return NS_OK;
+}
diff --git a/xpcom/build/Makefile.in b/xpcom/build/Makefile.in
index 6cbcbbe859dc..38a12c8c95a9 100644
--- a/xpcom/build/Makefile.in
+++ b/xpcom/build/Makefile.in
@@ -37,6 +37,7 @@ CPPSRCS = \
   Services.cpp \
   Omnijar.cpp \
   FileLocation.cpp \
+  FrozenFunctions.cpp \
   $(NULL)
 
 ifeq (Darwin, $(OS_ARCH))
diff --git a/xpcom/build/nsXPCOM.h b/xpcom/build/nsXPCOM.h
index 1c1965aa914d..badd7762cbce 100644
--- a/xpcom/build/nsXPCOM.h
+++ b/xpcom/build/nsXPCOM.h
@@ -6,34 +6,6 @@
 #ifndef nsXPCOM_h__
 #define nsXPCOM_h__
 
-/* Map frozen functions to private symbol names if not using strict API. */
-#ifdef MOZILLA_INTERNAL_API
-# define NS_InitXPCOM2               NS_InitXPCOM2_P
-# define NS_ShutdownXPCOM            NS_ShutdownXPCOM_P
-# define NS_GetServiceManager        NS_GetServiceManager_P
-# define NS_GetComponentManager      NS_GetComponentManager_P
-# define NS_GetComponentRegistrar    NS_GetComponentRegistrar_P
-# define NS_GetMemoryManager         NS_GetMemoryManager_P
-# define NS_NewLocalFile             NS_NewLocalFile_P
-# define NS_NewNativeLocalFile       NS_NewNativeLocalFile_P
-# define NS_GetDebug                 NS_GetDebug_P
-# define NS_GetTraceRefcnt           NS_GetTraceRefcnt_P
-# define NS_Alloc                    NS_Alloc_P
-# define NS_Realloc                  NS_Realloc_P
-# define NS_Free                     NS_Free_P
-# define NS_DebugBreak               NS_DebugBreak_P
-# define NS_LogInit                  NS_LogInit_P
-# define NS_LogTerm                  NS_LogTerm_P
-# define NS_LogAddRef                NS_LogAddRef_P
-# define NS_LogRelease               NS_LogRelease_P
-# define NS_LogCtor                  NS_LogCtor_P
-# define NS_LogDtor                  NS_LogDtor_P
-# define NS_LogCOMPtrAddRef          NS_LogCOMPtrAddRef_P
-# define NS_LogCOMPtrRelease         NS_LogCOMPtrRelease_P
-# define NS_CycleCollectorSuspect2   NS_CycleCollectorSuspect2_P
-# define NS_CycleCollectorForget2    NS_CycleCollectorForget2_P
-#endif
-
 #include "nscore.h"
 #include "nsXPCOMCID.h"
 
diff --git a/xpcom/build/nsXPCOMPrivate.h b/xpcom/build/nsXPCOMPrivate.h
index e449e2ee5c21..9688f29efd41 100644
--- a/xpcom/build/nsXPCOMPrivate.h
+++ b/xpcom/build/nsXPCOMPrivate.h
@@ -217,15 +217,15 @@ void LogTerm();
 #define XPCOM_SEARCH_KEY  "PATH"
 #define GRE_CONF_NAME     "gre.config"
 #define GRE_WIN_REG_LOC   L"Software\\mozilla.org\\GRE"
-#define XPCOM_DLL         "xpcom.dll"
-#define LXPCOM_DLL        L"xpcom.dll"
+#define XPCOM_DLL         XUL_DLL
+#define LXPCOM_DLL        LXUL_DLL
 #define XUL_DLL           "xul.dll"
 #define LXUL_DLL          L"xul.dll"
 
 #else // Unix
 #include  // for PATH_MAX
 
-#define XPCOM_DLL "libxpcom" MOZ_DLL_SUFFIX
+#define XPCOM_DLL         XUL_DLL
 
 // you have to love apple..
 #ifdef XP_MACOSX  
diff --git a/xpcom/glue/nsCycleCollectorUtils.h b/xpcom/glue/nsCycleCollectorUtils.h
index a7185df3dd5f..1430e0405f9e 100644
--- a/xpcom/glue/nsCycleCollectorUtils.h
+++ b/xpcom/glue/nsCycleCollectorUtils.h
@@ -9,7 +9,6 @@
 #include "mozilla/threads/nsThreadIDs.h"
 
 #if defined(MOZILLA_INTERNAL_API)
-#define NS_IsCycleCollectorThread NS_IsCycleCollectorThread_P
 #if defined(XP_WIN)
 bool NS_IsCycleCollectorThread();
 #elif defined(NS_TLS)
diff --git a/xpcom/glue/nsThreadUtils.h b/xpcom/glue/nsThreadUtils.h
index 7ad8409f8711..dca86eae2e8c 100644
--- a/xpcom/glue/nsThreadUtils.h
+++ b/xpcom/glue/nsThreadUtils.h
@@ -19,23 +19,6 @@
 #include "mozilla/threads/nsThreadIDs.h"
 #include "mozilla/Likely.h"
 
-// This is needed on some systems to prevent collisions between the symbols
-// appearing in xpcom_core and xpcomglue.  It may be unnecessary in the future
-// with better toolchain support.
-#ifdef MOZILLA_INTERNAL_API
-# define NS_SetThreadName NS_SetThreadName_P
-# define NS_NewThread NS_NewThread_P
-# define NS_NewNamedThread NS_NewNamedThread_P
-# define NS_GetCurrentThread NS_GetCurrentThread_P
-# define NS_GetMainThread NS_GetMainThread_P
-# define NS_IsMainThread NS_IsMainThread_P
-# define NS_DispatchToCurrentThread NS_DispatchToCurrentThread_P
-# define NS_DispatchToMainThread NS_DispatchToMainThread_P
-# define NS_ProcessPendingEvents NS_ProcessPendingEvents_P
-# define NS_HasPendingEvents NS_HasPendingEvents_P
-# define NS_ProcessNextEvent NS_ProcessNextEvent_P
-#endif
-
 //-----------------------------------------------------------------------------
 // These methods are alternatives to the methods on nsIThreadManager, provided
 // for convenience.
diff --git a/xpcom/glue/standalone/Makefile.in b/xpcom/glue/standalone/Makefile.in
index ea6fb4c66ee3..d9cfc9303d90 100644
--- a/xpcom/glue/standalone/Makefile.in
+++ b/xpcom/glue/standalone/Makefile.in
@@ -20,29 +20,6 @@ LOCAL_INCLUDES	= \
 	-I$(srcdir)/../../build \
 	$(NULL)
 
-ifeq (Darwin,$(OS_ARCH))
-ifeq (uikit,$(MOZ_WIDGET_TOOLKIT))
-LINKSRC = nsGlueLinkingDlopen.cpp
-else
-LINKSRC = nsGlueLinkingOSX.cpp
-endif
-endif
-
-ifeq ($(OS_ARCH),WINNT)
-LINKSRC = nsGlueLinkingWin.cpp
-endif
-ifneq (,$(filter AIX DragonFly FreeBSD GNU GNU_% Linux NetBSD OpenBSD SunOS,$(OS_ARCH)))
-LINKSRC = nsGlueLinkingDlopen.cpp
-endif
-ifeq (OS2,$(OS_ARCH))
-LINKSRC = nsGlueLinkingOS2.cpp
-endif
-
-ifndef LINKSRC
-LINKSRC = nsGlueLinkingNull.cpp
-$(warning TinderboxPrint:Error: XPCOM Glue)
-endif
-
 CPPSRCS		= \
 	$(XPCOM_GLUE_SRC_LCPPSRCS)   \
 	nsStringAPI.cpp              \
diff --git a/xpcom/glue/standalone/nsGlueLinking.h b/xpcom/glue/standalone/nsGlueLinking.h
deleted file mode 100644
index fce14d6c812a..000000000000
--- a/xpcom/glue/standalone/nsGlueLinking.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef nsGlueLinking_h__
-#define nsGlueLinking_h__
-
-#include "nsXPCOMPrivate.h"
-
-#define XPCOM_DEPENDENT_LIBS_LIST "dependentlibs.list"
-
-NS_HIDDEN_(nsresult)
-XPCOMGlueLoad(const char *xpcomFile, GetFrozenFunctionsFunc *func);
-
-NS_HIDDEN_(void)
-XPCOMGlueUnload();
-
-typedef void (*DependentLibsCallback)(const char *aDependentLib, bool do_preload);
-
-NS_HIDDEN_(void)
-XPCOMGlueLoadDependentLibs(const char *xpcomDir, DependentLibsCallback cb);
-
-#endif // nsGlueLinking_h__
diff --git a/xpcom/glue/standalone/nsGlueLinkingDlopen.cpp b/xpcom/glue/standalone/nsGlueLinkingDlopen.cpp
deleted file mode 100644
index 9e436f1c4dad..000000000000
--- a/xpcom/glue/standalone/nsGlueLinkingDlopen.cpp
+++ /dev/null
@@ -1,248 +0,0 @@
-/* -*- Mode: C++; tab-width: 6; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsGlueLinking.h"
-#include "nsXPCOMGlue.h"
-#include "nscore.h"
-#include "mozilla/FileUtils.h"
-
-#if defined(LINUX) && !defined(ANDROID)
-#define _GNU_SOURCE
-#include 
-#include 
-#include 
-#endif
-
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#if defined(SUNOS4) || defined(NEXTSTEP) || \
-    (defined(OPENBSD) || defined(NETBSD)) && !defined(__ELF__)
-#define LEADING_UNDERSCORE "_"
-#else
-#define LEADING_UNDERSCORE
-#endif
-
-#if defined(MOZ_LINKER) && !defined(ANDROID)
-extern "C" {
-NS_HIDDEN __typeof(dlopen) __wrap_dlopen;
-NS_HIDDEN __typeof(dlsym) __wrap_dlsym;
-NS_HIDDEN __typeof(dlclose) __wrap_dlclose;
-}
-
-#define dlopen __wrap_dlopen
-#define dlsym __wrap_dlsym
-#define dlclose __wrap_dlclose
-#endif
-
-#ifdef NS_TRACE_MALLOC
-extern "C" {
-NS_EXPORT_(__ptr_t) __libc_malloc(size_t);
-NS_EXPORT_(__ptr_t) __libc_calloc(size_t, size_t);
-NS_EXPORT_(__ptr_t) __libc_realloc(__ptr_t, size_t);
-NS_EXPORT_(void)    __libc_free(__ptr_t);
-NS_EXPORT_(__ptr_t) __libc_memalign(size_t, size_t);
-NS_EXPORT_(__ptr_t) __libc_valloc(size_t);
-}
-
-static __ptr_t (*_malloc)(size_t) = __libc_malloc;
-static __ptr_t (*_calloc)(size_t, size_t) = __libc_calloc;
-static __ptr_t (*_realloc)(__ptr_t, size_t) = __libc_realloc;
-static void (*_free)(__ptr_t) = __libc_free;
-static __ptr_t (*_memalign)(size_t, size_t) = __libc_memalign;
-static __ptr_t (*_valloc)(size_t) = __libc_valloc;
-
-NS_EXPORT_(__ptr_t) malloc(size_t size)
-{
-    return _malloc(size);
-}
-
-NS_EXPORT_(__ptr_t) calloc(size_t nmemb, size_t size)
-{
-    return _calloc(nmemb, size);
-}
-
-NS_EXPORT_(__ptr_t) realloc(__ptr_t ptr, size_t size)
-{
-    return _realloc(ptr, size);
-}
-
-NS_EXPORT_(void) free(__ptr_t ptr)
-{
-    _free(ptr);
-}
-
-NS_EXPORT_(void) cfree(__ptr_t ptr)
-{
-    _free(ptr);
-}
-
-NS_EXPORT_(__ptr_t) memalign(size_t boundary, size_t size)
-{
-    return _memalign(boundary, size);
-}
-
-NS_EXPORT_(int)
-posix_memalign(void **memptr, size_t alignment, size_t size)
-{
-    __ptr_t ptr = _memalign(alignment, size);
-    if (!ptr)
-        return ENOMEM;
-    *memptr = ptr;
-    return 0;
-}
-
-NS_EXPORT_(__ptr_t) valloc(size_t size)
-{
-    return _valloc(size);
-}
-#endif /* NS_TRACE_MALLOC */
-
-struct DependentLib
-{
-    void         *libHandle;
-    DependentLib *next;
-};
-
-static DependentLib *sTop;
-static void* sXULLibHandle;
-
-static void
-AppendDependentLib(void *libHandle)
-{
-    DependentLib *d = new DependentLib;
-    if (!d)
-        return;
-
-    d->next = sTop;
-    d->libHandle = libHandle;
-
-    sTop = d;
-}
-
-static void
-ReadDependentCB(const char *aDependentLib, bool do_preload)
-{
-#if defined(LINUX) && !defined(ANDROID)
-    if (do_preload)
-        mozilla::ReadAheadLib(aDependentLib);
-#endif
-    void *libHandle = dlopen(aDependentLib, RTLD_GLOBAL | RTLD_LAZY);
-    if (!libHandle)
-        return;
-
-    AppendDependentLib(libHandle);
-}
-
-nsresult
-XPCOMGlueLoad(const char *xpcomFile, GetFrozenFunctionsFunc *func)
-{
-    char xpcomDir[MAXPATHLEN];
-    if (realpath(xpcomFile, xpcomDir)) {
-        char *lastSlash = strrchr(xpcomDir, '/');
-        if (lastSlash) {
-            *lastSlash = '\0';
-
-            XPCOMGlueLoadDependentLibs(xpcomDir, ReadDependentCB);
-
-#ifdef __GLIBC__
-            // XUL_DLL is already loaded by XPCOMGlueLoadDependentLibs, so
-            // dlopening without the full path will return that one.
-            sXULLibHandle = dlopen(XUL_DLL, RTLD_GLOBAL | RTLD_LAZY);
-#else
-            snprintf(lastSlash, MAXPATHLEN - strlen(xpcomDir), "/" XUL_DLL);
-
-            sXULLibHandle = dlopen(xpcomDir, RTLD_GLOBAL | RTLD_LAZY);
-#endif
-
-#ifdef NS_TRACE_MALLOC
-            _malloc = (__ptr_t(*)(size_t)) dlsym(sXULLibHandle, "malloc");
-            _calloc = (__ptr_t(*)(size_t, size_t)) dlsym(sXULLibHandle, "calloc");
-            _realloc = (__ptr_t(*)(__ptr_t, size_t)) dlsym(sXULLibHandle, "realloc");
-            _free = (void(*)(__ptr_t)) dlsym(sXULLibHandle, "free");
-            _memalign = (__ptr_t(*)(size_t, size_t)) dlsym(sXULLibHandle, "memalign");
-            _valloc = (__ptr_t(*)(size_t)) dlsym(sXULLibHandle, "valloc");
-#endif
-        }
-    }
-
-    // RTLD_DEFAULT is not defined in non-GNU toolchains, and it is
-    // (void*) 0 in any case.
-
-    void *libHandle = nullptr;
-
-    if (xpcomFile[0] != '.' || xpcomFile[1] != '\0') {
-        libHandle = dlopen(xpcomFile, RTLD_GLOBAL | RTLD_LAZY);
-        if (libHandle) {
-            AppendDependentLib(libHandle);
-        } else {
-            fprintf(stderr, "XPCOMGlueLoad error for file %s:\n%s\n", xpcomFile,
-                    dlerror());
-        }
-    }
-
-    GetFrozenFunctionsFunc sym =
-        (GetFrozenFunctionsFunc) dlsym(libHandle,
-                                       LEADING_UNDERSCORE "NS_GetFrozenFunctions");
-
-    if (!sym) { // No symbol found.
-        XPCOMGlueUnload();
-        return NS_ERROR_NOT_AVAILABLE;
-    }
-
-    *func = sym;
-
-    return NS_OK;
-}
-
-void
-XPCOMGlueUnload()
-{
-    while (sTop) {
-        dlclose(sTop->libHandle);
-
-        DependentLib *temp = sTop;
-        sTop = sTop->next;
-
-        delete temp;
-    }
-
-    if (sXULLibHandle) {
-#ifdef NS_TRACE_MALLOC
-        _malloc = __libc_malloc;
-        _calloc = __libc_calloc;
-        _realloc = __libc_realloc;
-        _free = __libc_free;
-        _memalign = __libc_memalign;
-        _valloc = __libc_valloc;
-#endif
-        dlclose(sXULLibHandle);
-        sXULLibHandle = nullptr;
-    }
-}
-
-nsresult
-XPCOMGlueLoadXULFunctions(const nsDynamicFunctionLoad *symbols)
-{
-    // We don't null-check sXULLibHandle because this might work even
-    // if it is null (same as RTLD_DEFAULT)
-
-    nsresult rv = NS_OK;
-    while (symbols->functionName) {
-        char buffer[512];
-        snprintf(buffer, sizeof(buffer),
-                 LEADING_UNDERSCORE "%s", symbols->functionName);
-
-        *symbols->function = (NSFuncPtr) dlsym(sXULLibHandle, buffer);
-        if (!*symbols->function)
-            rv = NS_ERROR_LOSS_OF_SIGNIFICANT_DATA;
-
-        ++symbols;
-    }
-    return rv;
-}
diff --git a/xpcom/glue/standalone/nsGlueLinkingNull.cpp b/xpcom/glue/standalone/nsGlueLinkingNull.cpp
deleted file mode 100644
index e1043986c9a8..000000000000
--- a/xpcom/glue/standalone/nsGlueLinkingNull.cpp
+++ /dev/null
@@ -1,23 +0,0 @@
-/* -*- Mode: C++; tab-width: 6; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsGlueLinking.h"
-
-#include 
-
-nsresult
-XPCOMGlueLoad(const char *xpcomFile, GetFrozenFunctionsFunc *func)
-{
-    fprintf(stderr, "XPCOM glue dynamic linking is not implemented on this platform!");
-
-    *func = nullptr;
-
-    return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-void
-XPCOMGlueUnload()
-{
-}
diff --git a/xpcom/glue/standalone/nsGlueLinkingOS2.cpp b/xpcom/glue/standalone/nsGlueLinkingOS2.cpp
deleted file mode 100644
index e2ae976a4d0c..000000000000
--- a/xpcom/glue/standalone/nsGlueLinkingOS2.cpp
+++ /dev/null
@@ -1,156 +0,0 @@
-/* -*- Mode: C++; tab-width: 6; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsGlueLinking.h"
-#include "nsXPCOMGlue.h"
-
-#define INCL_DOS
-#define INCL_DOSERRORS
-#include 
-#include 
-#include 
-
-struct DependentLib
-{
-    HMODULE     libHandle;
-    DependentLib *next;
-};
-
-static DependentLib *sTop;
-HMODULE sXULLibrary = NULLHANDLE;
-
-static void
-AppendDependentLib(HMODULE libHandle)
-{
-    DependentLib *d = new DependentLib;
-    if (!d)
-        return;
-
-    d->next = sTop;
-    d->libHandle = libHandle;
-
-    sTop = d;
-}
-
-static void
-ReadDependentCB(const char *aDependentLib, bool do_preload)
-{
-    CHAR pszError[_MAX_PATH];
-    ULONG ulrc = NO_ERROR;
-    HMODULE h;
-
-    ulrc = DosLoadModule(pszError, _MAX_PATH, aDependentLib, &h);
-
-    if (ulrc != NO_ERROR)
-        return;
-
-    AppendDependentLib(h);
-}
-
-// like strpbrk but finds the *last* char, not the first
-static char*
-ns_strrpbrk(char *string, const char *strCharSet)
-{
-    char *found = NULL;
-    for (; *string; ++string) {
-        for (const char *search = strCharSet; *search; ++search) {
-            if (*search == *string) {
-                found = string;
-                // Since we're looking for the last char, we save "found"
-                // until we're at the end of the string.
-            }
-        }
-    }
-
-    return found;
-}
-
-nsresult
-XPCOMGlueLoad(const char *xpcomFile, GetFrozenFunctionsFunc *func)
-{
-    CHAR pszError[_MAX_PATH];
-    ULONG ulrc = NO_ERROR;
-    HMODULE h;
-
-    if (xpcomFile[0] == '.' && xpcomFile[1] == '\0') {
-        xpcomFile = XPCOM_DLL;
-    }
-    else {
-        char xpcomDir[MAXPATHLEN];
-
-        _fullpath(xpcomDir, xpcomFile, sizeof(xpcomDir));
-        char *lastSlash = ns_strrpbrk(xpcomDir, "/\\");
-        if (lastSlash) {
-            *lastSlash = '\0';
-
-            XPCOMGlueLoadDependentLibs(xpcomDir, ReadDependentCB);
-
-            snprintf(lastSlash, MAXPATHLEN - strlen(xpcomDir), "\\" XUL_DLL);
-
-            DosLoadModule(pszError, _MAX_PATH, xpcomDir, &sXULLibrary);
-        }
-    }
-
-    ulrc = DosLoadModule(pszError, _MAX_PATH, xpcomFile, &h);
-
-    if (ulrc != NO_ERROR)
-        return nullptr;
-
-    AppendDependentLib(h);
-
-    GetFrozenFunctionsFunc sym;
-
-    ulrc = DosQueryProcAddr(h, 0, "_NS_GetFrozenFunctions", (PFN*)&sym);
-
-    if (ulrc != NO_ERROR) {
-        XPCOMGlueUnload();
-        return NS_ERROR_NOT_AVAILABLE;
-    }
-
-    *func = sym;
-
-    return NS_OK;
-}
-
-void
-XPCOMGlueUnload()
-{
-    while (sTop) {
-        DosFreeModule(sTop->libHandle);
-
-        DependentLib *temp = sTop;
-        sTop = sTop->next;
-
-        delete temp;
-    }
-
-    if (sXULLibrary) {
-        DosFreeModule(sXULLibrary);
-        sXULLibrary = nullptr;
-    }
-}
-
-nsresult
-XPCOMGlueLoadXULFunctions(const nsDynamicFunctionLoad *symbols)
-{
-    ULONG ulrc = NO_ERROR;
-
-    if (!sXULLibrary)
-        return NS_ERROR_NOT_INITIALIZED;
-
-    nsresult rv = NS_OK;
-    while (symbols->functionName) {
-        char buffer[512];
-        snprintf(buffer, sizeof(buffer), "_%s", symbols->functionName);
-        ulrc = DosQueryProcAddr(sXULLibrary, 0, buffer, (PFN*)symbols->function);
-
-        if (ulrc != NO_ERROR)
-            rv = NS_ERROR_LOSS_OF_SIGNIFICANT_DATA;
-
-        ++symbols;
-    }
-
-    return rv;
-}
diff --git a/xpcom/glue/standalone/nsGlueLinkingOSX.cpp b/xpcom/glue/standalone/nsGlueLinkingOSX.cpp
deleted file mode 100644
index 1b75a5f9bb9d..000000000000
--- a/xpcom/glue/standalone/nsGlueLinkingOSX.cpp
+++ /dev/null
@@ -1,124 +0,0 @@
-/* -*- Mode: C++; tab-width: 6; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsGlueLinking.h"
-#include "nsXPCOMGlue.h"
-#include "mozilla/FileUtils.h"
-
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include 
-#include 
-#include 
-#include 
-#include 
-
-static const mach_header* sXULLibImage;
-
-static void
-ReadDependentCB(const char *aDependentLib, bool do_preload)
-{
-    if (do_preload)
-        mozilla::ReadAheadLib(aDependentLib);
-    (void) NSAddImage(aDependentLib,
-                      NSADDIMAGE_OPTION_RETURN_ON_ERROR |
-                      NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME);
-}
-
-static void*
-LookupSymbol(const mach_header* aLib, const char* aSymbolName)
-{
-    // Try to use |NSLookupSymbolInImage| since it is faster than searching
-    // the global symbol table.  If we couldn't get a mach_header pointer
-    // for the XPCOM dylib, then use |NSLookupAndBindSymbol| to search the
-    // global symbol table (this shouldn't normally happen, unless the user
-    // has called XPCOMGlueStartup(".") and relies on libxpcom.dylib
-    // already being loaded).
-    NSSymbol sym = nullptr;
-    if (aLib) {
-        sym = NSLookupSymbolInImage(aLib, aSymbolName,
-                                 NSLOOKUPSYMBOLINIMAGE_OPTION_BIND |
-                                 NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR);
-    } else {
-        if (NSIsSymbolNameDefined(aSymbolName))
-            sym = NSLookupAndBindSymbol(aSymbolName);
-    }
-    if (!sym)
-        return nullptr;
-
-    return NSAddressOfSymbol(sym);
-}
-
-nsresult
-XPCOMGlueLoad(const char *xpcomFile, GetFrozenFunctionsFunc *func)
-{
-    const mach_header* lib = nullptr;
-
-    if (xpcomFile[0] != '.' || xpcomFile[1] != '\0') {
-        char xpcomDir[PATH_MAX];
-        if (realpath(xpcomFile, xpcomDir)) {
-            char *lastSlash = strrchr(xpcomDir, '/');
-            if (lastSlash) {
-                *lastSlash = '\0';
-
-                XPCOMGlueLoadDependentLibs(xpcomDir, ReadDependentCB);
-
-                snprintf(lastSlash, PATH_MAX - strlen(xpcomDir), "/" XUL_DLL);
-
-                sXULLibImage = NSAddImage(xpcomDir,
-                              NSADDIMAGE_OPTION_RETURN_ON_ERROR |
-                              NSADDIMAGE_OPTION_WITH_SEARCHING |
-                              NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME);
-            }
-        }
-
-        lib = NSAddImage(xpcomFile,
-                         NSADDIMAGE_OPTION_RETURN_ON_ERROR |
-                         NSADDIMAGE_OPTION_WITH_SEARCHING |
-                         NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME);
-
-        if (!lib) {
-            NSLinkEditErrors linkEditError;
-            int errorNum;
-            const char *errorString;
-            const char *fileName;
-            NSLinkEditError(&linkEditError, &errorNum, &fileName, &errorString);
-            fprintf(stderr, "XPCOMGlueLoad error %d:%d for file %s:\n%s\n",
-                    linkEditError, errorNum, fileName, errorString);
-        }
-    }
-
-    *func = (GetFrozenFunctionsFunc) LookupSymbol(lib, "_NS_GetFrozenFunctions");
-
-    return *func ? NS_OK : NS_ERROR_NOT_AVAILABLE;
-}
-
-void
-XPCOMGlueUnload()
-{
-  // nothing to do, since we cannot unload dylibs on OS X
-}
-
-nsresult
-XPCOMGlueLoadXULFunctions(const nsDynamicFunctionLoad *symbols)
-{
-    nsresult rv = NS_OK;
-    while (symbols->functionName) {
-        char buffer[512];
-        snprintf(buffer, sizeof(buffer), "_%s", symbols->functionName);
-
-        *symbols->function = (NSFuncPtr) LookupSymbol(sXULLibImage, buffer);
-        if (!*symbols->function)
-            rv = NS_ERROR_LOSS_OF_SIGNIFICANT_DATA;
-
-        ++symbols;
-    }
-
-    return rv;
-}
diff --git a/xpcom/glue/standalone/nsGlueLinkingWin.cpp b/xpcom/glue/standalone/nsGlueLinkingWin.cpp
deleted file mode 100644
index 55537d041463..000000000000
--- a/xpcom/glue/standalone/nsGlueLinkingWin.cpp
+++ /dev/null
@@ -1,216 +0,0 @@
-/* -*- Mode: C++; tab-width: 6; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsGlueLinking.h"
-#include "nsXPCOMGlue.h"
-#include "mozilla/FileUtils.h"
-
-#include "nsStringAPI.h"
-#include 
-#include 
-#include 
-#include 
-
-#define MOZ_LOADLIBRARY_FLAGS LOAD_WITH_ALTERED_SEARCH_PATH
-
-struct DependentLib
-{
-    HINSTANCE     libHandle;
-    DependentLib *next;
-};
-
-static DependentLib *sTop;
-HINSTANCE sXULLibrary;
-
-static void
-AppendDependentLib(HINSTANCE libHandle)
-{
-    DependentLib *d = new DependentLib;
-    if (!d)
-        return;
-
-    d->next = sTop;
-    d->libHandle = libHandle;
-
-    sTop = d;
-}
-
-static void
-ReadDependentCB(const char *aDependentLib, bool do_preload)
-{
-    wchar_t wideDependentLib[MAX_PATH];
-    MultiByteToWideChar(CP_UTF8, 0, aDependentLib, -1, wideDependentLib, MAX_PATH);
-
-    if (do_preload)
-        mozilla::ReadAheadLib(wideDependentLib);
-
-    HINSTANCE h =
-        LoadLibraryExW(wideDependentLib, NULL, MOZ_LOADLIBRARY_FLAGS);
-
-    if (!h)
-        return;
-
-    AppendDependentLib(h);
-}
-
-// like strpbrk but finds the *last* char, not the first
-static wchar_t*
-ns_wcspbrk(wchar_t *string, const wchar_t *strCharSet)
-{
-    wchar_t *found = NULL;
-    for (; *string; ++string) {
-        for (const wchar_t *search = strCharSet; *search; ++search) {
-            if (*search == *string) {
-                found = string;
-                // Since we're looking for the last char, we save "found"
-                // until we're at the end of the string.
-            }
-        }
-    }
-
-    return found;
-}
-
-bool ns_isRelPath(wchar_t* path)
-{
-    return !(path[1] == ':');
-}
-
-nsresult
-XPCOMGlueLoad(const char *aXpcomFile, GetFrozenFunctionsFunc *func)
-{
-    wchar_t xpcomFile[MAXPATHLEN];
-    MultiByteToWideChar(CP_UTF8, 0, aXpcomFile,-1,
-                        xpcomFile, MAXPATHLEN);
-   
-    
-    if (xpcomFile[0] == '.' && xpcomFile[1] == '\0') {
-        wcscpy(xpcomFile, LXPCOM_DLL);
-    }
-    else {
-        wchar_t xpcomDir[MAXPATHLEN];
-        
-        if (ns_isRelPath(xpcomFile))
-        {
-            _wfullpath(xpcomDir, xpcomFile, sizeof(xpcomDir)/sizeof(wchar_t));
-        } 
-        else 
-        {
-            wcscpy(xpcomDir, xpcomFile);
-        }
-        wchar_t *lastSlash = ns_wcspbrk(xpcomDir, L"/\\");
-        if (lastSlash) {
-            *lastSlash = '\0';
-            char xpcomDir_narrow[MAXPATHLEN];
-            WideCharToMultiByte(CP_UTF8, 0, xpcomDir,-1,
-                                xpcomDir_narrow, MAX_PATH, NULL, NULL);
-
-            XPCOMGlueLoadDependentLibs(xpcomDir_narrow, ReadDependentCB);
-            
-            _snwprintf(lastSlash, MAXPATHLEN - wcslen(xpcomDir), L"\\" LXUL_DLL);
-            sXULLibrary =
-                LoadLibraryExW(xpcomDir, NULL, MOZ_LOADLIBRARY_FLAGS);
-
-            if (!sXULLibrary) 
-            {
-                DWORD err = GetLastError();
-#ifdef DEBUG
-                LPVOID lpMsgBuf;
-                FormatMessage(
-                              FORMAT_MESSAGE_ALLOCATE_BUFFER |
-                              FORMAT_MESSAGE_FROM_SYSTEM |
-                              FORMAT_MESSAGE_IGNORE_INSERTS,
-                              NULL,
-                              GetLastError(),
-                              MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
-                              (LPTSTR) &lpMsgBuf,
-                              0,
-                              NULL
-                              );
-                wprintf(L"Error loading %s: %s\n", xpcomDir, lpMsgBuf);
-                LocalFree(lpMsgBuf);
-#endif //DEBUG
-                return (err == ERROR_NOT_ENOUGH_MEMORY || err == ERROR_OUTOFMEMORY)
-                    ? NS_ERROR_OUT_OF_MEMORY : NS_ERROR_FAILURE;
-            }
-        }
-    }
-    HINSTANCE h =
-        LoadLibraryExW(xpcomFile, NULL, MOZ_LOADLIBRARY_FLAGS);
-
-    if (!h) 
-    {
-        DWORD err = GetLastError();
-#ifdef DEBUG
-        LPVOID lpMsgBuf;
-        FormatMessage(
-                      FORMAT_MESSAGE_ALLOCATE_BUFFER |
-                      FORMAT_MESSAGE_FROM_SYSTEM |
-                      FORMAT_MESSAGE_IGNORE_INSERTS,
-                      NULL,
-                      err,
-                      MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
-                      (LPTSTR) &lpMsgBuf,
-                      0,
-                      NULL
-                      );
-        wprintf(L"Error loading %s: %s\n", xpcomFile, lpMsgBuf);
-        LocalFree(lpMsgBuf);
-#endif        
-        return (err == ERROR_NOT_ENOUGH_MEMORY || err == ERROR_OUTOFMEMORY)
-            ? NS_ERROR_OUT_OF_MEMORY : NS_ERROR_FAILURE;
-    }
-
-    AppendDependentLib(h);
-
-    GetFrozenFunctionsFunc sym =
-        (GetFrozenFunctionsFunc) GetProcAddress(h, "NS_GetFrozenFunctions");
-
-    if (!sym) { // No symbol found.
-        XPCOMGlueUnload();
-        return NS_ERROR_NOT_AVAILABLE;
-    }
-
-    *func = sym;
-
-    return NS_OK;
-}
-
-void
-XPCOMGlueUnload()
-{
-    while (sTop) {
-        FreeLibrary(sTop->libHandle);
-
-        DependentLib *temp = sTop;
-        sTop = sTop->next;
-
-        delete temp;
-    }
-
-    if (sXULLibrary) {
-        FreeLibrary(sXULLibrary);
-        sXULLibrary = nullptr;
-    }
-}
-
-nsresult
-XPCOMGlueLoadXULFunctions(const nsDynamicFunctionLoad *symbols)
-{
-    if (!sXULLibrary)
-        return NS_ERROR_NOT_INITIALIZED;
-
-    nsresult rv = NS_OK;
-    while (symbols->functionName) {
-        *symbols->function = 
-            (NSFuncPtr) GetProcAddress(sXULLibrary, symbols->functionName);
-        if (!*symbols->function)
-            rv = NS_ERROR_LOSS_OF_SIGNIFICANT_DATA;
-
-        ++symbols;
-    }
-
-    return rv;
-}
diff --git a/xpcom/glue/standalone/nsXPCOMGlue.cpp b/xpcom/glue/standalone/nsXPCOMGlue.cpp
index 9087811267dc..087239271a10 100644
--- a/xpcom/glue/standalone/nsXPCOMGlue.cpp
+++ b/xpcom/glue/standalone/nsXPCOMGlue.cpp
@@ -5,7 +5,6 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsXPCOMGlue.h"
-#include "nsGlueLinking.h"
 
 #include "nspr.h"
 #include "nsDebug.h"
@@ -15,46 +14,15 @@
 #include 
 #include 
 
-#ifdef XP_WIN
-#include 
-#include 
-#include 
-#define snprintf _snprintf
-#endif
+#include "mozilla/FileUtils.h"
+
+using namespace mozilla;
+
+#define XPCOM_DEPENDENT_LIBS_LIST "dependentlibs.list"
 
 static XPCOMFunctions xpcomFunctions;
 static bool do_preload = false;
 
-extern "C"
-void XPCOMGlueEnablePreload()
-{
-    do_preload = true;
-}
-
-extern "C"
-nsresult XPCOMGlueStartup(const char* xpcomFile)
-{
-    xpcomFunctions.version = XPCOM_GLUE_VERSION;
-    xpcomFunctions.size    = sizeof(XPCOMFunctions);
-
-    GetFrozenFunctionsFunc func = nullptr;
-
-    if (!xpcomFile)
-        xpcomFile = XPCOM_DLL;
-    
-    nsresult rv = XPCOMGlueLoad(xpcomFile, &func);
-    if (NS_FAILED(rv))
-        return rv;
-
-    rv = (*func)(&xpcomFunctions, nullptr);
-    if (NS_FAILED(rv)) {
-        XPCOMGlueUnload();
-        return rv;
-    }
-
-    return NS_OK;
-}
-
 #if defined(XP_WIN)
 #define READ_TEXTMODE L"rt"
 #elif defined(XP_OS2)
@@ -63,7 +31,294 @@ nsresult XPCOMGlueStartup(const char* xpcomFile)
 #define READ_TEXTMODE "r"
 #endif
 
+#if defined(SUNOS4) || defined(NEXTSTEP) || \
+    defined(XP_DARWIN) || defined(XP_OS2) || \
+    (defined(OPENBSD) || defined(NETBSD)) && !defined(__ELF__)
+#define LEADING_UNDERSCORE "_"
+#else
+#define LEADING_UNDERSCORE
+#endif
+
+#if defined(XP_WIN)
+#include 
+#include 
+#define snprintf _snprintf
+
+typedef HINSTANCE LibHandleType;
+
+static LibHandleType
+GetLibHandle(pathstr_t aDependentLib)
+{
+    LibHandleType libHandle =
+        LoadLibraryExW(aDependentLib, nullptr, LOAD_WITH_ALTERED_SEARCH_PATH);
+
+    if (!libHandle) {
+        DWORD err = GetLastError();
+#ifdef DEBUG
+        LPVOID lpMsgBuf;
+        FormatMessage(
+                      FORMAT_MESSAGE_ALLOCATE_BUFFER |
+                      FORMAT_MESSAGE_FROM_SYSTEM |
+                      FORMAT_MESSAGE_IGNORE_INSERTS,
+                      nullptr,
+                      err,
+                      MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+                      (LPTSTR) &lpMsgBuf,
+                      0,
+                      nullptr
+                      );
+        wprintf(L"Error loading %ls: %s\n", aDependentLib, lpMsgBuf);
+        LocalFree(lpMsgBuf);
+#endif
+    }
+
+    return libHandle;
+}
+
+static NSFuncPtr
+GetSymbol(LibHandleType aLibHandle, const char *aSymbol)
+{
+    return (NSFuncPtr) GetProcAddress(aLibHandle, aSymbol);
+}
+
+static void
+CloseLibHandle(LibHandleType aLibHandle)
+{
+    FreeLibrary(aLibHandle);
+}
+
+#elif defined(XP_OS2)
+#define INCL_DOS
+#define INCL_DOSERRORS
+#include 
+
+typedef HMODULE LibHandleType;
+
+static LibHandleType
+GetLibHandle(pathstr_t aDependentLib)
+{
+    CHAR pszError[_MAX_PATH];
+    ULONG ulrc = NO_ERROR;
+    LibHandleType libHandle;
+    ulrc = DosLoadModule(pszError, _MAX_PATH, aDependentLib, &libHandle);
+    return (ulrc == NO_ERROR) ? libHandle : nullptr;
+}
+
+static NSFuncPtr
+GetSymbol(LibHandleType aLibHandle, const char *aSymbol)
+{
+    ULONG ulrc = NO_ERROR;
+    GetFrozenFunctionsFunc sym;
+    ulrc = DosQueryProcAddr(aLibHandle, 0, aSymbol, (PFN*)&sym);
+    return (ulrc == NO_ERROR) ? sym : nullptr;
+}
+
+static void
+CloseLibHandle(LibHandleType aLibHandle)
+{
+    DosFreeModule(aLibHandle);
+}
+
+#elif defined(XP_MACOSX)
+#include 
+
+typedef const mach_header *LibHandleType;
+
+static LibHandleType
+GetLibHandle(pathstr_t aDependentLib)
+{
+    LibHandleType libHandle = NSAddImage(aDependentLib,
+                                         NSADDIMAGE_OPTION_RETURN_ON_ERROR |
+                                         NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME);
+    if (!libHandle) {
+        NSLinkEditErrors linkEditError;
+        int errorNum;
+        const char *errorString;
+        const char *fileName;
+        NSLinkEditError(&linkEditError, &errorNum, &fileName, &errorString);
+        fprintf(stderr, "XPCOMGlueLoad error %d:%d for file %s:\n%s\n",
+                linkEditError, errorNum, fileName, errorString);
+    }
+    return libHandle;
+}
+
+static NSFuncPtr
+GetSymbol(LibHandleType aLibHandle, const char *aSymbol)
+{
+    // Try to use |NSLookupSymbolInImage| since it is faster than searching
+    // the global symbol table.  If we couldn't get a mach_header pointer
+    // for the XPCOM dylib, then use |NSLookupAndBindSymbol| to search the
+    // global symbol table (this shouldn't normally happen, unless the user
+    // has called XPCOMGlueStartup(".") and relies on libxpcom.dylib
+    // already being loaded).
+    NSSymbol sym = nullptr;
+    if (aLibHandle) {
+        sym = NSLookupSymbolInImage(aLibHandle, aSymbol,
+                                 NSLOOKUPSYMBOLINIMAGE_OPTION_BIND |
+                                 NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR);
+    } else {
+        if (NSIsSymbolNameDefined(aSymbol))
+            sym = NSLookupAndBindSymbol(aSymbol);
+    }
+    if (!sym)
+        return nullptr;
+
+    return (NSFuncPtr) NSAddressOfSymbol(sym);
+}
+
+static void
+CloseLibHandle(LibHandleType aLibHandle)
+{
+    // we cannot unload dylibs on OS X
+}
+
+#else
+#include 
+
+#if defined(MOZ_LINKER) && !defined(ANDROID)
+extern "C" {
+NS_HIDDEN __typeof(dlopen) __wrap_dlopen;
+NS_HIDDEN __typeof(dlsym) __wrap_dlsym;
+NS_HIDDEN __typeof(dlclose) __wrap_dlclose;
+}
+
+#define dlopen __wrap_dlopen
+#define dlsym __wrap_dlsym
+#define dlclose __wrap_dlclose
+#endif
+
+#ifdef NS_TRACE_MALLOC
+extern "C" {
+NS_EXPORT_(__ptr_t) __libc_malloc(size_t);
+NS_EXPORT_(__ptr_t) __libc_calloc(size_t, size_t);
+NS_EXPORT_(__ptr_t) __libc_realloc(__ptr_t, size_t);
+NS_EXPORT_(void)    __libc_free(__ptr_t);
+NS_EXPORT_(__ptr_t) __libc_memalign(size_t, size_t);
+NS_EXPORT_(__ptr_t) __libc_valloc(size_t);
+}
+
+static __ptr_t (*_malloc)(size_t) = __libc_malloc;
+static __ptr_t (*_calloc)(size_t, size_t) = __libc_calloc;
+static __ptr_t (*_realloc)(__ptr_t, size_t) = __libc_realloc;
+static void (*_free)(__ptr_t) = __libc_free;
+static __ptr_t (*_memalign)(size_t, size_t) = __libc_memalign;
+static __ptr_t (*_valloc)(size_t) = __libc_valloc;
+
+NS_EXPORT_(__ptr_t) malloc(size_t size)
+{
+    return _malloc(size);
+}
+
+NS_EXPORT_(__ptr_t) calloc(size_t nmemb, size_t size)
+{
+    return _calloc(nmemb, size);
+}
+
+NS_EXPORT_(__ptr_t) realloc(__ptr_t ptr, size_t size)
+{
+    return _realloc(ptr, size);
+}
+
+NS_EXPORT_(void) free(__ptr_t ptr)
+{
+    _free(ptr);
+}
+
+NS_EXPORT_(void) cfree(__ptr_t ptr)
+{
+    _free(ptr);
+}
+
+NS_EXPORT_(__ptr_t) memalign(size_t boundary, size_t size)
+{
+    return _memalign(boundary, size);
+}
+
+NS_EXPORT_(int)
+posix_memalign(void **memptr, size_t alignment, size_t size)
+{
+    __ptr_t ptr = _memalign(alignment, size);
+    if (!ptr)
+        return ENOMEM;
+    *memptr = ptr;
+    return 0;
+}
+
+NS_EXPORT_(__ptr_t) valloc(size_t size)
+{
+    return _valloc(size);
+}
+#endif /* NS_TRACE_MALLOC */
+
+typedef void *LibHandleType;
+
+static LibHandleType
+GetLibHandle(pathstr_t aDependentLib)
+{
+    LibHandleType libHandle = dlopen(aDependentLib, RTLD_GLOBAL | RTLD_LAZY);
+    if (!libHandle) {
+        fprintf(stderr, "XPCOMGlueLoad error for file %s:\n%s\n", aDependentLib, dlerror());
+    }
+    return libHandle;
+}
+
+static NSFuncPtr
+GetSymbol(LibHandleType aLibHandle, const char *aSymbol)
+{
+    return (NSFuncPtr) dlsym(aLibHandle, aSymbol);
+}
+
+static void
+CloseLibHandle(LibHandleType aLibHandle)
+{
+    dlclose(aLibHandle);
+}
+#endif
+
+struct DependentLib
+{
+    LibHandleType libHandle;
+    DependentLib *next;
+};
+
+static DependentLib *sTop;
+
+static void
+AppendDependentLib(LibHandleType libHandle)
+{
+    DependentLib *d = new DependentLib;
+    if (!d)
+        return;
+
+    d->next = sTop;
+    d->libHandle = libHandle;
+
+    sTop = d;
+}
+
+static bool
+ReadDependentCB(pathstr_t aDependentLib, bool do_preload)
+{
+    if (do_preload) {
+        ReadAheadLib(aDependentLib);
+    }
+    LibHandleType libHandle = GetLibHandle(aDependentLib);
+    if (libHandle) {
+        AppendDependentLib(libHandle);
+    }
+
+    return libHandle;
+}
+
 #ifdef XP_WIN
+static bool
+ReadDependentCB(const char *aDependentLib, bool do_preload)
+{
+    wchar_t wideDependentLib[MAX_PATH];
+    MultiByteToWideChar(CP_UTF8, 0, aDependentLib, -1, wideDependentLib, MAX_PATH);
+    return ReadDependentCB(wideDependentLib, do_preload);
+}
+
 inline FILE *TS_tfopen (const char *path, const wchar_t *mode)
 {
     wchar_t wPath[MAX_PATH];
@@ -77,36 +332,189 @@ inline FILE *TS_tfopen (const char *path, const char *mode)
 }
 #endif
 
-void
-XPCOMGlueLoadDependentLibs(const char *xpcomDir, DependentLibsCallback cb)
+/* RAII wrapper for FILE descriptors */
+struct ScopedCloseFileTraits
 {
-    char buffer[MAXPATHLEN];
-    sprintf(buffer, "%s" XPCOM_FILE_PATH_SEPARATOR XPCOM_DEPENDENT_LIBS_LIST,
-            xpcomDir);
+    typedef FILE *type;
+    static type empty() { return nullptr; }
+    static void release(type f) {
+        if (f) {
+            fclose(f);
+        }
+    }
+};
+typedef Scoped ScopedCloseFile;
 
-    FILE *flist = TS_tfopen(buffer, READ_TEXTMODE);
-    if (!flist)
-        return;
+static void
+XPCOMGlueUnload()
+{
+#if !defined(XP_WIN) && !defined(XP_OS2) && !defined(XP_MACOSX) \
+  && defined(NS_TRACE_MALLOC)
+    if (sTop) {
+        _malloc = __libc_malloc;
+        _calloc = __libc_calloc;
+        _realloc = __libc_realloc;
+        _free = __libc_free;
+        _memalign = __libc_memalign;
+        _valloc = __libc_valloc;
+    }
+#endif
+
+    while (sTop) {
+        CloseLibHandle(sTop->libHandle);
+
+        DependentLib *temp = sTop;
+        sTop = sTop->next;
+
+        delete temp;
+    }
+}
+
+#if defined(XP_WIN) || defined(XP_OS2)
+// like strpbrk but finds the *last* char, not the first
+static const char*
+ns_strrpbrk(const char *string, const char *strCharSet)
+{
+    const char *found = nullptr;
+    for (; *string; ++string) {
+        for (const char *search = strCharSet; *search; ++search) {
+            if (*search == *string) {
+                found = string;
+                // Since we're looking for the last char, we save "found"
+                // until we're at the end of the string.
+            }
+        }
+    }
+
+    return found;
+}
+#endif
+
+static GetFrozenFunctionsFunc
+XPCOMGlueLoad(const char *xpcomFile)
+{
+    char xpcomDir[MAXPATHLEN];
+#if defined(XP_WIN) || defined(XP_OS2)
+    const char *lastSlash = ns_strrpbrk(xpcomFile, "/\\");
+#else
+    const char *lastSlash = strrchr(xpcomFile, '/');
+#endif
+    char *cursor;
+    if (lastSlash) {
+        size_t len = size_t(lastSlash - xpcomFile);
+
+        if (len > MAXPATHLEN - sizeof(XPCOM_FILE_PATH_SEPARATOR
+                                      XPCOM_DEPENDENT_LIBS_LIST)) {
+            return nullptr;
+        }
+        memcpy(xpcomDir, xpcomFile, len);
+        strcpy(xpcomDir + len, XPCOM_FILE_PATH_SEPARATOR
+                               XPCOM_DEPENDENT_LIBS_LIST);
+        cursor = xpcomDir + len + 1;
+    } else {
+        strcpy(xpcomDir, XPCOM_DEPENDENT_LIBS_LIST);
+        cursor = xpcomDir;
+    }
+
+    ScopedCloseFile flist;
+    flist = TS_tfopen(xpcomDir, READ_TEXTMODE);
+    if (!flist) {
+        return nullptr;
+    }
+
+    *cursor = '\0';
+
+    char buffer[MAXPATHLEN];
 
     while (fgets(buffer, sizeof(buffer), flist)) {
         int l = strlen(buffer);
 
         // ignore empty lines and comments
-        if (l == 0 || *buffer == '#')
+        if (l == 0 || *buffer == '#') {
             continue;
+        }
 
         // cut the trailing newline, if present
         if (buffer[l - 1] == '\n')
             buffer[l - 1] = '\0';
 
-        char buffer2[MAXPATHLEN];
-        snprintf(buffer2, sizeof(buffer2),
-                 "%s" XPCOM_FILE_PATH_SEPARATOR "%s",
-                 xpcomDir, buffer);
-        cb(buffer2, do_preload);
+        if (l + size_t(cursor - xpcomDir) > MAXPATHLEN) {
+            return nullptr;
+        }
+
+        strcpy(cursor, buffer);
+        if (!ReadDependentCB(xpcomDir, do_preload)) {
+            XPCOMGlueUnload();
+            return nullptr;
+        }
     }
 
-    fclose(flist);
+    GetFrozenFunctionsFunc sym =
+        (GetFrozenFunctionsFunc) GetSymbol(sTop->libHandle, LEADING_UNDERSCORE "NS_GetFrozenFunctions");
+
+    if (!sym) { // No symbol found.
+        XPCOMGlueUnload();
+        return nullptr;
+    }
+
+#if !defined(XP_WIN) && !defined(XP_OS2) && !defined(XP_MACOSX) \
+  && defined(NS_TRACE_MALLOC)
+    _malloc = (__ptr_t(*)(size_t)) GetSymbol(sTop->libHandle, "malloc");
+    _calloc = (__ptr_t(*)(size_t, size_t)) GetSymbol(sTop->libHandle, "calloc");
+    _realloc = (__ptr_t(*)(__ptr_t, size_t)) GetSymbol(sTop->libHandle, "realloc");
+    _free = (void(*)(__ptr_t)) GetSymbol(sTop->libHandle, "free");
+    _memalign = (__ptr_t(*)(size_t, size_t)) GetSymbol(sTop->libHandle, "memalign");
+    _valloc = (__ptr_t(*)(size_t)) GetSymbol(sTop->libHandle, "valloc");
+#endif
+
+    return sym;
+}
+
+nsresult
+XPCOMGlueLoadXULFunctions(const nsDynamicFunctionLoad *symbols)
+{
+    // We don't null-check sXULLibHandle because this might work even
+    // if it is null (same as RTLD_DEFAULT)
+
+    nsresult rv = NS_OK;
+    while (symbols->functionName) {
+        char buffer[512];
+        snprintf(buffer, sizeof(buffer),
+                 LEADING_UNDERSCORE "%s", symbols->functionName);
+
+        *symbols->function = (NSFuncPtr) GetSymbol(sTop->libHandle, buffer);
+        if (!*symbols->function)
+            rv = NS_ERROR_LOSS_OF_SIGNIFICANT_DATA;
+
+        ++symbols;
+    }
+    return rv;
+}
+
+void XPCOMGlueEnablePreload()
+{
+    do_preload = true;
+}
+
+nsresult XPCOMGlueStartup(const char* xpcomFile)
+{
+    xpcomFunctions.version = XPCOM_GLUE_VERSION;
+    xpcomFunctions.size    = sizeof(XPCOMFunctions);
+
+    if (!xpcomFile)
+        xpcomFile = XPCOM_DLL;
+
+    GetFrozenFunctionsFunc func = XPCOMGlueLoad(xpcomFile);
+    if (!func)
+        return NS_ERROR_NOT_AVAILABLE;
+
+    nsresult rv = (*func)(&xpcomFunctions, nullptr);
+    if (NS_FAILED(rv)) {
+        XPCOMGlueUnload();
+        return rv;
+    }
+
+    return NS_OK;
 }
 
 XPCOM_API(nsresult)
diff --git a/xpcom/glue/standalone/staticruntime/Makefile.in b/xpcom/glue/standalone/staticruntime/Makefile.in
index 6b7217c107a0..f4683f7cda1e 100644
--- a/xpcom/glue/standalone/staticruntime/Makefile.in
+++ b/xpcom/glue/standalone/staticruntime/Makefile.in
@@ -19,34 +19,10 @@ LOCAL_INCLUDES	= \
 	-I$(srcdir)/../../../build \
 	$(NULL)
 
-ifeq (Darwin,$(OS_ARCH))
-ifeq (uikit,$(MOZ_WIDGET_TOOLKIT))
-LINKSRC = nsGlueLinkingDlopen.cpp
-else
-LINKSRC = nsGlueLinkingOSX.cpp
-endif
-endif
-
-ifeq ($(OS_ARCH),WINNT)
-LINKSRC = nsGlueLinkingWin.cpp
-endif
-ifneq (,$(filter AIX DragonFly FreeBSD GNU GNU_% Linux NetBSD OpenBSD SunOS,$(OS_ARCH)))
-LINKSRC = nsGlueLinkingDlopen.cpp
-endif
-ifeq (OS2,$(OS_ARCH))
-LINKSRC = nsGlueLinkingOS2.cpp
-endif
-
-ifndef LINKSRC
-LINKSRC = nsGlueLinkingNull.cpp
-$(warning TinderboxPrint:Error: XPCOM Glue)
-endif
-
 CPPSRCS		= \
 	$(XPCOM_GLUE_SRC_LCPPSRCS)   \
 	nsXPCOMGlue.cpp              \
 	nsStringAPI.cpp              \
-	$(LINKSRC)                   \
 	$(NULL)
 
 SDK_LIBRARY     	= \
@@ -75,10 +51,10 @@ OS_COMPILE_CFLAGS += -Zl
 DEFINES += -D_USE_ANSI_CPP
 endif
 
-export:: $(XPCOM_GLUE_SRC_CPPSRCS) $(topsrcdir)/xpcom/glue/nsStringAPI.cpp ../nsXPCOMGlue.cpp ../nsGlueLinking.h ../$(LINKSRC)
+export:: $(XPCOM_GLUE_SRC_CPPSRCS) $(topsrcdir)/xpcom/glue/nsStringAPI.cpp ../nsXPCOMGlue.cpp
 	$(INSTALL) $^ .
 
-GARBAGE += nsStringAPI.cpp nsXPCOMGlue.cpp nsGlueLinking.h $(LINKSRC)
+GARBAGE += nsStringAPI.cpp nsXPCOMGlue.cpp
 
 DEFINES		+= -DXPCOM_GLUE
 
diff --git a/xpcom/reflect/xptcall/public/xptcall.h b/xpcom/reflect/xptcall/public/xptcall.h
index 3ddbc9d3aff6..01e50469cb09 100644
--- a/xpcom/reflect/xptcall/public/xptcall.h
+++ b/xpcom/reflect/xptcall/public/xptcall.h
@@ -8,12 +8,6 @@
 #ifndef xptcall_h___
 #define xptcall_h___
 
-#ifdef MOZILLA_INTERNAL_API
-# define NS_GetXPTCallStub     NS_GetXPTCallStub_P
-# define NS_DestroyXPTCallStub NS_DestroyXPTCallStub_P
-# define NS_InvokeByIndex      NS_InvokeByIndex_P
-#endif
-
 #include "nscore.h"
 #include "nsISupports.h"
 #include "xpt_struct.h"
diff --git a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_alpha_openbsd.cpp b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_alpha_openbsd.cpp
index f3100bd8c9f4..dc111e435879 100644
--- a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_alpha_openbsd.cpp
+++ b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_alpha_openbsd.cpp
@@ -61,20 +61,20 @@ invoke_copy_to_stack(uint64_t* d, uint32_t paramCount, nsXPTCVariant* s)
 
 /*
  * EXPORT_XPCOM_API(nsresult)
- * NS_InvokeByIndex_P(nsISupports* that, uint32_t methodIndex,
+ * NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
  *                  uint32_t paramCount, nsXPTCVariant* params)
  */
 __asm__(
-    "#### NS_InvokeByIndex_P ####\n"
+    "#### NS_InvokeByIndex ####\n"
 ".text\n\t"
     ".align 5\n\t"
-    ".globl NS_InvokeByIndex_P\n\t"
-    ".ent NS_InvokeByIndex_P\n"
-"NS_InvokeByIndex_P:\n\t"
+    ".globl NS_InvokeByIndex\n\t"
+    ".ent NS_InvokeByIndex\n"
+"NS_InvokeByIndex:\n\t"
     ".frame $15,32,$26,0\n\t"
     ".mask 0x4008000,-32\n\t"
     "ldgp $29,0($27)\n"
-"$NS_InvokeByIndex_P..ng:\n\t"
+"$NS_InvokeByIndex..ng:\n\t"
     "subq $30,32,$30\n\t"
     "stq $26,0($30)\n\t"
     "stq $15,8($30)\n\t"
@@ -140,5 +140,5 @@ __asm__(
     "ldq $15,8($30)\n\t"
     "addq $30,32,$30\n\t"
     "ret $31,($26),1\n\t"
-    ".end NS_InvokeByIndex_P"
+    ".end NS_InvokeByIndex"
     );
diff --git a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_amd64_openbsd.cpp b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_amd64_openbsd.cpp
index 26cf2a5952b3..66098708a584 100644
--- a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_amd64_openbsd.cpp
+++ b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_amd64_openbsd.cpp
@@ -100,7 +100,7 @@ invoke_copy_to_stack(uint64_t * d, uint32_t paramCount, nsXPTCVariant * s,
 }
 
 EXPORT_XPCOM_API(nsresult)
-NS_InvokeByIndex_P(nsISupports * that, uint32_t methodIndex,
+NS_InvokeByIndex(nsISupports * that, uint32_t methodIndex,
                  uint32_t paramCount, nsXPTCVariant * params)
 {
     uint32_t nr_gpr, nr_fpr, nr_stack;
diff --git a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ipf32.s b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ipf32.s
index 67c1e410f9b5..794c4f5c17f4 100644
--- a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ipf32.s
+++ b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ipf32.s
@@ -7,8 +7,8 @@
         .psr    msb
 // Section has executable code
         .section .text, "ax","progbits"
-// procedure named 'NS_InvokeByIndex_P'
-        .proc   NS_InvokeByIndex_P
+// procedure named 'NS_InvokeByIndex'
+        .proc   NS_InvokeByIndex
 // manual bundling
         .explicit
 
@@ -19,12 +19,12 @@
 //      .exclass  invoke_copy_to_stack, @fullyvisible
         .type   invoke_copy_to_stack,@function
 
-//      .exclass  NS_InvokeByIndex_P, @fullyvisible
-        .type   NS_InvokeByIndex_P,@function
+//      .exclass  NS_InvokeByIndex, @fullyvisible
+        .type   NS_InvokeByIndex,@function
 
-// NS_InvokeByIndex_P(nsISupports* that, uint32_t methodIndex,
+// NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
 //   uint32_t paramCount, nsXPTCVariant* params);
-NS_InvokeByIndex_P::
+NS_InvokeByIndex::
         .prologue
         .save ar.pfs, r37
 // allocate 4 input args, 6 local args, and 8 output args
diff --git a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ipf64.s b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ipf64.s
index a9d30c933e4a..140c441177b9 100644
--- a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ipf64.s
+++ b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ipf64.s
@@ -7,8 +7,8 @@
         .psr    lsb
 // Section has executable code
         .section .text, "ax","progbits"
-// procedure named 'NS_InvokeByIndex_P'
-        .proc   NS_InvokeByIndex_P
+// procedure named 'NS_InvokeByIndex'
+        .proc   NS_InvokeByIndex
 // manual bundling
         .explicit
 
@@ -19,12 +19,12 @@
 //      .exclass  invoke_copy_to_stack, @fullyvisible
         .type   invoke_copy_to_stack,@function
 
-//      .exclass  NS_InvokeByIndex_P, @fullyvisible
-        .type   NS_InvokeByIndex_P,@function
+//      .exclass  NS_InvokeByIndex, @fullyvisible
+        .type   NS_InvokeByIndex,@function
 
 // XPTC_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
 //   uint32_t paramCount, nsXPTCVariant* params);
-NS_InvokeByIndex_P::
+NS_InvokeByIndex::
         .prologue
         .save ar.pfs, r37
 // allocate 4 input args, 6 local args, and 8 output args
diff --git a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_mips.s b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_mips.s
index a3e3b8aa072e..32ff3b356505 100644
--- a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_mips.s
+++ b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_mips.s
@@ -38,15 +38,15 @@
 	.text
 
 #	
-# _NS_InvokeByIndex_P(that, methodIndex, paramCount, params)
+# _NS_InvokeByIndex(that, methodIndex, paramCount, params)
 #                      a0       a1          a2         a3
 
-	.globl	_NS_InvokeByIndex_P
+	.globl	_NS_InvokeByIndex
 	.align	2
-	.type	_NS_InvokeByIndex_P,@function
-	.ent	_NS_InvokeByIndex_P,0
+	.type	_NS_InvokeByIndex,@function
+	.ent	_NS_InvokeByIndex,0
 	.frame	fp, FRAMESZ, ra
-_NS_InvokeByIndex_P:
+_NS_InvokeByIndex:
 	SETUP_GP
 	subu	sp, FRAMESZ
 
@@ -131,4 +131,4 @@ _NS_InvokeByIndex_P:
 
 	addiu	sp, FRAMESZ
 	j	ra
-END(_NS_InvokeByIndex_P)
+END(_NS_InvokeByIndex)
diff --git a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_mips64.s b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_mips64.s
index acddbd0c9dfc..ed897f1bf996 100644
--- a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_mips64.s
+++ b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_mips64.s
@@ -21,12 +21,12 @@ S0OFF=FRAMESZ-(6*SZREG)
 GPOFF=FRAMESZ-(7*SZREG)
 
 #
-# _NS_InvokeByIndex_P(that, methodIndex, paramCount, params)
+# _NS_InvokeByIndex(that, methodIndex, paramCount, params)
 #                      a0       a1          a2         a3
 
-NESTED(_NS_InvokeByIndex_P, FRAMESZ, ra)
+NESTED(_NS_InvokeByIndex, FRAMESZ, ra)
     PTR_SUBU sp, FRAMESZ
-    SETUP_GP64(GPOFF, _NS_InvokeByIndex_P)
+    SETUP_GP64(GPOFF, _NS_InvokeByIndex)
 
     REG_S    ra, RAOFF(sp)
     REG_S    a0, A0OFF(sp)
@@ -119,4 +119,4 @@ NESTED(_NS_InvokeByIndex_P, FRAMESZ, ra)
     REG_L    s0, S0OFF(sp)
     PTR_ADDU sp, FRAMESZ
     j    ra
-.end _NS_InvokeByIndex_P
+.end _NS_InvokeByIndex
diff --git a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_parisc_linux.s b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_parisc_linux.s
index 7de80f498af1..7a207addfdc5 100644
--- a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_parisc_linux.s
+++ b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_parisc_linux.s
@@ -12,11 +12,11 @@
 framesz:
   .equ 128
 
-.globl NS_InvokeByIndex_P
-  .type NS_InvokeByIndex_P, @function
+.globl NS_InvokeByIndex
+  .type NS_InvokeByIndex, @function
 
 
-NS_InvokeByIndex_P:
+NS_InvokeByIndex:
   .PROC
   .CALLINFO FRAME=72, CALLER,SAVE_RP, SAVE_SP, ENTRY_GR=3
   .ENTRY
@@ -104,5 +104,5 @@ NS_InvokeByIndex_P:
         NOP
   .EXIT
   .PROCEND  ;in=23,24,25,26;
-  .SIZE NS_InvokeByIndex_P, .-NS_InvokeByIndex_P
+  .SIZE NS_InvokeByIndex, .-NS_InvokeByIndex
 
diff --git a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc64_linux.s b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc64_linux.s
index 1b8292c5d463..5d4f70ca52b9 100644
--- a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc64_linux.s
+++ b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc64_linux.s
@@ -19,21 +19,21 @@
 
 
 #
-# NS_InvokeByIndex_P(nsISupports* that, uint32_t methodIndex,
+# NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
 #                    uint32_t paramCount, nsXPTCVariant* params)
 #
 
         .section ".toc","aw"
         .section ".text"
         .align 2
-        .globl  NS_InvokeByIndex_P
+        .globl  NS_InvokeByIndex
         .section ".opd","aw"
         .align 3
-NS_InvokeByIndex_P:
-        .quad   .NS_InvokeByIndex_P,.TOC.@tocbase
+NS_InvokeByIndex:
+        .quad   .NS_InvokeByIndex,.TOC.@tocbase
         .previous
-        .type   NS_InvokeByIndex_P,@function
-.NS_InvokeByIndex_P:
+        .type   NS_InvokeByIndex,@function
+.NS_InvokeByIndex:
         mflr    0
         std     0,16(r1)
 
@@ -126,7 +126,7 @@ NS_InvokeByIndex_P:
         mtlr    0
         blr
 
-        .size   NS_InvokeByIndex_P,.-.NS_InvokeByIndex_P
+        .size   NS_InvokeByIndex,.-.NS_InvokeByIndex
 
         # Magic indicating no need for an executable stack
         .section .note.GNU-stack, "", @progbits ; .previous
diff --git a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_aix.s b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_aix.s
index 46140fbd136e..eb6b6661d3da 100644
--- a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_aix.s
+++ b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_aix.s
@@ -25,24 +25,24 @@
 
 
         .rename H.10.NO_SYMBOL{PR},""
-        .rename H.18.NS_InvokeByIndex_P{TC},"NS_InvokeByIndex_P"
+        .rename H.18.NS_InvokeByIndex{TC},"NS_InvokeByIndex"
 
 
 # .text section
 
         .csect  H.10.NO_SYMBOL{PR}
-        .globl  .NS_InvokeByIndex_P
-        .globl  NS_InvokeByIndex_P{DS}
+        .globl  .NS_InvokeByIndex
+        .globl  NS_InvokeByIndex{DS}
         .extern .invoke_copy_to_stack
         .extern ._ptrgl{PR}
 
 
 #
-#   NS_InvokeByIndex_P(nsISupports* that, uint32_t methodIndex,
+#   NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
 #                   uint32_t paramCount, nsXPTCVariant* params)
 #
 
-.NS_InvokeByIndex_P:
+.NS_InvokeByIndex:
 		mflr	r0
 		stw	r31,-4(sp)
 #
@@ -117,13 +117,13 @@
 # .data section
 
         .toc                            # 0x00000038
-T.18.NS_InvokeByIndex_P:
-        .tc     H.18.NS_InvokeByIndex_P{TC},NS_InvokeByIndex_P{DS}
+T.18.NS_InvokeByIndex:
+        .tc     H.18.NS_InvokeByIndex{TC},NS_InvokeByIndex{DS}
 
-        .csect  NS_InvokeByIndex_P{DS}
-        .long   .NS_InvokeByIndex_P     # "\0\0\0\0"
+        .csect  NS_InvokeByIndex{DS}
+        .long   .NS_InvokeByIndex     # "\0\0\0\0"
         .long   TOC{TC0}                # "\0\0\0008"
         .long   0x00000000              # "\0\0\0\0"
-# End   csect   NS_InvokeByIndex_P{DS}
+# End   csect   NS_InvokeByIndex{DS}
 
 # .bss section	
diff --git a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_aix64.s b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_aix64.s
index dea9d63e4ec3..722583de5bc1 100644
--- a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_aix64.s
+++ b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_aix64.s
@@ -20,23 +20,23 @@
 .set CR0_EQ,2
 
         .rename H.10.NO_SYMBOL{PR},""
-        .rename H.18.NS_InvokeByIndex_P{TC},"NS_InvokeByIndex_P"
+        .rename H.18.NS_InvokeByIndex{TC},"NS_InvokeByIndex"
 
 
 # .text section
 
         .csect  H.10.NO_SYMBOL{PR}
-        .globl  .NS_InvokeByIndex_P
-        .globl  NS_InvokeByIndex_P{DS}
+        .globl  .NS_InvokeByIndex
+        .globl  NS_InvokeByIndex{DS}
         .extern .invoke_copy_to_stack
         .extern ._ptrgl{PR}
 
 #
-#   NS_InvokeByIndex_P(nsISupports* that, uint32_t methodIndex,
+#   NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
 #                      uint32_t paramCount, nsXPTCVariant* params)
 #
 
-.NS_InvokeByIndex_P:
+.NS_InvokeByIndex:
         mflr    r0
         std     r31,-8(sp)
 #
@@ -116,13 +116,13 @@
 # .data section
 
         .toc                            # 0x00000038
-T.18.NS_InvokeByIndex_P:
-        .tc     H.18.NS_InvokeByIndex_P{TC},NS_InvokeByIndex_P{DS}
+T.18.NS_InvokeByIndex:
+        .tc     H.18.NS_InvokeByIndex{TC},NS_InvokeByIndex{DS}
 
-        .csect  NS_InvokeByIndex_P{DS}
-        .llong  .NS_InvokeByIndex_P     # "\0\0\0\0"
+        .csect  NS_InvokeByIndex{DS}
+        .llong  .NS_InvokeByIndex     # "\0\0\0\0"
         .llong  TOC{TC0}                # "\0\0\0008"
         .llong  0x00000000              # "\0\0\0\0"
-# End   csect   NS_InvokeByIndex_P{DS}
+# End   csect   NS_InvokeByIndex{DS}
 
 # .bss section
diff --git a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_ibmobj_aix.s b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_ibmobj_aix.s
index 0835c71d8d08..414a6536faff 100644
--- a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_ibmobj_aix.s
+++ b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_ibmobj_aix.s
@@ -25,24 +25,24 @@
 
 
         .rename H.10.NO_SYMBOL{PR},""
-        .rename H.18.NS_InvokeByIndex_P{TC},"NS_InvokeByIndex_P"
+        .rename H.18.NS_InvokeByIndex{TC},"NS_InvokeByIndex"
 
 
 # .text section
 
         .csect  H.10.NO_SYMBOL{PR}
-        .globl  .NS_InvokeByIndex_P
-        .globl  NS_InvokeByIndex_P{DS}
+        .globl  .NS_InvokeByIndex
+        .globl  NS_InvokeByIndex{DS}
         .extern .invoke_copy_to_stack
         .extern ._ptrgl{PR}
 
 
 #
-#   NS_InvokeByIndex_P(nsISupports* that, uint32_t methodIndex,
+#   NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
 #                   uint32_t paramCount, nsXPTCVariant* params)
 #
 
-.NS_InvokeByIndex_P:
+.NS_InvokeByIndex:
 		mflr	r0
 		stw	r31,-4(sp)
 #
@@ -112,13 +112,13 @@
 # .data section
 
         .toc                            # 0x00000038
-T.18.NS_InvokeByIndex_P:
-        .tc     H.18.NS_InvokeByIndex_P{TC},NS_InvokeByIndex_P{DS}
+T.18.NS_InvokeByIndex:
+        .tc     H.18.NS_InvokeByIndex{TC},NS_InvokeByIndex{DS}
 
-        .csect  NS_InvokeByIndex_P{DS}
-        .long   .NS_InvokeByIndex_P     # "\0\0\0\0"
+        .csect  NS_InvokeByIndex{DS}
+        .long   .NS_InvokeByIndex     # "\0\0\0\0"
         .long   TOC{TC0}                # "\0\0\0008"
         .long   0x00000000              # "\0\0\0\0"
-# End   csect   NS_InvokeByIndex_P{DS}
+# End   csect   NS_InvokeByIndex{DS}
 
 # .bss section	
diff --git a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_linux.s b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_linux.s
index 9ed5123f59fb..e87382286c1f 100644
--- a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_linux.s
+++ b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_linux.s
@@ -21,15 +21,15 @@
 		      
         .section ".text"
 	.align 2
-	.globl NS_InvokeByIndex_P
-	.type  NS_InvokeByIndex_P,@function
+	.globl NS_InvokeByIndex
+	.type  NS_InvokeByIndex,@function
 
 //
-// NS_InvokeByIndex_P(nsISupports* that, uint32_t methodIndex,
+// NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
 //                  uint32_t paramCount, nsXPTCVariant* params)
 //
 
-NS_InvokeByIndex_P:
+NS_InvokeByIndex:
 	stwu    sp,-32(sp)			// setup standard stack frame
 	mflr    r0				// save LR
 	stw     r3,8(sp)			// r3 <= that
diff --git a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_openbsd.s b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_openbsd.s
index 6ebc820a554f..f02c0b220462 100644
--- a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_openbsd.s
+++ b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_openbsd.s
@@ -21,15 +21,15 @@
 
 	.section ".text"
 	.align 2
-	.globl NS_InvokeByIndex_P
-	.type  NS_InvokeByIndex_P,@function
+	.globl NS_InvokeByIndex
+	.type  NS_InvokeByIndex,@function
 
 //
-// NS_InvokeByIndex_P(nsISupports* that, uint32_t methodIndex,
+// NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
 //                    uint32_t paramCount, nsXPTCVariant* params)
 //
 
-NS_InvokeByIndex_P:
+NS_InvokeByIndex:
 	stwu	sp,-32(sp)			// setup standard stack frame
 	mflr	r0				// save LR
 	stw	r3,8(sp)			// r3 <= that
diff --git a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_rhapsody.s b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_rhapsody.s
index 557e51a31452..1dc12b2b30f4 100644
--- a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_rhapsody.s
+++ b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_ppc_rhapsody.s
@@ -14,12 +14,12 @@
 .text
 	.align 2
 #
-#   NS_InvokeByIndex_P(nsISupports* that, uint32_t methodIndex,
+#   NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
 #                    uint32_t paramCount, nsXPTCVariant* params)
 #
 
-.globl __NS_InvokeByIndex_P	
-__NS_InvokeByIndex_P:
+.globl __NS_InvokeByIndex	
+__NS_InvokeByIndex:
 	mflr	r0
 	stw	r31,-4(r1)
 #
diff --git a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc64_openbsd.s b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc64_openbsd.s
index 02d6c818bf7d..dfd6189f832b 100644
--- a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc64_openbsd.s
+++ b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc64_openbsd.s
@@ -14,15 +14,15 @@
     The SCD is available from http://www.sparc.com/.
 */
 
-        .global NS_InvokeByIndex_P
-        .type   NS_InvokeByIndex_P, #function
+        .global NS_InvokeByIndex
+        .type   NS_InvokeByIndex, #function
 
 /*
-    NS_InvokeByIndex_P(nsISupports* that, uint32_t methodIndex,
+    NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
                      uint32_t paramCount, nsXPTCVariant* params);
     
 */
-NS_InvokeByIndex_P:
+NS_InvokeByIndex:
         save    %sp,-(128 + 64),%sp ! room for the register window and
                                     ! struct pointer, rounded up to 0 % 64
         sll     %i2,4,%l0           ! assume the worst case
@@ -83,4 +83,4 @@ NS_InvokeByIndex_P:
         ret
         restore
 
-        .size    NS_InvokeByIndex_P, .-NS_InvokeByIndex
+        .size    NS_InvokeByIndex, .-NS_InvokeByIndex
diff --git a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_linux_GCC3.s b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_linux_GCC3.s
index f4ce2bc3a079..36196805e810 100644
--- a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_linux_GCC3.s
+++ b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_linux_GCC3.s
@@ -8,13 +8,13 @@
  * Platform specific code to invoke XPCOM methods on native objects for
  * Linux/Sparc with gcc 3 ABI.
  */
-        .global NS_InvokeByIndex_P
+        .global NS_InvokeByIndex
 /*
  *  NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
  *                 uint32_t paramCount, nsXPTCVariant* params);
  *   
  */
-NS_InvokeByIndex_P:
+NS_InvokeByIndex:
         save    %sp,-(64 + 16),%sp   ! room for the register window and
                                     ! struct pointer, rounded up to 0 % 16
         mov     %i2,%o0             ! paramCount
diff --git a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_solaris_GCC3.s b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_solaris_GCC3.s
index 52fe0d510105..54adcd147452 100644
--- a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_solaris_GCC3.s
+++ b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_solaris_GCC3.s
@@ -8,12 +8,12 @@
  * Platform specific code to invoke XPCOM methods on native objects for
  * solaris/sparc with gcc 3 ABI.
  */
-        .global NS_InvokeByIndex_P
+        .global NS_InvokeByIndex
 /*
- *  NS_InvokeByIndex_P(nsISupports* that, uint32_t methodIndex,
+ *  NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
  *                   uint32_t paramCount, nsXPTCVariant* params);
  */
-NS_InvokeByIndex_P:
+NS_InvokeByIndex:
         save    %sp,-(64 + 32),%sp  ! room for the register window and
                                     ! struct pointer, rounded up to 0 % 32
         mov     %i2,%o0             ! paramCount
diff --git a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_solaris_SUNW.s b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_solaris_SUNW.s
index abe92327d703..013770392469 100644
--- a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_solaris_SUNW.s
+++ b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparc_solaris_SUNW.s
@@ -6,14 +6,14 @@
 
 /* Platform specific code to invoke XPCOM methods on native objects */
 
-        .global NS_InvokeByIndex_P
-        .type   NS_InvokeByIndex_P, #function
+        .global NS_InvokeByIndex
+        .type   NS_InvokeByIndex, #function
 /*
-    NS_InvokeByIndex_P(nsISupports* that, uint32_t methodIndex,
+    NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
                      uint32_t paramCount, nsXPTCVariant* params);
     
 */
-NS_InvokeByIndex_P:
+NS_InvokeByIndex:
         save    %sp,-(64 + 32),%sp  ! room for the register window and
                                     ! struct pointer, rounded up to 0 % 32
         sll     %i2,3,%l0           ! assume the worst case
@@ -53,4 +53,4 @@ NS_InvokeByIndex_P:
         ret
         restore
 
-        .size    NS_InvokeByIndex_P, .-NS_InvokeByIndex_P
+        .size    NS_InvokeByIndex, .-NS_InvokeByIndex
diff --git a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparcv9_solaris_SUNW.s b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparcv9_solaris_SUNW.s
index 4f57d8dc9175..34861abc0ead 100644
--- a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparcv9_solaris_SUNW.s
+++ b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_sparcv9_solaris_SUNW.s
@@ -14,15 +14,15 @@
     The SCD is available from http://www.sparc.com/.
 */
 
-        .global NS_InvokeByIndex_P
-        .type   NS_InvokeByIndex_P, #function
+        .global NS_InvokeByIndex
+        .type   NS_InvokeByIndex, #function
 
 /*
-    NS_InvokeByIndex_P(nsISupports* that, uint32_t methodIndex,
+    NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
                      uint32_t paramCount, nsXPTCVariant* params);
     
 */
-NS_InvokeByIndex_P:
+NS_InvokeByIndex:
         save    %sp,-(128 + 64),%sp ! room for the register window and
                                     ! struct pointer, rounded up to 0 % 64
         sll     %i2,4,%l0           ! assume the worst case
@@ -82,4 +82,4 @@ NS_InvokeByIndex_P:
         ret
         restore
 
-        .size    NS_InvokeByIndex_P, .-NS_InvokeByIndex_P
+        .size    NS_InvokeByIndex, .-NS_InvokeByIndex
diff --git a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_x86_solaris_SUNW.s b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_x86_solaris_SUNW.s
index 684c53a5fba2..af665a16286f 100644
--- a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_x86_solaris_SUNW.s
+++ b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_asm_x86_solaris_SUNW.s
@@ -1,6 +1,6 @@
-	.globl NS_InvokeByIndex_P
-	.type NS_InvokeByIndex_P, @function
-NS_InvokeByIndex_P:
+	.globl NS_InvokeByIndex
+	.type NS_InvokeByIndex, @function
+NS_InvokeByIndex:
 	push       %ebp
 	movl       %esp,%ebp
 	push       %ebx
@@ -51,5 +51,5 @@ NS_InvokeByIndex_P:
 	movl       %ebp,%esp
 	pop        %ebp
 	ret        
-	.size NS_InvokeByIndex_P, . - NS_InvokeByIndex_P
+	.size NS_InvokeByIndex, . - NS_InvokeByIndex
 
diff --git a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_gcc_x86_unix.cpp b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_gcc_x86_unix.cpp
index fce1c53521c4..d4a8a12fbc3a 100644
--- a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_gcc_x86_unix.cpp
+++ b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_gcc_x86_unix.cpp
@@ -33,7 +33,7 @@ invoke_copy_to_stack(uint32_t paramCount, nsXPTCVariant* s, uint32_t* d)
 
 /*
   EXPORT_XPCOM_API(nsresult)
-  NS_InvokeByIndex_P(nsISupports* that, uint32_t methodIndex,
+  NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
                    uint32_t paramCount, nsXPTCVariant* params);
 
   Each param takes at most two 4-byte words.
@@ -52,11 +52,11 @@ __asm__ (
 /* alignment here seems unimportant here; this was 16, now it's 2 which
    is what xptcstubs uses. */
 	".align 2\n\t"
-	".globl " SYMBOL_UNDERSCORE "NS_InvokeByIndex_P\n\t"
+	".globl " SYMBOL_UNDERSCORE "NS_InvokeByIndex\n\t"
 #ifndef XP_MACOSX
-	".type  " SYMBOL_UNDERSCORE "NS_InvokeByIndex_P,@function\n"
+	".type  " SYMBOL_UNDERSCORE "NS_InvokeByIndex,@function\n"
 #endif
-	SYMBOL_UNDERSCORE "NS_InvokeByIndex_P:\n\t"
+	SYMBOL_UNDERSCORE "NS_InvokeByIndex:\n\t"
 	"pushl %ebp\n\t"
 	"movl  %esp, %ebp\n\t"
 	"movl  0x10(%ebp), %eax\n\t"
@@ -92,6 +92,6 @@ __asm__ (
 	"popl  %ebp\n\t"
 	"ret\n"
 #ifndef XP_MACOSX
-	".size " SYMBOL_UNDERSCORE "NS_InvokeByIndex_P, . -" SYMBOL_UNDERSCORE "NS_InvokeByIndex_P\n\t"
+	".size " SYMBOL_UNDERSCORE "NS_InvokeByIndex, . -" SYMBOL_UNDERSCORE "NS_InvokeByIndex\n\t"
 #endif
 );
diff --git a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_linux_alpha.cpp b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_linux_alpha.cpp
index f3100bd8c9f4..dc111e435879 100644
--- a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_linux_alpha.cpp
+++ b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_linux_alpha.cpp
@@ -61,20 +61,20 @@ invoke_copy_to_stack(uint64_t* d, uint32_t paramCount, nsXPTCVariant* s)
 
 /*
  * EXPORT_XPCOM_API(nsresult)
- * NS_InvokeByIndex_P(nsISupports* that, uint32_t methodIndex,
+ * NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
  *                  uint32_t paramCount, nsXPTCVariant* params)
  */
 __asm__(
-    "#### NS_InvokeByIndex_P ####\n"
+    "#### NS_InvokeByIndex ####\n"
 ".text\n\t"
     ".align 5\n\t"
-    ".globl NS_InvokeByIndex_P\n\t"
-    ".ent NS_InvokeByIndex_P\n"
-"NS_InvokeByIndex_P:\n\t"
+    ".globl NS_InvokeByIndex\n\t"
+    ".ent NS_InvokeByIndex\n"
+"NS_InvokeByIndex:\n\t"
     ".frame $15,32,$26,0\n\t"
     ".mask 0x4008000,-32\n\t"
     "ldgp $29,0($27)\n"
-"$NS_InvokeByIndex_P..ng:\n\t"
+"$NS_InvokeByIndex..ng:\n\t"
     "subq $30,32,$30\n\t"
     "stq $26,0($30)\n\t"
     "stq $15,8($30)\n\t"
@@ -140,5 +140,5 @@ __asm__(
     "ldq $15,8($30)\n\t"
     "addq $30,32,$30\n\t"
     "ret $31,($26),1\n\t"
-    ".end NS_InvokeByIndex_P"
+    ".end NS_InvokeByIndex"
     );
diff --git a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_linux_m68k.cpp b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_linux_m68k.cpp
index 4a0241117408..6f2934cbc893 100644
--- a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_linux_m68k.cpp
+++ b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_linux_m68k.cpp
@@ -97,7 +97,7 @@ extern "C" {
 }
 
 EXPORT_XPCOM_API(nsresult)
-NS_InvokeByIndex_P(nsISupports* that, uint32_t methodIndex,
+NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
                    uint32_t paramCount, nsXPTCVariant* params)
 {
     uint32_t result, n;
diff --git a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_mips.cpp b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_mips.cpp
index a02799ad1112..e881700e9a9e 100644
--- a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_mips.cpp
+++ b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_mips.cpp
@@ -87,13 +87,13 @@ invoke_copy_to_stack(uint32_t* d, uint32_t paramCount,
     }
 }
 
-extern "C" nsresult _NS_InvokeByIndex_P(nsISupports* that, uint32_t methodIndex,
+extern "C" nsresult _NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
                                         uint32_t paramCount,
                                         nsXPTCVariant* params);
 
 EXPORT_XPCOM_API(nsresult)
-NS_InvokeByIndex_P(nsISupports* that, uint32_t methodIndex,
+NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
                    uint32_t paramCount, nsXPTCVariant* params)
 {
-    return _NS_InvokeByIndex_P(that, methodIndex, paramCount, params);
+    return _NS_InvokeByIndex(that, methodIndex, paramCount, params);
 }
diff --git a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_mips64.cpp b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_mips64.cpp
index fc4a4368cb84..08b46165d343 100644
--- a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_mips64.cpp
+++ b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_mips64.cpp
@@ -128,13 +128,13 @@ invoke_copy_to_stack(uint64_t* d, uint32_t paramCount,
     }
 }
 
-extern "C" nsresult _NS_InvokeByIndex_P(nsISupports* that, uint32_t methodIndex,
+extern "C" nsresult _NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
                                         uint32_t paramCount,
                                         nsXPTCVariant* params);
 
 EXPORT_XPCOM_API(nsresult)
-NS_InvokeByIndex_P(nsISupports* that, uint32_t methodIndex,
+NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
                    uint32_t paramCount, nsXPTCVariant* params)
 {
-    return _NS_InvokeByIndex_P(that, methodIndex, paramCount, params);
+    return _NS_InvokeByIndex(that, methodIndex, paramCount, params);
 }
diff --git a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ppc64_linux.cpp b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ppc64_linux.cpp
index f1fc1f7cf695..e20e67ef5671 100644
--- a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ppc64_linux.cpp
+++ b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ppc64_linux.cpp
@@ -5,9 +5,9 @@
 
 // Platform specific code to invoke XPCOM methods on native objects
 
-// The purpose of NS_InvokeByIndex_P() is to map a platform
+// The purpose of NS_InvokeByIndex() is to map a platform
 // independent call to the platform ABI. To do that,
-// NS_InvokeByIndex_P() has to determine the method to call via vtable
+// NS_InvokeByIndex() has to determine the method to call via vtable
 // access. The parameters for the method are read from the
 // nsXPTCVariant* and prepared for the native ABI.
 
@@ -90,6 +90,6 @@ invoke_copy_to_stack(uint64_t* gpregs,
 }
 
 EXPORT_XPCOM_API(nsresult)
-NS_InvokeByIndex_P(nsISupports* that, uint32_t methodIndex,
+NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
                    uint32_t paramCount, nsXPTCVariant* params);
 
diff --git a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ppc_linux.cpp b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ppc_linux.cpp
index 946d752f3d22..7f235b46ddf9 100644
--- a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ppc_linux.cpp
+++ b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ppc_linux.cpp
@@ -5,9 +5,9 @@
 
 // Platform specific code to invoke XPCOM methods on native objects
 
-// The purpose of NS_InvokeByIndex_P() is to map a platform
+// The purpose of NS_InvokeByIndex() is to map a platform
 // indepenpent call to the platform ABI. To do that,
-// NS_InvokeByIndex_P() has to determine the method to call via vtable
+// NS_InvokeByIndex() has to determine the method to call via vtable
 // access. The parameters for the method are read from the
 // nsXPTCVariant* and prepared for th native ABI.  For the Linux/PPC
 // ABI this means that the first 8 integral and floating point
@@ -120,5 +120,5 @@ invoke_copy_to_stack(uint32_t* d,
 
 extern "C"
 EXPORT_XPCOM_API(nsresult)
-NS_InvokeByIndex_P(nsISupports* that, uint32_t methodIndex,
+NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
                  uint32_t paramCount, nsXPTCVariant* params);
diff --git a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ppc_openbsd.cpp b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ppc_openbsd.cpp
index 4312fbc03dff..70f40b38ec38 100644
--- a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ppc_openbsd.cpp
+++ b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ppc_openbsd.cpp
@@ -5,9 +5,9 @@
 
 // Platform specific code to invoke XPCOM methods on native objects
 
-// The purpose of NS_InvokeByIndex_P() is to map a platform
+// The purpose of NS_InvokeByIndex() is to map a platform
 // indepenpent call to the platform ABI. To do that,
-// NS_InvokeByIndex_P() has to determine the method to call via vtable
+// NS_InvokeByIndex() has to determine the method to call via vtable
 // access. The parameters for the method are read from the
 // nsXPTCVariant* and prepared for th native ABI.  For the Linux/PPC
 // ABI this means that the first 8 integral and floating point
@@ -102,5 +102,5 @@ invoke_copy_to_stack(uint32_t* d,
 
 extern "C"
 EXPORT_XPCOM_API(nsresult)
-NS_InvokeByIndex_P(nsISupports* that, uint32_t methodIndex,
+NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
                  uint32_t paramCount, nsXPTCVariant* params);
diff --git a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ppc_rhapsody.cpp b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ppc_rhapsody.cpp
index f5c60fe81ac3..1a40cfeea7e9 100644
--- a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ppc_rhapsody.cpp
+++ b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_ppc_rhapsody.cpp
@@ -101,13 +101,13 @@ invoke_copy_to_stack(uint32_t* d, uint32_t paramCount, nsXPTCVariant* s, double
     }
 }
 
-extern "C" nsresult _NS_InvokeByIndex_P(nsISupports* that, uint32_t methodIndex,
+extern "C" nsresult _NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
                                       uint32_t paramCount, 
                                       nsXPTCVariant* params);
 
 EXPORT_XPCOM_API(nsresult)
-NS_InvokeByIndex_P(nsISupports* that, uint32_t methodIndex,
+NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
                  uint32_t paramCount, nsXPTCVariant* params)
 {
-    return _NS_InvokeByIndex_P(that, methodIndex, paramCount, params);
+    return _NS_InvokeByIndex(that, methodIndex, paramCount, params);
 }    
diff --git a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_x86_64_solaris.cpp b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_x86_64_solaris.cpp
index 377fafb57ab5..4f63ea822f4f 100644
--- a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_x86_64_solaris.cpp
+++ b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_x86_64_solaris.cpp
@@ -101,7 +101,7 @@ invoke_copy_to_stack(uint64_t * d, uint32_t paramCount, nsXPTCVariant * s,
 }
 
 EXPORT_XPCOM_API(nsresult)
-NS_InvokeByIndex_P(nsISupports * that, uint32_t methodIndex,
+NS_InvokeByIndex(nsISupports * that, uint32_t methodIndex,
                  uint32_t paramCount, nsXPTCVariant * params)
 {
     uint32_t nr_gpr, nr_fpr, nr_stack;
diff --git a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_x86_64_unix.cpp b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_x86_64_unix.cpp
index a74dfbd837d2..cca44a7454ff 100644
--- a/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_x86_64_unix.cpp
+++ b/xpcom/reflect/xptcall/src/md/unix/xptcinvoke_x86_64_unix.cpp
@@ -102,7 +102,7 @@ invoke_copy_to_stack(uint64_t * d, uint32_t paramCount, nsXPTCVariant * s,
 }
 
 EXPORT_XPCOM_API(nsresult)
-NS_InvokeByIndex_P(nsISupports * that, uint32_t methodIndex,
+NS_InvokeByIndex(nsISupports * that, uint32_t methodIndex,
                  uint32_t paramCount, nsXPTCVariant * params)
 {
     uint32_t nr_stack;
diff --git a/xpcom/reflect/xptcall/src/md/win32/xptcinvoke.cpp b/xpcom/reflect/xptcall/src/md/win32/xptcinvoke.cpp
index 07d55322ad1c..f78ac74f96d3 100644
--- a/xpcom/reflect/xptcall/src/md/win32/xptcinvoke.cpp
+++ b/xpcom/reflect/xptcall/src/md/win32/xptcinvoke.cpp
@@ -49,7 +49,7 @@ invoke_copy_to_stack(uint32_t* d, uint32_t paramCount, nsXPTCVariant* s)
 // a custom FPO program.
 #pragma optimize( "y", off )
 extern "C" NS_EXPORT nsresult NS_FROZENCALL
-NS_InvokeByIndex_P(nsISupports* that, uint32_t methodIndex,
+NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
                  uint32_t paramCount, nsXPTCVariant* params)
 {
     __asm {
diff --git a/xpcom/reflect/xptcall/src/md/win32/xptcinvoke_x86_64.cpp b/xpcom/reflect/xptcall/src/md/win32/xptcinvoke_x86_64.cpp
index 1286d4f1894d..36b454b3524c 100644
--- a/xpcom/reflect/xptcall/src/md/win32/xptcinvoke_x86_64.cpp
+++ b/xpcom/reflect/xptcall/src/md/win32/xptcinvoke_x86_64.cpp
@@ -51,7 +51,7 @@ XPTC__InvokebyIndex(nsISupports* that, uint32_t methodIndex,
 
 extern "C"
 EXPORT_XPCOM_API(nsresult)
-NS_InvokeByIndex_P(nsISupports* that, uint32_t methodIndex,
+NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
                    uint32_t paramCount, nsXPTCVariant* params)
 {
     return XPTC__InvokebyIndex(that, methodIndex, paramCount, params);
diff --git a/xpcom/reflect/xptcall/src/md/win32/xptcinvoke_x86_gnu.cpp b/xpcom/reflect/xptcall/src/md/win32/xptcinvoke_x86_gnu.cpp
index 75c8b2adc0f1..0e73e99f3a9c 100644
--- a/xpcom/reflect/xptcall/src/md/win32/xptcinvoke_x86_gnu.cpp
+++ b/xpcom/reflect/xptcall/src/md/win32/xptcinvoke_x86_gnu.cpp
@@ -45,7 +45,7 @@ invoke_copy_to_stack(uint32_t paramCount, nsXPTCVariant* s, uint32_t* d)
 
 /*
   EXPORT_XPCOM_API(nsresult)
-  NS_InvokeByIndex_P(nsISupports* that, uint32_t methodIndex,
+  NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
                    uint32_t paramCount, nsXPTCVariant* params);
 
   Each param takes at most two 4-byte words.
@@ -64,8 +64,8 @@ __asm__ (
 /* alignment here seems unimportant here; this was 16, now it's 2 which
    is what xptcstubs uses. */
 	".align 2\n\t"
-	".globl _NS_InvokeByIndex_P\n\t"
-	"_NS_InvokeByIndex_P:\n\t"
+	".globl _NS_InvokeByIndex\n\t"
+	"_NS_InvokeByIndex:\n\t"
 	"pushl %ebp\n\t"
 	"movl  %esp, %ebp\n\t"
 	"movl  0x10(%ebp), %eax\n\t"
@@ -101,6 +101,6 @@ __asm__ (
 	"popl  %ebp\n\t"
 	"ret\n"
 	".section .drectve\n\t"
-	".ascii \" -export:NS_InvokeByIndex_P\"\n\t"
+	".ascii \" -export:NS_InvokeByIndex\"\n\t"
 	".text\n\t"
 );
diff --git a/xpcom/string/public/nsXPCOMStrings.h b/xpcom/string/public/nsXPCOMStrings.h
index 88ed11311809..a2e7ded668a9 100644
--- a/xpcom/string/public/nsXPCOMStrings.h
+++ b/xpcom/string/public/nsXPCOMStrings.h
@@ -18,34 +18,6 @@
  * dependency on the implementation details of the abstract string types.
  */
 
-// Map frozen functions to private symbol names if not using strict API.
-#ifdef MOZILLA_INTERNAL_API
-# define NS_StringContainerInit           NS_StringContainerInit_P
-# define NS_StringContainerInit2          NS_StringContainerInit2_P
-# define NS_StringContainerFinish         NS_StringContainerFinish_P
-# define NS_StringGetData                 NS_StringGetData_P
-# define NS_StringGetMutableData          NS_StringGetMutableData_P
-# define NS_StringCloneData               NS_StringCloneData_P
-# define NS_StringSetData                 NS_StringSetData_P
-# define NS_StringSetDataRange            NS_StringSetDataRange_P
-# define NS_StringCopy                    NS_StringCopy_P
-# define NS_StringSetIsVoid               NS_StringSetIsVoid_P
-# define NS_StringGetIsVoid               NS_StringGetIsVoid_P
-# define NS_CStringContainerInit          NS_CStringContainerInit_P
-# define NS_CStringContainerInit2         NS_CStringContainerInit2_P
-# define NS_CStringContainerFinish        NS_CStringContainerFinish_P
-# define NS_CStringGetData                NS_CStringGetData_P
-# define NS_CStringGetMutableData         NS_CStringGetMutableData_P
-# define NS_CStringCloneData              NS_CStringCloneData_P
-# define NS_CStringSetData                NS_CStringSetData_P
-# define NS_CStringSetDataRange           NS_CStringSetDataRange_P
-# define NS_CStringCopy                   NS_CStringCopy_P
-# define NS_CStringSetIsVoid              NS_CStringSetIsVoid_P
-# define NS_CStringGetIsVoid              NS_CStringGetIsVoid_P
-# define NS_CStringToUTF16                NS_CStringToUTF16_P
-# define NS_UTF16ToCString                NS_UTF16ToCString_P
-#endif
-
 #include "nscore.h"
 
 /* The base string types */
diff --git a/xpcom/stub/Makefile.in b/xpcom/stub/Makefile.in
deleted file mode 100644
index fa1af211031b..000000000000
--- a/xpcom/stub/Makefile.in
+++ /dev/null
@@ -1,58 +0,0 @@
-# vim:set ts=8 sw=8 sts=8 noet:
-# 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		= @DEPTH@
-topsrcdir	= @top_srcdir@
-srcdir		= @srcdir@
-VPATH		= @srcdir@
-
-include $(DEPTH)/config/autoconf.mk
-
-LIBRARY_NAME	= xpcom
-
-# The XPCOM glue uses realpath() on libxpcom.so to resolve any symlinks. We
-# want it to find dist/bin and not xpcom/stub so we copy instead of symlinking.
-NSDISTMODE = copy
-
-# Do not set EXPORT_LIBRARY as we do not want xpcom in the static libs list
-#EXPORT_LIBRARY = 1
-MOZILLA_INTERNAL_API = 1
-
-
-LOCAL_INCLUDES	= -I$(srcdir)/../build
-
-CPPSRCS		= nsXPComStub.cpp
-
-# If we have an import library, then copy that to the SDK.  Otherwise,
-# copy the shared library.
-ifneq (,$(filter OS2 WINNT,$(OS_ARCH)))
-SDK_LIBRARY = $(IMPORT_LIBRARY)
-else
-SDK_LIBRARY = $(SHARED_LIBRARY)
-endif
-
-
-FORCE_SHARED_LIB = 1
-
-EXTRA_DSO_LDOPTS = $(LIBS_DIR)
-
-ifeq (bundle,$(MOZ_FS_LAYOUT))
-EXTRA_DSO_LDOPTS += $(DIST)/bin/XUL
-else
-EXTRA_DSO_LIBS = xul
-endif
-
-EXTRA_DSO_LDOPTS +=				\
-	$(EXTRA_DSO_LIBS)			\
-	$(NSPR_LIBS)				\
-	$(MOZALLOC_LIB)				\
-	$(NULL)
-
-include $(topsrcdir)/config/rules.mk
-
-libs:: $(FINAL_TARGET)/dependentlibs.list
-
-$(FINAL_TARGET)/dependentlibs.list: dependentlibs.py $(SHARED_LIBRARY) $(wildcard $(if $(wildcard $(FINAL_TARGET)/dependentlibs.list),$(addprefix $(FINAL_TARGET)/,$(shell cat $(FINAL_TARGET)/dependentlibs.list))))
-	$(PYTHON) $< $(SHARED_LIBRARY) -L $(FINAL_TARGET) $(if $(TOOLCHAIN_PREFIX),$(addprefix -p ,$(TOOLCHAIN_PREFIX))) > $@
diff --git a/xpcom/stub/moz.build b/xpcom/stub/moz.build
deleted file mode 100644
index 319e138ea124..000000000000
--- a/xpcom/stub/moz.build
+++ /dev/null
@@ -1,7 +0,0 @@
-# vim: set filetype=python:
-# 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/.
-
-MODULE = 'xpcom'
-
diff --git a/xpcom/stub/nsXPComStub.cpp b/xpcom/stub/nsXPComStub.cpp
deleted file mode 100644
index 4e90cd87b448..000000000000
--- a/xpcom/stub/nsXPComStub.cpp
+++ /dev/null
@@ -1,514 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsXPCOM.h"
-#include "nsXPCOMPrivate.h"
-#include "nsXPCOMStrings.h"
-#include "xptcall.h"
-
-#include 
-
-/**
- * Private Method to register an exit routine.  This method
- * used to allow you to setup a callback that will be called from 
- * the NS_ShutdownXPCOM function after all services and 
- * components have gone away. It was fatally flawed in that the component
- * DLL could be released before the exit function was called; it is now a
- * stub implementation that does nothing.
- */
-XPCOM_API(nsresult)
-NS_RegisterXPCOMExitRoutine(XPCOMExitRoutine exitRoutine, uint32_t priority);
-
-XPCOM_API(nsresult)
-NS_UnregisterXPCOMExitRoutine(XPCOMExitRoutine exitRoutine);
-
-static const XPCOMFunctions kFrozenFunctions = {
-    XPCOM_GLUE_VERSION,
-    sizeof(XPCOMFunctions),
-    &NS_InitXPCOM2_P,
-    &NS_ShutdownXPCOM_P,
-    &NS_GetServiceManager_P,
-    &NS_GetComponentManager_P,
-    &NS_GetComponentRegistrar_P,
-    &NS_GetMemoryManager_P,
-    &NS_NewLocalFile_P,
-    &NS_NewNativeLocalFile_P,
-    &NS_RegisterXPCOMExitRoutine,
-    &NS_UnregisterXPCOMExitRoutine,
-
-    // these functions were added post 1.4
-    &NS_GetDebug_P,
-    &NS_GetTraceRefcnt_P,
-
-    // these functions were added post 1.6
-    &NS_StringContainerInit_P,
-    &NS_StringContainerFinish_P,
-    &NS_StringGetData_P,
-    &NS_StringSetData_P,
-    &NS_StringSetDataRange_P,
-    &NS_StringCopy_P,
-    &NS_CStringContainerInit_P,
-    &NS_CStringContainerFinish_P,
-    &NS_CStringGetData_P,
-    &NS_CStringSetData_P,
-    &NS_CStringSetDataRange_P,
-    &NS_CStringCopy_P,
-    &NS_CStringToUTF16_P,
-    &NS_UTF16ToCString_P,
-    &NS_StringCloneData_P,
-    &NS_CStringCloneData_P,
-
-    // these functions were added post 1.7 (post Firefox 1.0)
-    &NS_Alloc_P,
-    &NS_Realloc_P,
-    &NS_Free_P,
-    &NS_StringContainerInit2_P,
-    &NS_CStringContainerInit2_P,
-    &NS_StringGetMutableData_P,
-    &NS_CStringGetMutableData_P,
-    NULL,
-
-    // these functions were added post 1.8
-    &NS_DebugBreak_P,
-    &NS_LogInit_P,
-    &NS_LogTerm_P,
-    &NS_LogAddRef_P,
-    &NS_LogRelease_P,
-    &NS_LogCtor_P,
-    &NS_LogDtor_P,
-    &NS_LogCOMPtrAddRef_P,
-    &NS_LogCOMPtrRelease_P,
-    &NS_GetXPTCallStub_P,
-    &NS_DestroyXPTCallStub_P,
-    &NS_InvokeByIndex_P,
-    nullptr,
-    nullptr,
-    &NS_StringSetIsVoid_P,
-    &NS_StringGetIsVoid_P,
-    &NS_CStringSetIsVoid_P,
-    &NS_CStringGetIsVoid_P,
-
-    // these functions were added post 1.9
-    &NS_CycleCollectorSuspect2_P,
-    &NS_CycleCollectorForget2_P
-};
-
-EXPORT_XPCOM_API(nsresult)
-NS_GetFrozenFunctions(XPCOMFunctions *functions, const char* /* libraryPath */)
-{
-    if (!functions)
-        return NS_ERROR_OUT_OF_MEMORY;
-
-    if (functions->version != XPCOM_GLUE_VERSION)
-        return NS_ERROR_FAILURE;
-
-    uint32_t size = functions->size;
-    if (size > sizeof(XPCOMFunctions))
-        size = sizeof(XPCOMFunctions);
-
-    size -= offsetof(XPCOMFunctions, init);
-
-    memcpy(&functions->init, &kFrozenFunctions.init, size);
-
-    return NS_OK;
-}
-
-/*
- * Stubs for nsXPCOM.h
- */
-
-#undef NS_InitXPCOM2
-EXPORT_XPCOM_API(nsresult)
-NS_InitXPCOM2(nsIServiceManager **result,
-              nsIFile *binDirectory,
-              nsIDirectoryServiceProvider *dirProvider)
-{
-  return NS_InitXPCOM2_P(result, binDirectory, dirProvider);
-}
-
-#undef NS_ShutdownXPCOM
-EXPORT_XPCOM_API(nsresult)
-NS_ShutdownXPCOM(nsIServiceManager *svcMgr)
-{
-  return NS_ShutdownXPCOM_P(svcMgr);
-}
-
-#undef NS_GetServiceManager
-EXPORT_XPCOM_API(nsresult)
-NS_GetServiceManager(nsIServiceManager* *result)
-{
-  return NS_GetServiceManager_P(result);
-}
-
-#undef NS_GetComponentManager
-EXPORT_XPCOM_API(nsresult)
-NS_GetComponentManager(nsIComponentManager* *result)
-{
-  return NS_GetComponentManager_P(result);
-}
-
-#undef NS_GetComponentRegistrar
-EXPORT_XPCOM_API(nsresult)
-NS_GetComponentRegistrar(nsIComponentRegistrar** result)
-{
-  return NS_GetComponentRegistrar_P(result);
-}
-
-#undef NS_GetMemoryManager
-EXPORT_XPCOM_API(nsresult)
-NS_GetMemoryManager(nsIMemory* *result)
-{
-  return NS_GetMemoryManager_P(result);
-}
-
-#undef NS_NewLocalFile
-EXPORT_XPCOM_API(nsresult)
-NS_NewLocalFile(const nsAString &path,
-                bool followLinks,
-                nsIFile **result)
-{
-  return NS_NewLocalFile_P(path, followLinks, result);
-}
-
-#undef NS_NewNativeLocalFile
-EXPORT_XPCOM_API(nsresult)
-NS_NewNativeLocalFile(const nsACString &path,
-                      bool followLinks,
-                      nsIFile **result)
-{
-  return NS_NewNativeLocalFile_P(path, followLinks, result);
-}
-
-#undef NS_GetDebug
-EXPORT_XPCOM_API(nsresult)
-NS_GetDebug(nsIDebug **result)
-{
-  return NS_GetDebug_P(result);
-}
-
-#undef NS_GetTraceRefcnt
-EXPORT_XPCOM_API(nsresult)
-NS_GetTraceRefcnt(nsITraceRefcnt **result)
-{
-  return NS_GetTraceRefcnt_P(result);
-}
-
-#undef NS_Alloc
-EXPORT_XPCOM_API(void*)
-NS_Alloc(size_t size)
-{
-  return NS_Alloc_P(size);
-}
-
-#undef NS_Realloc
-EXPORT_XPCOM_API(void*)
-NS_Realloc(void* ptr, size_t size)
-{
-  return NS_Realloc_P(ptr, size);
-}
-
-#undef NS_Free
-EXPORT_XPCOM_API(void)
-NS_Free(void* ptr)
-{
-  NS_Free_P(ptr);
-}
-
-#undef NS_DebugBreak
-EXPORT_XPCOM_API(void)
-NS_DebugBreak(uint32_t aSeverity, const char *aStr, const char *aExpr,
-              const char *aFile, int32_t aLine)
-{
-  NS_DebugBreak_P(aSeverity, aStr, aExpr, aFile, aLine);
-}
-
-#undef NS_LogInit
-EXPORT_XPCOM_API(void)
-NS_LogInit()
-{
-  NS_LogInit_P();
-}
-
-#undef NS_LogTerm
-EXPORT_XPCOM_API(void)
-NS_LogTerm()
-{
-  NS_LogTerm_P();
-}
-
-#undef NS_LogAddRef
-EXPORT_XPCOM_API(void)
-NS_LogAddRef(void* aPtr, nsrefcnt aNewRefCnt,
-             const char *aTypeName, uint32_t aInstanceSize)
-{
-  NS_LogAddRef_P(aPtr, aNewRefCnt, aTypeName, aInstanceSize);
-}
-
-#undef NS_LogRelease
-EXPORT_XPCOM_API(void)
-NS_LogRelease(void* aPtr, nsrefcnt aNewRefCnt, const char *aTypeName)
-{
-  NS_LogRelease_P(aPtr, aNewRefCnt, aTypeName);
-}
-
-#undef NS_LogCtor
-EXPORT_XPCOM_API(void)
-NS_LogCtor(void *aPtr, const char *aTypeName, uint32_t aInstanceSize)
-{
-  NS_LogCtor_P(aPtr, aTypeName, aInstanceSize);
-}
-
-#undef NS_LogDtor
-EXPORT_XPCOM_API(void)
-NS_LogDtor(void *aPtr, const char *aTypeName, uint32_t aInstanceSize)
-{
-  NS_LogDtor_P(aPtr, aTypeName, aInstanceSize);
-}
-
-#undef NS_LogCOMPtrAddRef
-EXPORT_XPCOM_API(void)
-NS_LogCOMPtrAddRef(void *aCOMPtr, nsISupports* aObject)
-{
-  NS_LogCOMPtrAddRef_P(aCOMPtr, aObject);
-}
-
-#undef NS_LogCOMPtrRelease
-EXPORT_XPCOM_API(void)
-NS_LogCOMPtrRelease(void *aCOMPtr, nsISupports* aObject)
-{
-  NS_LogCOMPtrRelease_P(aCOMPtr, aObject);
-}
-
-#undef NS_GetXPTCallStub
-EXPORT_XPCOM_API(nsresult)
-NS_GetXPTCallStub(REFNSIID aIID, nsIXPTCProxy* aOuter,
-                  nsISomeInterface* *aStub)
-{
-  return NS_GetXPTCallStub_P(aIID, aOuter, aStub);
-}
-
-#undef NS_DestroyXPTCallStub
-EXPORT_XPCOM_API(void)
-NS_DestroyXPTCallStub(nsISomeInterface* aStub)
-{
-  NS_DestroyXPTCallStub_P(aStub);
-}
-
-#undef NS_InvokeByIndex
-EXPORT_XPCOM_API(nsresult)
-NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
-                 uint32_t paramCount, nsXPTCVariant* params)
-{
-  return NS_InvokeByIndex_P(that, methodIndex, paramCount, params);
-}
-
-/*
- * Stubs for nsXPCOMPrivate.h
- */
-
-EXPORT_XPCOM_API(nsresult)
-NS_RegisterXPCOMExitRoutine(XPCOMExitRoutine exitRoutine, uint32_t priority)
-{
-  return NS_OK;
-}
-
-EXPORT_XPCOM_API(nsresult)
-NS_UnregisterXPCOMExitRoutine(XPCOMExitRoutine exitRoutine)
-{
-  return NS_OK;
-}
-
-/*
- * Stubs for nsStringAPI.h
- */
-
-#undef NS_StringContainerInit
-EXPORT_XPCOM_API(nsresult)
-NS_StringContainerInit(nsStringContainer &aStr)
-{
-  return NS_StringContainerInit_P(aStr);
-}
-
-#undef NS_StringContainerInit2
-EXPORT_XPCOM_API(nsresult)
-NS_StringContainerInit2(nsStringContainer &aStr,
-                        const PRUnichar   *aData,
-                        uint32_t           aDataLength,
-                        uint32_t           aFlags)
-{   
-  return NS_StringContainerInit2_P(aStr, aData, aDataLength, aFlags);
-}
-
-#undef NS_StringContainerFinish
-EXPORT_XPCOM_API(void)
-NS_StringContainerFinish(nsStringContainer &aStr)
-{
-  NS_StringContainerFinish_P(aStr);
-}
-
-#undef NS_StringGetData
-EXPORT_XPCOM_API(uint32_t)
-NS_StringGetData(const nsAString &aStr, const PRUnichar **aBuf, bool *aTerm)
-{
-  return NS_StringGetData_P(aStr, aBuf, aTerm);
-}
-
-#undef NS_StringGetMutableData
-EXPORT_XPCOM_API(uint32_t)
-NS_StringGetMutableData(nsAString &aStr, uint32_t aLen, PRUnichar **aBuf)
-{
-  return NS_StringGetMutableData_P(aStr, aLen, aBuf);
-}
-
-#undef NS_StringCloneData
-EXPORT_XPCOM_API(PRUnichar *)
-NS_StringCloneData(const nsAString &aStr)
-{
-  return NS_StringCloneData_P(aStr);
-}
-
-#undef NS_StringSetData
-EXPORT_XPCOM_API(nsresult)
-NS_StringSetData(nsAString &aStr, const PRUnichar *aBuf, uint32_t aCount)
-{
-  return NS_StringSetData_P(aStr, aBuf, aCount);
-}
-
-#undef NS_StringSetDataRange
-EXPORT_XPCOM_API(nsresult)
-NS_StringSetDataRange(nsAString &aStr, uint32_t aCutStart, uint32_t aCutLength,
-                      const PRUnichar *aBuf, uint32_t aCount)
-{
-  return NS_StringSetDataRange_P(aStr, aCutStart, aCutLength, aBuf, aCount);
-}
-
-#undef NS_StringCopy
-EXPORT_XPCOM_API(nsresult)
-NS_StringCopy(nsAString &aDest, const nsAString &aSrc)
-{
-  return NS_StringCopy_P(aDest, aSrc);
-}
-
-#undef NS_StringSetIsVoid
-EXPORT_XPCOM_API(void)
-NS_StringSetIsVoid(nsAString &aStr, const bool aIsVoid)
-{
-  NS_StringSetIsVoid_P(aStr, aIsVoid);
-}
-
-#undef NS_StringGetIsVoid
-EXPORT_XPCOM_API(bool)
-NS_StringGetIsVoid(const nsAString &aStr)
-{
-  return NS_StringGetIsVoid_P(aStr);
-}
-
-#undef NS_CStringContainerInit
-EXPORT_XPCOM_API(nsresult)
-NS_CStringContainerInit(nsCStringContainer &aStr)
-{
-  return NS_CStringContainerInit_P(aStr);
-}
-
-#undef NS_CStringContainerInit2
-EXPORT_XPCOM_API(nsresult)
-NS_CStringContainerInit2(nsCStringContainer &aStr,
-                         const char         *aData,
-                         uint32_t            aDataLength,
-                         uint32_t            aFlags)
-{   
-  return NS_CStringContainerInit2_P(aStr, aData, aDataLength, aFlags);
-}
-
-#undef NS_CStringContainerFinish
-EXPORT_XPCOM_API(void)
-NS_CStringContainerFinish(nsCStringContainer &aStr)
-{
-  NS_CStringContainerFinish_P(aStr);
-}
-
-#undef NS_CStringGetData
-EXPORT_XPCOM_API(uint32_t)
-NS_CStringGetData(const nsACString &aStr, const char **aBuf, bool *aTerm)
-{
-  return NS_CStringGetData_P(aStr, aBuf, aTerm);
-}
-
-#undef NS_CStringGetMutableData
-EXPORT_XPCOM_API(uint32_t)
-NS_CStringGetMutableData(nsACString &aStr, uint32_t aLen, char **aBuf)
-{
-  return NS_CStringGetMutableData_P(aStr, aLen, aBuf);
-}
-
-#undef NS_CStringCloneData
-EXPORT_XPCOM_API(char *)
-NS_CStringCloneData(const nsACString &aStr)
-{
-  return NS_CStringCloneData_P(aStr);
-}
-
-#undef NS_CStringSetData
-EXPORT_XPCOM_API(nsresult)
-NS_CStringSetData(nsACString &aStr, const char *aBuf, uint32_t aCount)
-{
-  return NS_CStringSetData_P(aStr, aBuf, aCount);
-}
-
-#undef NS_CStringSetDataRange
-EXPORT_XPCOM_API(nsresult)
-NS_CStringSetDataRange(nsACString &aStr, uint32_t aCutStart, uint32_t aCutLength,
-                       const char *aBuf, uint32_t aCount)
-{
-  return NS_CStringSetDataRange_P(aStr, aCutStart, aCutLength, aBuf, aCount);
-}
-
-#undef NS_CStringCopy
-EXPORT_XPCOM_API(nsresult)
-NS_CStringCopy(nsACString &aDest, const nsACString &aSrc)
-{
-  return NS_CStringCopy_P(aDest, aSrc);
-}
-
-#undef NS_CStringSetIsVoid
-EXPORT_XPCOM_API(void)
-NS_CStringSetIsVoid(nsACString &aStr, const bool aIsVoid)
-{
-  NS_CStringSetIsVoid_P(aStr, aIsVoid);
-}
-
-#undef NS_CStringGetIsVoid
-EXPORT_XPCOM_API(bool)
-NS_CStringGetIsVoid(const nsACString &aStr)
-{
-  return NS_CStringGetIsVoid_P(aStr);
-}
-
-#undef NS_CStringToUTF16
-EXPORT_XPCOM_API(nsresult)
-NS_CStringToUTF16(const nsACString &aSrc, nsCStringEncoding aSrcEncoding, nsAString &aDest)
-{
-  return NS_CStringToUTF16_P(aSrc, aSrcEncoding, aDest);
-}
-
-#undef NS_UTF16ToCString
-EXPORT_XPCOM_API(nsresult)
-NS_UTF16ToCString(const nsAString &aSrc, nsCStringEncoding aDestEncoding, nsACString &aDest)
-{
-  return NS_UTF16ToCString_P(aSrc, aDestEncoding, aDest);
-}
-
-#undef NS_CycleCollectorSuspect2
-EXPORT_XPCOM_API(nsPurpleBufferEntry*)
-NS_CycleCollectorSuspect2(void *obj, nsCycleCollectionParticipant *p)
-{
-  return NS_CycleCollectorSuspect2_P(obj, p);
-}
-
-#undef NS_CycleCollectorForget2
-EXPORT_XPCOM_API(bool)
-NS_CycleCollectorForget2(nsPurpleBufferEntry* e)
-{
-  return NS_CycleCollectorForget2_P(e);
-}

From 550c552aadac1ab0689b3903204b8b9befaccdc7 Mon Sep 17 00:00:00 2001
From: Tim Taubert 
Date: Tue, 26 Mar 2013 15:00:59 +0100
Subject: [PATCH 123/129] Bug 854075 - Use mouseover instead of mouseenter for
 newtab page; r=jaws

---
 browser/base/content/newtab/sites.js | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/browser/base/content/newtab/sites.js b/browser/base/content/newtab/sites.js
index 229532eca987..d1745aff9edc 100644
--- a/browser/base/content/newtab/sites.js
+++ b/browser/base/content/newtab/sites.js
@@ -144,7 +144,7 @@ Site.prototype = {
     // Register drag-and-drop event handlers.
     this._node.addEventListener("dragstart", this, false);
     this._node.addEventListener("dragend", this, false);
-    this._node.addEventListener("mouseenter", this, false);
+    this._node.addEventListener("mouseover", this, false);
 
     let controls = this.node.querySelectorAll(".newtab-control");
     for (let i = 0; i < controls.length; i++)
@@ -174,7 +174,8 @@ Site.prototype = {
         else
           this.pin();
         break;
-      case "mouseenter":
+      case "mouseover":
+        this._node.removeEventListener("mouseover", this, false);
         this._speculativeConnect();
         break;
       case "dragstart":

From 23c0542a81270509dcb1c104d3768ce7fb1d8b29 Mon Sep 17 00:00:00 2001
From: Phil Ringnalda 
Date: Wed, 27 Mar 2013 00:03:49 -0700
Subject: [PATCH 124/129] Back out 8b8db1d07846 (bug 855178) for asserting

---
 gfx/gl/SharedSurfaceGL.cpp | 19 ++++++++++++++-----
 1 file changed, 14 insertions(+), 5 deletions(-)

diff --git a/gfx/gl/SharedSurfaceGL.cpp b/gfx/gl/SharedSurfaceGL.cpp
index 51a79c71fd51..7a96ef14cfc2 100644
--- a/gfx/gl/SharedSurfaceGL.cpp
+++ b/gfx/gl/SharedSurfaceGL.cpp
@@ -365,13 +365,22 @@ SharedSurface_GLTexture::WaitSync()
         // We must have used glFinish instead of glFenceSync.
         return true;
     }
-    MOZ_ASSERT(mConsGL->IsExtensionSupported(GLContext::ARB_sync));
+    MOZ_ASSERT(mGL->IsExtensionSupported(GLContext::ARB_sync));
 
-    mConsGL->fWaitSync(mSync,
-                       0,
-                       LOCAL_GL_TIMEOUT_IGNORED);
+    GLuint64 waitMS = 500;
+    const GLuint64 nsPerMS = 1000 * 1000;
+    GLuint64 waitNS = waitMS * nsPerMS;
+    GLenum status = mGL->fClientWaitSync(mSync,
+                                         0,
+                                         waitNS);
 
-    mConsGL->fDeleteSync(mSync);
+    if (status != LOCAL_GL_CONDITION_SATISFIED &&
+        status != LOCAL_GL_ALREADY_SIGNALED)
+    {
+        return false;
+    }
+
+    mGL->fDeleteSync(mSync);
     mSync = 0;
 
     return true;

From 93819890bdd088941c26da382ac26f909bb7d439 Mon Sep 17 00:00:00 2001
From: Daniel Holbert 
Date: Wed, 27 Mar 2013 00:03:58 -0700
Subject: [PATCH 125/129] Bug 855109: Fix typo in configure.in line for making
 gcc/clang c++ compilers use -Wsign-compare. r=glandium

---
 configure.in        | 2 +-
 js/src/configure.in | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/configure.in b/configure.in
index 1a4ff62c2a6c..fc2b072de57c 100644
--- a/configure.in
+++ b/configure.in
@@ -1489,7 +1489,7 @@ if test "$GNU_CXX"; then
     MOZ_CXX_SUPPORTS_WARNING(-W, error=return-type, ac_cxx_has_werror_return_type)
     MOZ_CXX_SUPPORTS_WARNING(-W, type-limits, ac_cxx_has_wtype_limits)
     MOZ_CXX_SUPPORTS_WARNING(-W, empty-body, ac_cxx_has_wempty_body)
-    MOZ_CXX_SUPPORTS_WARNING(-W, sign-compare, ac_c_has_sign_compare)
+    MOZ_CXX_SUPPORTS_WARNING(-W, sign-compare, ac_cxx_has_sign_compare)
 
     # Turn off the following warnings that -Wall turns on:
     # -Wno-invalid-offsetof - we use offsetof on non-POD types frequently
diff --git a/js/src/configure.in b/js/src/configure.in
index 25c6ffe1178f..78ea0b659349 100644
--- a/js/src/configure.in
+++ b/js/src/configure.in
@@ -1234,7 +1234,7 @@ if test "$GNU_CXX"; then
     MOZ_CXX_SUPPORTS_WARNING(-W, type-limits, ac_cxx_has_wtype_limits)
     MOZ_CXX_SUPPORTS_WARNING(-W, empty-body, ac_cxx_has_wempty_body)
     MOZ_CXX_SUPPORTS_WARNING(-W, error=conversion-null, ac_cxx_has_werror_conversion_null)
-    MOZ_CXX_SUPPORTS_WARNING(-W, sign-compare, ac_c_has_sign_compare)
+    MOZ_CXX_SUPPORTS_WARNING(-W, sign-compare, ac_cxx_has_sign_compare)
 
     # Turn off the following warnings that -Wall turns on:
     # -Wno-invalid-offsetof - we use offsetof on non-POD types frequently

From 7551fca1025e97659b6bb011bb04f561d23f54c6 Mon Sep 17 00:00:00 2001
From: Daniel Holbert 
Date: Wed, 27 Mar 2013 00:04:00 -0700
Subject: [PATCH 126/129] (no bug) Remove some whitespace on blank line, in
 configure.in. whitespace-only, DONTBUILD

---
 configure.in | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/configure.in b/configure.in
index fc2b072de57c..e700e2350175 100644
--- a/configure.in
+++ b/configure.in
@@ -1426,7 +1426,7 @@ if test "$GNU_CC"; then
     MOZ_C_SUPPORTS_WARNING(-W, type-limits, ac_c_has_wtype_limits)
     MOZ_C_SUPPORTS_WARNING(-W, empty-body, ac_c_has_wempty_body)
     MOZ_C_SUPPORTS_WARNING(-W, sign-compare, ac_c_has_sign_compare)
-    
+
     # Turn off the following warnings that -Wall turns on:
     # -Wno-unused - lots of violations in third-party code
     #

From 5beff520cd98ba812920aa66320627f568998c14 Mon Sep 17 00:00:00 2001
From: Makoto Kato 
Date: Wed, 27 Mar 2013 16:51:43 +0900
Subject: [PATCH 127/129] Bug 855173 - jsshell package needs nss3.dll due to
 MOZ_FOLD_LIBS. r=glandium

---
 toolkit/mozapps/installer/packager.mk | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/toolkit/mozapps/installer/packager.mk b/toolkit/mozapps/installer/packager.mk
index 3297480f70d4..7248b70afe9c 100644
--- a/toolkit/mozapps/installer/packager.mk
+++ b/toolkit/mozapps/installer/packager.mk
@@ -70,7 +70,6 @@ JSSHELL_BINS  = \
   $(DIST)/bin/$(DLL_PREFIX)mozglue$(DLL_SUFFIX) \
   $(NULL)
 ifndef MOZ_NATIVE_NSPR
-ifeq ($(OS_ARCH),WINNT)
 ifeq ($(_MSC_VER),1400)
 JSSHELL_BINS += $(DIST)/bin/Microsoft.VC80.CRT.manifest
 JSSHELL_BINS += $(DIST)/bin/msvcr80.dll
@@ -85,7 +84,6 @@ endif
 ifeq ($(_MSC_VER),1700)
 JSSHELL_BINS += $(DIST)/bin/msvcr110.dll
 endif
-else
 ifdef MOZ_FOLD_LIBS
 JSSHELL_BINS += $(DIST)/bin/$(DLL_PREFIX)nss3$(DLL_SUFFIX)
 else
@@ -95,7 +93,6 @@ JSSHELL_BINS += \
   $(DIST)/bin/$(DLL_PREFIX)plc4$(DLL_SUFFIX) \
   $(NULL)
 endif # MOZ_FOLD_LIBS
-endif
 endif # MOZ_NATIVE_NSPR
 MAKE_JSSHELL  = $(ZIP) -9j $(PKG_JSSHELL) $(JSSHELL_BINS)
 endif # LIBXUL_SDK

From 4dd126b52b936d2613867f1528e8039bb4e4ae7a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?D=C3=A3o=20Gottwald?= 
Date: Wed, 27 Mar 2013 10:01:04 +0100
Subject: [PATCH 128/129] Bug 764971 - Hide progress indicators in tabs for
 chrome pages. r=ttaubert

---
 browser/base/content/tabbrowser.xml | 20 ++++++++++++++++++--
 1 file changed, 18 insertions(+), 2 deletions(-)

diff --git a/browser/base/content/tabbrowser.xml b/browser/base/content/tabbrowser.xml
index 3acc43118b98..d3742ac6cc60 100644
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -448,12 +448,28 @@
               return this.mTabBrowser._callProgressListeners.apply(this.mTabBrowser, arguments);
             },
 
+            _shouldShowProgress: function (aRequest) {
+              if (this.mBlank)
+                return false;
+
+              // Don't show progress indicators in tabs for about: URIs
+              // pointing to local resources.
+              try {
+                let channel = aRequest.QueryInterface(Ci.nsIChannel);
+                if (channel.originalURI.schemeIs("about") &&
+                    (channel.URI.schemeIs("jar") || channel.URI.schemeIs("file")))
+                  return false;
+              } catch (e) {}
+
+              return true;
+            },
+
             onProgressChange: function (aWebProgress, aRequest,
                                         aCurSelfProgress, aMaxSelfProgress,
                                         aCurTotalProgress, aMaxTotalProgress) {
               this.mTotalProgress = aMaxTotalProgress ? aCurTotalProgress / aMaxTotalProgress : 0;
 
-              if (this.mBlank)
+              if (!this._shouldShowProgress(aRequest))
                 return;
 
               if (this.mTotalProgress)
@@ -510,7 +526,7 @@
                 if (aWebProgress.DOMWindow == this.mBrowser.contentWindow)
                   this.mBrowser.userTypedClear += 2;
 
-                if (!this.mBlank) {
+                if (this._shouldShowProgress(aRequest)) {
                   if (!(aStateFlags & nsIWebProgressListener.STATE_RESTORING)) {
                     this.mTab.setAttribute("busy", "true");
                     if (!(this.mBrowser.docShell.loadType & Ci.nsIDocShell.LOAD_CMD_RELOAD))

From dfd58002231f09966dd89eb0eebab142dfa64552 Mon Sep 17 00:00:00 2001
From: Robert Longson 
Date: Wed, 27 Mar 2013 10:19:02 +0000
Subject: [PATCH 129/129] Bug 842630 - Fix out of bounds in
 nsSVGTextFrame2::ResolvePositions. r=heycam

---
 layout/svg/crashtests/842630-1.svg    | 1 +
 layout/svg/crashtests/crashtests.list | 1 +
 layout/svg/nsSVGTextFrame2.cpp        | 8 ++++----
 3 files changed, 6 insertions(+), 4 deletions(-)
 create mode 100644 layout/svg/crashtests/842630-1.svg

diff --git a/layout/svg/crashtests/842630-1.svg b/layout/svg/crashtests/842630-1.svg
new file mode 100644
index 000000000000..8d36998be677
--- /dev/null
+++ b/layout/svg/crashtests/842630-1.svg
@@ -0,0 +1 @@
+AB
diff --git a/layout/svg/crashtests/crashtests.list b/layout/svg/crashtests/crashtests.list
index f5e25502aa74..a894c7fb5ecd 100644
--- a/layout/svg/crashtests/crashtests.list
+++ b/layout/svg/crashtests/crashtests.list
@@ -154,6 +154,7 @@ load 813420-1.svg
 load 841163-1.svg
 load 841812-1.svg
 load 842009-1.svg
+load 842630-1.svg
 load 842909-1.svg
 load 843072-1.svg
 load 847139-1.svg
diff --git a/layout/svg/nsSVGTextFrame2.cpp b/layout/svg/nsSVGTextFrame2.cpp
index 01de90562e20..5c981c833809 100644
--- a/layout/svg/nsSVGTextFrame2.cpp
+++ b/layout/svg/nsSVGTextFrame2.cpp
@@ -4079,10 +4079,7 @@ nsSVGTextFrame2::ResolvePositions(nsTArray& aDeltas)
 
   // Fill in unspecified positions for all remaining characters, noting
   // them as unaddressable if they are.
-  uint32_t index = it.TextElementCharIndex();
-  for (uint32_t i = 0; i < index; i++) {
-    mPositions.AppendElement(CharPosition::Unspecified(false));
-  }
+  uint32_t index = 0;
   while (it.Next()) {
     while (++index < it.TextElementCharIndex()) {
       mPositions.AppendElement(CharPosition::Unspecified(false));
@@ -4090,6 +4087,9 @@ nsSVGTextFrame2::ResolvePositions(nsTArray& aDeltas)
     mPositions.AppendElement(CharPosition::Unspecified(
                                              it.IsOriginalCharUnaddressable()));
   }
+  while (++index < it.TextElementCharIndex()) {
+    mPositions.AppendElement(CharPosition::Unspecified(false));
+  }
 
   // Recurse over the content and fill in character positions as we go.
   bool forceStartOfChunk = false;