author | Wes Kocher <wkocher@mozilla.com> |
Wed, 22 Mar 2017 17:10:01 -0700 | |
changeset 348980 | 7513b3f42058e9bcf9950d4acf4647d4ad2240f0 |
parent 348938 | 08b46c736a62d3d572d67259420a093d564afd2e (current diff) |
parent 348979 | 8b30d5f5b423e6047eff9095c6f7181c331c8972 (diff) |
child 349094 | 89b93d310da5bc7f86ebcdb8fe580d47a610757a |
push id | 31540 |
push user | kwierso@gmail.com |
push date | Thu, 23 Mar 2017 00:10:08 +0000 |
treeherder | mozilla-central@7513b3f42058 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | merge |
milestone | 55.0a1 |
first release with | nightly linux32
7513b3f42058
/
55.0a1
/
20170323110205
/
files
nightly linux64
7513b3f42058
/
55.0a1
/
20170323110205
/
files
nightly mac
7513b3f42058
/
55.0a1
/
20170323030203
/
files
nightly win32
7513b3f42058
/
55.0a1
/
20170323030203
/
files
nightly win64
7513b3f42058
/
55.0a1
/
20170323030203
/
files
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
releases | nightly linux32
55.0a1
/
20170323110205
/
pushlog to previous
nightly linux64
55.0a1
/
20170323110205
/
pushlog to previous
nightly mac
55.0a1
/
20170323030203
/
pushlog to previous
nightly win32
55.0a1
/
20170323030203
/
pushlog to previous
nightly win64
55.0a1
/
20170323030203
/
pushlog to previous
|
--- a/accessible/base/TextAttrs.cpp +++ b/accessible/base/TextAttrs.cpp @@ -13,20 +13,16 @@ #include "gfxFont.h" #include "nsFontMetrics.h" #include "nsLayoutUtils.h" #include "nsContainerFrame.h" #include "HyperTextAccessible.h" #include "mozilla/AppUnits.h" #include "mozilla/gfx/2D.h" -#if defined(MOZ_WIDGET_GTK) -#include "gfxPlatformGtk.h" // xxx - for UseFcFontList -#endif - using namespace mozilla; using namespace mozilla::a11y; //////////////////////////////////////////////////////////////////////////////// // TextAttrsMgr //////////////////////////////////////////////////////////////////////////////// void @@ -647,38 +643,24 @@ TextAttrsMgr::FontWeightTextAttr:: // When there doesn't exist a bold font in the family and so the rendering of // a non-bold font face is changed so that the user sees what looks like a // bold font, i.e. synthetic bolding is used. IsSyntheticBold method is only // needed on Mac, but it is "safe" to use on all platforms. (For non-Mac // platforms it always return false.) if (font->IsSyntheticBold()) return 700; - bool useFontEntryWeight = true; - - // Under Linux, when gfxPangoFontGroup code is used, - // font->GetStyle()->weight will give the absolute weight requested of the - // font face. The gfxPangoFontGroup code uses the gfxFontEntry constructor - // which doesn't initialize the weight field. -#if defined(MOZ_WIDGET_GTK) - useFontEntryWeight = gfxPlatformGtk::UseFcFontList(); -#endif - - if (useFontEntryWeight) { - // On Windows, font->GetStyle()->weight will give the same weight as - // fontEntry->Weight(), the weight of the first font in the font group, - // which may not be the weight of the font face used to render the - // characters. On Mac, font->GetStyle()->weight will just give the same - // number as getComputedStyle(). fontEntry->Weight() will give the weight - // of the font face used. - gfxFontEntry *fontEntry = font->GetFontEntry(); - return fontEntry->Weight(); - } else { - return font->GetStyle()->weight; - } + // On Windows, font->GetStyle()->weight will give the same weight as + // fontEntry->Weight(), the weight of the first font in the font group, + // which may not be the weight of the font face used to render the + // characters. On Mac, font->GetStyle()->weight will just give the same + // number as getComputedStyle(). fontEntry->Weight() will give the weight + // of the font face used. + gfxFontEntry *fontEntry = font->GetFontEntry(); + return fontEntry->Weight(); } //////////////////////////////////////////////////////////////////////////////// // AutoGeneratedTextAttr //////////////////////////////////////////////////////////////////////////////// TextAttrsMgr::AutoGeneratedTextAttr:: AutoGeneratedTextAttr(HyperTextAccessible* aHyperTextAcc, Accessible* aAccessible) :
--- a/browser/base/content/pageinfo/permissions.js +++ b/browser/base/content/pageinfo/permissions.js @@ -213,27 +213,28 @@ function onIndexedDBClear() { } function onIndexedDBUsageCallback(request) { let uri = request.principal.URI; if (!uri.equals(gPermURI)) { throw new Error("Callback received for bad URI: " + uri); } - if (request.usage) { + let usage = request.result.usage; + if (usage) { if (!("DownloadUtils" in window)) { Components.utils.import("resource://gre/modules/DownloadUtils.jsm"); } var status = document.getElementById("indexedDBStatus"); var button = document.getElementById("indexedDBClear"); status.value = gBundle.getFormattedString("indexedDBUsage", - DownloadUtils.convertByteUnits(request.usage)); + DownloadUtils.convertByteUnits(usage)); status.removeAttribute("hidden"); button.removeAttribute("hidden"); } } function fillInPluginPermissionTemplate(aPluginName, aPermissionString) { let permPluginTemplate = document.getElementById("permPluginTemplate").cloneNode(true); permPluginTemplate.setAttribute("permString", aPermissionString);
--- a/browser/base/content/tabbrowser.xml +++ b/browser/base/content/tabbrowser.xml @@ -63,19 +63,16 @@ <field name="mURIFixup" readonly="true"> Components.classes["@mozilla.org/docshell/urifixup;1"] .getService(Components.interfaces.nsIURIFixup); </field> <field name="_unifiedComplete" readonly="true"> Components.classes["@mozilla.org/autocomplete/search;1?name=unifiedcomplete"] .getService(Components.interfaces.mozIPlacesAutoComplete); </field> - <field name="AppConstants" readonly="true"> - (Components.utils.import("resource://gre/modules/AppConstants.jsm", {})).AppConstants; - </field> <field name="mTabBox" readonly="true"> document.getAnonymousElementByAttribute(this, "anonid", "tabbox"); </field> <field name="mPanelContainer" readonly="true"> document.getAnonymousElementByAttribute(this, "anonid", "panelcontainer"); </field> <field name="mStringBundle"> document.getAnonymousElementByAttribute(this, "anonid", "tbstringbundle"); @@ -103,17 +100,17 @@ </field> <field name="mIsBusy"> false </field> <field name="_outerWindowIDBrowserMap"> new Map(); </field> <field name="arrowKeysShouldWrap" readonly="true"> - this.AppConstants.platform == "macosx"; + AppConstants == "macosx"; </field> <field name="_autoScrollPopup"> null </field> <field name="_previewMode"> false @@ -2650,26 +2647,28 @@ <body> <![CDATA[ if (aTab.closing || this._windowIsClosing) return false; var browser = this.getBrowserForTab(aTab); - if (!aTab._pendingPermitUnload && !aAdoptedByTab && !aSkipPermitUnload) { + if (!aTab._pendingPermitUnload && + !aSkipPermitUnload && + aTab.linkedPanel && + !aAdoptedByTab) { // We need to block while calling permitUnload() because it // processes the event queue and may lead to another removeTab() // call before permitUnload() returns. TelemetryStopwatch.start("FX_TAB_CLOSE_PERMIT_UNLOAD_TIME_MS", aTab); aTab._pendingPermitUnload = true; - let {permitUnload, timedOut} = aTab.linkedPanel ? - browser.permitUnload() : {permitUnload: true, timedOut: false}; + let {permitUnload, timedOut} = browser.permitUnload(); delete aTab._pendingPermitUnload; TelemetryStopwatch.finish("FX_TAB_CLOSE_PERMIT_UNLOAD_TIME_MS", aTab); // If we were closed during onbeforeunload, we return false now // so we don't (try to) close the same tab again. Of course, we // also stop if the unload was cancelled by the user: if (aTab.closing || (!timedOut && !permitUnload)) { @@ -3420,17 +3419,17 @@ </body> </method> <!-- Opens a given tab to a non-remote window. --> <method name="openNonRemoteWindow"> <parameter name="aTab"/> <body> <![CDATA[ - if (!this.AppConstants.E10S_TESTING_ONLY) { + if (!AppConstants.E10S_TESTING_ONLY) { throw "This method is intended only for e10s testing!"; } let url = aTab.linkedBrowser.currentURI.spec; return window.openDialog("chrome://browser/content/", "_blank", "chrome,all,dialog=no,non-remote", url); ]]> </body> </method> @@ -4032,17 +4031,17 @@ this.lastVisibleTab = this.visibleTab; }, assert(cond) { if (!cond) { dump("Assertion failure\n" + Error().stack); // Don't break a user's browser if an assertion fails. - if (this.tabbrowser.AppConstants.DEBUG) { + if (AppConstants.DEBUG) { throw new Error("Assertion failure"); } } }, // We've decided to try to load requestedTab. loadRequestedTab() { this.assert(!this.loadTimer); @@ -4808,17 +4807,17 @@ return; case aEvent.DOM_VK_PAGE_DOWN: this.moveTabForward(); aEvent.preventDefault(); return; } } - if (this.AppConstants.platform != "macosx") { + if (AppConstants.platform != "macosx") { if (aEvent.ctrlKey && !aEvent.shiftKey && !aEvent.metaKey && aEvent.keyCode == KeyEvent.DOM_VK_F4 && !this.mCurrentTab.pinned) { this.removeCurrentTab({animate: true}); aEvent.preventDefault(); } } ]]></body> @@ -4830,17 +4829,17 @@ if (!aEvent.isTrusted) { // Don't let untrusted events mess with tabs. return; } if (aEvent.altKey) return; - if (this.AppConstants.platform == "macosx") { + if (AppConstants.platform == "macosx") { if (!aEvent.metaKey) return; var offset = 1; switch (aEvent.charCode) { case "}".charCodeAt(0): offset = -1; case "{".charCodeAt(0): @@ -4893,17 +4892,17 @@ "tabs.unmuteAudio.background.tooltip" : "tabs.muteAudio.background.tooltip"; } label = this.mStringBundle.getString(stringID); } } else { label = tab.getAttribute("label"); - if (this.AppConstants.E10S_TESTING_ONLY && + if (AppConstants.E10S_TESTING_ONLY && tab.linkedBrowser && tab.linkedBrowser.isRemoteBrowser) { label += " - e10s"; if (Services.prefs.getIntPref("dom.ipc.processCount") > 1) { label += " (" + tab.linkedBrowser.frameLoader.tabParent.osPid + ")"; } } if (tab.userContextId) { @@ -5176,17 +5175,17 @@ Services.obs.addObserver(this, "contextual-identity-updated", false); this.mCurrentTab = this.tabContainer.firstChild; const nsIEventListenerService = Components.interfaces.nsIEventListenerService; let els = Components.classes["@mozilla.org/eventlistenerservice;1"] .getService(nsIEventListenerService); els.addSystemEventListener(document, "keydown", this, false); - if (this.AppConstants.platform == "macosx") { + if (AppConstants.platform == "macosx") { els.addSystemEventListener(document, "keypress", this, false); } window.addEventListener("sizemodechange", this); var uniqueId = this._generateUniquePanelID(); this.mPanelContainer.childNodes[0].id = uniqueId; this.mCurrentTab.linkedPanel = uniqueId; this.mCurrentTab.permanentKey = this.mCurrentBrowser.permanentKey; @@ -5293,17 +5292,17 @@ this._tabFilters.delete(tab); this._tabListeners.delete(tab); } const nsIEventListenerService = Components.interfaces.nsIEventListenerService; let els = Components.classes["@mozilla.org/eventlistenerservice;1"] .getService(nsIEventListenerService); els.removeSystemEventListener(document, "keydown", this, false); - if (this.AppConstants.platform == "macosx") { + if (AppConstants.platform == "macosx") { els.removeSystemEventListener(document, "keypress", this, false); } window.removeEventListener("sizemodechange", this); if (gMultiProcessBrowser) { let messageManager = window.getGroupMessageManager("browsers"); messageManager.removeMessageListener("DOMTitleChanged", this); window.messageManager.removeMessageListener("contextmenu", this); @@ -6653,17 +6652,17 @@ event.stopPropagation(); ]]></handler> <handler event="keydown" group="system"><![CDATA[ if (event.altKey || event.shiftKey) return; let wrongModifiers; - if (this.tabbrowser.AppConstants.platform == "macosx") { + if (AppConstants.platform == "macosx") { wrongModifiers = !event.metaKey; } else { wrongModifiers = !event.ctrlKey || event.metaKey; } if (wrongModifiers) return; @@ -6736,17 +6735,17 @@ let toDrag = canvas; let dragImageOffset = -16; if (gMultiProcessBrowser) { var context = canvas.getContext("2d"); context.fillStyle = "white"; context.fillRect(0, 0, canvas.width, canvas.height); let captureListener; - let platform = this.tabbrowser.AppConstants.platform; + let platform = AppConstants.platform; // On Windows and Mac we can update the drag image during a drag // using updateDragImage. On Linux, we can use a panel. if (platform == "win" || platform == "macosx") { captureListener = function() { dt.updateDragImage(canvas, dragImageOffset, dragImageOffset); } } else { // Create a panel to use it in setDragImage @@ -7021,17 +7020,17 @@ // resize _before_ move to ensure the window fits the new screen. if // the window is too large for its screen, the window manager may do // automatic repositioning. window.resizeTo(winWidth, winHeight); window.moveTo(left, top); window.focus(); } else { let props = { screenX: left, screenY: top }; - if (this.tabbrowser.AppConstants.platform != "win") { + if (AppConstants.platform != "win") { props.outerWidth = winWidth; props.outerHeight = winHeight; } this.tabbrowser.replaceTabWithWindow(draggedTab, props); } event.stopPropagation(); ]]></handler>
--- a/browser/components/preferences/SiteDataManager.jsm +++ b/browser/components/preferences/SiteDataManager.jsm @@ -78,17 +78,17 @@ this.SiteDataManager = { _updateQuota() { this._quotaUsageRequests = []; let promises = []; for (let site of this._sites.values()) { promises.push(new Promise(resolve => { let callback = { onUsageResult(request) { - site.quotaUsage = request.usage; + site.quotaUsage = request.result.usage; resolve(); } }; // XXX: The work of integrating localStorage into Quota Manager is in progress. // After the bug 742822 and 1286798 landed, localStorage usage will be included. // So currently only get indexedDB usage. this._quotaUsageRequests.push( this._qms.getUsageForPrincipal(site.perm.principal, callback));
--- a/browser/components/preferences/in-content/tests/browser_advanced_siteData.js +++ b/browser/components/preferences/in-content/tests/browser_advanced_siteData.js @@ -127,17 +127,17 @@ function getPersistentStoragePermStatus( let principal = Services.scriptSecurityManager.createCodebasePrincipal(uri, {}); return Services.perms.testExactPermissionFromPrincipal(principal, "persistent-storage"); } function getQuotaUsage(origin) { return new Promise(resolve => { let uri = NetUtil.newURI(origin); let principal = Services.scriptSecurityManager.createCodebasePrincipal(uri, {}); - Services.qms.getUsageForPrincipal(principal, request => resolve(request.usage)); + Services.qms.getUsageForPrincipal(principal, request => resolve(request.result.usage)); }); } // XXX: The intermittent bug 1331851 // The implementation of nsICacheStorageConsumptionObserver must be passed as weak referenced, // so we must hold this observer here well. If we didn't, there would be a chance that // in Linux debug test run the observer was released before the operation at gecko was completed // (may be because of a relatively quicker GC cycle or a relatively slower operation).
--- a/build/valgrind/i386-redhat-linux-gnu.sup +++ b/build/valgrind/i386-redhat-linux-gnu.sup @@ -14,26 +14,16 @@ { Bug 793598 Memcheck:Leak ... obj:/lib/libdbus-1.so.3.4.0 ... } { - Bug 793600 - Memcheck:Leak - fun:realloc - obj:/usr/lib/libfontconfig.so.1.4.4 - ... - fun:FcDefaultSubstitute - fun:_ZN17gfxPangoFontGroup11MakeFontSetEP14_PangoLanguagedP9nsAutoRefI10_FcPatternE - ... -} -{ Bug 794366 Memcheck:Leak ... obj:/usr/lib/libgtk-x11-2.0.so.0.1800.9 ... } { Bug 794368
--- a/build/valgrind/x86_64-redhat-linux-gnu.sup +++ b/build/valgrind/x86_64-redhat-linux-gnu.sup @@ -13,26 +13,16 @@ } { Bug 793598 Memcheck:Leak ... obj:/lib64/libdbus-1.so.3.4.0 ... } -{ - Bug 793600 - Memcheck:Leak - fun:realloc - obj:/usr/lib64/libfontconfig.so.1.4.4 - ... - fun:FcDefaultSubstitute - fun:_ZN17gfxPangoFontGroup11MakeFontSetEP14_PangoLanguagedP9nsAutoRefI10_FcPatternE - ... -} # Fontconfig is going fancy with its cache structure and that confuses valgrind. # https://bugs.freedesktop.org/show_bug.cgi?id=8215 # https://bugs.freedesktop.org/show_bug.cgi?id=8428 { Bug 1187649 Memcheck:Leak match-leak-kinds: definite fun:realloc
--- a/caps/BasePrincipal.cpp +++ b/caps/BasePrincipal.cpp @@ -7,302 +7,32 @@ #include "mozilla/BasePrincipal.h" #include "nsDocShell.h" #ifdef MOZ_CRASHREPORTER #include "nsExceptionHandler.h" #endif #include "nsIAddonPolicyService.h" #include "nsIContentSecurityPolicy.h" -#include "nsIEffectiveTLDService.h" #include "nsIObjectInputStream.h" #include "nsIObjectOutputStream.h" -#include "nsPrincipal.h" +#include "ContentPrincipal.h" #include "nsNetUtil.h" #include "nsIURIWithPrincipal.h" -#include "nsNullPrincipal.h" +#include "NullPrincipal.h" #include "nsScriptSecurityManager.h" #include "nsServiceManagerUtils.h" #include "mozilla/dom/ChromeUtils.h" #include "mozilla/dom/CSPDictionariesBinding.h" -#include "mozilla/dom/quota/QuotaManager.h" #include "mozilla/dom/ToJSValue.h" -#include "mozilla/dom/URLSearchParams.h" namespace mozilla { -using dom::URLParams; - -bool OriginAttributes::sFirstPartyIsolation = false; -bool OriginAttributes::sRestrictedOpenerAccess = false; - -void -OriginAttributes::InitPrefs() -{ - MOZ_ASSERT(NS_IsMainThread()); - static bool sInited = false; - if (!sInited) { - sInited = true; - Preferences::AddBoolVarCache(&sFirstPartyIsolation, - "privacy.firstparty.isolate"); - Preferences::AddBoolVarCache(&sRestrictedOpenerAccess, - "privacy.firstparty.isolate.restrict_opener_access"); - } -} - -void -OriginAttributes::SetFirstPartyDomain(const bool aIsTopLevelDocument, - nsIURI* aURI) -{ - bool isFirstPartyEnabled = IsFirstPartyEnabled(); - - // If the pref is off or this is not a top level load, bail out. - if (!isFirstPartyEnabled || !aIsTopLevelDocument) { - return; - } - - nsCOMPtr<nsIEffectiveTLDService> tldService = - do_GetService(NS_EFFECTIVETLDSERVICE_CONTRACTID); - MOZ_ASSERT(tldService); - if (!tldService) { - return; - } - - nsAutoCString baseDomain; - nsresult rv = tldService->GetBaseDomain(aURI, 0, baseDomain); - if (NS_FAILED(rv)) { - nsAutoCString scheme; - rv = aURI->GetScheme(scheme); - NS_ENSURE_SUCCESS_VOID(rv); - if (scheme.EqualsLiteral("about")) { - baseDomain.AssignLiteral(ABOUT_URI_FIRST_PARTY_DOMAIN); - } - } - - mFirstPartyDomain = NS_ConvertUTF8toUTF16(baseDomain); -} - -void -OriginAttributes::SetFirstPartyDomain(const bool aIsTopLevelDocument, - const nsACString& aDomain) -{ - bool isFirstPartyEnabled = IsFirstPartyEnabled(); - - // If the pref is off or this is not a top level load, bail out. - if (!isFirstPartyEnabled || !aIsTopLevelDocument) { - return; - } - - mFirstPartyDomain = NS_ConvertUTF8toUTF16(aDomain); -} - -void -OriginAttributes::CreateSuffix(nsACString& aStr) const -{ - URLParams params; - nsAutoString value; - - // - // Important: While serializing any string-valued attributes, perform a - // release-mode assertion to make sure that they don't contain characters that - // will break the quota manager when it uses the serialization for file - // naming. - // - - if (mAppId != nsIScriptSecurityManager::NO_APP_ID) { - value.AppendInt(mAppId); - params.Set(NS_LITERAL_STRING("appId"), value); - } - - if (mInIsolatedMozBrowser) { - params.Set(NS_LITERAL_STRING("inBrowser"), NS_LITERAL_STRING("1")); - } - - if (mUserContextId != nsIScriptSecurityManager::DEFAULT_USER_CONTEXT_ID) { - value.Truncate(); - value.AppendInt(mUserContextId); - params.Set(NS_LITERAL_STRING("userContextId"), value); - } - - - if (mPrivateBrowsingId) { - value.Truncate(); - value.AppendInt(mPrivateBrowsingId); - params.Set(NS_LITERAL_STRING("privateBrowsingId"), value); - } - - if (!mFirstPartyDomain.IsEmpty()) { - MOZ_RELEASE_ASSERT(mFirstPartyDomain.FindCharInSet(dom::quota::QuotaManager::kReplaceChars) == kNotFound); - params.Set(NS_LITERAL_STRING("firstPartyDomain"), mFirstPartyDomain); - } - - aStr.Truncate(); - - params.Serialize(value); - if (!value.IsEmpty()) { - aStr.AppendLiteral("^"); - aStr.Append(NS_ConvertUTF16toUTF8(value)); - } - -// In debug builds, check the whole string for illegal characters too (just in case). -#ifdef DEBUG - nsAutoCString str; - str.Assign(aStr); - MOZ_ASSERT(str.FindCharInSet(dom::quota::QuotaManager::kReplaceChars) == kNotFound); -#endif -} - -void -OriginAttributes::CreateAnonymizedSuffix(nsACString& aStr) const -{ - OriginAttributes attrs = *this; - - if (!attrs.mFirstPartyDomain.IsEmpty()) { - attrs.mFirstPartyDomain.AssignLiteral("_anonymizedFirstPartyDomain_"); - } - - attrs.CreateSuffix(aStr); -} - -namespace { - -class MOZ_STACK_CLASS PopulateFromSuffixIterator final - : public URLParams::ForEachIterator -{ -public: - explicit PopulateFromSuffixIterator(OriginAttributes* aOriginAttributes) - : mOriginAttributes(aOriginAttributes) - { - MOZ_ASSERT(aOriginAttributes); - // If mPrivateBrowsingId is passed in as >0 and is not present in the suffix, - // then it will remain >0 when it should be 0 according to the suffix. Set to 0 before - // iterating to fix this. - mOriginAttributes->mPrivateBrowsingId = 0; - } - - bool URLParamsIterator(const nsString& aName, - const nsString& aValue) override - { - if (aName.EqualsLiteral("appId")) { - nsresult rv; - int64_t val = aValue.ToInteger64(&rv); - NS_ENSURE_SUCCESS(rv, false); - NS_ENSURE_TRUE(val <= UINT32_MAX, false); - mOriginAttributes->mAppId = static_cast<uint32_t>(val); - - return true; - } - - if (aName.EqualsLiteral("inBrowser")) { - if (!aValue.EqualsLiteral("1")) { - return false; - } - - mOriginAttributes->mInIsolatedMozBrowser = true; - return true; - } - - if (aName.EqualsLiteral("addonId")) { - // No longer supported. Silently ignore so that legacy origin strings - // don't cause failures. - return true; - } - - if (aName.EqualsLiteral("userContextId")) { - nsresult rv; - int64_t val = aValue.ToInteger64(&rv); - NS_ENSURE_SUCCESS(rv, false); - NS_ENSURE_TRUE(val <= UINT32_MAX, false); - mOriginAttributes->mUserContextId = static_cast<uint32_t>(val); - - return true; - } - - if (aName.EqualsLiteral("privateBrowsingId")) { - nsresult rv; - int64_t val = aValue.ToInteger64(&rv); - NS_ENSURE_SUCCESS(rv, false); - NS_ENSURE_TRUE(val >= 0 && val <= UINT32_MAX, false); - mOriginAttributes->mPrivateBrowsingId = static_cast<uint32_t>(val); - - return true; - } - - if (aName.EqualsLiteral("firstPartyDomain")) { - MOZ_RELEASE_ASSERT(mOriginAttributes->mFirstPartyDomain.IsEmpty()); - mOriginAttributes->mFirstPartyDomain.Assign(aValue); - return true; - } - - // No other attributes are supported. - return false; - } - -private: - OriginAttributes* mOriginAttributes; -}; - -} // namespace - -bool -OriginAttributes::PopulateFromSuffix(const nsACString& aStr) -{ - if (aStr.IsEmpty()) { - return true; - } - - if (aStr[0] != '^') { - return false; - } - - URLParams params; - params.ParseInput(Substring(aStr, 1, aStr.Length() - 1)); - - PopulateFromSuffixIterator iterator(this); - return params.ForEach(iterator); -} - -bool -OriginAttributes::PopulateFromOrigin(const nsACString& aOrigin, - nsACString& aOriginNoSuffix) -{ - // RFindChar is only available on nsCString. - nsCString origin(aOrigin); - int32_t pos = origin.RFindChar('^'); - - if (pos == kNotFound) { - aOriginNoSuffix = origin; - return true; - } - - aOriginNoSuffix = Substring(origin, 0, pos); - return PopulateFromSuffix(Substring(origin, pos)); -} - -void -OriginAttributes::SyncAttributesWithPrivateBrowsing(bool aInPrivateBrowsing) -{ - mPrivateBrowsingId = aInPrivateBrowsing ? 1 : 0; -} - -/* static */ -bool -OriginAttributes::IsPrivateBrowsing(const nsACString& aOrigin) -{ - nsAutoCString dummy; - OriginAttributes attrs; - if (NS_WARN_IF(!attrs.PopulateFromOrigin(aOrigin, dummy))) { - return false; - } - - return !!attrs.mPrivateBrowsingId; -} - BasePrincipal::BasePrincipal(PrincipalKind aKind) : mKind(aKind) , mDomainSet(false) {} BasePrincipal::~BasePrincipal() {} @@ -640,46 +370,46 @@ already_AddRefed<BasePrincipal> BasePrincipal::CreateCodebasePrincipal(nsIURI* aURI, const OriginAttributes& aAttrs) { // If the URI is supposed to inherit the security context of whoever loads it, // we shouldn't make a codebase principal for it. bool inheritsPrincipal; nsresult rv = NS_URIChainHasFlags(aURI, nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT, &inheritsPrincipal); if (NS_FAILED(rv) || inheritsPrincipal) { - return nsNullPrincipal::Create(aAttrs); + return NullPrincipal::Create(aAttrs); } // Check whether the URI knows what its principal is supposed to be. nsCOMPtr<nsIURIWithPrincipal> uriPrinc = do_QueryInterface(aURI); if (uriPrinc) { nsCOMPtr<nsIPrincipal> principal; uriPrinc->GetPrincipal(getter_AddRefs(principal)); if (!principal) { - return nsNullPrincipal::Create(aAttrs); + return NullPrincipal::Create(aAttrs); } RefPtr<BasePrincipal> concrete = Cast(principal); return concrete.forget(); } // Mint a codebase principal. - RefPtr<nsPrincipal> codebase = new nsPrincipal(); + RefPtr<ContentPrincipal> codebase = new ContentPrincipal(); rv = codebase->Init(aURI, aAttrs); NS_ENSURE_SUCCESS(rv, nullptr); return codebase.forget(); } already_AddRefed<BasePrincipal> BasePrincipal::CreateCodebasePrincipal(const nsACString& aOrigin) { MOZ_ASSERT(!StringBeginsWith(aOrigin, NS_LITERAL_CSTRING("[")), "CreateCodebasePrincipal does not support System and Expanded principals"); MOZ_ASSERT(!StringBeginsWith(aOrigin, NS_LITERAL_CSTRING(NS_NULLPRINCIPAL_SCHEME ":")), - "CreateCodebasePrincipal does not support nsNullPrincipal"); + "CreateCodebasePrincipal does not support NullPrincipal"); nsAutoCString originNoSuffix; mozilla::OriginAttributes attrs; if (!attrs.PopulateFromOrigin(aOrigin, originNoSuffix)) { return nullptr; } nsCOMPtr<nsIURI> uri;
--- a/caps/BasePrincipal.h +++ b/caps/BasePrincipal.h @@ -5,197 +5,27 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef mozilla_BasePrincipal_h #define mozilla_BasePrincipal_h #include "nsJSPrincipals.h" #include "mozilla/Attributes.h" -#include "mozilla/dom/ChromeUtils.h" -#include "mozilla/dom/ChromeUtilsBinding.h" -#include "nsIScriptSecurityManager.h" +#include "mozilla/OriginAttributes.h" class nsIContentSecurityPolicy; class nsIObjectOutputStream; class nsIObjectInputStream; class nsIURI; -class nsExpandedPrincipal; +class ExpandedPrincipal; namespace mozilla { -// Base OriginAttributes class. This has several subclass flavors, and is not -// directly constructable itself. -class OriginAttributes : public dom::OriginAttributesDictionary -{ -public: - OriginAttributes() {} - - OriginAttributes(uint32_t aAppId, bool aInIsolatedMozBrowser) - { - mAppId = aAppId; - mInIsolatedMozBrowser = aInIsolatedMozBrowser; - } - - explicit OriginAttributes(const OriginAttributesDictionary& aOther) - : OriginAttributesDictionary(aOther) - {} - - void SetFirstPartyDomain(const bool aIsTopLevelDocument, nsIURI* aURI); - void SetFirstPartyDomain(const bool aIsTopLevelDocument, const nsACString& aDomain); - - enum { - STRIP_FIRST_PARTY_DOMAIN = 0x01, - STRIP_USER_CONTEXT_ID = 0x02, - }; - - inline void StripAttributes(uint32_t aFlags) - { - if (aFlags & STRIP_FIRST_PARTY_DOMAIN) { - mFirstPartyDomain.Truncate(); - } - - if (aFlags & STRIP_USER_CONTEXT_ID) { - mUserContextId = nsIScriptSecurityManager::DEFAULT_USER_CONTEXT_ID; - } - } - - bool operator==(const OriginAttributes& aOther) const - { - return mAppId == aOther.mAppId && - mInIsolatedMozBrowser == aOther.mInIsolatedMozBrowser && - mUserContextId == aOther.mUserContextId && - mPrivateBrowsingId == aOther.mPrivateBrowsingId && - mFirstPartyDomain == aOther.mFirstPartyDomain; - } - - bool operator!=(const OriginAttributes& aOther) const - { - return !(*this == aOther); - } - - // Serializes/Deserializes non-default values into the suffix format, i.e. - // |!key1=value1&key2=value2|. If there are no non-default attributes, this - // returns an empty string. - void CreateSuffix(nsACString& aStr) const; - - // Don't use this method for anything else than debugging! - void CreateAnonymizedSuffix(nsACString& aStr) const; - - MOZ_MUST_USE bool PopulateFromSuffix(const nsACString& aStr); - - // Populates the attributes from a string like - // |uri!key1=value1&key2=value2| and returns the uri without the suffix. - MOZ_MUST_USE bool PopulateFromOrigin(const nsACString& aOrigin, - nsACString& aOriginNoSuffix); - - // Helper function to match mIsPrivateBrowsing to existing private browsing - // flags. Once all other flags are removed, this can be removed too. - void SyncAttributesWithPrivateBrowsing(bool aInPrivateBrowsing); - - // check if "privacy.firstparty.isolate" is enabled. - static inline bool IsFirstPartyEnabled() - { - return sFirstPartyIsolation; - } - - // check if the access of window.opener across different FPDs is restricted. - // We only restrict the access of window.opener when first party isolation - // is enabled and "privacy.firstparty.isolate.restrict_opener_access" is on. - static inline bool IsRestrictOpenerAccessForFPI() - { - // We always want to restrict window.opener if first party isolation is - // disabled. - return !sFirstPartyIsolation || sRestrictedOpenerAccess; - } - - // returns true if the originAttributes suffix has mPrivateBrowsingId value - // different than 0. - static bool IsPrivateBrowsing(const nsACString& aOrigin); - - static void InitPrefs(); - -private: - static bool sFirstPartyIsolation; - static bool sRestrictedOpenerAccess; -}; - -class OriginAttributesPattern : public dom::OriginAttributesPatternDictionary -{ -public: - // To convert a JSON string to an OriginAttributesPattern, do the following: - // - // OriginAttributesPattern pattern; - // if (!pattern.Init(aJSONString)) { - // ... // handle failure. - // } - OriginAttributesPattern() {} - - explicit OriginAttributesPattern(const OriginAttributesPatternDictionary& aOther) - : OriginAttributesPatternDictionary(aOther) {} - - // Performs a match of |aAttrs| against this pattern. - bool Matches(const OriginAttributes& aAttrs) const - { - if (mAppId.WasPassed() && mAppId.Value() != aAttrs.mAppId) { - return false; - } - - if (mInIsolatedMozBrowser.WasPassed() && mInIsolatedMozBrowser.Value() != aAttrs.mInIsolatedMozBrowser) { - return false; - } - - if (mUserContextId.WasPassed() && mUserContextId.Value() != aAttrs.mUserContextId) { - return false; - } - - if (mPrivateBrowsingId.WasPassed() && mPrivateBrowsingId.Value() != aAttrs.mPrivateBrowsingId) { - return false; - } - - if (mFirstPartyDomain.WasPassed() && mFirstPartyDomain.Value() != aAttrs.mFirstPartyDomain) { - return false; - } - - return true; - } - - bool Overlaps(const OriginAttributesPattern& aOther) const - { - if (mAppId.WasPassed() && aOther.mAppId.WasPassed() && - mAppId.Value() != aOther.mAppId.Value()) { - return false; - } - - if (mInIsolatedMozBrowser.WasPassed() && - aOther.mInIsolatedMozBrowser.WasPassed() && - mInIsolatedMozBrowser.Value() != aOther.mInIsolatedMozBrowser.Value()) { - return false; - } - - if (mUserContextId.WasPassed() && aOther.mUserContextId.WasPassed() && - mUserContextId.Value() != aOther.mUserContextId.Value()) { - return false; - } - - if (mPrivateBrowsingId.WasPassed() && aOther.mPrivateBrowsingId.WasPassed() && - mPrivateBrowsingId.Value() != aOther.mPrivateBrowsingId.Value()) { - return false; - } - - if (mFirstPartyDomain.WasPassed() && aOther.mFirstPartyDomain.WasPassed() && - mFirstPartyDomain.Value() != aOther.mFirstPartyDomain.Value()) { - return false; - } - - return true; - } -}; - /* * Base class from which all nsIPrincipal implementations inherit. Use this for * default implementations and other commonalities between principal * implementations. * * We should merge nsJSPrincipals into this class at some point. */ class BasePrincipal : public nsJSPrincipals @@ -278,17 +108,17 @@ protected: // Note that this does not check OriginAttributes. Callers that depend on // those must call Subsumes instead. virtual bool SubsumesInternal(nsIPrincipal* aOther, DocumentDomainConsideration aConsider) = 0; // Internal, side-effect-free check to determine whether the concrete // principal would allow the load ignoring any common behavior implemented in // BasePrincipal::CheckMayLoad. virtual bool MayLoadInternal(nsIURI* aURI) = 0; - friend class ::nsExpandedPrincipal; + friend class ::ExpandedPrincipal; // This function should be called as the last step of the initialization of the // principal objects. It's typically called as the last step from the Init() // method of the child classes. void FinishInit(); nsCOMPtr<nsIContentSecurityPolicy> mCSP; nsCOMPtr<nsIContentSecurityPolicy> mPreloadCSP;
rename from caps/nsPrincipal.cpp rename to caps/ContentPrincipal.cpp --- a/caps/nsPrincipal.cpp +++ b/caps/ContentPrincipal.cpp @@ -1,29 +1,31 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=2 sw=2 et 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 "nsPrincipal.h" +#include "ContentPrincipal.h" #include "mozIThirdPartyUtil.h" #include "nscore.h" #include "nsScriptSecurityManager.h" #include "nsString.h" #include "nsReadableUtils.h" #include "pratom.h" #include "nsIURI.h" #include "nsIURL.h" #include "nsIStandardURL.h" #include "nsIURIWithPrincipal.h" #include "nsJSPrincipals.h" #include "nsIEffectiveTLDService.h" #include "nsIClassInfoImpl.h" +#include "nsIObjectInputStream.h" +#include "nsIObjectOutputStream.h" #include "nsIProtocolHandler.h" #include "nsError.h" #include "nsIContentSecurityPolicy.h" #include "nsNetCID.h" #include "jswrapper.h" #include "mozilla/dom/nsCSPContext.h" #include "mozilla/dom/ScriptSettings.h" @@ -53,52 +55,53 @@ GetAddonPolicyService(nsresult* aRv) *aRv = NS_OK; if (!addonPolicyService) { addonPolicyService = do_GetService("@mozilla.org/addons/policy-service;1", aRv); ClearOnShutdown(&addonPolicyService); } return addonPolicyService; } -NS_IMPL_CLASSINFO(nsPrincipal, nullptr, nsIClassInfo::MAIN_THREAD_ONLY, +NS_IMPL_CLASSINFO(ContentPrincipal, nullptr, nsIClassInfo::MAIN_THREAD_ONLY, NS_PRINCIPAL_CID) -NS_IMPL_QUERY_INTERFACE_CI(nsPrincipal, +NS_IMPL_QUERY_INTERFACE_CI(ContentPrincipal, nsIPrincipal, nsISerializable) -NS_IMPL_CI_INTERFACE_GETTER(nsPrincipal, +NS_IMPL_CI_INTERFACE_GETTER(ContentPrincipal, nsIPrincipal, nsISerializable) // Called at startup: /* static */ void -nsPrincipal::InitializeStatics() +ContentPrincipal::InitializeStatics() { Preferences::AddBoolVarCache(&gCodeBasePrincipalSupport, "signed.applets.codebase_principal_support", false); } -nsPrincipal::nsPrincipal() +ContentPrincipal::ContentPrincipal() : BasePrincipal(eCodebasePrincipal) , mCodebaseImmutable(false) , mDomainImmutable(false) , mInitialized(false) { } -nsPrincipal::~nsPrincipal() +ContentPrincipal::~ContentPrincipal() { // let's clear the principal within the csp to avoid a tangling pointer if (mCSP) { static_cast<nsCSPContext*>(mCSP.get())->clearLoadingPrincipal(); } } nsresult -nsPrincipal::Init(nsIURI *aCodebase, const OriginAttributes& aOriginAttributes) +ContentPrincipal::Init(nsIURI *aCodebase, + const OriginAttributes& aOriginAttributes) { NS_ENSURE_STATE(!mInitialized); NS_ENSURE_ARG(aCodebase); mInitialized = true; // Assert that the URI we get here isn't any of the schemes that we know we // should not get here. These schemes always either inherit their principal @@ -118,23 +121,23 @@ nsPrincipal::Init(nsIURI *aCodebase, con mOriginAttributes = aOriginAttributes; FinishInit(); return NS_OK; } nsresult -nsPrincipal::GetScriptLocation(nsACString &aStr) +ContentPrincipal::GetScriptLocation(nsACString &aStr) { return mCodebase->GetSpec(aStr); } nsresult -nsPrincipal::GetOriginInternal(nsACString& aOrigin) +ContentPrincipal::GetOriginInternal(nsACString& aOrigin) { if (!mCodebase) { return NS_ERROR_FAILURE; } nsCOMPtr<nsIURI> origin = NS_GetInnermostURI(mCodebase); if (!origin) { return NS_ERROR_FAILURE; @@ -244,22 +247,22 @@ nsPrincipal::GetOriginInternal(nsACStrin if (pos != kNotFound) { aOrigin.Truncate(pos); } return NS_OK; } bool -nsPrincipal::SubsumesInternal(nsIPrincipal* aOther, - BasePrincipal::DocumentDomainConsideration aConsideration) +ContentPrincipal::SubsumesInternal(nsIPrincipal* aOther, + BasePrincipal::DocumentDomainConsideration aConsideration) { MOZ_ASSERT(aOther); - // For nsPrincipal, Subsumes is equivalent to Equals. + // For ContentPrincipal, Subsumes is equivalent to Equals. if (aOther == this) { return true; } // If either the subject or the object has changed its principal by // explicitly setting document.domain then the other must also have // done so in order to be considered the same origin. This prevents // DNS spoofing based on document.domain (154930) @@ -281,33 +284,33 @@ nsPrincipal::SubsumesInternal(nsIPrincip rv = aOther->GetURI(getter_AddRefs(otherURI)); NS_ENSURE_SUCCESS(rv, false); // Compare codebases. return nsScriptSecurityManager::SecurityCompareURIs(mCodebase, otherURI); } NS_IMETHODIMP -nsPrincipal::GetURI(nsIURI** aURI) +ContentPrincipal::GetURI(nsIURI** aURI) { if (mCodebaseImmutable) { NS_ADDREF(*aURI = mCodebase); return NS_OK; } if (!mCodebase) { *aURI = nullptr; return NS_OK; } return NS_EnsureSafeToReturn(mCodebase, aURI); } bool -nsPrincipal::MayLoadInternal(nsIURI* aURI) +ContentPrincipal::MayLoadInternal(nsIURI* aURI) { // See if aURI is something like a Blob URI that is actually associated with // a principal. nsCOMPtr<nsIURIWithPrincipal> uriWithPrin = do_QueryInterface(aURI); nsCOMPtr<nsIPrincipal> uriPrin; if (uriWithPrin) { uriWithPrin->GetPrincipal(getter_AddRefs(uriPrin)); } @@ -333,42 +336,42 @@ nsPrincipal::MayLoadInternal(nsIURI* aUR NS_RelaxStrictFileOriginPolicy(aURI, mCodebase)) { return true; } return false; } NS_IMETHODIMP -nsPrincipal::GetHashValue(uint32_t* aValue) +ContentPrincipal::GetHashValue(uint32_t* aValue) { NS_PRECONDITION(mCodebase, "Need a codebase"); *aValue = nsScriptSecurityManager::HashPrincipalByOrigin(this); return NS_OK; } NS_IMETHODIMP -nsPrincipal::GetDomain(nsIURI** aDomain) +ContentPrincipal::GetDomain(nsIURI** aDomain) { if (!mDomain) { *aDomain = nullptr; return NS_OK; } if (mDomainImmutable) { NS_ADDREF(*aDomain = mDomain); return NS_OK; } return NS_EnsureSafeToReturn(mDomain, aDomain); } NS_IMETHODIMP -nsPrincipal::SetDomain(nsIURI* aDomain) +ContentPrincipal::SetDomain(nsIURI* aDomain) { mDomain = NS_TryToMakeImmutable(aDomain); mDomainImmutable = URIIsImmutable(mDomain); mDomainSet = true; // Recompute all wrappers between compartments using this principal and other // non-chrome compartments. AutoSafeJSContext cx; @@ -379,17 +382,17 @@ nsPrincipal::SetDomain(nsIURI* aDomain) success = js::RecomputeWrappers(cx, js::CompartmentsWithPrincipals(principals), js::ContentCompartmentsOnly()); NS_ENSURE_TRUE(success, NS_ERROR_FAILURE); return NS_OK; } NS_IMETHODIMP -nsPrincipal::GetBaseDomain(nsACString& aBaseDomain) +ContentPrincipal::GetBaseDomain(nsACString& aBaseDomain) { // For a file URI, we return the file path. if (NS_URIIsLocalFile(mCodebase)) { nsCOMPtr<nsIURL> url = do_QueryInterface(mCodebase); if (url) { return url->GetFilePath(aBaseDomain); } @@ -414,17 +417,17 @@ nsPrincipal::GetBaseDomain(nsACString& a if (thirdPartyUtil) { return thirdPartyUtil->GetBaseDomain(mCodebase, aBaseDomain); } return NS_OK; } NS_IMETHODIMP -nsPrincipal::GetAddonId(nsAString& aAddonId) +ContentPrincipal::GetAddonId(nsAString& aAddonId) { if (mAddonIdCache.isSome()) { aAddonId.Assign(mAddonIdCache.ref()); return NS_OK; } NS_ENSURE_TRUE(mCodebase, NS_ERROR_FAILURE); @@ -443,17 +446,17 @@ nsPrincipal::GetAddonId(nsAString& aAddo mAddonIdCache.emplace(); } aAddonId.Assign(mAddonIdCache.ref()); return NS_OK; }; NS_IMETHODIMP -nsPrincipal::Read(nsIObjectInputStream* aStream) +ContentPrincipal::Read(nsIObjectInputStream* aStream) { nsCOMPtr<nsISupports> supports; nsCOMPtr<nsIURI> codebase; nsresult rv = NS_ReadOptionalObject(aStream, true, getter_AddRefs(supports)); if (NS_FAILED(rv)) { return rv; } @@ -489,17 +492,17 @@ nsPrincipal::Read(nsIObjectInputStream* } SetDomain(domain); return NS_OK; } NS_IMETHODIMP -nsPrincipal::Write(nsIObjectOutputStream* aStream) +ContentPrincipal::Write(nsIObjectOutputStream* aStream) { NS_ENSURE_STATE(mCodebase); nsresult rv = NS_WriteOptionalCompoundObject(aStream, mCodebase, NS_GET_IID(nsIURI), true); if (NS_FAILED(rv)) { return rv; }
rename from caps/nsPrincipal.h rename to caps/ContentPrincipal.h --- a/caps/nsPrincipal.h +++ b/caps/ContentPrincipal.h @@ -1,40 +1,40 @@ /* -*- 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 nsPrincipal_h__ -#define nsPrincipal_h__ +#ifndef ContentPrincipal_h +#define ContentPrincipal_h #include "nsCOMPtr.h" #include "nsJSPrincipals.h" #include "nsTArray.h" #include "nsIContentSecurityPolicy.h" #include "nsIProtocolHandler.h" #include "nsNetUtil.h" #include "nsScriptSecurityManager.h" #include "mozilla/BasePrincipal.h" -class nsPrincipal final : public mozilla::BasePrincipal +class ContentPrincipal final : public mozilla::BasePrincipal { public: NS_DECL_NSISERIALIZABLE NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) override; NS_IMETHOD GetHashValue(uint32_t* aHashValue) override; NS_IMETHOD GetURI(nsIURI** aURI) override; NS_IMETHOD GetDomain(nsIURI** aDomain) override; NS_IMETHOD SetDomain(nsIURI* aDomain) override; NS_IMETHOD GetBaseDomain(nsACString& aBaseDomain) override; NS_IMETHOD GetAddonId(nsAString& aAddonId) override; bool IsCodebasePrincipal() const override { return true; } nsresult GetOriginInternal(nsACString& aOrigin) override; - nsPrincipal(); + ContentPrincipal(); // Init() must be called before the principal is in a usable state. nsresult Init(nsIURI* aCodebase, const mozilla::OriginAttributes& aOriginAttributes); virtual nsresult GetScriptLocation(nsACString& aStr) override; /** @@ -45,23 +45,24 @@ public: nsCOMPtr<nsIURI> mDomain; nsCOMPtr<nsIURI> mCodebase; // If mCodebaseImmutable is true, mCodebase is non-null and immutable bool mCodebaseImmutable; bool mDomainImmutable; bool mInitialized; protected: - virtual ~nsPrincipal(); + virtual ~ContentPrincipal(); - bool SubsumesInternal(nsIPrincipal* aOther, DocumentDomainConsideration aConsideration) override; + bool SubsumesInternal(nsIPrincipal* aOther, + DocumentDomainConsideration aConsideration) override; bool MayLoadInternal(nsIURI* aURI) override; private: mozilla::Maybe<nsString> mAddonIdCache; }; #define NS_PRINCIPAL_CONTRACTID "@mozilla.org/principal;1" #define NS_PRINCIPAL_CID \ { 0x653e0e4d, 0x3ee4, 0x45fa, \ { 0xb2, 0x72, 0x97, 0xc2, 0x0b, 0xc0, 0x1e, 0xb8 } } -#endif // nsPrincipal_h__ +#endif // ContentPrincipal_h
rename from caps/nsExpandedPrincipal.cpp rename to caps/ExpandedPrincipal.cpp --- a/caps/nsExpandedPrincipal.cpp +++ b/caps/ExpandedPrincipal.cpp @@ -1,27 +1,27 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=2 sw=2 et 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 "nsExpandedPrincipal.h" +#include "ExpandedPrincipal.h" #include "nsIClassInfoImpl.h" using namespace mozilla; -NS_IMPL_CLASSINFO(nsExpandedPrincipal, nullptr, nsIClassInfo::MAIN_THREAD_ONLY, +NS_IMPL_CLASSINFO(ExpandedPrincipal, nullptr, nsIClassInfo::MAIN_THREAD_ONLY, NS_EXPANDEDPRINCIPAL_CID) -NS_IMPL_QUERY_INTERFACE_CI(nsExpandedPrincipal, +NS_IMPL_QUERY_INTERFACE_CI(ExpandedPrincipal, nsIPrincipal, nsIExpandedPrincipal) -NS_IMPL_CI_INTERFACE_GETTER(nsExpandedPrincipal, - nsIPrincipal, - nsIExpandedPrincipal) +NS_IMPL_CI_INTERFACE_GETTER(ExpandedPrincipal, + nsIPrincipal, + nsIExpandedPrincipal) struct OriginComparator { bool LessThan(nsIPrincipal* a, nsIPrincipal* b) const { nsAutoCString originA; nsresult rv = a->GetOrigin(originA); NS_ENSURE_SUCCESS(rv, false); @@ -38,56 +38,56 @@ struct OriginComparator NS_ENSURE_SUCCESS(rv, false); nsAutoCString originB; rv = b->GetOrigin(originB); NS_ENSURE_SUCCESS(rv, false); return a == b; } }; -nsExpandedPrincipal::nsExpandedPrincipal(nsTArray<nsCOMPtr<nsIPrincipal>> &aWhiteList, - const OriginAttributes& aAttrs) +ExpandedPrincipal::ExpandedPrincipal(nsTArray<nsCOMPtr<nsIPrincipal>> &aWhiteList, + const OriginAttributes& aAttrs) : BasePrincipal(eExpandedPrincipal) { - // We force the principals to be sorted by origin so that nsExpandedPrincipal + // We force the principals to be sorted by origin so that ExpandedPrincipal // origins can have a canonical form. OriginComparator c; for (size_t i = 0; i < aWhiteList.Length(); ++i) { mPrincipals.InsertElementSorted(aWhiteList[i], c); } mOriginAttributes = aAttrs; } -nsExpandedPrincipal::~nsExpandedPrincipal() +ExpandedPrincipal::~ExpandedPrincipal() { } -already_AddRefed<nsExpandedPrincipal> -nsExpandedPrincipal::Create(nsTArray<nsCOMPtr<nsIPrincipal>>& aWhiteList, - const OriginAttributes& aAttrs) +already_AddRefed<ExpandedPrincipal> +ExpandedPrincipal::Create(nsTArray<nsCOMPtr<nsIPrincipal>>& aWhiteList, + const OriginAttributes& aAttrs) { - RefPtr<nsExpandedPrincipal> ep = new nsExpandedPrincipal(aWhiteList, aAttrs); + RefPtr<ExpandedPrincipal> ep = new ExpandedPrincipal(aWhiteList, aAttrs); ep->FinishInit(); return ep.forget(); } NS_IMETHODIMP -nsExpandedPrincipal::GetDomain(nsIURI** aDomain) +ExpandedPrincipal::GetDomain(nsIURI** aDomain) { *aDomain = nullptr; return NS_OK; } NS_IMETHODIMP -nsExpandedPrincipal::SetDomain(nsIURI* aDomain) +ExpandedPrincipal::SetDomain(nsIURI* aDomain) { return NS_OK; } nsresult -nsExpandedPrincipal::GetOriginInternal(nsACString& aOrigin) +ExpandedPrincipal::GetOriginInternal(nsACString& aOrigin) { aOrigin.AssignLiteral("[Expanded Principal ["); for (size_t i = 0; i < mPrincipals.Length(); ++i) { if (i != 0) { aOrigin.AppendLiteral(", "); } nsAutoCString subOrigin; @@ -96,18 +96,18 @@ nsExpandedPrincipal::GetOriginInternal(n aOrigin.Append(subOrigin); } aOrigin.Append("]]"); return NS_OK; } bool -nsExpandedPrincipal::SubsumesInternal(nsIPrincipal* aOther, - BasePrincipal::DocumentDomainConsideration aConsideration) +ExpandedPrincipal::SubsumesInternal(nsIPrincipal* aOther, + BasePrincipal::DocumentDomainConsideration aConsideration) { // If aOther is an ExpandedPrincipal too, we break it down into its component // nsIPrincipals, and check subsumes on each one. nsCOMPtr<nsIExpandedPrincipal> expanded = do_QueryInterface(aOther); if (expanded) { nsTArray< nsCOMPtr<nsIPrincipal> >* otherList; expanded->GetWhiteList(&otherList); for (uint32_t i = 0; i < otherList->Length(); ++i){ @@ -128,73 +128,73 @@ nsExpandedPrincipal::SubsumesInternal(ns return true; } } return false; } bool -nsExpandedPrincipal::MayLoadInternal(nsIURI* uri) +ExpandedPrincipal::MayLoadInternal(nsIURI* uri) { for (uint32_t i = 0; i < mPrincipals.Length(); ++i){ if (BasePrincipal::Cast(mPrincipals[i])->MayLoadInternal(uri)) { return true; } } return false; } NS_IMETHODIMP -nsExpandedPrincipal::GetHashValue(uint32_t* result) +ExpandedPrincipal::GetHashValue(uint32_t* result) { MOZ_CRASH("extended principal should never be used as key in a hash map"); } NS_IMETHODIMP -nsExpandedPrincipal::GetURI(nsIURI** aURI) +ExpandedPrincipal::GetURI(nsIURI** aURI) { *aURI = nullptr; return NS_OK; } NS_IMETHODIMP -nsExpandedPrincipal::GetWhiteList(nsTArray<nsCOMPtr<nsIPrincipal> >** aWhiteList) +ExpandedPrincipal::GetWhiteList(nsTArray<nsCOMPtr<nsIPrincipal> >** aWhiteList) { *aWhiteList = &mPrincipals; return NS_OK; } NS_IMETHODIMP -nsExpandedPrincipal::GetBaseDomain(nsACString& aBaseDomain) +ExpandedPrincipal::GetBaseDomain(nsACString& aBaseDomain) { return NS_ERROR_NOT_AVAILABLE; } NS_IMETHODIMP -nsExpandedPrincipal::GetAddonId(nsAString& aAddonId) +ExpandedPrincipal::GetAddonId(nsAString& aAddonId) { aAddonId.Truncate(); return NS_OK; }; bool -nsExpandedPrincipal::AddonHasPermission(const nsAString& aPerm) +ExpandedPrincipal::AddonHasPermission(const nsAString& aPerm) { for (size_t i = 0; i < mPrincipals.Length(); ++i) { if (BasePrincipal::Cast(mPrincipals[i])->AddonHasPermission(aPerm)) { return true; } } return false; } nsresult -nsExpandedPrincipal::GetScriptLocation(nsACString& aStr) +ExpandedPrincipal::GetScriptLocation(nsACString& aStr) { aStr.Assign("[Expanded Principal ["); for (size_t i = 0; i < mPrincipals.Length(); ++i) { if (i != 0) { aStr.AppendLiteral(", "); } nsAutoCString spec; @@ -208,18 +208,18 @@ nsExpandedPrincipal::GetScriptLocation(n return NS_OK; } ////////////////////////////////////////// // Methods implementing nsISerializable // ////////////////////////////////////////// NS_IMETHODIMP -nsExpandedPrincipal::Read(nsIObjectInputStream* aStream) +ExpandedPrincipal::Read(nsIObjectInputStream* aStream) { return NS_ERROR_NOT_IMPLEMENTED; } NS_IMETHODIMP -nsExpandedPrincipal::Write(nsIObjectOutputStream* aStream) +ExpandedPrincipal::Write(nsIObjectOutputStream* aStream) { return NS_ERROR_NOT_IMPLEMENTED; }
rename from caps/nsExpandedPrincipal.h rename to caps/ExpandedPrincipal.h --- a/caps/nsExpandedPrincipal.h +++ b/caps/ExpandedPrincipal.h @@ -1,56 +1,59 @@ /* -*- 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 nsExpandedPrincipal_h -#define nsExpandedPrincipal_h +#ifndef ExpandedPrincipal_h +#define ExpandedPrincipal_h #include "nsCOMPtr.h" #include "nsJSPrincipals.h" #include "nsTArray.h" #include "nsNetUtil.h" #include "mozilla/BasePrincipal.h" -class nsExpandedPrincipal : public nsIExpandedPrincipal - , public mozilla::BasePrincipal +class ExpandedPrincipal : public nsIExpandedPrincipal + , public mozilla::BasePrincipal { - nsExpandedPrincipal(nsTArray<nsCOMPtr<nsIPrincipal>> &aWhiteList, - const mozilla::OriginAttributes& aAttrs); + ExpandedPrincipal(nsTArray<nsCOMPtr<nsIPrincipal>> &aWhiteList, + const mozilla::OriginAttributes& aAttrs); public: - static already_AddRefed<nsExpandedPrincipal> + static already_AddRefed<ExpandedPrincipal> Create(nsTArray<nsCOMPtr<nsIPrincipal>>& aWhiteList, const mozilla::OriginAttributes& aAttrs); NS_DECL_NSIEXPANDEDPRINCIPAL NS_DECL_NSISERIALIZABLE + NS_IMETHOD_(MozExternalRefCountType) AddRef() override { return nsJSPrincipals::AddRef(); }; NS_IMETHOD_(MozExternalRefCountType) Release() override { return nsJSPrincipals::Release(); }; NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) override; NS_IMETHOD GetHashValue(uint32_t* aHashValue) override; NS_IMETHOD GetURI(nsIURI** aURI) override; NS_IMETHOD GetDomain(nsIURI** aDomain) override; NS_IMETHOD SetDomain(nsIURI* aDomain) override; NS_IMETHOD GetBaseDomain(nsACString& aBaseDomain) override; NS_IMETHOD GetAddonId(nsAString& aAddonId) override; virtual bool AddonHasPermission(const nsAString& aPerm) override; virtual nsresult GetScriptLocation(nsACString &aStr) override; nsresult GetOriginInternal(nsACString& aOrigin) override; protected: - virtual ~nsExpandedPrincipal(); + virtual ~ExpandedPrincipal(); - bool SubsumesInternal(nsIPrincipal* aOther, DocumentDomainConsideration aConsideration) override; + bool SubsumesInternal(nsIPrincipal* aOther, + DocumentDomainConsideration aConsideration) override; + bool MayLoadInternal(nsIURI* aURI) override; private: nsTArray< nsCOMPtr<nsIPrincipal> > mPrincipals; }; #define NS_EXPANDEDPRINCIPAL_CONTRACTID "@mozilla.org/expandedprincipal;1" #define NS_EXPANDEDPRINCIPAL_CID \ { 0xe8ee88b0, 0x5571, 0x4086, \ { 0xa4, 0x5b, 0x39, 0xa7, 0x16, 0x90, 0x6b, 0xdb } } -#endif // nsExpandedPrincipal_h +#endif // ExpandedPrincipal_h
rename from caps/nsNullPrincipal.cpp rename to caps/NullPrincipal.cpp --- a/caps/nsNullPrincipal.cpp +++ b/caps/NullPrincipal.cpp @@ -8,191 +8,192 @@ * This is the principal that has no rights and can't be accessed by * anything other than itself and chrome; null principals are not * same-origin with anything but themselves. */ #include "mozilla/ArrayUtils.h" #include "nsDocShell.h" -#include "nsNullPrincipal.h" -#include "nsNullPrincipalURI.h" +#include "NullPrincipal.h" +#include "NullPrincipalURI.h" #include "nsMemory.h" #include "nsIURIWithPrincipal.h" #include "nsIClassInfoImpl.h" #include "nsNetCID.h" #include "nsError.h" #include "nsIScriptSecurityManager.h" -#include "nsPrincipal.h" +#include "ContentPrincipal.h" #include "nsScriptSecurityManager.h" #include "pratom.h" using namespace mozilla; -NS_IMPL_CLASSINFO(nsNullPrincipal, nullptr, nsIClassInfo::MAIN_THREAD_ONLY, +NS_IMPL_CLASSINFO(NullPrincipal, nullptr, nsIClassInfo::MAIN_THREAD_ONLY, NS_NULLPRINCIPAL_CID) -NS_IMPL_QUERY_INTERFACE_CI(nsNullPrincipal, +NS_IMPL_QUERY_INTERFACE_CI(NullPrincipal, nsIPrincipal, nsISerializable) -NS_IMPL_CI_INTERFACE_GETTER(nsNullPrincipal, +NS_IMPL_CI_INTERFACE_GETTER(NullPrincipal, nsIPrincipal, nsISerializable) -/* static */ already_AddRefed<nsNullPrincipal> -nsNullPrincipal::CreateWithInheritedAttributes(nsIPrincipal* aInheritFrom) +/* static */ already_AddRefed<NullPrincipal> +NullPrincipal::CreateWithInheritedAttributes(nsIPrincipal* aInheritFrom) { - RefPtr<nsNullPrincipal> nullPrin = new nsNullPrincipal(); + RefPtr<NullPrincipal> nullPrin = new NullPrincipal(); nsresult rv = nullPrin->Init(Cast(aInheritFrom)->OriginAttributesRef()); MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv)); return nullPrin.forget(); } -/* static */ already_AddRefed<nsNullPrincipal> -nsNullPrincipal::CreateWithInheritedAttributes(nsIDocShell* aDocShell, bool aIsFirstParty) +/* static */ already_AddRefed<NullPrincipal> +NullPrincipal::CreateWithInheritedAttributes(nsIDocShell* aDocShell, bool aIsFirstParty) { OriginAttributes attrs = nsDocShell::Cast(aDocShell)->GetOriginAttributes(); attrs.SetFirstPartyDomain(aIsFirstParty, NS_LITERAL_CSTRING(NULL_PRINCIPAL_FIRST_PARTY_DOMAIN)); - RefPtr<nsNullPrincipal> nullPrin = new nsNullPrincipal(); + RefPtr<NullPrincipal> nullPrin = new NullPrincipal(); nsresult rv = nullPrin->Init(attrs); MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv)); return nullPrin.forget(); } -/* static */ already_AddRefed<nsNullPrincipal> -nsNullPrincipal::Create(const OriginAttributes& aOriginAttributes, nsIURI* aURI) +/* static */ already_AddRefed<NullPrincipal> +NullPrincipal::Create(const OriginAttributes& aOriginAttributes, nsIURI* aURI) { - RefPtr<nsNullPrincipal> nullPrin = new nsNullPrincipal(); + RefPtr<NullPrincipal> nullPrin = new NullPrincipal(); nsresult rv = nullPrin->Init(aOriginAttributes, aURI); MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv)); return nullPrin.forget(); } nsresult -nsNullPrincipal::Init(const OriginAttributes& aOriginAttributes, nsIURI* aURI) +NullPrincipal::Init(const OriginAttributes& aOriginAttributes, nsIURI* aURI) { mOriginAttributes = aOriginAttributes; if (aURI) { nsAutoCString scheme; nsresult rv = aURI->GetScheme(scheme); NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_TRUE(scheme.EqualsLiteral(NS_NULLPRINCIPAL_SCHEME), NS_ERROR_NOT_AVAILABLE); mURI = aURI; } else { - mURI = nsNullPrincipalURI::Create(); + mURI = NullPrincipalURI::Create(); NS_ENSURE_TRUE(mURI, NS_ERROR_NOT_AVAILABLE); } FinishInit(); return NS_OK; } nsresult -nsNullPrincipal::GetScriptLocation(nsACString &aStr) +NullPrincipal::GetScriptLocation(nsACString &aStr) { return mURI->GetSpec(aStr); } /** * nsIPrincipal implementation */ NS_IMETHODIMP -nsNullPrincipal::GetHashValue(uint32_t *aResult) +NullPrincipal::GetHashValue(uint32_t *aResult) { *aResult = (NS_PTR_TO_INT32(this) >> 2); return NS_OK; } NS_IMETHODIMP -nsNullPrincipal::SetCsp(nsIContentSecurityPolicy* aCsp) { +NullPrincipal::SetCsp(nsIContentSecurityPolicy* aCsp) +{ // Never destroy an existing CSP on the principal. // This method should only be called in rare cases. MOZ_ASSERT(!mCSP, "do not destroy an existing CSP"); if (mCSP) { return NS_ERROR_ALREADY_INITIALIZED; } mCSP = aCsp; return NS_OK; } NS_IMETHODIMP -nsNullPrincipal::GetURI(nsIURI** aURI) +NullPrincipal::GetURI(nsIURI** aURI) { return NS_EnsureSafeToReturn(mURI, aURI); } NS_IMETHODIMP -nsNullPrincipal::GetDomain(nsIURI** aDomain) +NullPrincipal::GetDomain(nsIURI** aDomain) { return NS_EnsureSafeToReturn(mURI, aDomain); } NS_IMETHODIMP -nsNullPrincipal::SetDomain(nsIURI* aDomain) +NullPrincipal::SetDomain(nsIURI* aDomain) { // I think the right thing to do here is to just throw... Silently failing // seems counterproductive. return NS_ERROR_NOT_AVAILABLE; } nsresult -nsNullPrincipal::GetOriginInternal(nsACString& aOrigin) +NullPrincipal::GetOriginInternal(nsACString& aOrigin) { return mURI->GetSpec(aOrigin); } bool -nsNullPrincipal::MayLoadInternal(nsIURI* aURI) +NullPrincipal::MayLoadInternal(nsIURI* aURI) { // Also allow the load if we are the principal of the URI being checked. nsCOMPtr<nsIURIWithPrincipal> uriPrinc = do_QueryInterface(aURI); if (uriPrinc) { nsCOMPtr<nsIPrincipal> principal; uriPrinc->GetPrincipal(getter_AddRefs(principal)); if (principal == this) { return true; } } return false; } NS_IMETHODIMP -nsNullPrincipal::GetBaseDomain(nsACString& aBaseDomain) +NullPrincipal::GetBaseDomain(nsACString& aBaseDomain) { // For a null principal, we use our unique uuid as the base domain. return mURI->GetPath(aBaseDomain); } NS_IMETHODIMP -nsNullPrincipal::GetAddonId(nsAString& aAddonId) +NullPrincipal::GetAddonId(nsAString& aAddonId) { aAddonId.Truncate(); return NS_OK; }; /** * nsISerializable implementation */ NS_IMETHODIMP -nsNullPrincipal::Read(nsIObjectInputStream* aStream) +NullPrincipal::Read(nsIObjectInputStream* aStream) { - // Note - nsNullPrincipal use NS_GENERIC_FACTORY_CONSTRUCTOR_INIT, which means + // Note - NullPrincipal use NS_GENERIC_FACTORY_CONSTRUCTOR_INIT, which means // that the Init() method has already been invoked by the time we deserialize. - // This is in contrast to nsPrincipal, which uses NS_GENERIC_FACTORY_CONSTRUCTOR, + // This is in contrast to ContentPrincipal, which uses NS_GENERIC_FACTORY_CONSTRUCTOR, // in which case ::Read needs to invoke Init(). nsAutoCString spec; nsresult rv = aStream->ReadCString(spec); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIURI> uri; rv = NS_NewURI(getter_AddRefs(uri), spec); @@ -205,17 +206,17 @@ nsNullPrincipal::Read(nsIObjectInputStre OriginAttributes attrs; bool ok = attrs.PopulateFromSuffix(suffix); NS_ENSURE_TRUE(ok, NS_ERROR_FAILURE); return Init(attrs, uri); } NS_IMETHODIMP -nsNullPrincipal::Write(nsIObjectOutputStream* aStream) +NullPrincipal::Write(nsIObjectOutputStream* aStream) { NS_ENSURE_STATE(mURI); nsAutoCString spec; nsresult rv = mURI->GetSpec(spec); NS_ENSURE_SUCCESS(rv, rv); rv = aStream->WriteStringZ(spec.get());
rename from caps/nsNullPrincipal.h rename to caps/NullPrincipal.h --- a/caps/nsNullPrincipal.h +++ b/caps/NullPrincipal.h @@ -4,18 +4,18 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /** * This is the principal that has no rights and can't be accessed by * anything other than itself and chrome; null principals are not * same-origin with anything but themselves. */ -#ifndef nsNullPrincipal_h__ -#define nsNullPrincipal_h__ +#ifndef NullPrincipal_h +#define NullPrincipal_h #include "nsIPrincipal.h" #include "nsJSPrincipals.h" #include "nsIScriptSecurityManager.h" #include "nsCOMPtr.h" #include "nsIContentSecurityPolicy.h" #include "mozilla/BasePrincipal.h" @@ -25,62 +25,63 @@ class nsIURI; #define NS_NULLPRINCIPAL_CID \ { 0xbd066e5f, 0x146f, 0x4472, \ { 0x83, 0x31, 0x7b, 0xfd, 0x05, 0xb1, 0xed, 0x90 } } #define NS_NULLPRINCIPAL_CONTRACTID "@mozilla.org/nullprincipal;1" #define NS_NULLPRINCIPAL_SCHEME "moz-nullprincipal" -class nsNullPrincipal final : public mozilla::BasePrincipal +class NullPrincipal final : public mozilla::BasePrincipal { public: // This should only be used by deserialization, and the factory constructor. // Other consumers should use the Create and CreateWithInheritedAttributes // methods. - nsNullPrincipal() + NullPrincipal() : BasePrincipal(eNullPrincipal) { } NS_DECL_NSISERIALIZABLE NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) override; NS_IMETHOD GetHashValue(uint32_t* aHashValue) override; NS_IMETHOD SetCsp(nsIContentSecurityPolicy* aCsp) override; NS_IMETHOD GetURI(nsIURI** aURI) override; NS_IMETHOD GetDomain(nsIURI** aDomain) override; NS_IMETHOD SetDomain(nsIURI* aDomain) override; NS_IMETHOD GetBaseDomain(nsACString& aBaseDomain) override; NS_IMETHOD GetAddonId(nsAString& aAddonId) override; nsresult GetOriginInternal(nsACString& aOrigin) override; - static already_AddRefed<nsNullPrincipal> CreateWithInheritedAttributes(nsIPrincipal* aInheritFrom); + static already_AddRefed<NullPrincipal> CreateWithInheritedAttributes(nsIPrincipal* aInheritFrom); // Create NullPrincipal with origin attributes from docshell. // If aIsFirstParty is true, and the pref 'privacy.firstparty.isolate' is also // enabled, the mFirstPartyDomain value of the origin attributes will be set // to NULL_PRINCIPAL_FIRST_PARTY_DOMAIN. - static already_AddRefed<nsNullPrincipal> CreateWithInheritedAttributes(nsIDocShell* aDocShell, bool aIsFirstParty = false); + static already_AddRefed<NullPrincipal> + CreateWithInheritedAttributes(nsIDocShell* aDocShell, bool aIsFirstParty = false); - static already_AddRefed<nsNullPrincipal> + static already_AddRefed<NullPrincipal> Create(const mozilla::OriginAttributes& aOriginAttributes = mozilla::OriginAttributes(), nsIURI* aURI = nullptr); nsresult Init(const mozilla::OriginAttributes& aOriginAttributes = mozilla::OriginAttributes(), nsIURI* aURI = nullptr); virtual nsresult GetScriptLocation(nsACString &aStr) override; protected: - virtual ~nsNullPrincipal() {} + virtual ~NullPrincipal() = default; bool SubsumesInternal(nsIPrincipal* aOther, DocumentDomainConsideration aConsideration) override { return aOther == this; } bool MayLoadInternal(nsIURI* aURI) override; nsCOMPtr<nsIURI> mURI; }; -#endif // nsNullPrincipal_h__ +#endif // NullPrincipal_h__
rename from caps/nsNullPrincipalURI.cpp rename to caps/NullPrincipalURI.cpp --- a/caps/nsNullPrincipalURI.cpp +++ b/caps/NullPrincipalURI.cpp @@ -1,41 +1,41 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- * vim: sw=2 ts=2 sts=2 expandtab * 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 "nsNullPrincipalURI.h" +#include "NullPrincipalURI.h" #include "mozilla/DebugOnly.h" #include "mozilla/MemoryReporting.h" #include "mozilla/ipc/URIParams.h" #include "nsEscape.h" #include "nsCRT.h" #include "nsIUUIDGenerator.h" //////////////////////////////////////////////////////////////////////////////// -//// nsNullPrincipalURI +//// NullPrincipalURI -nsNullPrincipalURI::nsNullPrincipalURI() +NullPrincipalURI::NullPrincipalURI() : mPath(mPathBytes, ArrayLength(mPathBytes), ArrayLength(mPathBytes) - 1) { } -nsNullPrincipalURI::nsNullPrincipalURI(const nsNullPrincipalURI& aOther) +NullPrincipalURI::NullPrincipalURI(const NullPrincipalURI& aOther) : mPath(mPathBytes, ArrayLength(mPathBytes), ArrayLength(mPathBytes) - 1) { mPath.Assign(aOther.mPath); } nsresult -nsNullPrincipalURI::Init() +NullPrincipalURI::Init() { // FIXME: bug 327161 -- make sure the uuid generator is reseeding-resistant. nsCOMPtr<nsIUUIDGenerator> uuidgen = services::GetUUIDGenerator(); NS_ENSURE_TRUE(uuidgen, NS_ERROR_NOT_AVAILABLE); nsID id; nsresult rv = uuidgen->GenerateUUIDInPlace(&id); NS_ENSURE_SUCCESS(rv, rv); @@ -46,343 +46,343 @@ nsNullPrincipalURI::Init() MOZ_ASSERT(mPath.Length() == NSID_LENGTH - 1); MOZ_ASSERT(strlen(mPath.get()) == NSID_LENGTH - 1); return NS_OK; } /* static */ -already_AddRefed<nsNullPrincipalURI> -nsNullPrincipalURI::Create() +already_AddRefed<NullPrincipalURI> +NullPrincipalURI::Create() { - RefPtr<nsNullPrincipalURI> uri = new nsNullPrincipalURI(); + RefPtr<NullPrincipalURI> uri = new NullPrincipalURI(); nsresult rv = uri->Init(); NS_ENSURE_SUCCESS(rv, nullptr); return uri.forget(); } static NS_DEFINE_CID(kNullPrincipalURIImplementationCID, NS_NULLPRINCIPALURI_IMPLEMENTATION_CID); -NS_IMPL_ADDREF(nsNullPrincipalURI) -NS_IMPL_RELEASE(nsNullPrincipalURI) +NS_IMPL_ADDREF(NullPrincipalURI) +NS_IMPL_RELEASE(NullPrincipalURI) -NS_INTERFACE_MAP_BEGIN(nsNullPrincipalURI) +NS_INTERFACE_MAP_BEGIN(NullPrincipalURI) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIURI) if (aIID.Equals(kNullPrincipalURIImplementationCID)) - foundInterface = static_cast<nsIURI *>(this); + foundInterface = static_cast<nsIURI*>(this); else NS_INTERFACE_MAP_ENTRY(nsIURI) NS_INTERFACE_MAP_ENTRY(nsISizeOf) NS_INTERFACE_MAP_ENTRY(nsIIPCSerializableURI) NS_INTERFACE_MAP_END //////////////////////////////////////////////////////////////////////////////// //// nsIURI NS_IMETHODIMP -nsNullPrincipalURI::GetAsciiHost(nsACString &_host) +NullPrincipalURI::GetAsciiHost(nsACString& _host) { _host.Truncate(); return NS_OK; } NS_IMETHODIMP -nsNullPrincipalURI::GetAsciiHostPort(nsACString &_hostport) +NullPrincipalURI::GetAsciiHostPort(nsACString& _hostport) { return NS_ERROR_NOT_IMPLEMENTED; } NS_IMETHODIMP -nsNullPrincipalURI::GetAsciiSpec(nsACString &_spec) +NullPrincipalURI::GetAsciiSpec(nsACString& _spec) { nsAutoCString buffer; - // Ignore the return value -- nsNullPrincipalURI::GetSpec() is infallible. + // Ignore the return value -- NullPrincipalURI::GetSpec() is infallible. Unused << GetSpec(buffer); // This uses the infallible version of |NS_EscapeURL| as |GetSpec| is // already infallible. NS_EscapeURL(buffer, esc_OnlyNonASCII | esc_AlwaysCopy, _spec); return NS_OK; } NS_IMETHODIMP -nsNullPrincipalURI::GetHost(nsACString &_host) +NullPrincipalURI::GetHost(nsACString& _host) { _host.Truncate(); return NS_OK; } NS_IMETHODIMP -nsNullPrincipalURI::SetHost(const nsACString &aHost) +NullPrincipalURI::SetHost(const nsACString& aHost) { return NS_ERROR_NOT_IMPLEMENTED; } NS_IMETHODIMP -nsNullPrincipalURI::GetHostPort(nsACString &_host) +NullPrincipalURI::GetHostPort(nsACString& _host) { return NS_ERROR_NOT_IMPLEMENTED; } NS_IMETHODIMP -nsNullPrincipalURI::SetHostPort(const nsACString &aHost) +NullPrincipalURI::SetHostPort(const nsACString& aHost) { return NS_ERROR_NOT_IMPLEMENTED; } NS_IMETHODIMP -nsNullPrincipalURI::SetHostAndPort(const nsACString &aHost) +NullPrincipalURI::SetHostAndPort(const nsACString& aHost) { return NS_ERROR_NOT_IMPLEMENTED; } NS_IMETHODIMP -nsNullPrincipalURI::GetOriginCharset(nsACString &_charset) +NullPrincipalURI::GetOriginCharset(nsACString& _charset) { _charset.Truncate(); return NS_OK; } NS_IMETHODIMP -nsNullPrincipalURI::GetPassword(nsACString &_password) +NullPrincipalURI::GetPassword(nsACString& _password) { return NS_ERROR_NOT_IMPLEMENTED; } NS_IMETHODIMP -nsNullPrincipalURI::SetPassword(const nsACString &aPassword) +NullPrincipalURI::SetPassword(const nsACString& aPassword) { return NS_ERROR_NOT_IMPLEMENTED; } NS_IMETHODIMP -nsNullPrincipalURI::GetPath(nsACString &_path) +NullPrincipalURI::GetPath(nsACString& _path) { _path = mPath; return NS_OK; } NS_IMETHODIMP -nsNullPrincipalURI::SetPath(const nsACString &aPath) +NullPrincipalURI::SetPath(const nsACString& aPath) { return NS_ERROR_NOT_IMPLEMENTED; } NS_IMETHODIMP -nsNullPrincipalURI::GetFilePath(nsACString &aFilePath) +NullPrincipalURI::GetFilePath(nsACString& aFilePath) { aFilePath.Truncate(); return NS_ERROR_NOT_IMPLEMENTED; } NS_IMETHODIMP -nsNullPrincipalURI::SetFilePath(const nsACString &aFilePath) +NullPrincipalURI::SetFilePath(const nsACString& aFilePath) { return NS_ERROR_NOT_IMPLEMENTED; } NS_IMETHODIMP -nsNullPrincipalURI::GetQuery(nsACString &aQuery) +NullPrincipalURI::GetQuery(nsACString& aQuery) { aQuery.Truncate(); return NS_ERROR_NOT_IMPLEMENTED; } NS_IMETHODIMP -nsNullPrincipalURI::SetQuery(const nsACString &aQuery) +NullPrincipalURI::SetQuery(const nsACString& aQuery) { return NS_ERROR_NOT_IMPLEMENTED; } NS_IMETHODIMP -nsNullPrincipalURI::GetRef(nsACString &_ref) +NullPrincipalURI::GetRef(nsACString& _ref) { _ref.Truncate(); return NS_ERROR_NOT_IMPLEMENTED; } NS_IMETHODIMP -nsNullPrincipalURI::SetRef(const nsACString &aRef) +NullPrincipalURI::SetRef(const nsACString& aRef) { return NS_ERROR_NOT_IMPLEMENTED; } NS_IMETHODIMP -nsNullPrincipalURI::GetPrePath(nsACString &_prePath) +NullPrincipalURI::GetPrePath(nsACString& _prePath) { _prePath = NS_LITERAL_CSTRING(NS_NULLPRINCIPAL_SCHEME ":"); return NS_OK; } NS_IMETHODIMP -nsNullPrincipalURI::GetPort(int32_t *_port) +NullPrincipalURI::GetPort(int32_t* _port) { return NS_ERROR_NOT_IMPLEMENTED; } NS_IMETHODIMP -nsNullPrincipalURI::SetPort(int32_t aPort) +NullPrincipalURI::SetPort(int32_t aPort) { return NS_ERROR_NOT_IMPLEMENTED; } NS_IMETHODIMP -nsNullPrincipalURI::GetScheme(nsACString &_scheme) +NullPrincipalURI::GetScheme(nsACString& _scheme) { _scheme = NS_LITERAL_CSTRING(NS_NULLPRINCIPAL_SCHEME); return NS_OK; } NS_IMETHODIMP -nsNullPrincipalURI::SetScheme(const nsACString &aScheme) +NullPrincipalURI::SetScheme(const nsACString& aScheme) { return NS_ERROR_NOT_IMPLEMENTED; } NS_IMETHODIMP -nsNullPrincipalURI::GetSpec(nsACString &_spec) +NullPrincipalURI::GetSpec(nsACString& _spec) { _spec = NS_LITERAL_CSTRING(NS_NULLPRINCIPAL_SCHEME ":") + mPath; return NS_OK; } // result may contain unescaped UTF-8 characters NS_IMETHODIMP -nsNullPrincipalURI::GetSpecIgnoringRef(nsACString &result) +NullPrincipalURI::GetSpecIgnoringRef(nsACString& _result) { - return GetSpec(result); + return GetSpec(_result); } NS_IMETHODIMP -nsNullPrincipalURI::GetHasRef(bool *result) +NullPrincipalURI::GetHasRef(bool* _result) { - *result = false; + *_result = false; return NS_OK; } NS_IMETHODIMP -nsNullPrincipalURI::SetSpec(const nsACString &aSpec) +NullPrincipalURI::SetSpec(const nsACString& aSpec) { return NS_ERROR_NOT_IMPLEMENTED; } NS_IMETHODIMP -nsNullPrincipalURI::GetUsername(nsACString &_username) +NullPrincipalURI::GetUsername(nsACString& _username) { return NS_ERROR_NOT_IMPLEMENTED; } NS_IMETHODIMP -nsNullPrincipalURI::SetUsername(const nsACString &aUsername) +NullPrincipalURI::SetUsername(const nsACString& aUsername) { return NS_ERROR_NOT_IMPLEMENTED; } NS_IMETHODIMP -nsNullPrincipalURI::GetUserPass(nsACString &_userPass) +NullPrincipalURI::GetUserPass(nsACString& _userPass) { return NS_ERROR_NOT_IMPLEMENTED; } NS_IMETHODIMP -nsNullPrincipalURI::SetUserPass(const nsACString &aUserPass) +NullPrincipalURI::SetUserPass(const nsACString& aUserPass) { return NS_ERROR_NOT_IMPLEMENTED; } NS_IMETHODIMP -nsNullPrincipalURI::Clone(nsIURI **_newURI) +NullPrincipalURI::Clone(nsIURI** _newURI) { - nsCOMPtr<nsIURI> uri = new nsNullPrincipalURI(*this); + nsCOMPtr<nsIURI> uri = new NullPrincipalURI(*this); uri.forget(_newURI); return NS_OK; } NS_IMETHODIMP -nsNullPrincipalURI::CloneIgnoringRef(nsIURI **_newURI) +NullPrincipalURI::CloneIgnoringRef(nsIURI** _newURI) { - // GetRef/SetRef not supported by nsNullPrincipalURI, so + // GetRef/SetRef not supported by NullPrincipalURI, so // CloneIgnoringRef() is the same as Clone(). return Clone(_newURI); } NS_IMETHODIMP -nsNullPrincipalURI::CloneWithNewRef(const nsACString& newRef, nsIURI **_newURI) +NullPrincipalURI::CloneWithNewRef(const nsACString& newRef, nsIURI** _newURI) { - // GetRef/SetRef not supported by nsNullPrincipalURI, so + // GetRef/SetRef not supported by NullPrincipalURI, so // CloneWithNewRef() is the same as Clone(). return Clone(_newURI); } NS_IMETHODIMP -nsNullPrincipalURI::Equals(nsIURI *aOther, bool *_equals) +NullPrincipalURI::Equals(nsIURI* aOther, bool* _equals) { *_equals = false; - RefPtr<nsNullPrincipalURI> otherURI; + RefPtr<NullPrincipalURI> otherURI; nsresult rv = aOther->QueryInterface(kNullPrincipalURIImplementationCID, getter_AddRefs(otherURI)); if (NS_SUCCEEDED(rv)) { *_equals = mPath == otherURI->mPath; } return NS_OK; } NS_IMETHODIMP -nsNullPrincipalURI::EqualsExceptRef(nsIURI *aOther, bool *_equals) +NullPrincipalURI::EqualsExceptRef(nsIURI* aOther, bool* _equals) { - // GetRef/SetRef not supported by nsNullPrincipalURI, so + // GetRef/SetRef not supported by NullPrincipalURI, so // EqualsExceptRef() is the same as Equals(). return Equals(aOther, _equals); } NS_IMETHODIMP -nsNullPrincipalURI::Resolve(const nsACString &aRelativePath, - nsACString &_resolvedURI) +NullPrincipalURI::Resolve(const nsACString& aRelativePath, + nsACString& _resolvedURI) { _resolvedURI = aRelativePath; return NS_OK; } NS_IMETHODIMP -nsNullPrincipalURI::SchemeIs(const char *aScheme, bool *_schemeIs) +NullPrincipalURI::SchemeIs(const char* aScheme, bool* _schemeIs) { *_schemeIs = (0 == nsCRT::strcasecmp(NS_NULLPRINCIPAL_SCHEME, aScheme)); return NS_OK; } //////////////////////////////////////////////////////////////////////////////// //// nsIIPCSerializableURI void -nsNullPrincipalURI::Serialize(mozilla::ipc::URIParams &aParams) +NullPrincipalURI::Serialize(mozilla::ipc::URIParams& aParams) { aParams = mozilla::ipc::NullPrincipalURIParams(); } bool -nsNullPrincipalURI::Deserialize(const mozilla::ipc::URIParams &aParams) +NullPrincipalURI::Deserialize(const mozilla::ipc::URIParams& aParams) { if (aParams.type() != mozilla::ipc::URIParams::TNullPrincipalURIParams) { MOZ_ASSERT_UNREACHABLE("unexpected URIParams type"); return false; } nsresult rv = Init(); NS_ENSURE_SUCCESS(rv, false); return true; } //////////////////////////////////////////////////////////////////////////////// //// nsISizeOf size_t -nsNullPrincipalURI::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const +NullPrincipalURI::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const { return mPath.SizeOfExcludingThisIfUnshared(aMallocSizeOf); } size_t -nsNullPrincipalURI::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const { +NullPrincipalURI::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const +{ return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf); } -
rename from caps/nsNullPrincipalURI.h rename to caps/NullPrincipalURI.h --- a/caps/nsNullPrincipalURI.h +++ b/caps/NullPrincipalURI.h @@ -3,57 +3,57 @@ * 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/. */ /** * This wraps nsSimpleURI so that all calls to it are done on the main thread. */ -#ifndef __nsNullPrincipalURI_h__ -#define __nsNullPrincipalURI_h__ +#ifndef __NullPrincipalURI_h__ +#define __NullPrincipalURI_h__ #include "nsIURI.h" #include "nsISizeOf.h" #include "nsString.h" #include "mozilla/Attributes.h" #include "nsIIPCSerializableURI.h" #include "mozilla/MemoryReporting.h" -#include "nsNullPrincipal.h" +#include "NullPrincipal.h" #include "nsID.h" // {51fcd543-3b52-41f7-b91b-6b54102236e6} #define NS_NULLPRINCIPALURI_IMPLEMENTATION_CID \ {0x51fcd543, 0x3b52, 0x41f7, \ {0xb9, 0x1b, 0x6b, 0x54, 0x10, 0x22, 0x36, 0xe6} } -class nsNullPrincipalURI final : public nsIURI - , public nsISizeOf - , public nsIIPCSerializableURI +class NullPrincipalURI final : public nsIURI + , public nsISizeOf + , public nsIIPCSerializableURI { public: NS_DECL_THREADSAFE_ISUPPORTS NS_DECL_NSIURI NS_DECL_NSIIPCSERIALIZABLEURI // nsISizeOf virtual size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const override; virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const override; // NB: This constructor exists only for deserialization. Everyone // else should call Create. - nsNullPrincipalURI(); + NullPrincipalURI(); // Returns null on failure. - static already_AddRefed<nsNullPrincipalURI> Create(); + static already_AddRefed<NullPrincipalURI> Create(); private: - nsNullPrincipalURI(const nsNullPrincipalURI& aOther); + NullPrincipalURI(const NullPrincipalURI& aOther); - ~nsNullPrincipalURI() {} + ~NullPrincipalURI() {} nsresult Init(); char mPathBytes[NSID_LENGTH]; nsFixedCString mPath; }; -#endif // __nsNullPrincipalURI_h__ +#endif // __NullPrincipalURI_h__
copy from caps/BasePrincipal.cpp copy to caps/OriginAttributes.cpp --- a/caps/BasePrincipal.cpp +++ b/caps/OriginAttributes.cpp @@ -1,38 +1,20 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=2 sw=2 et 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 "mozilla/BasePrincipal.h" - -#include "nsDocShell.h" -#ifdef MOZ_CRASHREPORTER -#include "nsExceptionHandler.h" -#endif -#include "nsIAddonPolicyService.h" -#include "nsIContentSecurityPolicy.h" +#include "mozilla/OriginAttributes.h" +#include "mozilla/Preferences.h" +#include "mozilla/dom/URLSearchParams.h" +#include "mozilla/dom/quota/QuotaManager.h" #include "nsIEffectiveTLDService.h" -#include "nsIObjectInputStream.h" -#include "nsIObjectOutputStream.h" - -#include "nsPrincipal.h" -#include "nsNetUtil.h" -#include "nsIURIWithPrincipal.h" -#include "nsNullPrincipal.h" -#include "nsScriptSecurityManager.h" -#include "nsServiceManagerUtils.h" - -#include "mozilla/dom/ChromeUtils.h" -#include "mozilla/dom/CSPDictionariesBinding.h" -#include "mozilla/dom/quota/QuotaManager.h" -#include "mozilla/dom/ToJSValue.h" -#include "mozilla/dom/URLSearchParams.h" +#include "nsIURI.h" namespace mozilla { using dom::URLParams; bool OriginAttributes::sFirstPartyIsolation = false; bool OriginAttributes::sRestrictedOpenerAccess = false; @@ -293,457 +275,9 @@ OriginAttributes::IsPrivateBrowsing(cons OriginAttributes attrs; if (NS_WARN_IF(!attrs.PopulateFromOrigin(aOrigin, dummy))) { return false; } return !!attrs.mPrivateBrowsingId; } -BasePrincipal::BasePrincipal(PrincipalKind aKind) - : mKind(aKind) - , mDomainSet(false) -{} - -BasePrincipal::~BasePrincipal() -{} - -NS_IMETHODIMP -BasePrincipal::GetOrigin(nsACString& aOrigin) -{ - nsresult rv = GetOriginNoSuffix(aOrigin); - NS_ENSURE_SUCCESS(rv, rv); - - nsAutoCString suffix; - rv = GetOriginSuffix(suffix); - NS_ENSURE_SUCCESS(rv, rv); - aOrigin.Append(suffix); - return NS_OK; -} - -NS_IMETHODIMP -BasePrincipal::GetOriginNoSuffix(nsACString& aOrigin) -{ - if (mOriginNoSuffix) { - return mOriginNoSuffix->ToUTF8String(aOrigin); - } - return GetOriginInternal(aOrigin); -} - -bool -BasePrincipal::Subsumes(nsIPrincipal* aOther, DocumentDomainConsideration aConsideration) -{ - MOZ_ASSERT(aOther); - MOZ_ASSERT_IF(Kind() == eCodebasePrincipal, mOriginSuffix); - - // Expanded principals handle origin attributes for each of their - // sub-principals individually, null principals do only simple checks for - // pointer equality, and system principals are immune to origin attributes - // checks, so only do this check for codebase principals. - if (Kind() == eCodebasePrincipal && - mOriginSuffix != Cast(aOther)->mOriginSuffix) { - return false; - } - - return SubsumesInternal(aOther, aConsideration); -} - -NS_IMETHODIMP -BasePrincipal::Equals(nsIPrincipal *aOther, bool *aResult) -{ - NS_ENSURE_TRUE(aOther, NS_ERROR_INVALID_ARG); - - *aResult = FastEquals(aOther); - - return NS_OK; -} - -NS_IMETHODIMP -BasePrincipal::EqualsConsideringDomain(nsIPrincipal *aOther, bool *aResult) -{ - NS_ENSURE_TRUE(aOther, NS_ERROR_INVALID_ARG); - - *aResult = FastEqualsConsideringDomain(aOther); - - return NS_OK; -} - -NS_IMETHODIMP -BasePrincipal::Subsumes(nsIPrincipal *aOther, bool *aResult) -{ - NS_ENSURE_TRUE(aOther, NS_ERROR_INVALID_ARG); - - *aResult = FastSubsumes(aOther); - - return NS_OK; -} - -NS_IMETHODIMP -BasePrincipal::SubsumesConsideringDomain(nsIPrincipal *aOther, bool *aResult) -{ - NS_ENSURE_TRUE(aOther, NS_ERROR_INVALID_ARG); - - *aResult = FastSubsumesConsideringDomain(aOther); - - return NS_OK; -} - -NS_IMETHODIMP -BasePrincipal::SubsumesConsideringDomainIgnoringFPD(nsIPrincipal *aOther, - bool *aResult) -{ - NS_ENSURE_TRUE(aOther, NS_ERROR_INVALID_ARG); - - *aResult = FastSubsumesConsideringDomainIgnoringFPD(aOther); - - return NS_OK; -} - -NS_IMETHODIMP -BasePrincipal::CheckMayLoad(nsIURI* aURI, bool aReport, bool aAllowIfInheritsPrincipal) -{ - // Check the internal method first, which allows us to quickly approve loads - // for the System Principal. - if (MayLoadInternal(aURI)) { - return NS_OK; - } - - nsresult rv; - if (aAllowIfInheritsPrincipal) { - // If the caller specified to allow loads of URIs that inherit - // our principal, allow the load if this URI inherits its principal. - bool doesInheritSecurityContext; - rv = NS_URIChainHasFlags(aURI, nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT, - &doesInheritSecurityContext); - if (NS_SUCCEEDED(rv) && doesInheritSecurityContext) { - return NS_OK; - } - } - - bool fetchableByAnyone; - rv = NS_URIChainHasFlags(aURI, nsIProtocolHandler::URI_FETCHABLE_BY_ANYONE, &fetchableByAnyone); - if (NS_SUCCEEDED(rv) && fetchableByAnyone) { - return NS_OK; - } - - if (aReport) { - nsCOMPtr<nsIURI> prinURI; - rv = GetURI(getter_AddRefs(prinURI)); - if (NS_SUCCEEDED(rv) && prinURI) { - nsScriptSecurityManager::ReportError(nullptr, NS_LITERAL_STRING("CheckSameOriginError"), prinURI, aURI); - } - } - - return NS_ERROR_DOM_BAD_URI; -} - -NS_IMETHODIMP -BasePrincipal::GetCsp(nsIContentSecurityPolicy** aCsp) -{ - NS_IF_ADDREF(*aCsp = mCSP); - return NS_OK; -} - -NS_IMETHODIMP -BasePrincipal::SetCsp(nsIContentSecurityPolicy* aCsp) -{ - // Never destroy an existing CSP on the principal. - // This method should only be called in rare cases. - - MOZ_ASSERT(!mCSP, "do not destroy an existing CSP"); - if (mCSP) { - return NS_ERROR_ALREADY_INITIALIZED; - } - - mCSP = aCsp; - return NS_OK; -} - -NS_IMETHODIMP -BasePrincipal::EnsureCSP(nsIDOMDocument* aDocument, - nsIContentSecurityPolicy** aCSP) -{ - if (mCSP) { - // if there is a CSP already associated with this principal - // then just return that - do not overwrite it!!! - NS_IF_ADDREF(*aCSP = mCSP); - return NS_OK; - } - - nsresult rv = NS_OK; - mCSP = do_CreateInstance("@mozilla.org/cspcontext;1", &rv); - NS_ENSURE_SUCCESS(rv, rv); - - // Store the request context for violation reports - rv = aDocument ? mCSP->SetRequestContext(aDocument, nullptr) - : mCSP->SetRequestContext(nullptr, this); - NS_ENSURE_SUCCESS(rv, rv); - NS_IF_ADDREF(*aCSP = mCSP); - return NS_OK; -} - -NS_IMETHODIMP -BasePrincipal::GetPreloadCsp(nsIContentSecurityPolicy** aPreloadCSP) -{ - NS_IF_ADDREF(*aPreloadCSP = mPreloadCSP); - return NS_OK; -} - -NS_IMETHODIMP -BasePrincipal::EnsurePreloadCSP(nsIDOMDocument* aDocument, - nsIContentSecurityPolicy** aPreloadCSP) -{ - if (mPreloadCSP) { - // if there is a speculative CSP already associated with this principal - // then just return that - do not overwrite it!!! - NS_IF_ADDREF(*aPreloadCSP = mPreloadCSP); - return NS_OK; - } - - nsresult rv = NS_OK; - mPreloadCSP = do_CreateInstance("@mozilla.org/cspcontext;1", &rv); - NS_ENSURE_SUCCESS(rv, rv); - - // Store the request context for violation reports - rv = aDocument ? mPreloadCSP->SetRequestContext(aDocument, nullptr) - : mPreloadCSP->SetRequestContext(nullptr, this); - NS_ENSURE_SUCCESS(rv, rv); - NS_IF_ADDREF(*aPreloadCSP = mPreloadCSP); - return NS_OK; -} - -NS_IMETHODIMP -BasePrincipal::GetCspJSON(nsAString& outCSPinJSON) -{ - outCSPinJSON.Truncate(); - dom::CSPPolicies jsonPolicies; - - if (!mCSP) { - jsonPolicies.ToJSON(outCSPinJSON); - return NS_OK; - } - return mCSP->ToJSON(outCSPinJSON); -} - -NS_IMETHODIMP -BasePrincipal::GetIsNullPrincipal(bool* aResult) -{ - *aResult = Kind() == eNullPrincipal; - return NS_OK; -} - -NS_IMETHODIMP -BasePrincipal::GetIsCodebasePrincipal(bool* aResult) -{ - *aResult = Kind() == eCodebasePrincipal; - return NS_OK; -} - -NS_IMETHODIMP -BasePrincipal::GetIsExpandedPrincipal(bool* aResult) -{ - *aResult = Kind() == eExpandedPrincipal; - return NS_OK; -} - -NS_IMETHODIMP -BasePrincipal::GetIsSystemPrincipal(bool* aResult) -{ - *aResult = Kind() == eSystemPrincipal; - return NS_OK; -} - -NS_IMETHODIMP -BasePrincipal::GetOriginAttributes(JSContext* aCx, JS::MutableHandle<JS::Value> aVal) -{ - if (NS_WARN_IF(!ToJSValue(aCx, mOriginAttributes, aVal))) { - return NS_ERROR_FAILURE; - } - return NS_OK; -} - -NS_IMETHODIMP -BasePrincipal::GetOriginSuffix(nsACString& aOriginAttributes) -{ - MOZ_ASSERT(mOriginSuffix); - return mOriginSuffix->ToUTF8String(aOriginAttributes); -} - -NS_IMETHODIMP -BasePrincipal::GetAppStatus(uint16_t* aAppStatus) -{ - // TODO: Remove GetAppStatus. - *aAppStatus = nsIPrincipal::APP_STATUS_NOT_INSTALLED; - return NS_OK; -} - -NS_IMETHODIMP -BasePrincipal::GetAppId(uint32_t* aAppId) -{ - if (AppId() == nsIScriptSecurityManager::UNKNOWN_APP_ID) { - MOZ_ASSERT(false); - *aAppId = nsIScriptSecurityManager::NO_APP_ID; - return NS_OK; - } - - *aAppId = AppId(); - return NS_OK; -} - -NS_IMETHODIMP -BasePrincipal::GetUserContextId(uint32_t* aUserContextId) -{ - *aUserContextId = UserContextId(); - return NS_OK; -} - -NS_IMETHODIMP -BasePrincipal::GetPrivateBrowsingId(uint32_t* aPrivateBrowsingId) -{ - *aPrivateBrowsingId = PrivateBrowsingId(); - return NS_OK; -} - -NS_IMETHODIMP -BasePrincipal::GetIsInIsolatedMozBrowserElement(bool* aIsInIsolatedMozBrowserElement) -{ - *aIsInIsolatedMozBrowserElement = IsInIsolatedMozBrowserElement(); - return NS_OK; -} - -NS_IMETHODIMP -BasePrincipal::GetUnknownAppId(bool* aUnknownAppId) -{ - *aUnknownAppId = AppId() == nsIScriptSecurityManager::UNKNOWN_APP_ID; - return NS_OK; -} - -bool -BasePrincipal::AddonHasPermission(const nsAString& aPerm) -{ - nsAutoString addonId; - NS_ENSURE_SUCCESS(GetAddonId(addonId), false); - - if (addonId.IsEmpty()) { - return false; - } - - nsCOMPtr<nsIAddonPolicyService> aps = - do_GetService("@mozilla.org/addons/policy-service;1"); - NS_ENSURE_TRUE(aps, false); - - bool retval = false; - nsresult rv = aps->AddonHasPermission(addonId, aPerm, &retval); - NS_ENSURE_SUCCESS(rv, false); - return retval; -} - -already_AddRefed<BasePrincipal> -BasePrincipal::CreateCodebasePrincipal(nsIURI* aURI, const OriginAttributes& aAttrs) -{ - // If the URI is supposed to inherit the security context of whoever loads it, - // we shouldn't make a codebase principal for it. - bool inheritsPrincipal; - nsresult rv = NS_URIChainHasFlags(aURI, nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT, - &inheritsPrincipal); - if (NS_FAILED(rv) || inheritsPrincipal) { - return nsNullPrincipal::Create(aAttrs); - } - - // Check whether the URI knows what its principal is supposed to be. - nsCOMPtr<nsIURIWithPrincipal> uriPrinc = do_QueryInterface(aURI); - if (uriPrinc) { - nsCOMPtr<nsIPrincipal> principal; - uriPrinc->GetPrincipal(getter_AddRefs(principal)); - if (!principal) { - return nsNullPrincipal::Create(aAttrs); - } - RefPtr<BasePrincipal> concrete = Cast(principal); - return concrete.forget(); - } - - // Mint a codebase principal. - RefPtr<nsPrincipal> codebase = new nsPrincipal(); - rv = codebase->Init(aURI, aAttrs); - NS_ENSURE_SUCCESS(rv, nullptr); - return codebase.forget(); -} - -already_AddRefed<BasePrincipal> -BasePrincipal::CreateCodebasePrincipal(const nsACString& aOrigin) -{ - MOZ_ASSERT(!StringBeginsWith(aOrigin, NS_LITERAL_CSTRING("[")), - "CreateCodebasePrincipal does not support System and Expanded principals"); - - MOZ_ASSERT(!StringBeginsWith(aOrigin, NS_LITERAL_CSTRING(NS_NULLPRINCIPAL_SCHEME ":")), - "CreateCodebasePrincipal does not support nsNullPrincipal"); - - nsAutoCString originNoSuffix; - mozilla::OriginAttributes attrs; - if (!attrs.PopulateFromOrigin(aOrigin, originNoSuffix)) { - return nullptr; - } - - nsCOMPtr<nsIURI> uri; - nsresult rv = NS_NewURI(getter_AddRefs(uri), originNoSuffix); - NS_ENSURE_SUCCESS(rv, nullptr); - - return BasePrincipal::CreateCodebasePrincipal(uri, attrs); -} - -already_AddRefed<BasePrincipal> -BasePrincipal::CloneStrippingUserContextIdAndFirstPartyDomain() -{ - OriginAttributes attrs = OriginAttributesRef(); - attrs.StripAttributes(OriginAttributes::STRIP_USER_CONTEXT_ID | - OriginAttributes::STRIP_FIRST_PARTY_DOMAIN); - - nsAutoCString originNoSuffix; - nsresult rv = GetOriginNoSuffix(originNoSuffix); - NS_ENSURE_SUCCESS(rv, nullptr); - - nsCOMPtr<nsIURI> uri; - rv = NS_NewURI(getter_AddRefs(uri), originNoSuffix); - NS_ENSURE_SUCCESS(rv, nullptr); - - return BasePrincipal::CreateCodebasePrincipal(uri, attrs); -} - -bool -BasePrincipal::AddonAllowsLoad(nsIURI* aURI, bool aExplicit /* = false */) -{ - nsAutoString addonId; - NS_ENSURE_SUCCESS(GetAddonId(addonId), false); - - if (addonId.IsEmpty()) { - return false; - } - - nsCOMPtr<nsIAddonPolicyService> aps = do_GetService("@mozilla.org/addons/policy-service;1"); - NS_ENSURE_TRUE(aps, false); - - bool allowed = false; - nsresult rv = aps->AddonMayLoadURI(addonId, aURI, aExplicit, &allowed); - return NS_SUCCEEDED(rv) && allowed; -} - -void -BasePrincipal::FinishInit() -{ - // First compute the origin suffix since it's infallible. - nsAutoCString originSuffix; - mOriginAttributes.CreateSuffix(originSuffix); - mOriginSuffix = NS_Atomize(originSuffix); - - // Then compute the origin without the suffix. - nsAutoCString originNoSuffix; - nsresult rv = GetOriginInternal(originNoSuffix); - if (NS_FAILED(rv)) { - // If GetOriginInternal fails, we will get a null atom for mOriginNoSuffix, - // which we deal with anywhere mOriginNoSuffix is used. - // Once this is made infallible we can remove those null checks. - mOriginNoSuffix = nullptr; - return; - } - mOriginNoSuffix = NS_Atomize(originNoSuffix); -} - } // namespace mozilla
copy from caps/BasePrincipal.h copy to caps/OriginAttributes.h --- a/caps/BasePrincipal.h +++ b/caps/OriginAttributes.h @@ -1,35 +1,23 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=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_BasePrincipal_h -#define mozilla_BasePrincipal_h +#ifndef mozilla_OriginAttributes_h +#define mozilla_OriginAttributes_h -#include "nsJSPrincipals.h" - -#include "mozilla/Attributes.h" #include "mozilla/dom/ChromeUtils.h" #include "mozilla/dom/ChromeUtilsBinding.h" #include "nsIScriptSecurityManager.h" -class nsIContentSecurityPolicy; -class nsIObjectOutputStream; -class nsIObjectInputStream; -class nsIURI; - -class nsExpandedPrincipal; - namespace mozilla { -// Base OriginAttributes class. This has several subclass flavors, and is not -// directly constructable itself. class OriginAttributes : public dom::OriginAttributesDictionary { public: OriginAttributes() {} OriginAttributes(uint32_t aAppId, bool aInIsolatedMozBrowser) { mAppId = aAppId; @@ -186,214 +174,11 @@ public: mFirstPartyDomain.Value() != aOther.mFirstPartyDomain.Value()) { return false; } return true; } }; -/* - * Base class from which all nsIPrincipal implementations inherit. Use this for - * default implementations and other commonalities between principal - * implementations. - * - * We should merge nsJSPrincipals into this class at some point. - */ -class BasePrincipal : public nsJSPrincipals -{ -public: - enum PrincipalKind { - eNullPrincipal, - eCodebasePrincipal, - eExpandedPrincipal, - eSystemPrincipal - }; - - explicit BasePrincipal(PrincipalKind aKind); - - enum DocumentDomainConsideration { DontConsiderDocumentDomain, ConsiderDocumentDomain}; - bool Subsumes(nsIPrincipal* aOther, DocumentDomainConsideration aConsideration); - - NS_IMETHOD GetOrigin(nsACString& aOrigin) final; - NS_IMETHOD GetOriginNoSuffix(nsACString& aOrigin) final; - NS_IMETHOD Equals(nsIPrincipal* other, bool* _retval) final; - NS_IMETHOD EqualsConsideringDomain(nsIPrincipal* other, bool* _retval) final; - NS_IMETHOD Subsumes(nsIPrincipal* other, bool* _retval) final; - NS_IMETHOD SubsumesConsideringDomain(nsIPrincipal* other, bool* _retval) final; - NS_IMETHOD SubsumesConsideringDomainIgnoringFPD(nsIPrincipal* other, bool* _retval) final; - NS_IMETHOD CheckMayLoad(nsIURI* uri, bool report, bool allowIfInheritsPrincipal) final; - NS_IMETHOD GetCsp(nsIContentSecurityPolicy** aCsp) override; - NS_IMETHOD SetCsp(nsIContentSecurityPolicy* aCsp) override; - NS_IMETHOD EnsureCSP(nsIDOMDocument* aDocument, nsIContentSecurityPolicy** aCSP) override; - NS_IMETHOD GetPreloadCsp(nsIContentSecurityPolicy** aPreloadCSP) override; - NS_IMETHOD EnsurePreloadCSP(nsIDOMDocument* aDocument, nsIContentSecurityPolicy** aCSP) override; - NS_IMETHOD GetCspJSON(nsAString& outCSPinJSON) override; - NS_IMETHOD GetIsNullPrincipal(bool* aResult) override; - NS_IMETHOD GetIsCodebasePrincipal(bool* aResult) override; - NS_IMETHOD GetIsExpandedPrincipal(bool* aResult) override; - NS_IMETHOD GetIsSystemPrincipal(bool* aResult) override; - NS_IMETHOD GetOriginAttributes(JSContext* aCx, JS::MutableHandle<JS::Value> aVal) final; - NS_IMETHOD GetOriginSuffix(nsACString& aOriginSuffix) final; - NS_IMETHOD GetAppStatus(uint16_t* aAppStatus) final; - NS_IMETHOD GetAppId(uint32_t* aAppStatus) final; - NS_IMETHOD GetIsInIsolatedMozBrowserElement(bool* aIsInIsolatedMozBrowserElement) final; - NS_IMETHOD GetUnknownAppId(bool* aUnknownAppId) final; - NS_IMETHOD GetUserContextId(uint32_t* aUserContextId) final; - NS_IMETHOD GetPrivateBrowsingId(uint32_t* aPrivateBrowsingId) final; - - virtual bool AddonHasPermission(const nsAString& aPerm); - - virtual bool IsCodebasePrincipal() const { return false; }; - - static BasePrincipal* Cast(nsIPrincipal* aPrin) { return static_cast<BasePrincipal*>(aPrin); } - static already_AddRefed<BasePrincipal> - CreateCodebasePrincipal(nsIURI* aURI, const OriginAttributes& aAttrs); - static already_AddRefed<BasePrincipal> CreateCodebasePrincipal(const nsACString& aOrigin); - - const OriginAttributes& OriginAttributesRef() final { return mOriginAttributes; } - uint32_t AppId() const { return mOriginAttributes.mAppId; } - uint32_t UserContextId() const { return mOriginAttributes.mUserContextId; } - uint32_t PrivateBrowsingId() const { return mOriginAttributes.mPrivateBrowsingId; } - bool IsInIsolatedMozBrowserElement() const { return mOriginAttributes.mInIsolatedMozBrowser; } - - PrincipalKind Kind() const { return mKind; } - - already_AddRefed<BasePrincipal> CloneStrippingUserContextIdAndFirstPartyDomain(); - - // Helper to check whether this principal is associated with an addon that - // allows unprivileged code to load aURI. aExplicit == true will prevent - // use of all_urls permission, requiring the domain in its permissions. - bool AddonAllowsLoad(nsIURI* aURI, bool aExplicit = false); - - // Call these to avoid the cost of virtual dispatch. - inline bool FastEquals(nsIPrincipal* aOther); - inline bool FastEqualsConsideringDomain(nsIPrincipal* aOther); - inline bool FastSubsumes(nsIPrincipal* aOther); - inline bool FastSubsumesConsideringDomain(nsIPrincipal* aOther); - inline bool FastSubsumesConsideringDomainIgnoringFPD(nsIPrincipal* aOther); - -protected: - virtual ~BasePrincipal(); - - virtual nsresult GetOriginInternal(nsACString& aOrigin) = 0; - // Note that this does not check OriginAttributes. Callers that depend on - // those must call Subsumes instead. - virtual bool SubsumesInternal(nsIPrincipal* aOther, DocumentDomainConsideration aConsider) = 0; - - // Internal, side-effect-free check to determine whether the concrete - // principal would allow the load ignoring any common behavior implemented in - // BasePrincipal::CheckMayLoad. - virtual bool MayLoadInternal(nsIURI* aURI) = 0; - friend class ::nsExpandedPrincipal; - - // This function should be called as the last step of the initialization of the - // principal objects. It's typically called as the last step from the Init() - // method of the child classes. - void FinishInit(); - - nsCOMPtr<nsIContentSecurityPolicy> mCSP; - nsCOMPtr<nsIContentSecurityPolicy> mPreloadCSP; - nsCOMPtr<nsIAtom> mOriginNoSuffix; - nsCOMPtr<nsIAtom> mOriginSuffix; - OriginAttributes mOriginAttributes; - PrincipalKind mKind; - bool mDomainSet; -}; - -inline bool -BasePrincipal::FastEquals(nsIPrincipal* aOther) -{ - auto other = Cast(aOther); - if (Kind() != other->Kind()) { - // Principals of different kinds can't be equal. - return false; - } - - // Two principals are considered to be equal if their origins are the same. - // If the two principals are codebase principals, their origin attributes - // (aka the origin suffix) must also match. - // If the two principals are null principals, they're only equal if they're - // the same object. - if (Kind() == eNullPrincipal || Kind() == eSystemPrincipal) { - return this == other; - } - - if (mOriginNoSuffix) { - if (Kind() == eCodebasePrincipal) { - return mOriginNoSuffix == other->mOriginNoSuffix && - mOriginSuffix == other->mOriginSuffix; - } - - MOZ_ASSERT(Kind() == eExpandedPrincipal); - return mOriginNoSuffix == other->mOriginNoSuffix; - } - - // If mOriginNoSuffix is null on one of our principals, we must fall back - // to the slow path. - return Subsumes(aOther, DontConsiderDocumentDomain) && - other->Subsumes(this, DontConsiderDocumentDomain); -} - -inline bool -BasePrincipal::FastEqualsConsideringDomain(nsIPrincipal* aOther) -{ - // If neither of the principals have document.domain set, we use the fast path - // in Equals(). Otherwise, we fall back to the slow path below. - auto other = Cast(aOther); - if (!mDomainSet && !other->mDomainSet) { - return FastEquals(aOther); - } - - return Subsumes(aOther, ConsiderDocumentDomain) && - other->Subsumes(this, ConsiderDocumentDomain); -} - -inline bool -BasePrincipal::FastSubsumes(nsIPrincipal* aOther) -{ - // If two principals are equal, then they both subsume each other. - // We deal with two special cases first: - // Null principals only subsume each other if they are equal, and are only - // equal if they're the same object. - // Also, if mOriginNoSuffix is null, FastEquals falls back to the slow path - // using Subsumes, so we don't want to use it in that case to avoid an - // infinite recursion. - auto other = Cast(aOther); - if (Kind() == eNullPrincipal && other->Kind() == eNullPrincipal) { - return this == other; - } - if (mOriginNoSuffix && FastEquals(aOther)) { - return true; - } - - // Otherwise, fall back to the slow path. - return Subsumes(aOther, DontConsiderDocumentDomain); -} - -inline bool -BasePrincipal::FastSubsumesConsideringDomain(nsIPrincipal* aOther) -{ - // If neither of the principals have document.domain set, we hand off to - // FastSubsumes() which has fast paths for some special cases. Otherwise, we fall - // back to the slow path below. - if (!mDomainSet && !Cast(aOther)->mDomainSet) { - return FastSubsumes(aOther); - } - - return Subsumes(aOther, ConsiderDocumentDomain); -} - -inline bool -BasePrincipal::FastSubsumesConsideringDomainIgnoringFPD(nsIPrincipal* aOther) -{ - if (Kind() == eCodebasePrincipal && - !dom::ChromeUtils::IsOriginAttributesEqualIgnoringFPD( - mOriginAttributes, Cast(aOther)->mOriginAttributes)) { - return false; - } - - return SubsumesInternal(aOther, ConsiderDocumentDomain); -} - } // namespace mozilla -#endif /* mozilla_BasePrincipal_h */ +#endif /* mozilla_OriginAttributes_h */
rename from caps/nsSystemPrincipal.cpp rename to caps/SystemPrincipal.cpp --- a/caps/nsSystemPrincipal.cpp +++ b/caps/SystemPrincipal.cpp @@ -1,156 +1,156 @@ /* -*- Mode: C++; tab-width: 4; 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/. */ /* The privileged system principal. */ #include "nscore.h" -#include "nsSystemPrincipal.h" +#include "SystemPrincipal.h" #include "nsIComponentManager.h" #include "nsIServiceManager.h" #include "nsIURL.h" #include "nsCOMPtr.h" #include "nsXPIDLString.h" #include "nsReadableUtils.h" #include "nsCRT.h" #include "nsString.h" #include "nsIClassInfoImpl.h" #include "nsIScriptSecurityManager.h" #include "pratom.h" -NS_IMPL_CLASSINFO(nsSystemPrincipal, nullptr, +NS_IMPL_CLASSINFO(SystemPrincipal, nullptr, nsIClassInfo::SINGLETON | nsIClassInfo::MAIN_THREAD_ONLY, NS_SYSTEMPRINCIPAL_CID) -NS_IMPL_QUERY_INTERFACE_CI(nsSystemPrincipal, +NS_IMPL_QUERY_INTERFACE_CI(SystemPrincipal, nsIPrincipal, nsISerializable) -NS_IMPL_CI_INTERFACE_GETTER(nsSystemPrincipal, +NS_IMPL_CI_INTERFACE_GETTER(SystemPrincipal, nsIPrincipal, nsISerializable) #define SYSTEM_PRINCIPAL_SPEC "[System Principal]" -already_AddRefed<nsSystemPrincipal> -nsSystemPrincipal::Create() +already_AddRefed<SystemPrincipal> +SystemPrincipal::Create() { - RefPtr<nsSystemPrincipal> sp = new nsSystemPrincipal(); + RefPtr<SystemPrincipal> sp = new SystemPrincipal(); sp->FinishInit(); return sp.forget(); } nsresult -nsSystemPrincipal::GetScriptLocation(nsACString &aStr) +SystemPrincipal::GetScriptLocation(nsACString &aStr) { aStr.AssignLiteral(SYSTEM_PRINCIPAL_SPEC); return NS_OK; } /////////////////////////////////////// // Methods implementing nsIPrincipal // /////////////////////////////////////// NS_IMETHODIMP -nsSystemPrincipal::GetHashValue(uint32_t *result) +SystemPrincipal::GetHashValue(uint32_t *result) { *result = NS_PTR_TO_INT32(this); return NS_OK; } NS_IMETHODIMP -nsSystemPrincipal::GetURI(nsIURI** aURI) +SystemPrincipal::GetURI(nsIURI** aURI) { *aURI = nullptr; return NS_OK; } nsresult -nsSystemPrincipal::GetOriginInternal(nsACString& aOrigin) +SystemPrincipal::GetOriginInternal(nsACString& aOrigin) { aOrigin.AssignLiteral(SYSTEM_PRINCIPAL_SPEC); return NS_OK; } NS_IMETHODIMP -nsSystemPrincipal::GetCsp(nsIContentSecurityPolicy** aCsp) +SystemPrincipal::GetCsp(nsIContentSecurityPolicy** aCsp) { *aCsp = nullptr; return NS_OK; } NS_IMETHODIMP -nsSystemPrincipal::SetCsp(nsIContentSecurityPolicy* aCsp) +SystemPrincipal::SetCsp(nsIContentSecurityPolicy* aCsp) { // Never destroy an existing CSP on the principal. // This method should only be called in rare cases. return NS_ERROR_FAILURE; } NS_IMETHODIMP -nsSystemPrincipal::EnsureCSP(nsIDOMDocument* aDocument, - nsIContentSecurityPolicy** aCSP) +SystemPrincipal::EnsureCSP(nsIDOMDocument* aDocument, + nsIContentSecurityPolicy** aCSP) { // CSP on a system principal makes no sense return NS_ERROR_FAILURE; } NS_IMETHODIMP -nsSystemPrincipal::GetPreloadCsp(nsIContentSecurityPolicy** aPreloadCSP) +SystemPrincipal::GetPreloadCsp(nsIContentSecurityPolicy** aPreloadCSP) { *aPreloadCSP = nullptr; return NS_OK; } NS_IMETHODIMP -nsSystemPrincipal::EnsurePreloadCSP(nsIDOMDocument* aDocument, - nsIContentSecurityPolicy** aPreloadCSP) +SystemPrincipal::EnsurePreloadCSP(nsIDOMDocument* aDocument, + nsIContentSecurityPolicy** aPreloadCSP) { // CSP on a system principal makes no sense return NS_OK; } NS_IMETHODIMP -nsSystemPrincipal::GetDomain(nsIURI** aDomain) +SystemPrincipal::GetDomain(nsIURI** aDomain) { *aDomain = nullptr; return NS_OK; } NS_IMETHODIMP -nsSystemPrincipal::SetDomain(nsIURI* aDomain) +SystemPrincipal::SetDomain(nsIURI* aDomain) { return NS_OK; } NS_IMETHODIMP -nsSystemPrincipal::GetBaseDomain(nsACString& aBaseDomain) +SystemPrincipal::GetBaseDomain(nsACString& aBaseDomain) { // No base domain for chrome. return NS_OK; } NS_IMETHODIMP -nsSystemPrincipal::GetAddonId(nsAString& aAddonId) +SystemPrincipal::GetAddonId(nsAString& aAddonId) { aAddonId.Truncate(); return NS_OK; }; ////////////////////////////////////////// // Methods implementing nsISerializable // ////////////////////////////////////////// NS_IMETHODIMP -nsSystemPrincipal::Read(nsIObjectInputStream* aStream) +SystemPrincipal::Read(nsIObjectInputStream* aStream) { // no-op: CID is sufficient to identify the mSystemPrincipal singleton return NS_OK; } NS_IMETHODIMP -nsSystemPrincipal::Write(nsIObjectOutputStream* aStream) +SystemPrincipal::Write(nsIObjectOutputStream* aStream) { // no-op: CID is sufficient to identify the mSystemPrincipal singleton return NS_OK; }
rename from caps/nsSystemPrincipal.h rename to caps/SystemPrincipal.h --- a/caps/nsSystemPrincipal.h +++ b/caps/SystemPrincipal.h @@ -1,39 +1,39 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=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/. */ /* The privileged system principal. */ -#ifndef nsSystemPrincipal_h__ -#define nsSystemPrincipal_h__ +#ifndef SystemPrincipal_h +#define SystemPrincipal_h #include "nsIPrincipal.h" #include "nsJSPrincipals.h" #include "mozilla/BasePrincipal.h" #define NS_SYSTEMPRINCIPAL_CID \ { 0x4a6212db, 0xaccb, 0x11d3, \ { 0xb7, 0x65, 0x0, 0x60, 0xb0, 0xb6, 0xce, 0xcb }} #define NS_SYSTEMPRINCIPAL_CONTRACTID "@mozilla.org/systemprincipal;1" -class nsSystemPrincipal final : public mozilla::BasePrincipal +class SystemPrincipal final : public mozilla::BasePrincipal { - nsSystemPrincipal() + SystemPrincipal() : BasePrincipal(eSystemPrincipal) { } public: - static already_AddRefed<nsSystemPrincipal> Create(); + static already_AddRefed<SystemPrincipal> Create(); NS_DECL_NSISERIALIZABLE NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) override; NS_IMETHOD GetHashValue(uint32_t* aHashValue) override; NS_IMETHOD GetURI(nsIURI** aURI) override; NS_IMETHOD GetDomain(nsIURI** aDomain) override; NS_IMETHOD SetDomain(nsIURI* aDomain) override; NS_IMETHOD GetCsp(nsIContentSecurityPolicy** aCsp) override; @@ -43,22 +43,23 @@ public: NS_IMETHOD EnsurePreloadCSP(nsIDOMDocument* aDocument, nsIContentSecurityPolicy** aCSP) override; NS_IMETHOD GetBaseDomain(nsACString& aBaseDomain) override; NS_IMETHOD GetAddonId(nsAString& aAddonId) override; nsresult GetOriginInternal(nsACString& aOrigin) override; virtual nsresult GetScriptLocation(nsACString &aStr) override; protected: - virtual ~nsSystemPrincipal(void) {} + virtual ~SystemPrincipal(void) {} - bool SubsumesInternal(nsIPrincipal *aOther, DocumentDomainConsideration aConsideration) override + bool SubsumesInternal(nsIPrincipal *aOther, + DocumentDomainConsideration aConsideration) override { return true; } bool MayLoadInternal(nsIURI* aURI) override { return true; } }; -#endif // nsSystemPrincipal_h__ +#endif // SystemPrincipal_h
--- a/caps/moz.build +++ b/caps/moz.build @@ -20,39 +20,41 @@ XPIDL_SOURCES += [ 'nsIPrincipal.idl', 'nsIScriptSecurityManager.idl', ] XPIDL_MODULE = 'caps' EXPORTS += [ 'nsJSPrincipals.h', - 'nsNullPrincipal.h', - 'nsNullPrincipalURI.h', + 'NullPrincipal.h', + 'NullPrincipalURI.h', ] EXPORTS.mozilla = [ - 'BasePrincipal.h' + 'BasePrincipal.h', + 'OriginAttributes.h', ] SOURCES += [ # Compile this separately since nsExceptionHandler.h conflicts - # with something from nsNullPrincipal.cpp. + # with something from NullPrincipal.cpp. 'BasePrincipal.cpp', ] UNIFIED_SOURCES += [ + 'ContentPrincipal.cpp', 'DomainPolicy.cpp', - 'nsExpandedPrincipal.cpp', + 'ExpandedPrincipal.cpp', 'nsJSPrincipals.cpp', - 'nsNullPrincipal.cpp', - 'nsNullPrincipalURI.cpp', - 'nsPrincipal.cpp', 'nsScriptSecurityManager.cpp', - 'nsSystemPrincipal.cpp', + 'NullPrincipal.cpp', + 'NullPrincipalURI.cpp', + 'OriginAttributes.cpp', + 'SystemPrincipal.cpp', ] LOCAL_INCLUDES += [ '/docshell/base', '/dom/base', '/js/xpconnect/src', ]
--- a/caps/nsIPrincipal.idl +++ b/caps/nsIPrincipal.idl @@ -352,22 +352,22 @@ interface nsIPrincipal : nsISerializable /** * Returns true iff this is the system principal. */ [infallible] readonly attribute boolean isSystemPrincipal; }; /** - * If nsSystemPrincipal is too risky to use, but we want a principal to access - * more than one origin, nsExpandedPrincipals letting us define an array of - * principals it subsumes. So script with an nsExpandedPrincipals will gain + * If SystemPrincipal is too risky to use, but we want a principal to access + * more than one origin, ExpandedPrincipals letting us define an array of + * principals it subsumes. So script with an ExpandedPrincipals will gain * same origin access when at least one of its principals it contains gained - * sameorigin acccess. An nsExpandedPrincipal will be subsumed by the system - * principal, and by another nsExpandedPrincipal that has all its principals. + * sameorigin acccess. An ExpandedPrincipal will be subsumed by the system + * principal, and by another ExpandedPrincipal that has all its principals. * It is added for jetpack content-scripts to let them interact with the * content and a well defined set of other domains, without the risk of * leaking out a system principal to the content. See: Bug 734891 */ [uuid(f3e177Df-6a5e-489f-80a7-2dd1481471d8)] interface nsIExpandedPrincipal : nsISupports { /**
--- a/caps/nsScriptSecurityManager.cpp +++ b/caps/nsScriptSecurityManager.cpp @@ -15,19 +15,18 @@ #include "nsIServiceManager.h" #include "nsIScriptObjectPrincipal.h" #include "nsIScriptContext.h" #include "nsIURL.h" #include "nsINestedURI.h" #include "nspr.h" #include "nsJSPrincipals.h" #include "mozilla/BasePrincipal.h" -#include "nsSystemPrincipal.h" -#include "nsPrincipal.h" -#include "nsNullPrincipal.h" +#include "SystemPrincipal.h" +#include "NullPrincipal.h" #include "DomainPolicy.h" #include "nsXPIDLString.h" #include "nsCRT.h" #include "nsCRTGlue.h" #include "nsDocShell.h" #include "nsError.h" #include "nsDOMCID.h" #include "nsTextFormatter.h" @@ -1136,17 +1135,17 @@ nsScriptSecurityManager::CreateCodebaseP NS_IMETHODIMP nsScriptSecurityManager::CreateNullPrincipal(JS::Handle<JS::Value> aOriginAttributes, JSContext* aCx, nsIPrincipal** aPrincipal) { OriginAttributes attrs; if (!aOriginAttributes.isObject() || !attrs.Init(aCx, aOriginAttributes)) { return NS_ERROR_INVALID_ARG; } - nsCOMPtr<nsIPrincipal> prin = nsNullPrincipal::Create(attrs); + nsCOMPtr<nsIPrincipal> prin = NullPrincipal::Create(attrs); prin.forget(aPrincipal); return NS_OK; } NS_IMETHODIMP nsScriptSecurityManager::GetAppCodebasePrincipal(nsIURI* aURI, uint32_t aAppId, bool aInIsolatedMozBrowser, @@ -1330,17 +1329,17 @@ nsresult nsScriptSecurityManager::Init() mozilla::services::GetStringBundleService(); if (!bundleService) return NS_ERROR_FAILURE; rv = bundleService->CreateBundle("chrome://global/locale/security/caps.properties", &sStrBundle); NS_ENSURE_SUCCESS(rv, rv); // Create our system principal singleton - RefPtr<nsSystemPrincipal> system = nsSystemPrincipal::Create(); + RefPtr<SystemPrincipal> system = SystemPrincipal::Create(); mSystemPrincipal = system; //-- Register security check callback in the JS engine // Currently this is used to control access to function.caller sContext = danger::GetJSContext(); static const JSSecurityCallbacks securityCallbacks = { @@ -1402,23 +1401,23 @@ nsScriptSecurityManager::InitStatics() ClearOnShutdown(&gScriptSecMan); gScriptSecMan = ssManager; } // Currently this nsGenericFactory constructor is used only from FastLoad // (XPCOM object deserialization) code, when "creating" the system principal // singleton. -nsSystemPrincipal * +SystemPrincipal * nsScriptSecurityManager::SystemPrincipalSingletonConstructor() { nsIPrincipal *sysprin = nullptr; if (gScriptSecMan) NS_ADDREF(sysprin = gScriptSecMan->mSystemPrincipal); - return static_cast<nsSystemPrincipal*>(sysprin); + return static_cast<SystemPrincipal*>(sysprin); } struct IsWhitespace { static bool Test(char aChar) { return NS_IsAsciiWhitespace(aChar); }; }; struct IsWhitespaceOrComma { static bool Test(char aChar) { return aChar == ',' || NS_IsAsciiWhitespace(aChar); }; };
--- a/caps/nsScriptSecurityManager.h +++ b/caps/nsScriptSecurityManager.h @@ -19,17 +19,17 @@ #include "plstr.h" #include "js/TypeDecls.h" #include <stdint.h> class nsCString; class nsIIOService; class nsIStringBundle; -class nsSystemPrincipal; +class SystemPrincipal; namespace mozilla { class OriginAttributes; } // namespace mozilla ///////////////////////////// // nsScriptSecurityManager // ///////////////////////////// @@ -50,17 +50,17 @@ public: NS_DECL_NSIOBSERVER static nsScriptSecurityManager* GetScriptSecurityManager(); // Invoked exactly once, by XPConnect. static void InitStatics(); - static nsSystemPrincipal* + static SystemPrincipal* SystemPrincipalSingletonConstructor(); /** * Utility method for comparing two URIs. For security purposes, two URIs * are equivalent if their schemes, hosts, and ports (if any) match. This * method returns true if aSubjectURI and aObjectURI have the same origin, * false otherwise. */
--- a/devtools/client/jsonview/main.js +++ b/devtools/client/jsonview/main.js @@ -45,17 +45,17 @@ var JsonView = { // Message handlers for events from child processes /** * Save JSON to a file needs to be implemented here * in the parent process. */ onSave: function (message) { - JsonViewUtils.getTargetFile(file => { + JsonViewUtils.getTargetFile().then(file => { if (file) { JsonViewUtils.saveToFile(file, message.data); } }); } }; // Exports from this module
--- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -115,17 +115,17 @@ #include "nsIFormPOSTActionChannel.h" #include "nsIUploadChannel.h" #include "nsIUploadChannel2.h" #include "nsIWebProgress.h" #include "nsILayoutHistoryState.h" #include "nsITimer.h" #include "nsISHistoryInternal.h" #include "nsIPrincipal.h" -#include "nsNullPrincipal.h" +#include "NullPrincipal.h" #include "nsISHEntry.h" #include "nsIWindowWatcher.h" #include "nsIPromptFactory.h" #include "nsITransportSecurityInfo.h" #include "nsINode.h" #include "nsINSSErrorsService.h" #include "nsIApplicationCacheChannel.h" #include "nsIApplicationCacheContainer.h" @@ -1496,30 +1496,30 @@ nsDocShell::LoadURI(nsIURI* aURI, if (principalIsExplicit) { return NS_ERROR_DOM_SECURITY_ERR; } // Don't inherit from the current page. Just do the safe thing // and pretend that we were loaded by a nullprincipal. // // We didn't inherit OriginAttributes here as ExpandedPrincipal doesn't // have origin attributes. - principalToInherit = nsNullPrincipal::CreateWithInheritedAttributes(this); + principalToInherit = NullPrincipal::CreateWithInheritedAttributes(this); inheritPrincipal = false; } } if (!principalToInherit && !inheritPrincipal && !principalIsExplicit) { // See if there's system or chrome JS code running inheritPrincipal = nsContentUtils::LegacyIsCallerChromeOrNativeCode(); } if (aLoadFlags & LOAD_FLAGS_DISALLOW_INHERIT_PRINCIPAL) { inheritPrincipal = false; // If aFirstParty is true and the pref 'privacy.firstparty.isolate' is // enabled, we will set firstPartyDomain on the origin attributes. - principalToInherit = nsNullPrincipal::CreateWithInheritedAttributes(this, aFirstParty); + principalToInherit = NullPrincipal::CreateWithInheritedAttributes(this, aFirstParty); } // If the triggeringPrincipal is not passed explicitly, we first try to create // a principal from the referrer, since the referrer URI reflects the web origin // that triggered the load. If there is no referrer URI, we fall back to using // the SystemPrincipal. It's safe to assume that no provided triggeringPrincipal // and no referrer simulate a load that was triggered by the system. // It's important to note that this block of code needs to appear *after* the block @@ -8122,19 +8122,19 @@ nsDocShell::CreateAboutBlankContentViewe nsCOMPtr<nsIDocumentLoaderFactory> docFactory = nsContentUtils::FindInternalContentViewer(NS_LITERAL_CSTRING("text/html")); if (docFactory) { nsCOMPtr<nsIPrincipal> principal; if (mSandboxFlags & SANDBOXED_ORIGIN) { if (aPrincipal) { - principal = nsNullPrincipal::CreateWithInheritedAttributes(aPrincipal); + principal = NullPrincipal::CreateWithInheritedAttributes(aPrincipal); } else { - principal = nsNullPrincipal::CreateWithInheritedAttributes(this); + principal = NullPrincipal::CreateWithInheritedAttributes(this); } } else { principal = aPrincipal; } // generate (about:blank) document to load docFactory->CreateBlankDocument(mLoadGroup, principal, getter_AddRefs(blankDoc)); if (blankDoc) { @@ -12404,23 +12404,23 @@ nsDocShell::AddToSessionHistory(nsIURI* if (!triggeringPrincipal) { triggeringPrincipal = loadInfo->TriggeringPrincipal(); } // For now keep storing just the principal in the SHEntry. if (!principalToInherit) { if (loadInfo->GetLoadingSandboxed()) { if (loadInfo->LoadingPrincipal()) { - principalToInherit = nsNullPrincipal::CreateWithInheritedAttributes( + principalToInherit = NullPrincipal::CreateWithInheritedAttributes( loadInfo->LoadingPrincipal()); } else { // get the OriginAttributes OriginAttributes attrs; loadInfo->GetOriginAttributes(&attrs); - principalToInherit = nsNullPrincipal::Create(attrs); + principalToInherit = NullPrincipal::Create(attrs); } } else { principalToInherit = loadInfo->PrincipalToInherit(); } } } } @@ -12601,17 +12601,17 @@ nsDocShell::LoadHistoryEntry(nsISHEntry* // user prevented it). Interrupt the history load. return NS_OK; } if (!triggeringPrincipal) { // Ensure that we have a triggeringPrincipal. Otherwise javascript: // URIs will pick it up from the about:blank page we just loaded, // and we don't really want even that in this case. - triggeringPrincipal = nsNullPrincipal::CreateWithInheritedAttributes(this); + triggeringPrincipal = NullPrincipal::CreateWithInheritedAttributes(this); } } /* If there is a valid postdata *and* the user pressed * reload or shift-reload, take user's permission before we * repost the data to the server. */ if ((aLoadType & LOAD_CMD_RELOAD) && postData) { @@ -14373,17 +14373,17 @@ nsDocShell::GetPrintPreview(nsIWebBrowse #if NS_PRINT_PREVIEW nsCOMPtr<nsIDocumentViewerPrint> print = do_QueryInterface(mContentViewer); if (!print || !print->IsInitializedForPrintPreview()) { // XXX: Creating a brand new content viewer to host preview every // time we enter here seems overwork. We could skip ahead to where // we QI the mContentViewer if the current URI is either about:blank // or about:printpreview. Stop(nsIWebNavigation::STOP_ALL); - nsCOMPtr<nsIPrincipal> principal = nsNullPrincipal::CreateWithInheritedAttributes(this); + nsCOMPtr<nsIPrincipal> principal = NullPrincipal::CreateWithInheritedAttributes(this); nsCOMPtr<nsIURI> uri; NS_NewURI(getter_AddRefs(uri), NS_LITERAL_CSTRING("about:printpreview")); nsresult rv = CreateAboutBlankContentViewer(principal, uri); NS_ENSURE_SUCCESS(rv, rv); // Here we manually set current URI since we have just created a // brand new content viewer (about:blank) to host preview. SetCurrentURI(uri, nullptr, true, 0); print = do_QueryInterface(mContentViewer);
--- a/dom/asmjscache/AsmJSCache.cpp +++ b/dom/asmjscache/AsmJSCache.cpp @@ -1618,28 +1618,34 @@ public: { return ASMJS; } nsresult InitOrigin(PersistenceType aPersistenceType, const nsACString& aGroup, const nsACString& aOrigin, + const AtomicBool& aCanceled, UsageInfo* aUsageInfo) override { if (!aUsageInfo) { return NS_OK; } - return GetUsageForOrigin(aPersistenceType, aGroup, aOrigin, aUsageInfo); + return GetUsageForOrigin(aPersistenceType, + aGroup, + aOrigin, + aCanceled, + aUsageInfo); } nsresult GetUsageForOrigin(PersistenceType aPersistenceType, const nsACString& aGroup, const nsACString& aOrigin, + const AtomicBool& aCanceled, UsageInfo* aUsageInfo) override { QuotaManager* qm = QuotaManager::Get(); MOZ_ASSERT(qm, "We were being called by the QuotaManager"); nsCOMPtr<nsIFile> directory; nsresult rv = qm->GetDirectoryForOrigin(aPersistenceType, aOrigin, getter_AddRefs(directory)); @@ -1653,17 +1659,17 @@ public: MOZ_ASSERT(NS_SUCCEEDED(directory->Exists(&exists)) && exists); nsCOMPtr<nsISimpleEnumerator> entries; rv = directory->GetDirectoryEntries(getter_AddRefs(entries)); NS_ENSURE_SUCCESS(rv, rv); bool hasMore; while (NS_SUCCEEDED((rv = entries->HasMoreElements(&hasMore))) && - hasMore && !aUsageInfo->Canceled()) { + hasMore && !aCanceled) { nsCOMPtr<nsISupports> entry; rv = entries->GetNext(getter_AddRefs(entry)); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIFile> file = do_QueryInterface(entry); NS_ENSURE_TRUE(file, NS_NOINTERFACE); int64_t fileSize;
--- a/dom/base/DOMParser.cpp +++ b/dom/base/DOMParser.cpp @@ -13,17 +13,17 @@ #include "nsIScriptError.h" #include "nsIScriptSecurityManager.h" #include "nsCRT.h" #include "nsStreamUtils.h" #include "nsContentUtils.h" #include "nsDOMJSUtils.h" #include "nsError.h" #include "nsPIDOMWindow.h" -#include "nsNullPrincipal.h" +#include "NullPrincipal.h" #include "mozilla/LoadInfo.h" #include "mozilla/dom/BindingUtils.h" #include "mozilla/dom/ScriptSettings.h" using namespace mozilla; using namespace mozilla::dom; DOMParser::DOMParser() @@ -340,17 +340,17 @@ DOMParser::Init(nsIPrincipal* principal, OriginAttributes attrs; mPrincipal = BasePrincipal::CreateCodebasePrincipal(mDocumentURI, attrs); NS_ENSURE_TRUE(mPrincipal, NS_ERROR_FAILURE); } else { if (nsContentUtils::IsSystemPrincipal(mPrincipal)) { // Don't give DOMParsers the system principal. Use a null // principal instead. mOriginalPrincipalWasSystem = true; - mPrincipal = nsNullPrincipal::Create(); + mPrincipal = NullPrincipal::Create(); if (!mDocumentURI) { rv = mPrincipal->GetURI(getter_AddRefs(mDocumentURI)); NS_ENSURE_SUCCESS(rv, rv); } } } @@ -451,17 +451,17 @@ DOMParser::SetUpDocument(DocumentFlavor // off of nsIScriptGlobalObject, but that's a yak to shave another day. nsCOMPtr<nsIScriptGlobalObject> scriptHandlingObject = do_QueryReferent(mScriptHandlingObject); nsresult rv; if (!mPrincipal) { NS_ENSURE_TRUE(!mAttemptedInit, NS_ERROR_NOT_INITIALIZED); AttemptedInitMarker marker(&mAttemptedInit); - nsCOMPtr<nsIPrincipal> prin = nsNullPrincipal::Create(); + nsCOMPtr<nsIPrincipal> prin = NullPrincipal::Create(); rv = Init(prin, nullptr, nullptr, scriptHandlingObject); NS_ENSURE_SUCCESS(rv, rv); } NS_ASSERTION(mPrincipal, "Must have principal by now"); NS_ASSERTION(mDocumentURI, "Must have document URI by now"); return NS_NewDOMDocument(aResult, EmptyString(), EmptyString(), nullptr,
--- a/dom/base/Location.cpp +++ b/dom/base/Location.cpp @@ -26,17 +26,17 @@ #include "nsDOMClassInfoID.h" #include "nsReadableUtils.h" #include "nsITextToSubURI.h" #include "nsJSUtils.h" #include "nsContentUtils.h" #include "nsGlobalWindow.h" #include "mozilla/Likely.h" #include "nsCycleCollectionParticipant.h" -#include "nsNullPrincipal.h" +#include "NullPrincipal.h" #include "ScriptSettings.h" #include "mozilla/Unused.h" #include "mozilla/dom/LocationBinding.h" namespace mozilla { namespace dom { static nsresult @@ -159,17 +159,17 @@ Location::CheckURL(nsIURI* aURI, nsIDocS bool urisEqual = false; if (docOriginalURI && docCurrentURI && principalURI) { principalURI->Equals(docOriginalURI, &urisEqual); } if (urisEqual) { sourceURI = docCurrentURI; } else { - // Use principalURI as long as it is not an nsNullPrincipalURI. We + // Use principalURI as long as it is not an NullPrincipalURI. We // could add a method such as GetReferrerURI to principals to make this // cleaner, but given that we need to start using Source Browsing // Context for referrer (see Bug 960639) this may be wasted effort at // this stage. if (principalURI) { bool isNullPrincipalScheme; rv = principalURI->SchemeIs(NS_NULLPRINCIPAL_SCHEME, &isNullPrincipalScheme);
--- a/dom/base/ScriptSettings.cpp +++ b/dom/base/ScriptSettings.cpp @@ -159,17 +159,17 @@ ScriptSettingsStackEntry::~ScriptSetting { // We must have an actual JS global for the entire time this is on the stack. MOZ_ASSERT_IF(mGlobalObject, mGlobalObject->GetGlobalJSObject()); } // If the entry or incumbent global ends up being something that the subject // principal doesn't subsume, we don't want to use it. This never happens on // the web, but can happen with asymmetric privilege relationships (i.e. -// nsExpandedPrincipal and System Principal). +// ExpandedPrincipal and System Principal). // // The most correct thing to use instead would be the topmost global on the // callstack whose principal is subsumed by the subject principal. But that's // hard to compute, so we just substitute the global of the current // compartment. In practice, this is fine. // // Note that in particular things like: //
--- a/dom/base/nsContentUtils.cpp +++ b/dom/base/nsContentUtils.cpp @@ -177,17 +177,17 @@ #include "nsIWindowMediator.h" #include "nsIWordBreaker.h" #include "nsIXPConnect.h" #include "nsJSUtils.h" #include "nsLWBrkCIID.h" #include "nsNetCID.h" #include "nsNetUtil.h" #include "nsNodeInfoManager.h" -#include "nsNullPrincipal.h" +#include "NullPrincipal.h" #include "nsParserCIID.h" #include "nsParserConstants.h" #include "nsPIDOMWindow.h" #include "nsPresContext.h" #include "nsPrintfCString.h" #include "nsReferencedElement.h" #include "nsSandboxFlags.h" #include "nsScriptSecurityManager.h" @@ -509,17 +509,17 @@ nsContentUtils::Init() sSecurityManager = nsScriptSecurityManager::GetScriptSecurityManager(); if(!sSecurityManager) return NS_ERROR_FAILURE; NS_ADDREF(sSecurityManager); sSecurityManager->GetSystemPrincipal(&sSystemPrincipal); MOZ_ASSERT(sSystemPrincipal); - RefPtr<nsNullPrincipal> nullPrincipal = nsNullPrincipal::Create(); + RefPtr<NullPrincipal> nullPrincipal = NullPrincipal::Create(); if (!nullPrincipal) { return NS_ERROR_FAILURE; } nullPrincipal.forget(&sNullSubjectPrincipal); nsresult rv = CallGetService(NS_IOSERVICE_CONTRACTID, &sIOService); if (NS_FAILED(rv)) { @@ -4785,17 +4785,17 @@ nsContentUtils::ParseFragmentXML(const n nsresult nsContentUtils::ConvertToPlainText(const nsAString& aSourceBuffer, nsAString& aResultBuffer, uint32_t aFlags, uint32_t aWrapCol) { nsCOMPtr<nsIURI> uri; NS_NewURI(getter_AddRefs(uri), "about:blank"); - nsCOMPtr<nsIPrincipal> principal = nsNullPrincipal::Create(); + nsCOMPtr<nsIPrincipal> principal = NullPrincipal::Create(); nsCOMPtr<nsIDOMDocument> domDocument; nsresult rv = NS_NewDOMDocument(getter_AddRefs(domDocument), EmptyString(), EmptyString(), nullptr, uri, uri, principal,
--- a/dom/base/nsContentUtils.h +++ b/dom/base/nsContentUtils.h @@ -1573,22 +1573,22 @@ public: static void NotifyInstalledMenuKeyboardListener(bool aInstalling); /** * Returns true if aPrincipal is the system principal. */ static bool IsSystemPrincipal(nsIPrincipal* aPrincipal); /** - * Returns true if aPrincipal is an nsExpandedPrincipal. + * Returns true if aPrincipal is an ExpandedPrincipal. */ static bool IsExpandedPrincipal(nsIPrincipal* aPrincipal); /** - * Returns true if aPrincipal is the system or an nsExpandedPrincipal. + * Returns true if aPrincipal is the system or an ExpandedPrincipal. */ static bool IsSystemOrExpandedPrincipal(nsIPrincipal* aPrincipal) { return IsSystemPrincipal(aPrincipal) || IsExpandedPrincipal(aPrincipal); } /** * Gets the system principal from the security manager.
--- a/dom/base/nsDocument.cpp +++ b/dom/base/nsDocument.cpp @@ -101,17 +101,17 @@ #include "nsNetUtil.h" // for NS_NewURI #include "nsIInputStreamChannel.h" #include "nsIAuthPrompt.h" #include "nsIAuthPrompt2.h" #include "nsIScriptSecurityManager.h" #include "nsIPermissionManager.h" #include "nsIPrincipal.h" -#include "nsNullPrincipal.h" +#include "NullPrincipal.h" #include "nsIDOMWindow.h" #include "nsPIDOMWindow.h" #include "nsIDOMElement.h" #include "nsFocusManager.h" // for radio group stuff #include "nsIDOMHTMLInputElement.h" @@ -2718,17 +2718,17 @@ nsDocument::InitCSP(nsIChannel* aChannel rv = csp->GetCSPSandboxFlags(&cspSandboxFlags); NS_ENSURE_SUCCESS(rv, rv); mSandboxFlags |= cspSandboxFlags; if (cspSandboxFlags & SANDBOXED_ORIGIN) { // If the new CSP sandbox flags do not have the allow-same-origin flag // reset the document principal to a null principal - principal = nsNullPrincipal::Create(); + principal = NullPrincipal::Create(); SetPrincipal(principal); } // ----- Enforce frame-ancestor policy on any applied policies nsCOMPtr<nsIDocShell> docShell(mDocumentContainer); if (docShell) { bool safeAncestry = false;
--- a/dom/base/nsFrameLoader.cpp +++ b/dom/base/nsFrameLoader.cpp @@ -45,17 +45,17 @@ #include "nsError.h" #include "nsISHistory.h" #include "nsISHistoryInternal.h" #include "nsIDOMHTMLDocument.h" #include "nsIXULWindow.h" #include "nsIEditor.h" #include "nsIMozBrowserFrame.h" #include "nsISHistory.h" -#include "nsNullPrincipal.h" +#include "NullPrincipal.h" #include "nsIScriptError.h" #include "nsGlobalWindow.h" #include "nsPIWindowRoot.h" #include "nsLayoutUtils.h" #include "nsView.h" #include "GroupedSHistory.h" #include "PartialSHistory.h" @@ -93,17 +93,17 @@ #include "mozilla/dom/CustomEvent.h" #include "mozilla/dom/ipc/StructuredCloneData.h" #include "mozilla/WebBrowserPersistLocalDocument.h" #include "mozilla/dom/GroupedHistoryEvent.h" #include "mozilla/dom/Promise.h" #include "mozilla/dom/PromiseNativeHandler.h" -#include "nsPrincipal.h" +#include "ContentPrincipal.h" #ifdef XP_WIN #include "mozilla/plugins/PPluginWidgetParent.h" #include "../plugins/ipc/PluginWidgetParent.h" #endif #ifdef MOZ_XUL #include "nsXULPopupManager.h" @@ -826,17 +826,17 @@ nsFrameLoader::ReallyStartLoadingInterna nsCOMPtr<nsIURI> baseURI = mOwnerContent->GetBaseURI(); loadInfo->SetBaseURI(baseURI); } else { rv = mOwnerContent->NodePrincipal()->GetURI(getter_AddRefs(referrer)); NS_ENSURE_SUCCESS(rv, rv); } - // Use referrer as long as it is not an nsNullPrincipalURI. + // Use referrer as long as it is not an NullPrincipalURI. // We could add a method such as GetReferrerURI to principals to make this // cleaner, but given that we need to start using Source Browsing Context for // referrer (see Bug 960639) this may be wasted effort at this stage. if (referrer) { bool isNullPrincipalScheme; rv = referrer->SchemeIs(NS_NULLPRINCIPAL_SCHEME, &isNullPrincipalScheme); if (NS_SUCCEEDED(rv) && !isNullPrincipalScheme) { loadInfo->SetReferrer(referrer);
--- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -13072,19 +13072,24 @@ nsGlobalWindow::RunTimeoutHandler(Timeou handler->GetLocation(&filename, &lineNo, &dummyColumn); // New script entry point required, due to the "Create a script" sub-step of // http://www.whatwg.org/specs/web-apps/current-work/#timer-initialisation-steps nsAutoMicroTask mt; AutoEntryScript aes(this, reason, true); JS::CompileOptions options(aes.cx()); options.setFileAndLine(filename, lineNo).setVersion(JSVERSION_DEFAULT); + options.setNoScriptRval(true); JS::Rooted<JSObject*> global(aes.cx(), FastGetGlobalJSObject()); - nsresult rv = - nsJSUtils::EvaluateString(aes.cx(), script, global, options); + nsresult rv = NS_OK; + { + nsJSUtils::ExecutionContext exec(aes.cx(), global); + rv = exec.CompileAndExec(options, script); + } + if (rv == NS_SUCCESS_DOM_SCRIPT_EVALUATION_THREW_UNCATCHABLE) { abortIntervalHandler = true; } } else { // Hold strong ref to ourselves while we call the callback. nsCOMPtr<nsISupports> me(static_cast<nsIDOMWindow*>(this)); ErrorResult rv; JS::Rooted<JS::Value> ignoredVal(RootingCx());
--- a/dom/base/nsJSUtils.cpp +++ b/dom/base/nsJSUtils.cpp @@ -118,166 +118,172 @@ nsJSUtils::CompileFunction(AutoJSAPI& js { return NS_ERROR_FAILURE; } *aFunctionObject = JS_GetFunctionObject(fun); return NS_OK; } -nsresult -nsJSUtils::EvaluateString(JSContext* aCx, - const nsAString& aScript, - JS::Handle<JSObject*> aEvaluationGlobal, - JS::CompileOptions& aCompileOptions, - const EvaluateOptions& aEvaluateOptions, - JS::MutableHandle<JS::Value> aRetValue) +static nsresult +EvaluationExceptionToNSResult(JSContext* aCx) +{ + if (JS_IsExceptionPending(aCx)) { + return NS_SUCCESS_DOM_SCRIPT_EVALUATION_THREW; + } + return NS_SUCCESS_DOM_SCRIPT_EVALUATION_THREW_UNCATCHABLE; +} + +nsJSUtils::ExecutionContext::ExecutionContext(JSContext* aCx, + JS::Handle<JSObject*> aGlobal) + : mSamplerRAII("nsJSUtils::ExecutionContext", /* PROFILER_LABEL */ + js::ProfileEntry::Category::JS, __LINE__) + , mCx(aCx) + , mCompartment(aCx, aGlobal) + , mRetValue(aCx) + , mScopeChain(aCx) + , mRv(NS_OK) + , mSkip(false) + , mCoerceToString(false) +#ifdef DEBUG + , mWantsReturnValue(false) + , mExpectScopeChain(false) +#endif { - const nsPromiseFlatString& flatScript = PromiseFlatString(aScript); - JS::SourceBufferHolder srcBuf(flatScript.get(), aScript.Length(), - JS::SourceBufferHolder::NoOwnership); - return EvaluateString(aCx, srcBuf, aEvaluationGlobal, aCompileOptions, - aEvaluateOptions, aRetValue, nullptr); + MOZ_ASSERT(aCx == nsContentUtils::GetCurrentJSContext()); + MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(nsContentUtils::IsInMicroTask()); + MOZ_ASSERT(mRetValue.isUndefined()); + + MOZ_ASSERT(js::GetGlobalForObjectCrossCompartment(aGlobal) == aGlobal); + if (MOZ_UNLIKELY(!xpc::Scriptability::Get(aGlobal).Allowed())) { + mSkip = true; + mRv = NS_OK; + } +} + +void +nsJSUtils::ExecutionContext::SetScopeChain( + const JS::AutoObjectVector& aScopeChain) +{ + if (mSkip) { + return; + } + +#ifdef DEBUG + mExpectScopeChain = true; +#endif + // Now make sure to wrap the scope chain into the right compartment. + if (!mScopeChain.reserve(aScopeChain.length())) { + mSkip = true; + mRv = NS_ERROR_OUT_OF_MEMORY; + return; + } + + for (size_t i = 0; i < aScopeChain.length(); ++i) { + JS::ExposeObjectToActiveJS(aScopeChain[i]); + mScopeChain.infallibleAppend(aScopeChain[i]); + if (!JS_WrapObject(mCx, mScopeChain[i])) { + mSkip = true; + mRv = NS_ERROR_OUT_OF_MEMORY; + return; + } + } } nsresult -nsJSUtils::EvaluateString(JSContext* aCx, - JS::SourceBufferHolder& aSrcBuf, - JS::Handle<JSObject*> aEvaluationGlobal, - JS::CompileOptions& aCompileOptions, - const EvaluateOptions& aEvaluateOptions, - JS::MutableHandle<JS::Value> aRetValue, - void **aOffThreadToken) +nsJSUtils::ExecutionContext::SyncAndExec(void **aOffThreadToken, + JS::MutableHandle<JSScript*> aScript) { - PROFILER_LABEL("nsJSUtils", "EvaluateString", - js::ProfileEntry::Category::JS); + if (mSkip) { + return mRv; + } + + MOZ_ASSERT(!mWantsReturnValue); + MOZ_ASSERT(!mExpectScopeChain); + aScript.set(JS::FinishOffThreadScript(mCx, *aOffThreadToken)); + *aOffThreadToken = nullptr; // Mark the token as having been finished. + if (!aScript || !JS_ExecuteScript(mCx, mScopeChain, aScript)) { + mSkip = true; + mRv = EvaluationExceptionToNSResult(mCx); + return mRv; + } + + return NS_OK; +} + +nsresult +nsJSUtils::ExecutionContext::CompileAndExec(JS::CompileOptions& aCompileOptions, + JS::SourceBufferHolder& aSrcBuf) +{ + if (mSkip) { + return mRv; + } MOZ_ASSERT_IF(aCompileOptions.versionSet, aCompileOptions.version != JSVERSION_UNKNOWN); - MOZ_ASSERT_IF(aEvaluateOptions.coerceToString, !aCompileOptions.noScriptRval); - MOZ_ASSERT(aCx == nsContentUtils::GetCurrentJSContext()); MOZ_ASSERT(aSrcBuf.get()); - MOZ_ASSERT(js::GetGlobalForObjectCrossCompartment(aEvaluationGlobal) == - aEvaluationGlobal); - MOZ_ASSERT_IF(aOffThreadToken, aCompileOptions.noScriptRval); - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(nsContentUtils::IsInMicroTask()); - - // Unfortunately, the JS engine actually compiles scripts with a return value - // in a different, less efficient way. Furthermore, it can't JIT them in many - // cases. So we need to be explicitly told whether the caller cares about the - // return value. Callers can do this by calling the other overload of - // EvaluateString() which calls this function with - // aCompileOptions.noScriptRval set to true. - aRetValue.setUndefined(); - - nsresult rv = NS_OK; - - NS_ENSURE_TRUE(xpc::Scriptability::Get(aEvaluationGlobal).Allowed(), NS_OK); - - bool ok = true; - // Scope the JSAutoCompartment so that we can later wrap the return value - // into the caller's cx. - { - JSAutoCompartment ac(aCx, aEvaluationGlobal); - - // Now make sure to wrap the scope chain into the right compartment. - JS::AutoObjectVector scopeChain(aCx); - if (!scopeChain.reserve(aEvaluateOptions.scopeChain.length())) { - return NS_ERROR_OUT_OF_MEMORY; - } - - for (size_t i = 0; i < aEvaluateOptions.scopeChain.length(); ++i) { - JS::ExposeObjectToActiveJS(aEvaluateOptions.scopeChain[i]); - scopeChain.infallibleAppend(aEvaluateOptions.scopeChain[i]); - if (!JS_WrapObject(aCx, scopeChain[i])) { - ok = false; - break; - } - } - - if (ok && aOffThreadToken) { - JS::Rooted<JSScript*> - script(aCx, JS::FinishOffThreadScript(aCx, *aOffThreadToken)); - *aOffThreadToken = nullptr; // Mark the token as having been finished. - if (script) { - ok = JS_ExecuteScript(aCx, scopeChain, script); - } else { - ok = false; - } - } else if (ok) { - ok = JS::Evaluate(aCx, scopeChain, aCompileOptions, aSrcBuf, aRetValue); - } - - if (ok && aEvaluateOptions.coerceToString && !aRetValue.isUndefined()) { - JS::Rooted<JS::Value> value(aCx, aRetValue); - JSString* str = JS::ToString(aCx, value); - ok = !!str; - aRetValue.set(ok ? JS::StringValue(str) : JS::UndefinedValue()); - } + MOZ_ASSERT(mRetValue.isUndefined()); +#ifdef DEBUG + mWantsReturnValue = !aCompileOptions.noScriptRval; +#endif + MOZ_ASSERT(!mCoerceToString || mWantsReturnValue); + if (!JS::Evaluate(mCx, mScopeChain, aCompileOptions, aSrcBuf, &mRetValue)) { + mSkip = true; + mRv = EvaluationExceptionToNSResult(mCx); + return mRv; } - if (!ok) { - if (JS_IsExceptionPending(aCx)) { - rv = NS_SUCCESS_DOM_SCRIPT_EVALUATION_THREW; - } else { - rv = NS_SUCCESS_DOM_SCRIPT_EVALUATION_THREW_UNCATCHABLE; - } + return NS_OK; +} - if (!aCompileOptions.noScriptRval) { - aRetValue.setUndefined(); - } +nsresult +nsJSUtils::ExecutionContext::CompileAndExec(JS::CompileOptions& aCompileOptions, + const nsAString& aScript) +{ + if (mSkip) { + return mRv; } - // Wrap the return value into whatever compartment aCx was in. - if (ok && !aCompileOptions.noScriptRval) { - if (!JS_WrapValue(aCx, aRetValue)) { - return NS_ERROR_OUT_OF_MEMORY; - } - } - return rv; + const nsPromiseFlatString& flatScript = PromiseFlatString(aScript); + JS::SourceBufferHolder srcBuf(flatScript.get(), aScript.Length(), + JS::SourceBufferHolder::NoOwnership); + return CompileAndExec(aCompileOptions, srcBuf); } nsresult -nsJSUtils::EvaluateString(JSContext* aCx, - JS::SourceBufferHolder& aSrcBuf, - JS::Handle<JSObject*> aEvaluationGlobal, - JS::CompileOptions& aCompileOptions, - const EvaluateOptions& aEvaluateOptions, - JS::MutableHandle<JS::Value> aRetValue) -{ - return EvaluateString(aCx, aSrcBuf, aEvaluationGlobal, aCompileOptions, - aEvaluateOptions, aRetValue, nullptr); -} - -nsresult -nsJSUtils::EvaluateString(JSContext* aCx, - const nsAString& aScript, - JS::Handle<JSObject*> aEvaluationGlobal, - JS::CompileOptions& aCompileOptions) +nsJSUtils::ExecutionContext::ExtractReturnValue(JS::MutableHandle<JS::Value> aRetValue) { - EvaluateOptions options(aCx); - aCompileOptions.setNoScriptRval(true); - JS::RootedValue unused(aCx); - return EvaluateString(aCx, aScript, aEvaluationGlobal, aCompileOptions, - options, &unused); -} + MOZ_ASSERT(aRetValue.isUndefined()); + if (mSkip) { + // Repeat earlier result, as NS_SUCCESS_DOM_SCRIPT_EVALUATION_THREW are not + // failures cases. +#ifdef DEBUG + mWantsReturnValue = false; +#endif + return mRv; + } -nsresult -nsJSUtils::EvaluateString(JSContext* aCx, - JS::SourceBufferHolder& aSrcBuf, - JS::Handle<JSObject*> aEvaluationGlobal, - JS::CompileOptions& aCompileOptions, - void **aOffThreadToken) -{ - EvaluateOptions options(aCx); - aCompileOptions.setNoScriptRval(true); - JS::RootedValue unused(aCx); - return EvaluateString(aCx, aSrcBuf, aEvaluationGlobal, aCompileOptions, - options, &unused, aOffThreadToken); + MOZ_ASSERT(mWantsReturnValue); +#ifdef DEBUG + mWantsReturnValue = false; +#endif + if (mCoerceToString && !mRetValue.isUndefined()) { + JSString* str = JS::ToString(mCx, mRetValue); + if (!str) { + // ToString can be a function call, so an exception can be raised while + // executing the function. + mSkip = true; + return EvaluationExceptionToNSResult(mCx); + } + mRetValue.set(JS::StringValue(str)); + } + + aRetValue.set(mRetValue); + return NS_OK; } nsresult nsJSUtils::CompileModule(JSContext* aCx, JS::SourceBufferHolder& aSrcBuf, JS::Handle<JSObject*> aEvaluationGlobal, JS::CompileOptions &aCompileOptions, JS::MutableHandle<JSObject*> aModule)
--- a/dom/base/nsJSUtils.h +++ b/dom/base/nsJSUtils.h @@ -11,16 +11,17 @@ * This is not a generated file. It contains common utility functions * invoked from the JavaScript code generated from IDL interfaces. * The goal of the utility functions is to cut down on the size of * the generated code itself. */ #include "mozilla/Assertions.h" +#include "GeckoProfiler.h" #include "jsapi.h" #include "jsfriendapi.h" #include "js/Conversions.h" #include "nsString.h" class nsIScriptContext; class nsIScriptGlobalObject; @@ -59,61 +60,104 @@ public: JS::AutoObjectVector& aScopeChain, JS::CompileOptions& aOptions, const nsACString& aName, uint32_t aArgCount, const char** aArgArray, const nsAString& aBody, JSObject** aFunctionObject); - struct MOZ_STACK_CLASS EvaluateOptions { - bool coerceToString; - JS::AutoObjectVector scopeChain; + + // ExecutionContext is used to switch compartment. + class MOZ_STACK_CLASS ExecutionContext { + // Register stack annotations for the Gecko profiler. + mozilla::SamplerStackFrameRAII mSamplerRAII; + + JSContext* mCx; + + // Handles switching to our global's compartment. + JSAutoCompartment mCompartment; + + // Set to a valid handle if a return value is expected. + JS::Rooted<JS::Value> mRetValue; + + // Scope chain in which the execution takes place. + JS::AutoObjectVector mScopeChain; + + // returned value forwarded when we have to interupt the execution eagerly + // with mSkip. + nsresult mRv; + + // Used to skip upcoming phases in case of a failure. In such case the + // result is carried by mRv. + bool mSkip; - explicit EvaluateOptions(JSContext* cx) - : coerceToString(false) - , scopeChain(cx) - {} + // Should the result be serialized before being returned. + bool mCoerceToString; + +#ifdef DEBUG + // Should we set the return value. + bool mWantsReturnValue; + + bool mExpectScopeChain; +#endif + + public: - EvaluateOptions& setCoerceToString(bool aCoerce) { - coerceToString = aCoerce; + // Enter compartment in which the code would be executed. The JSContext + // must come from an AutoEntryScript that has had + // TakeOwnershipOfErrorReporting() called on it. + ExecutionContext(JSContext* aCx, JS::Handle<JSObject*> aGlobal); + + ExecutionContext(const ExecutionContext&) = delete; + ExecutionContext(ExecutionContext&&) = delete; + + ~ExecutionContext() { + // This flag is resetted, when the returned value is extracted. + MOZ_ASSERT(!mWantsReturnValue); + } + + // The returned value would be converted to a string if the + // |aCoerceToString| is flag set. + ExecutionContext& SetCoerceToString(bool aCoerceToString) { + mCoerceToString = aCoerceToString; return *this; } - }; + + // Set the scope chain in which the code should be executed. + void SetScopeChain(const JS::AutoObjectVector& aScopeChain); - // aEvaluationGlobal is the global to evaluate in. The return value - // will then be wrapped back into the compartment aCx is in when - // this function is called. For all the EvaluateString overloads, - // the JSContext must come from an AutoJSAPI that has had - // TakeOwnershipOfErrorReporting() called on it. - static nsresult EvaluateString(JSContext* aCx, - const nsAString& aScript, - JS::Handle<JSObject*> aEvaluationGlobal, - JS::CompileOptions &aCompileOptions, - const EvaluateOptions& aEvaluateOptions, - JS::MutableHandle<JS::Value> aRetValue); + // Copy the returned value in the mutable handle argument, in case of a + // evaluation failure either during the execution or the conversion of the + // result to a string, the nsresult would be set to the corresponding result + // code, and the mutable handle argument would remain unchanged. + // + // The value returned in the mutable handle argument is part of the + // compartment given as argument to the ExecutionContext constructor. If the + // caller is in a different compartment, then the out-param value should be + // wrapped by calling |JS_WrapValue|. + MOZ_MUST_USE nsresult + ExtractReturnValue(JS::MutableHandle<JS::Value> aRetValue); - static nsresult EvaluateString(JSContext* aCx, - JS::SourceBufferHolder& aSrcBuf, - JS::Handle<JSObject*> aEvaluationGlobal, - JS::CompileOptions &aCompileOptions, - const EvaluateOptions& aEvaluateOptions, - JS::MutableHandle<JS::Value> aRetValue); - + // After getting a notification that an off-thread compilation terminated, + // this function will synchronize the result by moving it to the main thread + // before starting the execution of the script. + // + // The compiled script would be returned in the |aScript| out-param. + MOZ_MUST_USE nsresult SyncAndExec(void **aOffThreadToken, + JS::MutableHandle<JSScript*> aScript); - static nsresult EvaluateString(JSContext* aCx, - const nsAString& aScript, - JS::Handle<JSObject*> aEvaluationGlobal, - JS::CompileOptions &aCompileOptions); + // Compile a script contained in a SourceBuffer, and execute it. + nsresult CompileAndExec(JS::CompileOptions& aCompileOptions, + JS::SourceBufferHolder& aSrcBuf); - static nsresult EvaluateString(JSContext* aCx, - JS::SourceBufferHolder& aSrcBuf, - JS::Handle<JSObject*> aEvaluationGlobal, - JS::CompileOptions &aCompileOptions, - void **aOffThreadToken); + // Compile a script contained in a string, and execute it. + nsresult CompileAndExec(JS::CompileOptions& aCompileOptions, + const nsAString& aScript); + }; static nsresult CompileModule(JSContext* aCx, JS::SourceBufferHolder& aSrcBuf, JS::Handle<JSObject*> aEvaluationGlobal, JS::CompileOptions &aCompileOptions, JS::MutableHandle<JSObject*> aModule); static nsresult ModuleDeclarationInstantiation(JSContext* aCx, @@ -124,26 +168,16 @@ public: // Returns false if an exception got thrown on aCx. Passing a null // aElement is allowed; that wil produce an empty aScopeChain. static bool GetScopeChainForElement(JSContext* aCx, mozilla::dom::Element* aElement, JS::AutoObjectVector& aScopeChain); static void ResetTimeZone(); - -private: - // Implementation for our EvaluateString bits - static nsresult EvaluateString(JSContext* aCx, - JS::SourceBufferHolder& aSrcBuf, - JS::Handle<JSObject*> aEvaluationGlobal, - JS::CompileOptions& aCompileOptions, - const EvaluateOptions& aEvaluateOptions, - JS::MutableHandle<JS::Value> aRetValue, - void **aOffThreadToken); }; template<typename T> inline bool AssignJSString(JSContext *cx, T &dest, JSString *s) { size_t len = js::GetStringLength(s); static_assert(js::MaxStringLength < (1 << 28),
--- a/dom/base/nsNodeInfoManager.cpp +++ b/dom/base/nsNodeInfoManager.cpp @@ -25,17 +25,17 @@ #include "nsGkAtoms.h" #include "nsComponentManagerUtils.h" #include "nsLayoutStatics.h" #include "nsBindingManager.h" #include "nsHashKeys.h" #include "nsCCUncollectableMarker.h" #include "nsNameSpaceManager.h" #include "nsDocument.h" -#include "nsNullPrincipal.h" +#include "NullPrincipal.h" using namespace mozilla; using mozilla::dom::NodeInfo; #include "mozilla/Logging.h" static LazyLogModule gNodeInfoManagerLeakPRLog("NodeInfoManagerLeak"); @@ -177,17 +177,17 @@ NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_E nsresult nsNodeInfoManager::Init(nsIDocument *aDocument) { NS_ENSURE_TRUE(mNodeInfoHash, NS_ERROR_OUT_OF_MEMORY); NS_PRECONDITION(!mPrincipal, "Being inited when we already have a principal?"); - mPrincipal = nsNullPrincipal::Create(); + mPrincipal = NullPrincipal::Create(); if (aDocument) { mBindingManager = new nsBindingManager(aDocument); } mDefaultPrincipal = mPrincipal; mDocument = aDocument;
--- a/dom/base/nsScriptLoader.cpp +++ b/dom/base/nsScriptLoader.cpp @@ -2147,18 +2147,16 @@ nsScriptLoader::FillCompileOptionsForReq bool isScriptElement = !aRequest->IsModuleRequest() || aRequest->AsModuleRequest()->IsTopLevel(); aOptions->setIntroductionType(isScriptElement ? "scriptElement" : "importedModule"); aOptions->setFileAndLine(aRequest->mURL.get(), aRequest->mLineNo); aOptions->setVersion(JSVersion(aRequest->mJSVersion)); aOptions->setIsRunOnce(true); - // We only need the setNoScriptRval bit when compiling off-thread here, since - // otherwise nsJSUtils::EvaluateString will set it up for us. aOptions->setNoScriptRval(true); if (aRequest->mHasSourceMapURL) { aOptions->setSourceMapURL(aRequest->mSourceMapURL.get()); } if (aRequest->mOriginPrincipal) { nsIPrincipal* scriptPrin = nsContentUtils::ObjectPrincipal(aScopeChain); bool subsumes = scriptPrin->Subsumes(aRequest->mOriginPrincipal); aOptions->setMutedErrors(!subsumes); @@ -2253,20 +2251,27 @@ nsScriptLoader::EvaluateScript(nsScriptL MOZ_ASSERT(module); rv = nsJSUtils::ModuleEvaluation(aes.cx(), module); } } else { JS::CompileOptions options(aes.cx()); rv = FillCompileOptionsForRequest(aes, aRequest, global, &options); if (NS_SUCCEEDED(rv)) { - nsAutoString inlineData; - SourceBufferHolder srcBuf = GetScriptSource(aRequest, inlineData); - rv = nsJSUtils::EvaluateString(aes.cx(), srcBuf, global, options, - aRequest->OffThreadTokenPtr()); + { + nsJSUtils::ExecutionContext exec(aes.cx(), global); + if (aRequest->mOffThreadToken) { + JS::Rooted<JSScript*> script(aes.cx()); + rv = exec.SyncAndExec(&aRequest->mOffThreadToken, &script); + } else { + nsAutoString inlineData; + SourceBufferHolder srcBuf = GetScriptSource(aRequest, inlineData); + rv = exec.CompileAndExec(options, srcBuf); + } + } } } } context->SetProcessingScriptTag(oldProcessingScriptTag); return rv; }
--- a/dom/base/nsTreeSanitizer.cpp +++ b/dom/base/nsTreeSanitizer.cpp @@ -14,17 +14,17 @@ #include "nsCSSParser.h" #include "nsCSSPropertyID.h" #include "nsUnicharInputStream.h" #include "nsIDOMCSSRule.h" #include "nsAttrName.h" #include "nsIScriptSecurityManager.h" #include "nsNetUtil.h" #include "nsComponentManagerUtils.h" -#include "nsNullPrincipal.h" +#include "NullPrincipal.h" #include "nsContentUtils.h" #include "nsIParserUtils.h" #include "nsIDocument.h" #include "nsQueryObject.h" using namespace mozilla; // @@ -1517,17 +1517,17 @@ nsTreeSanitizer::InitializeStatics() sElementsMathML->PutEntry(*kElementsMathML[i]); } sAttributesMathML = new nsTHashtable<nsISupportsHashKey>(ArrayLength(kAttributesMathML)); for (uint32_t i = 0; kAttributesMathML[i]; i++) { sAttributesMathML->PutEntry(*kAttributesMathML[i]); } - nsCOMPtr<nsIPrincipal> principal = nsNullPrincipal::Create(); + nsCOMPtr<nsIPrincipal> principal = NullPrincipal::Create(); principal.forget(&sNullPrincipal); } void nsTreeSanitizer::ReleaseStatics() { delete sElementsHTML; sElementsHTML = nullptr;
--- a/dom/bindings/SimpleGlobalObject.cpp +++ b/dom/bindings/SimpleGlobalObject.cpp @@ -5,17 +5,17 @@ * You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "mozilla/dom/SimpleGlobalObject.h" #include "jsapi.h" #include "js/Class.h" #include "nsJSPrincipals.h" -#include "nsNullPrincipal.h" +#include "NullPrincipal.h" #include "nsThreadUtils.h" #include "nsContentUtils.h" #include "xpcprivate.h" #include "mozilla/dom/ScriptSettings.h" namespace mozilla { @@ -108,17 +108,17 @@ SimpleGlobalObject::Create(GlobalType gl .setInvisibleToDebugger(true) // Put our SimpleGlobalObjects in the system zone, so we won't create // lots of zones for what are probably very short-lived // compartments. This should help them be GCed quicker and take up // less memory before they're GCed. .setSystemZone(); if (NS_IsMainThread()) { - nsCOMPtr<nsIPrincipal> principal = nsNullPrincipal::Create(); + nsCOMPtr<nsIPrincipal> principal = NullPrincipal::Create(); options.creationOptions().setTrace(xpc::TraceXPCGlobal); global = xpc::CreateGlobalObject(cx, js::Jsvalify(&SimpleGlobalClass), nsJSPrincipals::get(principal), options); } else { global = JS_NewGlobalObject(cx, js::Jsvalify(&SimpleGlobalClass), nullptr, JS::DontFireOnNewGlobalHook, options);
--- a/dom/cache/QuotaClient.cpp +++ b/dom/cache/QuotaClient.cpp @@ -11,46 +11,48 @@ #include "mozilla/dom/quota/UsageInfo.h" #include "mozilla/ipc/BackgroundParent.h" #include "nsIFile.h" #include "nsISimpleEnumerator.h" #include "nsThreadUtils.h" namespace { +using mozilla::Atomic; using mozilla::dom::ContentParentId; using mozilla::dom::cache::Manager; using mozilla::dom::quota::Client; using mozilla::dom::quota::PersistenceType; using mozilla::dom::quota::QuotaManager; using mozilla::dom::quota::UsageInfo; using mozilla::ipc::AssertIsOnBackgroundThread; static nsresult -GetBodyUsage(nsIFile* aDir, UsageInfo* aUsageInfo) +GetBodyUsage(nsIFile* aDir, const Atomic<bool>& aCanceled, + UsageInfo* aUsageInfo) { nsCOMPtr<nsISimpleEnumerator> entries; nsresult rv = aDir->GetDirectoryEntries(getter_AddRefs(entries)); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } bool hasMore; while (NS_SUCCEEDED(rv = entries->HasMoreElements(&hasMore)) && hasMore && - !aUsageInfo->Canceled()) { + !aCanceled) { nsCOMPtr<nsISupports> entry; rv = entries->GetNext(getter_AddRefs(entry)); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } nsCOMPtr<nsIFile> file = do_QueryInterface(entry); bool isDir; rv = file->IsDirectory(&isDir); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } if (isDir) { - rv = GetBodyUsage(file, aUsageInfo); + rv = GetBodyUsage(file, aCanceled, aUsageInfo); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } continue; } int64_t fileSize; rv = file->GetFileSize(&fileSize); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } MOZ_DIAGNOSTIC_ASSERT(fileSize >= 0); @@ -67,30 +69,32 @@ public: virtual Type GetType() override { return DOMCACHE; } virtual nsresult InitOrigin(PersistenceType aPersistenceType, const nsACString& aGroup, - const nsACString& aOrigin, UsageInfo* aUsageInfo) override + const nsACString& aOrigin, const AtomicBool& aCanceled, + UsageInfo* aUsageInfo) override { // The QuotaManager passes a nullptr UsageInfo if there is no quota being // enforced against the origin. if (!aUsageInfo) { return NS_OK; } - return GetUsageForOrigin(aPersistenceType, aGroup, aOrigin, aUsageInfo); + return GetUsageForOrigin(aPersistenceType, aGroup, aOrigin, aCanceled, + aUsageInfo); } virtual nsresult GetUsageForOrigin(PersistenceType aPersistenceType, const nsACString& aGroup, - const nsACString& aOrigin, + const nsACString& aOrigin, const AtomicBool& aCanceled, UsageInfo* aUsageInfo) override { MOZ_DIAGNOSTIC_ASSERT(aUsageInfo); QuotaManager* qm = QuotaManager::Get(); MOZ_DIAGNOSTIC_ASSERT(qm); nsCOMPtr<nsIFile> dir; @@ -102,34 +106,34 @@ public: if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } nsCOMPtr<nsISimpleEnumerator> entries; rv = dir->GetDirectoryEntries(getter_AddRefs(entries)); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } bool hasMore; while (NS_SUCCEEDED(rv = entries->HasMoreElements(&hasMore)) && hasMore && - !aUsageInfo->Canceled()) { + !aCanceled) { nsCOMPtr<nsISupports> entry; rv = entries->GetNext(getter_AddRefs(entry)); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } nsCOMPtr<nsIFile> file = do_QueryInterface(entry); nsAutoString leafName; rv = file->GetLeafName(leafName); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } bool isDir; rv = file->IsDirectory(&isDir); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } if (isDir) { if (leafName.EqualsLiteral("morgue")) { - rv = GetBodyUsage(file, aUsageInfo); + rv = GetBodyUsage(file, aCanceled, aUsageInfo); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } } else { NS_WARNING("Unknown Cache directory found!"); } continue; }
--- a/dom/cache/test/mochitest/test_cache_orphaned_body.html +++ b/dom/cache/test/mochitest/test_cache_orphaned_body.html @@ -32,17 +32,18 @@ function clearStorage() { }); } function storageUsage() { return new Promise(function(resolve, reject) { var qms = SpecialPowers.Services.qms; var principal = SpecialPowers.wrap(document).nodePrincipal; var cb = SpecialPowers.wrapCallback(function(request) { - resolve(request.usage, request.fileUsage); + var result = request.result; + resolve(result.usage, result.fileUsage); }); qms.getUsageForPrincipal(principal, cb); }); } function groupUsage() { return new Promise(function(resolve, reject) { navigator.storage.estimate().then(storageEstimation => {
--- a/dom/cache/test/mochitest/test_cache_orphaned_cache.html +++ b/dom/cache/test/mochitest/test_cache_orphaned_cache.html @@ -32,17 +32,18 @@ function clearStorage() { }); } function storageUsage() { return new Promise(function(resolve, reject) { var qms = SpecialPowers.Services.qms; var principal = SpecialPowers.wrap(document).nodePrincipal; var cb = SpecialPowers.wrapCallback(function(request) { - resolve(request.usage, request.fileUsage); + var result = request.result; + resolve(result.usage, result.fileUsage); }); qms.getUsageForPrincipal(principal, cb); }); } function resetStorage() { return new Promise(function(resolve, reject) { var qms = SpecialPowers.Services.qms;
--- a/dom/cache/test/mochitest/test_cache_shrink.html +++ b/dom/cache/test/mochitest/test_cache_shrink.html @@ -32,17 +32,18 @@ function clearStorage() { }); } function storageUsage() { return new Promise(function(resolve, reject) { var qms = SpecialPowers.Services.qms; var principal = SpecialPowers.wrap(document).nodePrincipal; var cb = SpecialPowers.wrapCallback(function(request) { - resolve(request.usage, request.fileUsage); + var result = request.result; + resolve(result.usage, result.fileUsage); }); qms.getUsageForPrincipal(principal, cb); }); } function resetStorage() { return new Promise(function(resolve, reject) { var qms = SpecialPowers.Services.qms;
--- a/dom/html/nsTextEditorState.cpp +++ b/dom/html/nsTextEditorState.cpp @@ -374,38 +374,41 @@ NS_IMETHODIMP nsTextInputSelectionImpl::ScrollSelectionIntoView( RawSelectionType aRawSelectionType, int16_t aRegion, int16_t aFlags) { if (!mFrameSelection) return NS_ERROR_FAILURE; - return mFrameSelection->ScrollSelectionIntoView( - ToSelectionType(aRawSelectionType), - aRegion, aFlags); + RefPtr<nsFrameSelection> frameSelection = mFrameSelection; + return frameSelection->ScrollSelectionIntoView( + ToSelectionType(aRawSelectionType), + aRegion, aFlags); } NS_IMETHODIMP nsTextInputSelectionImpl::RepaintSelection(RawSelectionType aRawSelectionType) { if (!mFrameSelection) return NS_ERROR_FAILURE; - return mFrameSelection->RepaintSelection(ToSelectionType(aRawSelectionType)); + RefPtr<nsFrameSelection> frameSelection = mFrameSelection; + return frameSelection->RepaintSelection(ToSelectionType(aRawSelectionType)); } nsresult nsTextInputSelectionImpl::RepaintSelection(nsPresContext* aPresContext, SelectionType aSelectionType) { if (!mFrameSelection) return NS_ERROR_FAILURE; - return mFrameSelection->RepaintSelection(aSelectionType); + RefPtr<nsFrameSelection> frameSelection = mFrameSelection; + return frameSelection->RepaintSelection(aSelectionType); } NS_IMETHODIMP nsTextInputSelectionImpl::SetCaretEnabled(bool enabled) { if (!mPresShellWeak) return NS_ERROR_NOT_INITIALIZED; nsCOMPtr<nsIPresShell> shell = do_QueryReferent(mPresShellWeak); @@ -482,92 +485,108 @@ nsTextInputSelectionImpl::SetCaretVisibi } return NS_ERROR_FAILURE; } NS_IMETHODIMP nsTextInputSelectionImpl::PhysicalMove(int16_t aDirection, int16_t aAmount, bool aExtend) { - if (mFrameSelection) - return mFrameSelection->PhysicalMove(aDirection, aAmount, aExtend); + if (mFrameSelection) { + RefPtr<nsFrameSelection> frameSelection = mFrameSelection; + return frameSelection->PhysicalMove(aDirection, aAmount, aExtend); + } return NS_ERROR_NULL_POINTER; } NS_IMETHODIMP nsTextInputSelectionImpl::CharacterMove(bool aForward, bool aExtend) { - if (mFrameSelection) - return mFrameSelection->CharacterMove(aForward, aExtend); + if (mFrameSelection) { + RefPtr<nsFrameSelection> frameSelection = mFrameSelection; + return frameSelection->CharacterMove(aForward, aExtend); + } return NS_ERROR_NULL_POINTER; } NS_IMETHODIMP nsTextInputSelectionImpl::CharacterExtendForDelete() { - if (mFrameSelection) - return mFrameSelection->CharacterExtendForDelete(); + if (mFrameSelection) { + RefPtr<nsFrameSelection> frameSelection = mFrameSelection; + return frameSelection->CharacterExtendForDelete(); + } return NS_ERROR_NULL_POINTER; } NS_IMETHODIMP nsTextInputSelectionImpl::CharacterExtendForBackspace() { - if (mFrameSelection) - return mFrameSelection->CharacterExtendForBackspace(); + if (mFrameSelection) { + RefPtr<nsFrameSelection> frameSelection = mFrameSelection; + return frameSelection->CharacterExtendForBackspace(); + } return NS_ERROR_NULL_POINTER; } NS_IMETHODIMP nsTextInputSelectionImpl::WordMove(bool aForward, bool aExtend) { - if (mFrameSelection) - return mFrameSelection->WordMove(aForward, aExtend); + if (mFrameSelection) { + RefPtr<nsFrameSelection> frameSelection = mFrameSelection; + return frameSelection->WordMove(aForward, aExtend); + } return NS_ERROR_NULL_POINTER; } NS_IMETHODIMP nsTextInputSelectionImpl::WordExtendForDelete(bool aForward) { - if (mFrameSelection) - return mFrameSelection->WordExtendForDelete(aForward); + if (mFrameSelection) { + RefPtr<nsFrameSelection> frameSelection = mFrameSelection; + return frameSelection->WordExtendForDelete(aForward); + } return NS_ERROR_NULL_POINTER; } NS_IMETHODIMP nsTextInputSelectionImpl::LineMove(bool aForward, bool aExtend) { if (mFrameSelection) { - nsresult result = mFrameSelection->LineMove(aForward, aExtend); + RefPtr<nsFrameSelection> frameSelection = mFrameSelection; + nsresult result = frameSelection->LineMove(aForward, aExtend); if (NS_FAILED(result)) result = CompleteMove(aForward,aExtend); return result; } return NS_ERROR_NULL_POINTER; } NS_IMETHODIMP nsTextInputSelectionImpl::IntraLineMove(bool aForward, bool aExtend) { - if (mFrameSelection) - return mFrameSelection->IntraLineMove(aForward, aExtend); + if (mFrameSelection) { + RefPtr<nsFrameSelection> frameSelection = mFrameSelection; + return frameSelection->IntraLineMove(aForward, aExtend); + } return NS_ERROR_NULL_POINTER; } NS_IMETHODIMP nsTextInputSelectionImpl::PageMove(bool aForward, bool aExtend) { // expected behavior for PageMove is to scroll AND move the caret // and to remain relative position of the caret in view. see Bug 4302. if (mScrollFrame) { - mFrameSelection->CommonPageMove(aForward, aExtend, mScrollFrame); + RefPtr<nsFrameSelection> frameSelection = mFrameSelection; + frameSelection->CommonPageMove(aForward, aExtend, mScrollFrame); } // After ScrollSelectionIntoView(), the pending notifications might be // flushed and PresShell/PresContext/Frames may be dead. See bug 418470. return ScrollSelectionIntoView(nsISelectionController::SELECTION_NORMAL, nsISelectionController::SELECTION_FOCUS_REGION, nsISelectionController::SCROLL_SYNCHRONOUS | nsISelectionController::SCROLL_FOR_CARET_MOVE); } @@ -585,18 +604,21 @@ nsTextInputSelectionImpl::CompleteScroll nsIScrollableFrame::WHOLE, nsIScrollableFrame::INSTANT); return NS_OK; } NS_IMETHODIMP nsTextInputSelectionImpl::CompleteMove(bool aForward, bool aExtend) { + NS_ENSURE_STATE(mFrameSelection); + RefPtr<nsFrameSelection> frameSelection = mFrameSelection; + // grab the parent / root DIV for this text widget - nsIContent* parentDIV = mFrameSelection->GetLimiter(); + nsIContent* parentDIV = frameSelection->GetLimiter(); if (!parentDIV) return NS_ERROR_UNEXPECTED; // make the caret be either at the very beginning (0) or the very end int32_t offset = 0; CaretAssociationHint hint = CARET_ASSOCIATE_BEFORE; if (aForward) { @@ -612,17 +634,17 @@ nsTextInputSelectionImpl::CompleteMove(b if (child->IsHTMLElement(nsGkAtoms::br)) { --offset; hint = CARET_ASSOCIATE_AFTER; // for Bug 106855 } } } - mFrameSelection->HandleClick(parentDIV, offset, offset, aExtend, + frameSelection->HandleClick(parentDIV, offset, offset, aExtend, false, hint); // if we got this far, attempt to scroll no matter what the above result is return CompleteScroll(aForward); } NS_IMETHODIMP nsTextInputSelectionImpl::ScrollPage(bool aForward) @@ -667,18 +689,20 @@ nsTextInputSelectionImpl::ScrollCharacte nsIScrollableFrame::LINES, nsIScrollableFrame::SMOOTH); return NS_OK; } NS_IMETHODIMP nsTextInputSelectionImpl::SelectAll() { - if (mFrameSelection) - return mFrameSelection->SelectAll(); + if (mFrameSelection) { + RefPtr<nsFrameSelection> frameSelection = mFrameSelection; + return frameSelection->SelectAll(); + } return NS_ERROR_NULL_POINTER; } NS_IMETHODIMP nsTextInputSelectionImpl::CheckVisibility(nsIDOMNode *node, int16_t startOffset, int16_t EndOffset, bool *_retval) { if (!mPresShellWeak) return NS_ERROR_NOT_INITIALIZED; nsresult result;
--- a/dom/indexedDB/ActorsParent.cpp +++ b/dom/indexedDB/ActorsParent.cpp @@ -9342,22 +9342,24 @@ public: nsresult UpgradeStorageFrom1_0To2_0(nsIFile* aDirectory) override; nsresult InitOrigin(PersistenceType aPersistenceType, const nsACString& aGroup, const nsACString& aOrigin, + const AtomicBool& aCanceled, UsageInfo* aUsageInfo) override; nsresult GetUsageForOrigin(PersistenceType aPersistenceType, const nsACString& aGroup, const nsACString& aOrigin, + const AtomicBool& aCanceled, UsageInfo* aUsageInfo) override; void OnOriginClearCompleted(PersistenceType aPersistenceType, const nsACString& aOrigin) override; void @@ -9389,23 +9391,24 @@ private: nsresult GetDirectory(PersistenceType aPersistenceType, const nsACString& aOrigin, nsIFile** aDirectory); nsresult GetDatabaseFilenames(nsIFile* aDirectory, - UsageInfo* aUsageInfo, + const AtomicBool& aCanceled, bool aForUpgrade, nsTArray<nsString>& aSubdirsToProcess, nsTHashtable<nsStringHashKey>& aDatabaseFilename); nsresult GetUsageForDirectoryInternal(nsIFile* aDirectory, + const AtomicBool& aCanceled, UsageInfo* aUsageInfo, bool aDatabaseFiles); // Runs on the PBackground thread. Checks to see if there's a queued // Maintenance to run. void ProcessMaintenanceQueue(); }; @@ -17823,20 +17826,21 @@ QuotaClient::GetType() } nsresult QuotaClient::UpgradeStorageFrom1_0To2_0(nsIFile* aDirectory) { AssertIsOnIOThread(); MOZ_ASSERT(aDirectory); + AtomicBool dummy(false); AutoTArray<nsString, 20> subdirsToProcess; nsTHashtable<nsStringHashKey> databaseFilenames(20); nsresult rv = GetDatabaseFilenames(aDirectory, - nullptr, + /* aCanceled */ dummy, /* aForUpgrade */ true, subdirsToProcess, databaseFilenames); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } const NS_ConvertASCIItoUTF16 filesSuffix( @@ -17919,16 +17923,17 @@ QuotaClient::UpgradeStorageFrom1_0To2_0( return NS_OK; } nsresult QuotaClient::InitOrigin(PersistenceType aPersistenceType, const nsACString& aGroup, const nsACString& aOrigin, + const AtomicBool& aCanceled, UsageInfo* aUsageInfo) { AssertIsOnIOThread(); nsCOMPtr<nsIFile> directory; nsresult rv = GetDirectory(aPersistenceType, aOrigin, getter_AddRefs(directory)); if (NS_WARN_IF(NS_FAILED(rv))) { @@ -17937,17 +17942,17 @@ QuotaClient::InitOrigin(PersistenceType // 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. AutoTArray<nsString, 20> subdirsToProcess; nsTHashtable<nsStringHashKey> databaseFilenames(20); rv = GetDatabaseFilenames(directory, - aUsageInfo, + aCanceled, /* aForUpgrade */ false, subdirsToProcess, databaseFilenames); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } const NS_ConvertASCIItoUTF16 filesSuffix( @@ -17969,17 +17974,19 @@ QuotaClient::InitOrigin(PersistenceType } } const NS_ConvertASCIItoUTF16 sqliteSuffix(kSQLiteSuffix, LiteralStringLength(kSQLiteSuffix)); const NS_ConvertASCIItoUTF16 walSuffix(kSQLiteWALSuffix, LiteralStringLength(kSQLiteWALSuffix)); - for (auto iter = databaseFilenames.ConstIter(); !iter.Done(); iter.Next()) { + for (auto iter = databaseFilenames.ConstIter(); + !iter.Done() && !aCanceled; + iter.Next()) { auto& databaseFilename = iter.Get()->GetKey(); nsCOMPtr<nsIFile> fmDirectory; rv = directory->Clone(getter_AddRefs(fmDirectory)); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } @@ -18017,17 +18024,17 @@ QuotaClient::InitOrigin(PersistenceType aPersistenceType, aGroup, aOrigin, TelemetryIdForFile(databaseFile)); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } - if (aUsageInfo && !aUsageInfo->Canceled()) { + if (aUsageInfo) { int64_t fileSize; rv = databaseFile->GetFileSize(&fileSize); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } MOZ_ASSERT(fileSize >= 0); @@ -18054,29 +18061,30 @@ QuotaClient::InitOrigin(PersistenceType return NS_OK; } nsresult QuotaClient::GetUsageForOrigin(PersistenceType aPersistenceType, const nsACString& aGroup, const nsACString& aOrigin, + const AtomicBool& aCanceled, UsageInfo* aUsageInfo) { AssertIsOnIOThread(); MOZ_ASSERT(aUsageInfo); nsCOMPtr<nsIFile> directory; nsresult rv = GetDirectory(aPersistenceType, aOrigin, getter_AddRefs(directory)); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } - rv = GetUsageForDirectoryInternal(directory, aUsageInfo, true); + rv = GetUsageForDirectoryInternal(directory, aCanceled, aUsageInfo, true); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } return NS_OK; } void @@ -18255,22 +18263,23 @@ QuotaClient::GetDirectory(PersistenceTyp directory.forget(aDirectory); return NS_OK; } nsresult QuotaClient::GetDatabaseFilenames( nsIFile* aDirectory, - UsageInfo* aUsageInfo, + const AtomicBool& aCanceled, bool aForUpgrade, nsTArray<nsString>& aSubdirsToProcess, nsTHashtable<nsStringHashKey>& aDatabaseFilenames) { AssertIsOnIOThread(); + MOZ_ASSERT(aDirectory); nsCOMPtr<nsISimpleEnumerator> entries; nsresult rv = aDirectory->GetDirectoryEntries(getter_AddRefs(entries)); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } const NS_ConvertASCIItoUTF16 sqliteSuffix(kSQLiteSuffix, @@ -18281,17 +18290,17 @@ QuotaClient::GetDatabaseFilenames( const NS_ConvertASCIItoUTF16 shmSuffix(kSQLiteSHMSuffix, LiteralStringLength(kSQLiteSHMSuffix)); const NS_ConvertASCIItoUTF16 walSuffix(kSQLiteWALSuffix, LiteralStringLength(kSQLiteWALSuffix)); bool hasMore; while (NS_SUCCEEDED((rv = entries->HasMoreElements(&hasMore))) && hasMore && - (!aUsageInfo || !aUsageInfo->Canceled())) { + !aCanceled) { nsCOMPtr<nsISupports> entry; rv = entries->GetNext(getter_AddRefs(entry)); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } nsCOMPtr<nsIFile> file = do_QueryInterface(entry); MOZ_ASSERT(file); @@ -18357,16 +18366,17 @@ QuotaClient::GetDatabaseFilenames( return rv; } return NS_OK; } nsresult QuotaClient::GetUsageForDirectoryInternal(nsIFile* aDirectory, + const AtomicBool& aCanceled, UsageInfo* aUsageInfo, bool aDatabaseFiles) { AssertIsOnIOThread(); MOZ_ASSERT(aDirectory); MOZ_ASSERT(aUsageInfo); nsCOMPtr<nsISimpleEnumerator> entries; @@ -18383,17 +18393,17 @@ QuotaClient::GetUsageForDirectoryInterna kSQLiteJournalSuffix, LiteralStringLength(kSQLiteJournalSuffix)); const NS_ConvertASCIItoUTF16 shmSuffix(kSQLiteSHMSuffix, LiteralStringLength(kSQLiteSHMSuffix)); bool hasMore; while (NS_SUCCEEDED((rv = entries->HasMoreElements(&hasMore))) && hasMore && - !aUsageInfo->Canceled()) { + !aCanceled) { nsCOMPtr<nsISupports> entry; rv = entries->GetNext(getter_AddRefs(entry)); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } nsCOMPtr<nsIFile> file = do_QueryInterface(entry); MOZ_ASSERT(file); @@ -18418,17 +18428,17 @@ QuotaClient::GetUsageForDirectoryInterna } if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } if (isDirectory) { if (aDatabaseFiles) { - rv = GetUsageForDirectoryInternal(file, aUsageInfo, false); + rv = GetUsageForDirectoryInternal(file, aCanceled, aUsageInfo, false); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } } else { nsString leafName; rv = file->GetLeafName(leafName); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; @@ -21231,18 +21241,17 @@ FactoryOp::CheckPermission(ContentParent mChromeWriteAccessAllowed = canWrite; } else { mChromeWriteAccessAllowed = true; } if (State::Initial == mState) { QuotaManager::GetInfoForChrome(&mSuffix, &mGroup, &mOrigin); - MOZ_ASSERT( - QuotaManager::IsOriginWhitelistedForPersistentStorage(mOrigin)); + MOZ_ASSERT(QuotaManager::IsOriginInternal(mOrigin)); mEnforcingQuota = false; } *aPermission = PermissionRequestBase::kPermissionAllowed; return NS_OK; } @@ -21264,17 +21273,17 @@ FactoryOp::CheckPermission(ContentParent &origin); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } PermissionRequestBase::PermissionValue permission; if (persistenceType == PERSISTENCE_TYPE_PERSISTENT) { - if (QuotaManager::IsOriginWhitelistedForPersistentStorage(origin)) { + if (QuotaManager::IsOriginInternal(origin)) { permission = PermissionRequestBase::kPermissionAllowed; } else { #ifdef IDB_MOBILE return NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR; #else rv = PermissionRequestBase::GetCurrentPermission(principal, &permission); if (NS_WARN_IF(NS_FAILED(rv))) { return rv;
--- a/dom/indexedDB/test/file.js +++ b/dom/indexedDB/test/file.js @@ -215,20 +215,20 @@ function verifyWasmModule(module1, modul ok(code2 instanceof getGlobalForObject(code1).Uint8Array, "Instance of Uint8Array"); ok(code1.length == code2.length, "Correct length"); verifyBuffers(code1, code2); continueToNextStep(); } function grabFileUsageAndContinueHandler(request) { - testGenerator.next(request.fileUsage); + testGenerator.next(request.result.fileUsage); } -function getUsage(usageHandler) +function getCurrentUsage(usageHandler) { let qms = SpecialPowers.Services.qms; let principal = SpecialPowers.wrap(document).nodePrincipal; let cb = SpecialPowers.wrapCallback(usageHandler); qms.getUsageForPrincipal(principal, cb); } function getFileId(file)
--- a/dom/indexedDB/test/test_file_os_delete.html +++ b/dom/indexedDB/test/test_file_os_delete.html @@ -13,17 +13,17 @@ function* testSteps() { const READ_WRITE = "readwrite"; const name = window.location.pathname; const objectStoreName = "Blobs"; - getUsage(grabFileUsageAndContinueHandler); + getCurrentUsage(grabFileUsageAndContinueHandler); let startUsage = yield undefined; const fileData1 = { key: 1, obj: { id: 1, file: getRandomFile("random.bin", 100000) } }; const fileData2 = { key: 2, @@ -56,46 +56,46 @@ request.addEventListener("error", new ExpectError("ConstraintError", true)); request.onsuccess = unexpectedSuccessHandler; yield undefined; event = yield undefined; is(event.type, "success", "Got correct event type"); - getUsage(grabFileUsageAndContinueHandler); + getCurrentUsage(grabFileUsageAndContinueHandler); let usage = yield undefined; is(usage, startUsage + fileData1.obj.file.size + fileData2.obj.file.size, "Correct file usage"); let trans = db.transaction([objectStoreName], READ_WRITE); trans.objectStore(objectStoreName).delete(fileData1.key); trans.oncomplete = grabEventAndContinueHandler; event = yield undefined; is(event.type, "complete", "Got correct event type"); - getUsage(grabFileUsageAndContinueHandler); + getCurrentUsage(grabFileUsageAndContinueHandler); usage = yield undefined; is(usage, startUsage + fileData1.obj.file.size + fileData2.obj.file.size, "OS files exists"); fileData1.obj.file = null; fileData2.obj.file = null; } scheduleGC(); yield undefined; // Flush pending file deletions before checking usage. flushPendingFileDeletions(); - getUsage(grabFileUsageAndContinueHandler); + getCurrentUsage(grabFileUsageAndContinueHandler); let endUsage = yield undefined; is(endUsage, startUsage, "OS files deleted"); finishTest(); } </script> <script type="text/javascript" src="file.js"></script>
--- a/dom/indexedDB/test/unit/test_idle_maintenance.js +++ b/dom/indexedDB/test/unit/test_idle_maintenance.js @@ -117,18 +117,19 @@ function* testSteps() } yield undefined; info("Getting usage before maintenance"); let usageBeforeMaintenance; quotaManagerService.getUsageForPrincipal(principal, (request) => { - ok(request.usage > 0, "Usage is non-zero"); - usageBeforeMaintenance = request.usage; + let usage = request.result.usage; + ok(usage > 0, "Usage is non-zero"); + usageBeforeMaintenance = usage; continueToNextStep(); }); yield undefined; info("Sending fake 'idle-daily' notification to QuotaManager"); let observer = quotaManagerService.QueryInterface(Ci.nsIObserver); observer.observe(null, "idle-daily", ""); @@ -150,18 +151,19 @@ function* testSteps() setTimeout(continueToNextStep, 10000); yield undefined; info("Getting usage after maintenance"); let usageAfterMaintenance; quotaManagerService.getUsageForPrincipal(principal, (request) => { - ok(request.usage > 0, "Usage is non-zero"); - usageAfterMaintenance = request.usage; + let usage = request.result.usage; + ok(usage > 0, "Usage is non-zero"); + usageAfterMaintenance = usage; continueToNextStep(); }); yield undefined; info("Usage before: " + usageBeforeMaintenance + ". " + "Usage after: " + usageAfterMaintenance); ok(usageAfterMaintenance <= usageBeforeMaintenance,
--- a/dom/indexedDB/test/unit/test_view_put_get_values.js +++ b/dom/indexedDB/test/unit/test_view_put_get_values.js @@ -75,17 +75,17 @@ function* testSteps() request = db.transaction([objectStoreName]) .objectStore(objectStoreName).get(viewData.key); request.onsuccess = continueToNextStepSync; yield undefined; verifyView(request.result, viewData.view); yield undefined; - getUsage(grabFileUsageAndContinueHandler); + getCurrentUsage(grabFileUsageAndContinueHandler); let fileUsage = yield undefined; if (external) { ok(fileUsage > 0, "File usage is not zero"); } else { ok(fileUsage == 0, "File usage is zero"); }
--- a/dom/indexedDB/test/unit/xpcshell-head-parent-process.js +++ b/dom/indexedDB/test/unit/xpcshell-head-parent-process.js @@ -511,20 +511,20 @@ function verifyWasmModule(module1, modul ok(code1 instanceof Uint8Array, "Instance of Uint8Array"); ok(code1.length == code2.length, "Correct length"); verifyBuffers(code1, code2); continueToNextStep(); } function grabFileUsageAndContinueHandler(request) { - testGenerator.next(request.fileUsage); + testGenerator.next(request.result.fileUsage); } -function getUsage(usageHandler) +function getCurrentUsage(usageHandler) { let qms = Cc["@mozilla.org/dom/quota-manager-service;1"] .getService(Ci.nsIQuotaManagerService); let principal = Cc["@mozilla.org/systemprincipal;1"] .createInstance(Ci.nsIPrincipal); qms.getUsageForPrincipal(principal, usageHandler); }
--- a/dom/ipc/TabParent.cpp +++ b/dom/ipc/TabParent.cpp @@ -53,27 +53,27 @@ #include "nsIDocShell.h" #include "nsIDocShellTreeOwner.h" #include "nsIDOMElement.h" #include "nsIDOMEvent.h" #include "nsIDOMWindow.h" #include "nsIDOMWindowUtils.h" #include "nsIInterfaceRequestorUtils.h" #include "nsILoadInfo.h" -#include "nsPrincipal.h" #include "nsIPromptFactory.h" #include "nsIURI.h" #include "nsIWindowWatcher.h" #include "nsIWebBrowserChrome.h" #include "nsIXULBrowserWindow.h" #include "nsIXULWindow.h" #include "nsIRemoteBrowser.h" #include "nsViewManager.h" #include "nsVariant.h" #include "nsIWidget.h" +#include "nsNetUtil.h" #ifndef XP_WIN #include "nsJARProtocolHandler.h" #endif #include "nsPIDOMWindow.h" #include "nsPrintfCString.h" #include "nsServiceManagerUtils.h" #include "nsThreadUtils.h" #include "PermissionMessageUtils.h"
--- a/dom/json/nsJSON.cpp +++ b/dom/json/nsJSON.cpp @@ -17,17 +17,17 @@ #include "nsIUnicodeDecoder.h" #include "nsNetUtil.h" #include "nsIURI.h" #include "nsComponentManagerUtils.h" #include "nsContentUtils.h" #include "nsIScriptError.h" #include "nsCRTGlue.h" #include "nsIScriptSecurityManager.h" -#include "nsNullPrincipal.h" +#include "NullPrincipal.h" #include "mozilla/Maybe.h" #include <algorithm> using mozilla::dom::EncodingUtils; #define JSON_STREAM_BUFSIZE 4096 NS_INTERFACE_MAP_BEGIN(nsJSON) @@ -402,17 +402,17 @@ nsJSON::DecodeInternal(JSContext* cx, nsCOMPtr<nsIChannel> jsonChannel; if (!mURI) { NS_NewURI(getter_AddRefs(mURI), NS_LITERAL_CSTRING("about:blank"), 0, 0 ); if (!mURI) return NS_ERROR_OUT_OF_MEMORY; } nsresult rv; - nsCOMPtr<nsIPrincipal> nullPrincipal = nsNullPrincipal::Create(); + nsCOMPtr<nsIPrincipal> nullPrincipal = NullPrincipal::Create(); // The ::Decode function is deprecated [Bug 675797] and the following // channel is never openend, so it does not matter what securityFlags // we pass to NS_NewInputStreamChannel here. rv = NS_NewInputStreamChannel(getter_AddRefs(jsonChannel), mURI, aStream, nullPrincipal,
--- a/dom/jsurl/nsJSProtocolHandler.cpp +++ b/dom/jsurl/nsJSProtocolHandler.cpp @@ -264,20 +264,24 @@ nsresult nsJSThunk::EvaluateScript(nsICh return NS_ERROR_DOM_SECURITY_ERR; } JS::Rooted<JS::Value> v (cx, JS::UndefinedValue()); // Finally, we have everything needed to evaluate the expression. JS::CompileOptions options(cx); options.setFileAndLine(mURL.get(), 1) .setVersion(JSVERSION_DEFAULT); - nsJSUtils::EvaluateOptions evalOptions(cx); - evalOptions.setCoerceToString(true); - rv = nsJSUtils::EvaluateString(cx, NS_ConvertUTF8toUTF16(script), - globalJSObject, options, evalOptions, &v); + { + nsJSUtils::ExecutionContext exec(cx, globalJSObject); + exec.SetCoerceToString(true); + exec.CompileAndExec(options, NS_ConvertUTF8toUTF16(script)); + rv = exec.ExtractReturnValue(&v); + } + + js::AssertSameCompartment(cx, v); if (NS_FAILED(rv) || !(v.isString() || v.isUndefined())) { return NS_ERROR_MALFORMED_URI; } else if (v.isUndefined()) { return NS_ERROR_DOM_RETVAL_UNDEFINED; } else { MOZ_ASSERT(rv != NS_SUCCESS_DOM_SCRIPT_EVALUATION_THREW, "How did we get a non-undefined return value?");
--- a/dom/media/MediaManager.cpp +++ b/dom/media/MediaManager.cpp @@ -23,17 +23,16 @@ #include "nsIPopupWindowManager.h" #include "nsIDocShell.h" #include "nsIDocument.h" #include "nsISupportsPrimitives.h" #include "nsIInterfaceRequestorUtils.h" #include "nsIIDNService.h" #include "nsNetCID.h" #include "nsNetUtil.h" -#include "nsPrincipal.h" #include "nsICryptoHash.h" #include "nsICryptoHMAC.h" #include "nsIKeyModule.h" #include "nsAppDirectoryServiceDefs.h" #include "nsIInputStream.h" #include "nsILineInputStream.h" #include "mozilla/Telemetry.h" #include "mozilla/Types.h" @@ -49,17 +48,17 @@ #include "mozilla/Base64.h" #include "mozilla/ipc/BackgroundChild.h" #include "mozilla/media/MediaChild.h" #include "mozilla/media/MediaTaskUtils.h" #include "MediaTrackConstraints.h" #include "VideoUtils.h" #include "Latency.h" #include "nsProxyRelease.h" -#include "nsNullPrincipal.h" +#include "NullPrincipal.h" #include "nsVariant.h" // For snprintf #include "mozilla/Sprintf.h" #include "nsJSUtils.h" #include "nsGlobalWindow.h" #include "nsIUUIDGenerator.h" @@ -1150,17 +1149,17 @@ public: RefPtr<GetUserMediaCallbackMediaStreamListener> mListener; const MediaSourceEnum mSource; const TrackID mTrackID; const RefPtr<const PeerIdentity> mPeerIdentity; }; nsCOMPtr<nsIPrincipal> principal; if (mPeerIdentity) { - principal = nsNullPrincipal::CreateWithInheritedAttributes(window->GetExtantDoc()->NodePrincipal()); + principal = NullPrincipal::CreateWithInheritedAttributes(window->GetExtantDoc()->NodePrincipal()); } else { principal = window->GetExtantDoc()->NodePrincipal(); } // Normal case, connect the source stream to the track union stream to // avoid us blocking. Pass a simple TrackSourceGetter for potential // fake tracks. Apart from them gUM never adds tracks dynamically. domStream =
--- a/dom/media/MediaStreamTrack.h +++ b/dom/media/MediaStreamTrack.h @@ -92,17 +92,17 @@ public: * PrincipalChanged(). */ virtual CORSMode GetCORSMode() const { return CORS_NONE; } /** * This is used in WebRTC. A peerIdentity constrained MediaStreamTrack cannot * be sent across the network to anything other than a peer with the provided * identity. If this is set, then GetPrincipal() should return an instance of - * nsNullPrincipal. + * NullPrincipal. * * A track's PeerIdentity is immutable and will not change during the track's * lifetime. */ virtual const PeerIdentity* GetPeerIdentity() const { return nullptr; } /** * MediaStreamTrack::GetLabel (see spec) calls through to here.
--- a/dom/media/mediasink/DecodedAudioDataSink.cpp +++ b/dom/media/mediasink/DecodedAudioDataSink.cpp @@ -255,37 +255,16 @@ DecodedAudioDataSink::PopFrames(uint32_t uint32_t Rate() const { return mBuffer ? mBuffer->mRate : 0; } AudioDataValue* GetWritable() const { return mData; } private: const RefPtr<AudioData> mBuffer; const uint32_t mFrames; AudioDataValue* const mData; }; - class SilentChunk : public AudioStream::Chunk { - public: - SilentChunk(uint32_t aFrames, uint32_t aChannels, uint32_t aRate) - : mFrames(aFrames) - , mChannels(aChannels) - , mRate(aRate) - , mData(MakeUnique<AudioDataValue[]>(aChannels * aFrames)) { - memset(mData.get(), 0, aChannels * aFrames * sizeof(AudioDataValue)); - } - const AudioDataValue* Data() const { return mData.get(); } - uint32_t Frames() const { return mFrames; } - uint32_t Channels() const { return mChannels; } - uint32_t Rate() const { return mRate; } - AudioDataValue* GetWritable() const { return mData.get(); } - private: - const uint32_t mFrames; - const uint32_t mChannels; - const uint32_t mRate; - UniquePtr<AudioDataValue[]> mData; - }; - bool needPopping = false; if (!mCurrentData) { // No data in the queue. Return an empty chunk. if (!mProcessedQueue.GetSize()) { return MakeUnique<Chunk>(); } // We need to update our values prior popping the processed queue in
--- a/dom/plugins/base/nsNPAPIPlugin.cpp +++ b/dom/plugins/base/nsNPAPIPlugin.cpp @@ -1363,24 +1363,33 @@ bool NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY, ("NPN_Evaluate(npp %p, npobj %p, script <<<%s>>>) called\n", npp, npobj, script->UTF8Characters)); JS::CompileOptions options(cx); options.setFileAndLine(spec, 0) .setVersion(JSVERSION_DEFAULT); JS::Rooted<JS::Value> rval(cx); - nsJSUtils::EvaluateOptions evalOptions(cx); + JS::AutoObjectVector scopeChain(cx); if (obj != js::GetGlobalForObjectCrossCompartment(obj) && - !evalOptions.scopeChain.append(obj)) { + !scopeChain.append(obj)) { return false; } obj = js::GetGlobalForObjectCrossCompartment(obj); - nsresult rv = nsJSUtils::EvaluateString(cx, utf16script, obj, options, - evalOptions, &rval); + nsresult rv = NS_OK; + { + nsJSUtils::ExecutionContext exec(cx, obj); + exec.SetScopeChain(scopeChain); + exec.CompileAndExec(options, utf16script); + rv = exec.ExtractReturnValue(&rval); + } + + if (!JS_WrapValue(cx, &rval)) { + return false; + } return NS_SUCCEEDED(rv) && (!result || JSValToNPVariant(npp, cx, rval, result)); } bool _getproperty(NPP npp, NPObject* npobj, NPIdentifier property, NPVariant *result)
--- a/dom/plugins/base/nsPluginHost.cpp +++ b/dom/plugins/base/nsPluginHost.cpp @@ -89,17 +89,17 @@ #include "nsPluginNativeWindow.h" #include "nsIContentPolicy.h" #include "nsContentPolicyUtils.h" #include "mozilla/TimeStamp.h" #include "mozilla/Telemetry.h" #include "nsIImageLoadingContent.h" #include "mozilla/Preferences.h" #include "nsVersionComparator.h" -#include "nsNullPrincipal.h" +#include "NullPrincipal.h" #if defined(XP_WIN) #include "nsIWindowMediator.h" #include "nsIBaseWindow.h" #include "windows.h" #include "winbase.h" #endif
--- a/dom/plugins/base/nsPluginStreamListenerPeer.cpp +++ b/dom/plugins/base/nsPluginStreamListenerPeer.cpp @@ -28,17 +28,17 @@ #include "nsIDocument.h" #include "nsIWebNavigation.h" #include "nsContentUtils.h" #include "nsNetUtil.h" #include "nsPluginNativeWindow.h" #include "GeckoProfiler.h" #include "nsPluginInstanceOwner.h" #include "nsDataHashtable.h" -#include "nsNullPrincipal.h" +#include "NullPrincipal.h" #define BYTERANGE_REQUEST_CONTEXT 0x01020304 // nsPluginByteRangeStreamListener class nsPluginByteRangeStreamListener : public nsIStreamListener , public nsIInterfaceRequestor
--- a/dom/quota/ActorsChild.cpp +++ b/dom/quota/ActorsChild.cpp @@ -4,16 +4,17 @@ * 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 "ActorsChild.h" #include "nsVariant.h" #include "QuotaManagerService.h" #include "QuotaRequests.h" +#include "QuotaResults.h" namespace mozilla { namespace dom { namespace quota { /******************************************************************************* * QuotaChild ******************************************************************************/ @@ -136,24 +137,66 @@ QuotaUsageRequestChild::HandleResponse(n AssertIsOnOwningThread(); MOZ_ASSERT(NS_FAILED(aResponse)); MOZ_ASSERT(mRequest); mRequest->SetError(aResponse); } void -QuotaUsageRequestChild::HandleResponse(const UsageResponse& aResponse) +QuotaUsageRequestChild::HandleResponse(const nsTArray<OriginUsage>& aResponse) { AssertIsOnOwningThread(); MOZ_ASSERT(mRequest); - mRequest->SetResult(aResponse.usage(), - aResponse.fileUsage(), - aResponse.limit()); + RefPtr<nsVariant> variant = new nsVariant(); + + if (aResponse.IsEmpty()) { + variant->SetAsEmptyArray(); + } else { + nsTArray<RefPtr<UsageResult>> usageResults; + + const uint32_t count = aResponse.Length(); + + usageResults.SetCapacity(count); + + for (uint32_t index = 0; index < count; index++) { + auto& originUsage = aResponse[index]; + + RefPtr<UsageResult> usageResult = new UsageResult(originUsage.origin(), + originUsage.persisted(), + originUsage.usage()); + + usageResults.AppendElement(usageResult.forget()); + } + + variant->SetAsArray(nsIDataType::VTYPE_INTERFACE_IS, + &NS_GET_IID(nsIQuotaUsageResult), + usageResults.Length(), + static_cast<void*>(usageResults.Elements())); + } + + mRequest->SetResult(variant); +} + +void +QuotaUsageRequestChild::HandleResponse(const OriginUsageResponse& aResponse) +{ + AssertIsOnOwningThread(); + MOZ_ASSERT(mRequest); + + RefPtr<OriginUsageResult> result = + new OriginUsageResult(aResponse.usage(), + aResponse.fileUsage(), + aResponse.limit()); + + RefPtr<nsVariant> variant = new nsVariant(); + variant->SetAsInterface(NS_GET_IID(nsIQuotaOriginUsageResult), result); + + mRequest->SetResult(variant); } void QuotaUsageRequestChild::ActorDestroy(ActorDestroyReason aWhy) { AssertIsOnOwningThread(); if (mRequest) { @@ -170,18 +213,22 @@ QuotaUsageRequestChild::Recv__delete__(c AssertIsOnOwningThread(); MOZ_ASSERT(mRequest); switch (aResponse.type()) { case UsageRequestResponse::Tnsresult: HandleResponse(aResponse.get_nsresult()); break; - case UsageRequestResponse::TUsageResponse: - HandleResponse(aResponse.get_UsageResponse()); + case UsageRequestResponse::TAllUsageResponse: + HandleResponse(aResponse.get_AllUsageResponse().originUsages()); + break; + + case UsageRequestResponse::TOriginUsageResponse: + HandleResponse(aResponse.get_OriginUsageResponse()); break; default: MOZ_CRASH("Unknown response type!"); } return IPC_OK(); }
--- a/dom/quota/ActorsChild.h +++ b/dom/quota/ActorsChild.h @@ -93,17 +93,20 @@ private: // Only destroyed by QuotaChild. ~QuotaUsageRequestChild(); void HandleResponse(nsresult aResponse); void - HandleResponse(const UsageResponse& aResponse); + HandleResponse(const nsTArray<OriginUsage>& aResponse); + + void + HandleResponse(const OriginUsageResponse& aResponse); // IPDL methods are only called by IPDL. virtual void ActorDestroy(ActorDestroyReason aWhy) override; virtual mozilla::ipc::IPCResult Recv__delete__(const UsageRequestResponse& aResponse) override; };
--- a/dom/quota/ActorsParent.cpp +++ b/dom/quota/ActorsParent.cpp @@ -910,16 +910,17 @@ class NormalOriginOperationBase : public OriginOperationBase , public OpenDirectoryListener { RefPtr<DirectoryLock> mDirectoryLock; protected: Nullable<PersistenceType> mPersistenceType; OriginScope mOriginScope; + mozilla::Atomic<bool> mCanceled; const bool mExclusive; public: void RunImmediately() { MOZ_ASSERT(GetState() == State_Initial); @@ -1037,59 +1038,113 @@ private: virtual mozilla::ipc::IPCResult RecvStartIdleMaintenance() override; virtual mozilla::ipc::IPCResult RecvStopIdleMaintenance() override; }; -class GetUsageOp final +class QuotaUsageRequestBase : public NormalOriginOperationBase , public PQuotaUsageRequestParent { +public: + // May be overridden by subclasses if they need to perform work on the + // background thread before being run. + virtual bool + Init(Quota* aQuota); + +protected: + QuotaUsageRequestBase() + : NormalOriginOperationBase(Nullable<PersistenceType>(), + OriginScope::FromNull(), + /* aExclusive */ false) + { } + + nsresult + GetUsageForOrigin(QuotaManager* aQuotaManager, + PersistenceType aPersistenceType, + const nsACString& aGroup, + const nsACString& aOrigin, + UsageInfo* aUsageInfo); + + // Subclasses use this override to set the IPDL response value. + virtual void + GetResponse(UsageRequestResponse& aResponse) = 0; + +private: + void + SendResults() override; + + // IPDL methods. + void + ActorDestroy(ActorDestroyReason aWhy) override; + + mozilla::ipc::IPCResult + RecvCancel() override; +}; + +class GetUsageOp final + : public QuotaUsageRequestBase +{ + nsTArray<OriginUsage> mOriginUsages; + nsDataHashtable<nsCStringHashKey, uint32_t> mOriginUsagesIndex; + + bool mGetAll; + +public: + explicit GetUsageOp(const UsageRequestParams& aParams); + +private: + ~GetUsageOp() + { } + + nsresult + TraverseRepository(QuotaManager* aQuotaManager, + PersistenceType aPersistenceType); + + nsresult + DoDirectoryWork(QuotaManager* aQuotaManager) override; + + void + GetResponse(UsageRequestResponse& aResponse) override; +}; + +class GetOriginUsageOp final + : public QuotaUsageRequestBase +{ // If mGetGroupUsage is false, we use mUsageInfo to record the origin usage // and the file usage. Otherwise, we use it to record the group usage and the // limit. UsageInfo mUsageInfo; - const UsageParams mParams; + const OriginUsageParams mParams; nsCString mSuffix; nsCString mGroup; bool mGetGroupUsage; public: - explicit GetUsageOp(const UsageRequestParams& aParams); + explicit GetOriginUsageOp(const UsageRequestParams& aParams); MOZ_IS_CLASS_INIT bool - Init(Quota* aQuota); + Init(Quota* aQuota) override; private: - ~GetUsageOp() + ~GetOriginUsageOp() { } MOZ_IS_CLASS_INIT virtual nsresult DoInitOnMainThread() override; - nsresult - AddToUsage(QuotaManager* aQuotaManager, - PersistenceType aPersistenceType); - virtual nsresult DoDirectoryWork(QuotaManager* aQuotaManager) override; - virtual void - SendResults() override; - - // IPDL methods. - virtual void - ActorDestroy(ActorDestroyReason aWhy) override; - - virtual mozilla::ipc::IPCResult - RecvCancel() override; + void + GetResponse(UsageRequestResponse& aResponse) override; }; class QuotaRequestBase : public NormalOriginOperationBase , public PQuotaRequestParent { public: // May be overridden by subclasses if they need to perform work on the @@ -4191,17 +4246,21 @@ QuotaManager::InitializeOrigin(Persisten Client::Type clientType; rv = Client::TypeFromText(leafName, clientType); if (NS_FAILED(rv)) { UNKNOWN_FILE_WARNING(leafName); return NS_ERROR_UNEXPECTED; } - rv = mClients[clientType]->InitOrigin(aPersistenceType, aGroup, aOrigin, + Atomic<bool> dummy(false); + rv = mClients[clientType]->InitOrigin(aPersistenceType, + aGroup, + aOrigin, + /* aCanceled */ dummy, usageInfo); NS_ENSURE_SUCCESS(rv, rv); } if (trackQuota) { InitQuotaForOrigin(aPersistenceType, aGroup, aOrigin, usageInfo->TotalUsage(), aAccessTime, aPersisted); } @@ -5291,20 +5350,19 @@ QuotaManager::GetInfoForChrome(nsACStrin } if (aOrigin) { ChromeOrigin(*aOrigin); } } // static bool -QuotaManager::IsOriginWhitelistedForPersistentStorage(const nsACString& aOrigin) -{ - // The first prompt and quota tracking is not required for these origins in - // persistent storage. +QuotaManager::IsOriginInternal(const nsACString& aOrigin) +{ + // The first prompt is not required for these origins. if (aOrigin.EqualsLiteral(kChromeOrigin) || StringBeginsWith(aOrigin, nsDependentCString(kAboutHomeOriginPrefix)) || StringBeginsWith(aOrigin, nsDependentCString(kIndexedDBOriginPrefix)) || StringBeginsWith(aOrigin, nsDependentCString(kResourceOriginPrefix))) { return true; } return false; @@ -6225,49 +6283,67 @@ Quota::ActorDestroy(ActorDestroyReason a MOZ_ASSERT(!mActorDestroyed); mActorDestroyed = true; #endif } PQuotaUsageRequestParent* Quota::AllocPQuotaUsageRequestParent(const UsageRequestParams& aParams) { - RefPtr<GetUsageOp> actor = new GetUsageOp(aParams); + AssertIsOnBackgroundThread(); + MOZ_ASSERT(aParams.type() != UsageRequestParams::T__None); + + RefPtr<QuotaUsageRequestBase> actor; + + switch (aParams.type()) { + case UsageRequestParams::TAllUsageParams: + actor = new GetUsageOp(aParams); + break; + + case UsageRequestParams::TOriginUsageParams: + actor = new GetOriginUsageOp(aParams); + break; + + default: + MOZ_CRASH("Should never get here!"); + } + + MOZ_ASSERT(actor); // Transfer ownership to IPDL. return actor.forget().take(); } mozilla::ipc::IPCResult Quota::RecvPQuotaUsageRequestConstructor(PQuotaUsageRequestParent* aActor, const UsageRequestParams& aParams) { AssertIsOnBackgroundThread(); MOZ_ASSERT(aActor); MOZ_ASSERT(aParams.type() != UsageRequestParams::T__None); - auto* op = static_cast<GetUsageOp*>(aActor); + auto* op = static_cast<QuotaUsageRequestBase*>(aActor); if (NS_WARN_IF(!op->Init(this))) { return IPC_FAIL_NO_REASON(this); } op->RunImmediately(); return IPC_OK(); } bool Quota::DeallocPQuotaUsageRequestParent(PQuotaUsageRequestParent* aActor) { AssertIsOnBackgroundThread(); MOZ_ASSERT(aActor); // Transfer ownership back from IPDL. - RefPtr<GetUsageOp> actor = - dont_AddRef(static_cast<GetUsageOp*>(aActor)); + RefPtr<QuotaUsageRequestBase> actor = + dont_AddRef(static_cast<QuotaUsageRequestBase*>(aActor)); return true; } PQuotaRequestParent* Quota::AllocPQuotaRequestParent(const RequestParams& aParams) { AssertIsOnBackgroundThread(); MOZ_ASSERT(aParams.type() != RequestParams::T__None); @@ -6331,16 +6407,17 @@ mozilla::ipc::IPCResult Quota::RecvPQuotaRequestConstructor(PQuotaRequestParent* aActor, const RequestParams& aParams) { AssertIsOnBackgroundThread(); MOZ_ASSERT(aActor); MOZ_ASSERT(aParams.type() != RequestParams::T__None); auto* op = static_cast<QuotaRequestBase*>(aActor); + if (NS_WARN_IF(!op->Init(this))) { return IPC_FAIL_NO_REASON(this); } op->RunImmediately(); return IPC_OK(); } @@ -6409,103 +6486,67 @@ Quota::RecvStopIdleMaintenance() return IPC_OK(); } quotaManager->StopIdleMaintenance(); return IPC_OK(); } -GetUsageOp::GetUsageOp(const UsageRequestParams& aParams) - : NormalOriginOperationBase(Nullable<PersistenceType>(), - OriginScope::FromNull(), - /* aExclusive */ false) - , mParams(aParams.get_UsageParams()) - , mGetGroupUsage(aParams.get_UsageParams().getGroupUsage()) -{ - AssertIsOnOwningThread(); - MOZ_ASSERT(aParams.type() == UsageRequestParams::TUsageParams); -} - bool -GetUsageOp::Init(Quota* aQuota) +QuotaUsageRequestBase::Init(Quota* aQuota) { AssertIsOnOwningThread(); MOZ_ASSERT(aQuota); - mNeedsMainThreadInit = true; mNeedsQuotaManagerInit = true; return true; } nsresult -GetUsageOp::DoInitOnMainThread() -{ - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(GetState() == State_Initializing); - MOZ_ASSERT(mNeedsMainThreadInit); - - const PrincipalInfo& principalInfo = mParams.principalInfo(); - - nsresult rv; - nsCOMPtr<nsIPrincipal> principal = - PrincipalInfoToPrincipal(principalInfo, &rv); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - // Figure out which origin we're dealing with. - nsCString origin; - rv = QuotaManager::GetInfoFromPrincipal(principal, &mSuffix, &mGroup, - &origin); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - mOriginScope.SetFromOrigin(origin); - - return NS_OK; -} - -nsresult -GetUsageOp::AddToUsage(QuotaManager* aQuotaManager, - PersistenceType aPersistenceType) +QuotaUsageRequestBase::GetUsageForOrigin(QuotaManager* aQuotaManager, + PersistenceType aPersistenceType, + const nsACString& aGroup, + const nsACString& aOrigin, + UsageInfo* aUsageInfo) { AssertIsOnIOThread(); + MOZ_ASSERT(aQuotaManager); + MOZ_ASSERT(aUsageInfo); + MOZ_ASSERT(aUsageInfo->TotalUsage() == 0); nsCOMPtr<nsIFile> directory; nsresult rv = aQuotaManager->GetDirectoryForOrigin(aPersistenceType, - mOriginScope.GetOrigin(), + aOrigin, 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 && !mUsageInfo.Canceled()) { + if (exists && !mCanceled) { bool initialized; if (aPersistenceType == PERSISTENCE_TYPE_PERSISTENT) { - initialized = - aQuotaManager->IsOriginInitialized(mOriginScope.GetOrigin()); + initialized = aQuotaManager->IsOriginInitialized(aOrigin); } else { initialized = aQuotaManager->IsTemporaryStorageInitialized(); } nsCOMPtr<nsISimpleEnumerator> entries; rv = directory->GetDirectoryEntries(getter_AddRefs(entries)); NS_ENSURE_SUCCESS(rv, rv); bool hasMore; while (NS_SUCCEEDED((rv = entries->HasMoreElements(&hasMore))) && - hasMore && !mUsageInfo.Canceled()) { + hasMore && !mCanceled) { nsCOMPtr<nsISupports> entry; rv = entries->GetNext(getter_AddRefs(entry)); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIFile> file = do_QueryInterface(entry); NS_ENSURE_TRUE(file, NS_NOINTERFACE); bool isDirectory; @@ -6557,44 +6598,319 @@ GetUsageOp::AddToUsage(QuotaManager* aQu continue; } Client* client = aQuotaManager->GetClient(clientType); MOZ_ASSERT(client); if (initialized) { rv = client->GetUsageForOrigin(aPersistenceType, - mGroup, - mOriginScope.GetOrigin(), - &mUsageInfo); + aGroup, + aOrigin, + mCanceled, + aUsageInfo); } else { rv = client->InitOrigin(aPersistenceType, - mGroup, - mOriginScope.GetOrigin(), - &mUsageInfo); + aGroup, + aOrigin, + mCanceled, + aUsageInfo); } NS_ENSURE_SUCCESS(rv, rv); } } return NS_OK; } +void +QuotaUsageRequestBase::SendResults() +{ + AssertIsOnOwningThread(); + + if (IsActorDestroyed()) { + if (NS_SUCCEEDED(mResultCode)) { + mResultCode = NS_ERROR_FAILURE; + } + } else { + if (mCanceled) { + mResultCode = NS_ERROR_FAILURE; + } + + UsageRequestResponse response; + + if (NS_SUCCEEDED(mResultCode)) { + GetResponse(response); + } else { + response = mResultCode; + } + + Unused << PQuotaUsageRequestParent::Send__delete__(this, response); + } +} + +void +QuotaUsageRequestBase::ActorDestroy(ActorDestroyReason aWhy) +{ + AssertIsOnOwningThread(); + + NoteActorDestroyed(); +} + +mozilla::ipc::IPCResult +QuotaUsageRequestBase::RecvCancel() +{ + AssertIsOnOwningThread(); + + if (mCanceled.exchange(true)) { + NS_WARNING("Canceled more than once?!"); + return IPC_FAIL_NO_REASON(this); + } + + return IPC_OK(); +} + +GetUsageOp::GetUsageOp(const UsageRequestParams& aParams) + : mGetAll(aParams.get_AllUsageParams().getAll()) +{ + AssertIsOnOwningThread(); + MOZ_ASSERT(aParams.type() == UsageRequestParams::TAllUsageParams); +} + +nsresult +GetUsageOp::TraverseRepository(QuotaManager* aQuotaManager, + PersistenceType aPersistenceType) +{ + AssertIsOnIOThread(); + MOZ_ASSERT(aQuotaManager); + + nsresult rv; + + nsCOMPtr<nsIFile> directory = + do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + rv = directory->InitWithPath(aQuotaManager->GetStoragePath(aPersistenceType)); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + bool exists; + rv = directory->Exists(&exists); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + if (!exists) { + return NS_OK; + } + + nsCOMPtr<nsISimpleEnumerator> entries; + rv = directory->GetDirectoryEntries(getter_AddRefs(entries)); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + bool persistent = aPersistenceType == PERSISTENCE_TYPE_PERSISTENT; + + bool hasMore; + while (NS_SUCCEEDED((rv = entries->HasMoreElements(&hasMore))) && + hasMore && !mCanceled) { + nsCOMPtr<nsISupports> entry; + rv = entries->GetNext(getter_AddRefs(entry)); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + nsCOMPtr<nsIFile> originDir = do_QueryInterface(entry); + MOZ_ASSERT(originDir); + + bool isDirectory; + rv = originDir->IsDirectory(&isDirectory); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + if (!isDirectory) { + nsString leafName; + rv = originDir->GetLeafName(leafName); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + if (!IsOSMetadata(leafName)) { + UNKNOWN_FILE_WARNING(leafName); + } + continue; + } + + int64_t timestamp; + bool persisted; + nsCString suffix; + nsCString group; + nsCString origin; + rv = aQuotaManager->GetDirectoryMetadata2WithRestore(originDir, + persistent, + ×tamp, + &persisted, + suffix, + group, + origin); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + if (!mGetAll && aQuotaManager->IsOriginInternal(origin)) { + continue; + } + + OriginUsage* originUsage; + + // We can't store pointers to OriginUsage objects in the hashtable + // since AppendElement() reallocates its internal array buffer as number + // of elements grows. + uint32_t index; + if (mOriginUsagesIndex.Get(origin, &index)) { + originUsage = &mOriginUsages[index]; + } else { + index = mOriginUsages.Length(); + + originUsage = mOriginUsages.AppendElement(); + + originUsage->origin() = origin; + originUsage->persisted() = false; + originUsage->usage() = 0; + + mOriginUsagesIndex.Put(origin, index); + } + + if (aPersistenceType == PERSISTENCE_TYPE_DEFAULT) { + originUsage->persisted() = persisted; + } + + UsageInfo usageInfo; + rv = GetUsageForOrigin(aQuotaManager, + aPersistenceType, + group, + origin, + &usageInfo); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + originUsage->usage() = originUsage->usage() + usageInfo.TotalUsage(); + } + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + return NS_OK; +} + nsresult GetUsageOp::DoDirectoryWork(QuotaManager* aQuotaManager) { AssertIsOnIOThread(); - MOZ_ASSERT(mUsageInfo.TotalUsage() == 0); PROFILER_LABEL("Quota", "GetUsageOp::DoDirectoryWork", js::ProfileEntry::Category::OTHER); nsresult rv; + for (const PersistenceType type : kAllPersistenceTypes) { + rv = TraverseRepository(aQuotaManager, type); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + } + + return NS_OK; +} + +void +GetUsageOp::GetResponse(UsageRequestResponse& aResponse) +{ + AssertIsOnOwningThread(); + + aResponse = AllUsageResponse(); + + if (!mOriginUsages.IsEmpty()) { + nsTArray<OriginUsage>& originUsages = + aResponse.get_AllUsageResponse().originUsages(); + + mOriginUsages.SwapElements(originUsages); + } +} + +GetOriginUsageOp::GetOriginUsageOp(const UsageRequestParams& aParams) + : mParams(aParams.get_OriginUsageParams()) + , mGetGroupUsage(aParams.get_OriginUsageParams().getGroupUsage()) +{ + AssertIsOnOwningThread(); + MOZ_ASSERT(aParams.type() == UsageRequestParams::TOriginUsageParams); +} + +bool +GetOriginUsageOp::Init(Quota* aQuota) +{ + AssertIsOnOwningThread(); + MOZ_ASSERT(aQuota); + + if (NS_WARN_IF(!QuotaUsageRequestBase::Init(aQuota))) { + return false; + } + + mNeedsMainThreadInit = true; + + return true; +} + +nsresult +GetOriginUsageOp::DoInitOnMainThread() +{ + MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(GetState() == State_Initializing); + MOZ_ASSERT(mNeedsMainThreadInit); + + const PrincipalInfo& principalInfo = mParams.principalInfo(); + + nsresult rv; + nsCOMPtr<nsIPrincipal> principal = + PrincipalInfoToPrincipal(principalInfo, &rv); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + // Figure out which origin we're dealing with. + nsCString origin; + rv = QuotaManager::GetInfoFromPrincipal(principal, &mSuffix, &mGroup, + &origin); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + mOriginScope.SetFromOrigin(origin); + + return NS_OK; +} + +nsresult +GetOriginUsageOp::DoDirectoryWork(QuotaManager* aQuotaManager) +{ + AssertIsOnIOThread(); + MOZ_ASSERT(mUsageInfo.TotalUsage() == 0); + + PROFILER_LABEL("Quota", "GetOriginUsageOp::DoDirectoryWork", + js::ProfileEntry::Category::OTHER); + + nsresult rv; + if (mGetGroupUsage) { nsCOMPtr<nsIFile> directory; // Ensure origin is initialized first. It will initialize all origins for // temporary storage including origins belonging to our group. rv = aQuotaManager->EnsureOriginIsInitialized(PERSISTENCE_TYPE_TEMPORARY, mSuffix, mGroup, mOriginScope.GetOrigin(), @@ -6606,82 +6922,50 @@ GetUsageOp::DoDirectoryWork(QuotaManager // Get cached usage and limit (the method doesn't have to stat any files). aQuotaManager->GetGroupUsageAndLimit(mGroup, &mUsageInfo); return NS_OK; } // Add all the persistent/temporary/default storage files we care about. for (const PersistenceType type : kAllPersistenceTypes) { - rv = AddToUsage(aQuotaManager, type); + UsageInfo usageInfo; + rv = GetUsageForOrigin(aQuotaManager, + type, + mGroup, + mOriginScope.GetOrigin(), + &usageInfo); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } + + mUsageInfo.Append(usageInfo); } return NS_OK; } void -GetUsageOp::SendResults() +GetOriginUsageOp::GetResponse(UsageRequestResponse& aResponse) { AssertIsOnOwningThread(); - if (IsActorDestroyed()) { - if (NS_SUCCEEDED(mResultCode)) { - mResultCode = NS_ERROR_FAILURE; - } + OriginUsageResponse usageResponse; + + // We'll get the group usage when mGetGroupUsage is true and get the + // origin usage when mGetGroupUsage is false. + usageResponse.usage() = mUsageInfo.TotalUsage(); + + if (mGetGroupUsage) { + usageResponse.limit() = mUsageInfo.Limit(); } else { - if (mUsageInfo.Canceled()) { - mResultCode = NS_ERROR_FAILURE; - } - - UsageRequestResponse response; - - if (NS_SUCCEEDED(mResultCode)) { - UsageResponse usageResponse; - - // We'll get the group usage when mGetGroupUsage is true and get the - // origin usage when mGetGroupUsage is false. - usageResponse.usage() = mUsageInfo.TotalUsage(); - - if (mGetGroupUsage) { - usageResponse.limit() = mUsageInfo.Limit(); - } else { - usageResponse.fileUsage() = mUsageInfo.FileUsage(); - } - - response = usageResponse; - } else { - response = mResultCode; - } - - Unused << PQuotaUsageRequestParent::Send__delete__(this, response); - } -} - -void -GetUsageOp::ActorDestroy(ActorDestroyReason aWhy) -{ - AssertIsOnOwningThread(); - - NoteActorDestroyed(); -} - -mozilla::ipc::IPCResult -GetUsageOp::RecvCancel() -{ - AssertIsOnOwningThread(); - - nsresult rv = mUsageInfo.Cancel(); - if (NS_WARN_IF(NS_FAILED(rv))) { - return IPC_FAIL_NO_REASON(this); - } - - return IPC_OK(); + usageResponse.fileUsage() = mUsageInfo.FileUsage(); + } + + aResponse = usageResponse; } bool QuotaRequestBase::Init(Quota* aQuota) { AssertIsOnOwningThread(); MOZ_ASSERT(aQuota); @@ -8180,19 +8464,17 @@ CreateOrUpgradeDirectoryMetadataHelper:: if (NS_FAILED(rv)) { originProps.mTimestamp = GetLastModifiedTime(originDir, mPersistent); originProps.mNeedsRestore = true; } else if (!isApp.IsNull()) { originProps.mIgnore = true; } } else { - bool persistent = - QuotaManager::IsOriginWhitelistedForPersistentStorage( - originProps.mSpec); + bool persistent = QuotaManager::IsOriginInternal(originProps.mSpec); originProps.mTimestamp = GetLastModifiedTime(originDir, persistent); } mOriginProps.AppendElement(Move(originProps)); } if (mOriginProps.IsEmpty()) { return NS_OK; @@ -8326,19 +8608,18 @@ CreateOrUpgradeDirectoryMetadataHelper:: aOriginProps.mTimestamp, aOriginProps.mSuffix, aOriginProps.mGroup, aOriginProps.mOrigin); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } - // Move whitelisted origins to new persistent storage. - if (QuotaManager::IsOriginWhitelistedForPersistentStorage( - aOriginProps.mSpec)) { + // Move internal origins to new persistent storage. + if (QuotaManager::IsOriginInternal(aOriginProps.mSpec)) { if (!mPermanentStorageDir) { mPermanentStorageDir = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } QuotaManager* quotaManager = QuotaManager::Get();
--- a/dom/quota/Client.h +++ b/dom/quota/Client.h @@ -26,16 +26,18 @@ class QuotaManager; class UsageInfo; // 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: + typedef mozilla::Atomic<bool> AtomicBool; + NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING enum Type { IDB = 0, //LS, //APPCACHE, ASMJS, DOMCACHE, @@ -95,22 +97,24 @@ public: { return NS_OK; } virtual nsresult InitOrigin(PersistenceType aPersistenceType, const nsACString& aGroup, const nsACString& aOrigin, + const AtomicBool& aCanceled, UsageInfo* aUsageInfo) = 0; virtual nsresult GetUsageForOrigin(PersistenceType aPersistenceType, const nsACString& aGroup, const nsACString& aOrigin, + const AtomicBool& aCanceled, UsageInfo* aUsageInfo) = 0; virtual void OnOriginClearCompleted(PersistenceType aPersistenceType, const nsACString& aOrigin) = 0; virtual void ReleaseIOThreadObjects() = 0;
--- a/dom/quota/PQuota.ipdl +++ b/dom/quota/PQuota.ipdl @@ -22,25 +22,31 @@ struct InitParams }; struct InitOriginParams { PrincipalInfo principalInfo; PersistenceType persistenceType; }; -struct UsageParams +struct AllUsageParams +{ + bool getAll; +}; + +struct OriginUsageParams { PrincipalInfo principalInfo; bool getGroupUsage; }; union UsageRequestParams { - UsageParams; + AllUsageParams; + OriginUsageParams; }; struct ClearOriginParams { PrincipalInfo principalInfo; PersistenceType persistenceType; bool persistenceTypeIsExplicit; bool clearAll;
--- a/dom/quota/PQuotaUsageRequest.ipdl +++ b/dom/quota/PQuotaUsageRequest.ipdl @@ -3,27 +3,40 @@ * You can obtain one at http://mozilla.org/MPL/2.0/. */ include protocol PQuota; namespace mozilla { namespace dom { namespace quota { -struct UsageResponse +struct OriginUsage +{ + nsCString origin; + bool persisted; + uint64_t usage; +}; + +struct AllUsageResponse +{ + OriginUsage[] originUsages; +}; + +struct OriginUsageResponse { uint64_t usage; uint64_t fileUsage; uint64_t limit; }; union UsageRequestResponse { nsresult; - UsageResponse; + AllUsageResponse; + OriginUsageResponse; }; protocol PQuotaUsageRequest { manager PQuota; parent: async Cancel();
--- a/dom/quota/QuotaManager.h +++ b/dom/quota/QuotaManager.h @@ -393,17 +393,17 @@ public: nsACString* aOrigin); static void GetInfoForChrome(nsACString* aSuffix, nsACString* aGroup, nsACString* aOrigin); static bool - IsOriginWhitelistedForPersistentStorage(const nsACString& aOrigin); + IsOriginInternal(const nsACString& aOrigin); static void ChromeOrigin(nsACString& aOrigin); static bool AreOriginsEqualOnDisk(nsACString& aOrigin1, nsACString& aOrigin2);
--- a/dom/quota/QuotaManagerService.cpp +++ b/dom/quota/QuotaManagerService.cpp @@ -580,28 +580,53 @@ QuotaManagerService::InitStoragesForPrin return rv; } request.forget(_retval); return NS_OK; } NS_IMETHODIMP +QuotaManagerService::GetUsage(nsIQuotaUsageCallback* aCallback, + bool aGetAll, + nsIQuotaUsageRequest** _retval) +{ + MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(aCallback); + + RefPtr<UsageRequest> request = new UsageRequest(aCallback); + + AllUsageParams params; + + params.getAll() = aGetAll; + + nsAutoPtr<PendingRequestInfo> info(new UsageRequestInfo(request, params)); + + nsresult rv = InitiateRequest(info); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + request.forget(_retval); + return NS_OK; +} + +NS_IMETHODIMP QuotaManagerService::GetUsageForPrincipal(nsIPrincipal* aPrincipal, nsIQuotaUsageCallback* aCallback, bool aGetGroupUsage, nsIQuotaUsageRequest** _retval) { MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(aPrincipal); MOZ_ASSERT(aCallback); RefPtr<UsageRequest> request = new UsageRequest(aPrincipal, aCallback); - UsageParams params; + OriginUsageParams params; nsresult rv = CheckedPrincipalToPrincipalInfo(aPrincipal, params.principalInfo()); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } params.getGroupUsage() = aGetGroupUsage;
--- a/dom/quota/QuotaRequests.cpp +++ b/dom/quota/QuotaRequests.cpp @@ -86,23 +86,29 @@ RequestBase::GetResultCode(nsresult* aRe if (!mHaveResultOrErrorCode) { return NS_ERROR_FAILURE; } *aResultCode = mResultCode; return NS_OK; } +UsageRequest::UsageRequest(nsIQuotaUsageCallback* aCallback) + : mCallback(aCallback) + , mBackgroundActor(nullptr) + , mCanceled(false) +{ + AssertIsOnOwningThread(); + MOZ_ASSERT(aCallback); +} + UsageRequest::UsageRequest(nsIPrincipal* aPrincipal, nsIQuotaUsageCallback* aCallback) : RequestBase(aPrincipal) , mCallback(aCallback) - , mUsage(0) - , mFileUsage(0) - , mLimit(0) , mBackgroundActor(nullptr) , mCanceled(false) { AssertIsOnOwningThread(); MOZ_ASSERT(aPrincipal); MOZ_ASSERT(aCallback); } @@ -121,76 +127,51 @@ UsageRequest::SetBackgroundActor(QuotaUs mBackgroundActor = aBackgroundActor; if (mCanceled) { mBackgroundActor->SendCancel(); } } void -UsageRequest::SetResult(uint64_t aUsage, uint64_t aFileUsage, uint64_t aLimit) +UsageRequest::SetResult(nsIVariant* aResult) { AssertIsOnOwningThread(); + MOZ_ASSERT(aResult); MOZ_ASSERT(!mHaveResultOrErrorCode); - mUsage = aUsage; - mFileUsage = aFileUsage; - mLimit = aLimit; + mResult = aResult; + mHaveResultOrErrorCode = true; FireCallback(); } NS_IMPL_CYCLE_COLLECTION_INHERITED(UsageRequest, RequestBase, mCallback) NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(UsageRequest) NS_INTERFACE_MAP_ENTRY(nsIQuotaUsageRequest) NS_INTERFACE_MAP_END_INHERITING(RequestBase) NS_IMPL_ADDREF_INHERITED(UsageRequest, RequestBase) NS_IMPL_RELEASE_INHERITED(UsageRequest, RequestBase) NS_IMETHODIMP -UsageRequest::GetUsage(uint64_t* aUsage) +UsageRequest::GetResult(nsIVariant** aResult) { AssertIsOnOwningThread(); + MOZ_ASSERT(aResult); if (!mHaveResultOrErrorCode) { return NS_ERROR_FAILURE; } - *aUsage = mUsage; - return NS_OK; -} - -NS_IMETHODIMP -UsageRequest::GetFileUsage(uint64_t* aFileUsage) -{ - AssertIsOnOwningThread(); - MOZ_ASSERT(aFileUsage); - - if (!mHaveResultOrErrorCode) { - return NS_ERROR_FAILURE; - } + MOZ_ASSERT(mResult); - *aFileUsage = mFileUsage; - return NS_OK; -} - -NS_IMETHODIMP -UsageRequest::GetLimit(uint64_t* aLimit) -{ - AssertIsOnOwningThread(); - MOZ_ASSERT(aLimit); - - if (!mHaveResultOrErrorCode) { - return NS_ERROR_FAILURE; - } - - *aLimit = mLimit; + NS_ADDREF(*aResult = mResult); return NS_OK; } NS_IMETHODIMP UsageRequest::GetCallback(nsIQuotaUsageCallback** aCallback) { AssertIsOnOwningThread(); MOZ_ASSERT(aCallback);
--- a/dom/quota/QuotaRequests.h +++ b/dom/quota/QuotaRequests.h @@ -67,43 +67,41 @@ protected: }; class UsageRequest final : public RequestBase , public nsIQuotaUsageRequest { nsCOMPtr<nsIQuotaUsageCallback> mCallback; - uint64_t mUsage; - uint64_t mFileUsage; - - // Group Limit. - uint64_t mLimit; + nsCOMPtr<nsIVariant> mResult; QuotaUsageRequestChild* mBackgroundActor; bool mCanceled; public: + explicit UsageRequest(nsIQuotaUsageCallback* aCallback); + UsageRequest(nsIPrincipal* aPrincipal, nsIQuotaUsageCallback* aCallback); void SetBackgroundActor(QuotaUsageRequestChild* aBackgroundActor); void ClearBackgroundActor() { AssertIsOnOwningThread(); mBackgroundActor = nullptr; } void - SetResult(uint64_t aUsage, uint64_t aFileUsage, uint64_t aLimit); + SetResult(nsIVariant* aResult); NS_DECL_ISUPPORTS_INHERITED NS_FORWARD_NSIQUOTAREQUESTBASE(RequestBase::) NS_DECL_NSIQUOTAUSAGEREQUEST NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(UsageRequest, RequestBase) private: ~UsageRequest();
new file mode 100644 --- /dev/null +++ b/dom/quota/QuotaResults.cpp @@ -0,0 +1,91 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=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 "QuotaResults.h" + +namespace mozilla { +namespace dom { +namespace quota { + +UsageResult::UsageResult(const nsACString& aOrigin, + bool aPersisted, + uint64_t aUsage) + : mOrigin(aOrigin) + , mUsage(aUsage) + , mPersisted(aPersisted) +{ +} + +NS_IMPL_ISUPPORTS(UsageResult, + nsIQuotaUsageResult) + +NS_IMETHODIMP +UsageResult::GetOrigin(nsACString& aOrigin) +{ + aOrigin = mOrigin; + return NS_OK; +} + +NS_IMETHODIMP +UsageResult::GetPersisted(bool* aPersisted) +{ + MOZ_ASSERT(aPersisted); + + *aPersisted = mPersisted; + return NS_OK; +} + +NS_IMETHODIMP +UsageResult::GetUsage(uint64_t* aUsage) +{ + MOZ_ASSERT(aUsage); + + *aUsage = mUsage; + return NS_OK; +} + +OriginUsageResult::OriginUsageResult(uint64_t aUsage, + uint64_t aFileUsage, + uint64_t aLimit) + : mUsage(aUsage) + , mFileUsage(aFileUsage) + , mLimit(aLimit) +{ +} + +NS_IMPL_ISUPPORTS(OriginUsageResult, + nsIQuotaOriginUsageResult) + +NS_IMETHODIMP +OriginUsageResult::GetUsage(uint64_t* aUsage) +{ + MOZ_ASSERT(aUsage); + + *aUsage = mUsage; + return NS_OK; +} + +NS_IMETHODIMP +OriginUsageResult::GetFileUsage(uint64_t* aFileUsage) +{ + MOZ_ASSERT(aFileUsage); + + *aFileUsage = mFileUsage; + return NS_OK; +} + +NS_IMETHODIMP +OriginUsageResult::GetLimit(uint64_t* aLimit) +{ + MOZ_ASSERT(aLimit); + + *aLimit = mLimit; + return NS_OK; +} + +} // namespace quota +} // namespace dom +} // namespace mozilla
new file mode 100644 --- /dev/null +++ b/dom/quota/QuotaResults.h @@ -0,0 +1,60 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=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_QuotaResults_h +#define mozilla_dom_quota_QuotaResults_h + +#include "nsIQuotaResults.h" + +namespace mozilla { +namespace dom { +namespace quota { + +class UsageResult + : public nsIQuotaUsageResult +{ + nsCString mOrigin; + uint64_t mUsage; + bool mPersisted; + +public: + UsageResult(const nsACString& aOrigin, + bool aPersisted, + uint64_t aUsage); + +private: + virtual ~UsageResult() + { } + + NS_DECL_ISUPPORTS + NS_DECL_NSIQUOTAUSAGERESULT +}; + +class OriginUsageResult + : public nsIQuotaOriginUsageResult +{ + uint64_t mUsage; + uint64_t mFileUsage; + uint64_t mLimit; + +public: + OriginUsageResult(uint64_t aUsage, + uint64_t aFileUsage, + uint64_t aLimit); + +private: + virtual ~OriginUsageResult() + { } + + NS_DECL_ISUPPORTS + NS_DECL_NSIQUOTAORIGINUSAGERESULT +}; + +} // namespace quota +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_quota_QuotaResults_h
--- a/dom/quota/StorageManager.cpp +++ b/dom/quota/StorageManager.cpp @@ -128,30 +128,41 @@ GetUsageForPrincipal(nsIPrincipal* aPrin }; nsresult GetStorageEstimate(nsIQuotaUsageRequest* aRequest, StorageEstimate& aStorageEstimate) { MOZ_ASSERT(aRequest); - uint64_t usage; - nsresult rv = aRequest->GetUsage(&usage); + nsCOMPtr<nsIVariant> result; + nsresult rv = aRequest->GetResult(getter_AddRefs(result)); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + nsID* iid; + nsCOMPtr<nsISupports> supports; + rv = result->GetAsInterface(&iid, getter_AddRefs(supports)); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } - uint64_t limit; - rv = aRequest->GetLimit(&limit); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } + free(iid); + + nsCOMPtr<nsIQuotaOriginUsageResult> originUsageResult = + do_QueryInterface(supports); + MOZ_ASSERT(originUsageResult); - aStorageEstimate.mUsage.Construct() = usage; - aStorageEstimate.mQuota.Construct() = limit; + MOZ_ALWAYS_SUCCEEDS( + originUsageResult->GetUsage(&aStorageEstimate.mUsage.Construct())); + + MOZ_ALWAYS_SUCCEEDS( + originUsageResult->GetLimit(&aStorageEstimate.mQuota.Construct())); + return NS_OK; } } // namespace /******************************************************************************* * Local class implementations ******************************************************************************/
--- a/dom/quota/UsageInfo.h +++ b/dom/quota/UsageInfo.h @@ -13,36 +13,29 @@ #include "mozilla/CheckedInt.h" BEGIN_QUOTA_NAMESPACE class UsageInfo { public: UsageInfo() - : mCanceled(false), mDatabaseUsage(0), mFileUsage(0), mLimit(0) + : mDatabaseUsage(0) + , mFileUsage(0) + , mLimit(0) { } virtual ~UsageInfo() { } - bool - Canceled() + void + Append(const UsageInfo& aUsageInfo) { - return mCanceled; - } - - nsresult - Cancel() - { - if (mCanceled.exchange(true)) { - NS_WARNING("Canceled more than once?!"); - return NS_ERROR_UNEXPECTED; - } - return NS_OK; + IncrementUsage(&mDatabaseUsage, aUsageInfo.mDatabaseUsage); + IncrementUsage(&mFileUsage, aUsageInfo.mFileUsage); } void AppendToDatabaseUsage(uint64_t aUsage) { IncrementUsage(&mDatabaseUsage, aUsage); } @@ -99,19 +92,16 @@ public: value += aDelta; if (value.isValid()) { *aUsage = value.value(); } else { *aUsage = UINT64_MAX; } } -protected: - mozilla::Atomic<bool> mCanceled; - private: uint64_t mDatabaseUsage; uint64_t mFileUsage; uint64_t mLimit; }; END_QUOTA_NAMESPACE
--- a/dom/quota/moz.build +++ b/dom/quota/moz.build @@ -10,16 +10,17 @@ with Files("**"): XPCSHELL_TESTS_MANIFESTS += [ 'test/unit/xpcshell.ini' ] XPIDL_SOURCES += [ 'nsIQuotaCallbacks.idl', 'nsIQuotaManagerService.idl', 'nsIQuotaRequests.idl', + 'nsIQuotaResults.idl', ] XPIDL_MODULE = 'dom_quota' EXPORTS.mozilla.dom += [ 'StorageManager.h', ] @@ -38,16 +39,17 @@ EXPORTS.mozilla.dom.quota += [ ] UNIFIED_SOURCES += [ 'ActorsChild.cpp', 'ActorsParent.cpp', 'FileStreams.cpp', 'QuotaManagerService.cpp', 'QuotaRequests.cpp', + 'QuotaResults.cpp', 'StorageManager.cpp', ] IPDL_SOURCES += [ 'PQuota.ipdl', 'PQuotaRequest.ipdl', 'PQuotaUsageRequest.ipdl', ]
--- a/dom/quota/nsIQuotaManagerService.idl +++ b/dom/quota/nsIQuotaManagerService.idl @@ -37,16 +37,31 @@ interface nsIQuotaManagerService : nsISu * A string that tells what persistence type of storages will be * initialized. */ [must_use] nsIQuotaRequest initStoragesForPrincipal(in nsIPrincipal aPrincipal, in ACString aPersistenceType); /** + * Schedules an asynchronous callback that will inspect all origins and + * return the total amount of disk space being used by storages for each + * origin separately. + * + * @param aCallback + * The callback that will be called when the usage is available. + * @param aGetAll + * An optional boolean to indicate inspection of all origins, + * including internal ones. + */ + [must_use] nsIQuotaUsageRequest + getUsage(in nsIQuotaUsageCallback aCallback, + [optional] in boolean aGetAll); + + /** * Schedules an asynchronous callback that will return the total amount of * disk space being used by storages for the given origin. * * @param aPrincipal * A principal for the origin whose usage is being queried. * @param aCallback * The callback that will be called when the usage is available. * @param aGetGroupUsage
--- a/dom/quota/nsIQuotaRequests.idl +++ b/dom/quota/nsIQuotaRequests.idl @@ -17,27 +17,29 @@ interface nsIQuotaRequestBase : nsISuppo readonly attribute nsIPrincipal principal; [must_use] readonly attribute nsresult resultCode; }; [scriptable, uuid(166e28e6-cf6d-4927-a6d7-b51bca9d3469)] interface nsIQuotaUsageRequest : nsIQuotaRequestBase { - [must_use] readonly attribute unsigned long long usage; - - [must_use] readonly attribute unsigned long long fileUsage; - - [must_use] readonly attribute unsigned long long limit; + // The result can contain one of these types: + // array of nsIQuotaUsageResult + // nsIQuotaOriginUsageResult + [must_use] readonly attribute nsIVariant result; attribute nsIQuotaUsageCallback callback; [must_use] void cancel(); }; [scriptable, uuid(22890e3e-ff25-4372-9684-d901060e2f6c)] interface nsIQuotaRequest : nsIQuotaRequestBase { + // The result can contain one of these types: + // void + // bool [must_use] readonly attribute nsIVariant result; attribute nsIQuotaCallback callback; };
new file mode 100644 --- /dev/null +++ b/dom/quota/nsIQuotaResults.idl @@ -0,0 +1,27 @@ +/* -*- 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(d8c9328b-9aa8-4f5d-90e6-482de4a6d5b8)] +interface nsIQuotaUsageResult : nsISupports +{ + readonly attribute ACString origin; + + readonly attribute boolean persisted; + + readonly attribute unsigned long long usage; +}; + +[scriptable, function, uuid(96df03d2-116a-493f-bb0b-118c212a6b32)] +interface nsIQuotaOriginUsageResult : nsISupports +{ + readonly attribute unsigned long long usage; + + readonly attribute unsigned long long fileUsage; + + readonly attribute unsigned long long limit; +};
new file mode 100644 index 0000000000000000000000000000000000000000..5144112bde351703f42ab87f817421af09cdae53 GIT binary patch literal 24717 zc%1EAcRZEv`>&)WDvC-}vX7Bnh$MRp(XjVAvSoc5l$1SEC|MDqW6Ma$CVNv>c1C80 z-;wnk&N&|a`s4eD)9b0{QC;urzV7Q>@B97SLs|@L_kkUYpE_wt(H(%#z8$A_n3+RO z)pWEN<>mJ8zzQvVqd0=NEUa;M?A-lp=Z+n_k0Sn^G+GPz01GBsrbcSUTE^y^+B*6N z`<k(dXr`Wfg%;wkJa_HbaS&lk!&FPnTuVh$ok8F1j}?+9#fpp9IxD`Oe9-3e2c1Ud zk3E!<lvW%_;y(m=GL(Ew*Y>0{pQrB22XyK9t>pA$?Ls&r^?0pnLbC27_F<*zyQYs$ zbyzo1_3zzT-0{^LcAxYi-=2prZ3qfKvAO%HzdQG!&|K}Qn64A)*U<~6rSy?);sOJ% zHQZ|IW^E4VYn$Y1LnY2U@5T`nSGe#=D+-Do*%HH}AkQI0m3If8u5!uX%{9k+7oB4G z+mm)mpQhQxMZBk6_ElydG^N?Hi|W8922IDz@8xdSauga3?59KeB7Jm)YJBdhO*e+N z=rn80LFxtg6FMX2+10`t9;B#quxq@(-p%&<a_%D~q1yXzzL3lgyz`T9rz@a+;QgjH zweezUiR=sdqdFfu<5D3R?Zcsv2;1BaH3gU(*=!Zd9ygd+Z6DK1ikpnPTYULrJJJk) zGX_=!8siHHdE-8NKNDHmS9{`P<vhp8TpslKPCTcVWZmB+GyNBM<+69Kb(MmFiRcK< z%P6MBK1XyF-deXanB6hdGuQglSq~l-D=uE^ItvGHqKHmJUbuv@Sb|RGytb;ks-~ui zw6rSX^H9Czzx{D^Sc=)Ck$V{L=nH*9$~P8$6Qq1Q49GW4Ep0Um!{uyKyI-uhc%jW) zj&+uRnQN|PWP-RewOO*Ihp?lE$(FAHvaJ&+zXck)rck5hFV+kqDl;1+vlih+lfUP} zqX`jDB#4U)lSu|6Eps(ZHFGsgwl!3LrH9OZ9U;cT!n$cHDC1yEi;uGo@oR<!?;;{C z;-UbBNN>pu4)mm|SUGiZg@l0mP7IMF!33(OslI9SP@Co1%q%Mt2h;fr?9A*e=4M*@ zW(<g$qobpyWo9nVpsi=9WwwMni@==Stk)KtkKFRujd;xY|KS3@M`&<|TH1}96i)3m z;UZ@um#B9=o2(EZc~k()g);W8yoI-5?!9=K>Jy>lFDbinMEc!$N!V+vxODF(q%@GK z64^dz8$7|T=U+{#3XRv$$XS@KwyY(bfK%@->9ulmL|puI0yK_FH4=j5O+gXbUbeZo zYI-8mPY?4QCi|Vl@YLvM{RcC{AflOi_XkrhWVyz4dKN8@^PC18l^son+<&Rm85d;v zDaXzy&3-PfDB%@w=$6>Aa5}S@xGL6mRM)Y3@JDZNj9CPSV$xjV`+%5!PK(!-Peom# zkB-?ydw5WL6-9jvAEP$F_S58Y?h-u^67YckjgMR5*R#GZ;_jAQgE4i($>L))Y5bFV zS!cZI=w;g&BYjBm?vANC;b)d>h~^KzS9ZMoHgG8DmbbB1awwdj_rp*%RgAWR4dsob z@{@*v9`Ew~;axoC<bj&g<hMf3nkC@F#6s$EWvL0$!tm2%={U`3$JOxUzSrno=nKoZ z-sC3LXg2VrZYV7?^)xdFG@<upa}9Q}r%Vr&M~YN0w)bXz4x3=HQg2exKupTPIwqAk z!ZsdB`U9o`wEcrK*^Q@SAIGQJAM?f^O>Gc+-lX?H$*9i2{<)oYw(#DR%U&b%_hV!Y z7~FkwKR-3SlJ%NOk2&4ZIrj5I+04$jK5qwI;B$B1m1m74PmHAhuBsb-jaQMlhxe;) zeWJ4&&tX`PrmP2S;&~~{L-|jaPf4}&)D7r;ANHDzDM=a3)swuK@{z0V_8`$|VOe#k zl$}!20AZ?f$JNqnUoV?^9URB;`C9aNkVtIqy|-kWbK`LQPvfkBnY};7%k;%E>e-~@ z<(isY6FvMh%V^$Io?`U1yIhhL7V|jl*tdaxu}dC$4IY-ByGVvqvlOs@#mmXW+J<=y z*?*v=7`v(NSS_jAuY7_-@Y0-N&mP-HTm$f9Gzm!*S*(LWY+04l!efKsj%oxFO=PgC z1_R?a9kMFEw`&)yl|&7puKssym2SarKYADJbVo(QP1d=lJsbBK-(|lZX5a7UbtjZw zS81?G3|{IZ{sJQpsSZ*uae1c}_aIxg{c2cVYsPm9v+Ko4)}L4)Y8GaU903#GSTbVh zV~Yl>ti^8IM+dmWds}(^_?`7Fi6hEyX!nwZeNEfD$MrR_e5^sT5QkutT-b@mV{pRS z;UPK^mmrda>?3dE=B#bhC8(}fmn%VQIb({h@Kg#BkCdO%lK2IEBCBq8?W4~icdWfl z^oh`^$5h$h8p8}!N3M*w`%d^RJgHFpQrR3E6~NB=xhq8~w%JHQBIpngi=u(vGuK|j za$Ox=en%eq1}pD|LnGr3SW5-$KZxG5?7S%lf@z}Vl6H$;q;K+3LalC|rnAx|9qs(e z^2T9;(8<(lV`jDP@ph|u9=Ncz)`Cp7NoTg?%KvJk;9giZNyjrVvM~Dl(9%<U!_U>* z>CJB!7IyAH`n=C_1k_)@b@lfg$~vfPZf*jBKn$T8YKFQ{vt{P~jVN@#F%{WG<IN@I zDd(1niVmD{WRgUKvcy*j^M?^6sUzuNsxB$$aA&{AIS(0GS=I13_rqB09C;C~QcZ?< z;y_%CTXbZFJ2&;^WJhU{lw@g9AtS?1)7{LXq6cCoejQQA5O6ARuB<XDhM+G2_^$&H z1`hy^Tj2<FIHqo2^dN{}An(O8xBeRs04$5fgQ1oRNn)W>dw<?O7=wGZETmALER1ho zt=~cNG8zd;Z3k1TMP1)r`q%PW^w$4LJd;3_>Mrd^r|u3BBp#~dZ$INtY8zLhAs<zr z#ivtm09$w(6ei>P3%>8OelG_sd!~#|o5FRhSHPRaw8k*#WMGTGvB<S+Ra6g!y^a#Z z+4NQ2x0cBGGHIh^2d|vFC?|eHDs0dVCqbaE=QPLZwrTtM-n3>HMqhuJW4Qyzc=d#P zg348boCP5rBfc~<N2a#h-|5GvpC`GMa=uHh(BGpYUlB$BOxr@#JT^X4f(`$Ozz3V# ziE^a9gE?OPc^-Bm=U6k6_!Fxb8e2nXW%`Eix{{EvH{(k3P+ApHwlcgW7jl)GC@}~Z z$_yq`49$yic`nP8Vq8axAKk+_$Kk`(=xc4&o@qGVv7f6;-qS@UHi0ukys#R-(82n& z6}~aEI(~5F<Fp2si{a-D2x)v=ZdAG4pdoC%=$n83Cg+`jnpft<&5+K#$e=U}g7NZ} zVBW{iUuHLSmJJnS7kl&d#PLcU(TnRPuFqi+Y`Wc>_HDqBov!YCoC1#H=@dfjByl$T ziQg(vH_NLvEm^|UMfn10-dzQJL5)U}23fD{EMda7DVIeD=kG^fvt@8k$_<T4mf{JW zJHedlI2#LpSQV6+>J?*H*t%Ccv>?lfqZHcoy=wAK9G=v(^b0aj(vucbcGTMCWnr&- zevqEf*_UxY<br3GnPDAsUNc4KP5-#YwB|rds0}nGrJ<tznon1O^Y1tPHT340l`aqC z-h}iV?dv6?4Sji}k<O3(5>@L*`ZmLaAIA3ru=oCyC^Igxu4j{rH!o;&O^lD7eOY}q z)JBHZ!qpE;r11z17g;5n$6e~`w`YUMoH#i@smC6em5h4RJSBX#enwY8#F(+9m4fOX zWU5$8qa~$6&^SIN71kCc<5f~JhEvk0<WH2&Eo*1nr_ylsb8_L2OOsDtQh%(e*Sc=e z{z}0M0vXGH1EUL`5B{vwo@*V)BuI0v|8$G90^=E>@kY^v)2!Bvm3_g%XUl^RKJC2e zRoJI|yCme@w;29-S(SXBu1wo8>~V!+nDsXn78#3i296VxJuK-lxSc*1!$<wo?`r?_ z?ywn&>wX*}*=%9_VGlG&h&6rcGW3Y}JN-l(GZPITQGplom%c)!hsyhXyl&n0&A<tn zz3U$NsLtG)Ehw<8K+QGi!()z#PX!rVf=bn`%^$pO-SA>ON+o5hLVCQeL#NbVWx=qR zCEhV4zg<-OoOOO=j8;Hdfp0(^uB&TvZ+t6Htm(CbJj@Nc$A69M7?$c<>6X}8%A0gh z-XU%K0^hS-*y^hSt&2u})4DJ&{~#5QN4l;KA2xbihcJ$mMLFTAM)G_f=eOU3pP%9O z@}HrSa1~>DHJ>~?HRUM67<A~DSjzlB-ZDLQ80C)hF5TvI!FU(kdmWbvy~ug(_R*%d z3k!#k`PKvu$6Bk-q3fzM5eiuhl%M!c#fpm;+F~2JPJW(2ZxESR(OBM0e1@(QpXWf} zt<dMDkf^2S`j`=;hg_ve3~@tklpC{AaMTE@w}7(q?@<AChz50AbZ(2zZPB?cI{)`X zXV|*hdlp3%L@hZ95M_=4Q-KXzCpl@sm_{Z>G#FbFoMGz(C;gV(SmDc~2rrIe@?>+l zxjxhsU>sRxQ8W&qH!ld*JUBkZfWH=Jpw#>q_yA@_gTE~_w}s}m(A*Z9|I0!%0>ez_ z+N>#1Y7!v|9TBEt8-Zb_bAw4_PDNvTGqD+gVWty3;tG9k3W{28u8$lECeT%?#1K8y zW_dO<3yvZ|^%}aF&aL7Cs1XhBw&>gzo!g>wTXg>KiO%))_Z-SPh+1|YM-;l_n-y7f zGo2WWBa<W=lr0I*2n;iwU>sTD&P{#UTzak#I2AZoRv8sT&`|>jg9iY|t)RLc-Aw1- zdjMcrG#+dV&}{*_EkL&g=>M_+B{N3Px9eWbX<4fonHXv@Xh4mY3U9VcvEt%|w(u?* zS6C1bra(L~tm9h@#*z6J4ay?N$*}c`@gn%vN?$<Tm`^fV+0=o-1LCvHxO4~BxsoS> z#Y>KO;#$YJU|d;Y+)ceX*&!J#TuNUkQY%(ofo<xv%(<QdJJAQ73Y;^moQomwr~!n* z1AyaPP+gCuP^1)yf^+}g0|4iu@nEP$LW)@E_#)>jA3R%hc7=0K?Gt6xyAid={n<^O zp!fB=ZV1$=AJV**Ej_|{pk>g5pZ99`B-TWwSVh`I4Wo3_m+1CT*g#SvhX$2ijVjzR z*E(subdaT@R9)eUPZq-u%5y@omi#P5_TM7Tvz)Wzdwgc!k@*`(8R$mqW0s_?6nx5) zELV_D&EnP*I-L52toff!Dz4cKEpGOZOt*OgxZ1FP<EwMo<COm$5}F$JGVh%qvxDXv z4t)6%V;@$p6mBM4Ev|4Us7XfmM)+0vv9we2!oo*IbmZG)9Rd?}xqcww{~+L0IZ@6a z^TbvY>R)^{!j{;`QqIWY1?5a&%eiJ&e}55YLh2EJ`6uqPmu%v%xF~lr<zLa}kGn)J zS8jgjy@*wn!FVQC?}ymWIx+eR)|5BG3;GAi&R%zAocn4YC~~3br%37*{vLG-ZT~BA zC&*REOl2rc)1*y$<i39%e47_lty;C;D$a-GRbp?QD}9rh?aUcX<2H3E_7pK9YBA@4 zY&f?~SW@uFEv)+EB051tf^o1mR>fvJ*bVEs3rU3~6wz-xdlxLt63KFVCMCq5FfzKf zrbdy}1=MP167DUEOu<QX#37#^t|*~R>KRik;uVGL?SkC(Ap1P0Q^_ez-Prod|9iJY z0)h<c8eAo>Eo6OWG$NTA_<8HyIKeLk`FC8sSWGyQlr|Unr;5n=6^|Xv8=V-^$n+x{ zW}vA^xBDU))Dvb_lA+O>?=a&@p3lLNfBjg7@x1|T$vp03xU5u#XR<G!2zpv*8In50 z+1F+CJeD12q~~RT<Bp1&m}DQ@+gR9Q5iyy<;};v71IZ7RjmZ{qC3cAwKM__ulJ!2T z1}nfBSC5FM@+)4Cf$w!ISFPG~p|OBr9T}S7o5yS+mb?6ieO(J|DtL%9KDBk0r?XMz zU%#Gz-8mD+z+ird+-9=MG2TVc$aB<o5SK&7Br2}>eZM_7B)`5cZ(M6h+sahrrp7Vx z(eU?=v^xv(p5ce}nW`OT{Y@v`m-T{dGI-)yr;=A?pR#g^=aROSB9pZ<5aZSv7EL2$ zwAN;bF&^%w4CS#a@K1_jdw%;QGzvoXVy4Ei4X$xf^Q~Z{aes_nvK0TxAluj3`_g5; za%vk`YaDgOe&Kif>xlHw@a)s0Dk?;_V)tg#-F1ZO%+1+`0)J^Im7S#P!m>{t9hQ); z(;P{r&cCjZXI4~R-Q@r11(Th-^%!xWMCzVN2G)h!BGB2m>A)o1%-WBv)#=*Le@{kP zaz1+!HU8<#9s`M3hr0!oPc5C<CtxM_?KxcFKY98%RtVOMa9Zr+=%bwM<sWo>o^mm_ zf)EC|KQBEG`BF+p+{Dyut<B9=<}Jm+(TEd!M^=ZpR)PQd+*k$dbZGYexFOztBIEh? zsAXxJGxu<nJNtCtaNgh*xf(&dc6)l$+xZ1vWY*28onl<8&*b0<z{<*s!3cU+&(Khf z0cxtVRDSaig)a|N`CSC)J^%}*K|C=duJhmlkl7av(lXz@SX8@K#t!n@l9F$f9b`B? zAbv~itD>y@{t+Ee^M=Tni5k4r<6LxUF*q!L;nE5V2aA;}+9ED=UY*0D?I<scD=sY( zsVQL;-D{e^Ov5E5CBHnhcA)PG2zakn=@>(Apav1&8VEQ_29*<3X0*j2%ar`@ya3QL z8ZU-g+9jJ8UpT+qK`Gs&d{9f@$^7sYu`t%e{xU@ly?cR|lWY1;3FSo7Fn3*Uy|~{s zh&feElyMR-WBHA<xV@7|Mj+)7ljY!rPYb*BGNLJF9j-p^9_RX!jktD;Js#r_XjSie z-56~^n8w(0l#=ox<NhPN&laed<)+!pzc6<n8Yf$r4WHtX6EDp3w)`^FaNh(zGH~cU zoNa1uFm_s_uX}>GnpXnOK4UO=sBQPpZ$DZB{EgdHp7$}_pojnTNWwFJAm1#+R;G?n z!njV_@}hF#@o6H*{wQJJ6gkpvgc2THRKjOjGZF-Rs@NOb-Y|RiSw`gJO}-p*7RWkd zRm9m!SBOx;K2s%-@JE@!+=?Mr<3<rm*#E1+p?$t)L9GT=LxW@DR`r>NW+ODsDbd^n zu{SjKa7h7_u-&Q>t~8)TDB)YOF1P+D;hFQqw11RvRWoELFETLAqSFkagyRHC%Txxx z_E>(~)m?OEoZ}Uhdt&`~tU<?#bKUR92Y*`B5mOo{#a&-g!fE2ievK`@aUOd7HqD;c zA0G!tok~s5b`Pw1u>KbB%-~(mN#lFu?Qm?R@X1@GG)|9{wEXQPtg1Cl7A9`a?GNYV zVv&9Gf!4BqLhu>9!T1Mn;!OBZr!q;f-X2~x)+x5nmrg$kuwbDnyqL}}cp~?`Dz#hW z$f<!O)=^85xw>v!%kS)wEjQbU2k0lq-6?1i(rL5aa$4ZrW;7=oey98PqR8xwQ}GY& zt97p778N2K&}#i;Me~%L()(D`5!xx?nFA+j6={t|1a36=z!%>*b2IvW<SV%sHuyM< z<j9Yc!k2vXYCI%8uaE>SzHzpACnqyx8|E=!$3suS?w>dO#yiK!w)^9qf|Lq|R@D&` z9eY*^3O~O*q6iqQoYCBYd}gw0A>PH=$g||nE9akoUOB@xWku;2U3GBEKUmM&;zioy zbY>Rp3xE37(S-O#=6|QkbRhW-l^w9l;avJJF4!`kcY}(MMcUq>fAroNhWAO-p2!=2 zYS=}m^d?Qkcc%(*f!eZ+7R`o772R4!x)wb?1uFghp4yl82T#o_x*d;hW2XyZi>VX2 z8ftrJf{>5n-Hm2_JmaUbQNpkfRI~Katx5qN_z;M?6_1?C$Y@vP3%s}pZ&+IcG=bA~ z`toVRj~VBD*lIH=L|yU)M#W9X5~sR@wei|CvVPC%cn9Bu<CHmGuOj{g;nASK24!a` zt*I1uZReRAvdq-)v->IbAjw%fFz~~X(AE$M_{5uz9EtDTAKhnhm+Ra6Fr|5X=tun3 zSI%|~Jify*`H?#6ge<ZBXJNDvmW9kxWmJ9^6OH}-qoa2s+PG_R`Ab-DKFY1R?if7( zdj#?=d|U{gTQ(KMvuxy}nDzYLrQ73<lkE$gGpCoHR6l-Oz5TuU?ZV1??3K?g`vrhF zV_jFQX)x`JK*`Qsi2B!ssS>lUV`t{AKp^uo8mzzI=S8P%sr8RjFY`0oUpckH(3|>o z5+p&d?+*H{xV1{r7`g;CjO12fz>zel)Buw7zw`q@(`fwIrs-{(-lpkon*JZA>7Bbs zvCy5ia(wyj@QxwA#Xr~1Ucp{EFJ(j7MQ;rs$=VfwHQ+fcnCzlEg=NX^;;VxH?ztg; zM?RAUd+AIT3>G&Y7IJ*m>;LXu+_mcIYQe`|IywYH>o=YQvex<>z7K0Q0jGjsFP#d4 z!Rp2{L4a0&1FQm12*F-DAq0cnjpu^^?FwU|>Z{c?bl6MhU0?|C#<N0z0e*?eJYaAJ z4hMPN91sV0HyE5h<1I{3=*|TJM(jQ&sHHK~)**P1AR0G=05N{TUOKsBlZYa(q60=$ z2K(=Q0DP6u`hae)J}?eS2T=KdVm%A?(k5~Yjor9!AK2Jra6rfj3jz^&*$NPm7iVjT zE2)bX6x~*QU_6V#fvzU;CSV)4<paSW2SI~@OJ|fD^w;9Oaf?1M-m(A08$e>C^#<Lh zSYT|5j%?%zV9iCj;c~618#l-Tn|cx-t#RZ827!XSEf$FK1O&=T(xL@Iw;2`~D>!<f z)kNJQ05=kVECEIUaLEZGmdKlAfw3(7YYzYkxk(H*Zcqcpp#1no4^Y=xlv~x-8oF__ z8nB@>CqTd;Cn*R#<Xve%y!b8Qt)wf;?OEs}Nr4o}izh)qt|smlp#+hjo`Zz~m%?a$ zLANgr80q80|9@Wq$-GHiHtqxg#)bI|s<AS#zM|Y+u-4R#yF!3Xb;4vGIe9_gpdZst zfx=lyTC`B;c7OmQW_T6@)M~PB5dwKk`*|}6a7hXxqUgu8Tx5Um10XrK7zgArEk6}1 zA5hm?lnZr{8;gES`x+b&a>9Z@L_embq23zeO6sBoMYrf07|%p-psPu|MKI(s?J*kA zVBpdjM7+_DY5o6+H-N<6BsLqDKLTR|V?fIQ$crJdm)4_UX!gdXkicdiW&{O<oY)`` zkykt-y~Wrf;!0wp1x2^A5g1SE^PoUi6MKtb$cgO&9t>P!gNQfsibr6)ahU#vH-N<6 zBsLpY7y)BL!;aRQjWe3qORG9CG=1Z0BP3Y`9t=6bH$mOFpa_Uc!m)MKl_U?|xU>jU zY$3=+13d6*qN8moy7faqz~dLT1PCtKLG(ECS|VWVga4UFfP~*9MjNN?ficRzgyCHY z%9KYrOS=|;jZ^r*08sO60S-CoLEs|K(gSfb{|a{{?a@M`n~4WTSdMoK(5s2RMMy~` s$c(K*f=hi6J%Btz59|T{%m2<NK=PyX3H#5^6K=#W9E4Og6j*%vKdFhjQ2+n{
--- a/dom/quota/test/unit/head.js +++ b/dom/quota/test/unit/head.js @@ -256,22 +256,34 @@ function getPersistedFromMetadata(readBu { const persistedPosition = 8; // Persisted state is stored in the 9th byte let view = readBuffer instanceof Uint8Array ? readBuffer : new Uint8Array(readBuffer); return !!view[persistedPosition]; } +function grabResultAndContinueHandler(request) +{ + testGenerator.next(request.result); +} + function grabUsageAndContinueHandler(request) { - testGenerator.next(request.usage); + testGenerator.next(request.result.usage); } -function getUsage(usageHandler) +function getUsage(usageHandler, getAll) +{ + let request = SpecialPowers._getQuotaManager().getUsage(usageHandler, getAll); + + return request; +} + +function getCurrentUsage(usageHandler) { let principal = Cc["@mozilla.org/systemprincipal;1"] .createInstance(Ci.nsIPrincipal); let request = SpecialPowers._getQuotaManager().getUsageForPrincipal(principal, usageHandler); return request;
--- a/dom/quota/test/unit/test_basics.js +++ b/dom/quota/test/unit/test_basics.js @@ -33,32 +33,32 @@ function* testSteps() info("Clearing"); clear(continueToNextStepSync); yield undefined; info("Getting usage"); - getUsage(grabUsageAndContinueHandler); + getCurrentUsage(grabUsageAndContinueHandler); let usage = yield undefined; ok(usage == 0, "Usage is zero"); info("Installing package"); // The profile contains just one empty IndexedDB database. The file // create_db.js in the package was run locally, specifically it was // temporarily added to xpcshell.ini and then executed: // mach xpcshell-test --interactive dom/quota/test/unit/create_db.js installPackage("basics_profile"); info("Getting usage"); - getUsage(grabUsageAndContinueHandler); + getCurrentUsage(grabUsageAndContinueHandler); usage = yield undefined; ok(usage > 0, "Usage is not zero"); info("Clearing"); clear(continueToNextStepSync); yield undefined;
new file mode 100644 --- /dev/null +++ b/dom/quota/test/unit/test_getUsage.js @@ -0,0 +1,127 @@ +/** + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +var testGenerator = testSteps(); + +function* testSteps() +{ + const origins = [ + { + origin: "http://example.com", + persisted: false, + usage: 49152 + }, + + { + origin: "http://localhost", + persisted: false, + usage: 147456 + }, + + { + origin: "http://www.mozilla.org", + persisted: true, + usage: 98304 + } + ]; + + const allOrigins = [ + { + origin: "chrome", + persisted: false, + usage: 147456 + }, + + { + origin: "http://example.com", + persisted: false, + usage: 49152 + }, + + { + origin: "http://localhost", + persisted: false, + usage: 147456 + }, + + { + origin: "http://www.mozilla.org", + persisted: true, + usage: 98304 + } + ]; + + function verifyResult(result, origins) { + ok(result instanceof Array, "Got an array object"); + ok(result.length == origins.length, "Correct number of elements"); + + info("Sorting elements"); + + result.sort(function(a, b) { + let originA = a.origin + let originB = b.origin + + if (originA < originB) { + return -1; + } + if (originA > originB) { + return 1; + } + return 0; + }); + + info("Verifying elements"); + + for (let i = 0; i < result.length; i++) { + let a = result[i]; + let b = origins[i]; + ok(a.origin == b.origin, "Origin equals"); + ok(a.persisted == b.persisted, "Persisted equals"); + ok(a.usage == b.usage, "Usage equals"); + } + } + + info("Clearing"); + + clear(continueToNextStepSync); + yield undefined; + + info("Getting usage"); + + getUsage(grabResultAndContinueHandler, /* getAll */ true); + let result = yield undefined; + + info("Verifying result"); + + verifyResult(result, []); + + info("Installing package"); + + // The profile contains IndexedDB databases placed across the repositories. + // The file create_db.js in the package was run locally, specifically it was + // temporarily added to xpcshell.ini and then executed: + // mach xpcshell-test --interactive dom/quota/test/unit/create_db.js + installPackage("getUsage_profile"); + + info("Getting usage"); + + getUsage(grabResultAndContinueHandler, /* getAll */ false); + result = yield undefined; + + info("Verifying result"); + + verifyResult(result, origins); + + info("Getting usage"); + + getUsage(grabResultAndContinueHandler, /* getAll */ true); + result = yield undefined; + + info("Verifying result"); + + verifyResult(result, allOrigins); + + finishTest(); +}
--- a/dom/quota/test/unit/test_unknownFiles.js +++ b/dom/quota/test/unit/test_unknownFiles.js @@ -126,42 +126,42 @@ function* testSteps() request = initChromeOrigin("persistent", continueToNextStepSync); yield undefined; ok(request.resultCode == NS_ERROR_UNEXPECTED, "Initialization failed"); info("Getting usage"); - request = getUsage(continueToNextStepSync); + request = getCurrentUsage(continueToNextStepSync); yield undefined; ok(request.resultCode == NS_ERROR_UNEXPECTED, "Get usage failed"); file.remove(/* recursive */ false); info("Getting usage"); - request = getUsage(continueToNextStepSync); + request = getCurrentUsage(continueToNextStepSync); yield undefined; ok(request.resultCode == NS_OK, "Get usage succeeded"); info("Initializing origin"); request = initChromeOrigin("persistent", continueToNextStepSync); yield undefined; ok(request.resultCode == NS_OK, "Initialization succeeded"); file = createFile(unknownFile); info("Getting usage"); - request = getUsage(continueToNextStepSync); + request = getCurrentUsage(continueToNextStepSync); yield undefined; ok(request.resultCode == NS_OK, "Get usage succeeded"); info("Clearing origin"); request = clearChromeOrigin(continueToNextStepSync); yield undefined;
--- a/dom/quota/test/unit/xpcshell.ini +++ b/dom/quota/test/unit/xpcshell.ini @@ -2,27 +2,29 @@ # 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/. [DEFAULT] head = head.js support-files = basics_profile.zip defaultStorageUpgrade_profile.zip + getUsage_profile.zip idbSubdirUpgrade1_profile.zip idbSubdirUpgrade2_profile.zip morgueCleanup_profile.zip obsoleteOriginAttributes_profile.zip originAttributesUpgrade_profile.zip removeAppsUpgrade_profile.zip storagePersistentUpgrade_profile.zip tempMetadataCleanup_profile.zip [test_basics.js] [test_defaultStorageUpgrade.js] +[test_getUsage.js] [test_idbSubdirUpgrade.js] [test_morgueCleanup.js] [test_obsoleteOriginAttributesUpgrade.js] [test_originAttributesUpgrade.js] [test_persist.js] [test_removeAppsUpgrade.js] [test_storagePersistentUpgrade.js] [test_tempMetadataCleanup.js]
--- a/dom/security/nsCSPService.cpp +++ b/dom/security/nsCSPService.cpp @@ -15,17 +15,16 @@ #include "nsIContentSecurityPolicy.h" #include "nsError.h" #include "nsIAsyncVerifyRedirectCallback.h" #include "nsAsyncRedirectVerifyHelper.h" #include "mozilla/Preferences.h" #include "nsIScriptError.h" #include "nsContentUtils.h" #include "nsContentPolicyUtils.h" -#include "nsPrincipal.h" using namespace mozilla; /* Keeps track of whether or not CSP is enabled */ bool CSPService::sCSPEnabled = true; static LazyLogModule gCspPRLog("CSP");
--- a/dom/security/test/csp/file_upgrade_insecure.html +++ b/dom/security/test/csp/file_upgrade_insecure.html @@ -52,16 +52,17 @@ var mySocket = new WebSocket("ws://example.com/tests/dom/security/test/csp/file_upgrade_insecure"); mySocket.onopen = function(e) { if (mySocket.url.includes("wss://")) { window.parent.postMessage({result: "websocket-ok"}, "*"); } else { window.parent.postMessage({result: "websocket-error"}, "*"); } + mySocket.close(); }; mySocket.onerror = function(e) { // debug information for Bug 1316305 dump(" xxx mySocket.onerror: (mySocket): " + mySocket + "\n"); dump(" xxx mySocket.onerror: (mySocket.url): " + mySocket.url + "\n"); dump(" xxx mySocket.onerror: (e): " + e + "\n"); dump(" xxx mySocket.onerror: (e.message): " + e.message + "\n"); window.parent.postMessage({result: "websocket-unexpected-error"}, "*");
--- a/dom/security/test/csp/file_upgrade_insecure_meta.html +++ b/dom/security/test/csp/file_upgrade_insecure_meta.html @@ -53,16 +53,17 @@ var mySocket = new WebSocket("ws://example.com/tests/dom/security/test/csp/file_upgrade_insecure"); mySocket.onopen = function(e) { if (mySocket.url.includes("wss://")) { window.parent.postMessage({result: "websocket-ok"}, "*"); } else { window.parent.postMessage({result: "websocket-error"}, "*"); } + mySocket.close(); }; mySocket.onerror = function(e) { window.parent.postMessage({result: "websocket-unexpected-error"}, "*"); }; </script> <!-- form action: (upgrade POST from http:// to https://) --> <iframe name='formFrame' id='formFrame'></iframe>
--- a/dom/worklet/Worklet.cpp +++ b/dom/worklet/Worklet.cpp @@ -200,19 +200,16 @@ public: (void) new XPCWrappedNativeScope(cx, globalObj); JS::CompileOptions compileOptions(cx); compileOptions.setIntroductionType("Worklet"); compileOptions.setFileAndLine(NS_ConvertUTF16toUTF8(mURL).get(), 0); compileOptions.setVersion(JSVERSION_DEFAULT); compileOptions.setIsRunOnce(true); - - // We only need the setNoScriptRval bit when compiling off-thread here, - // since otherwise nsJSUtils::EvaluateString will set it up for us. compileOptions.setNoScriptRval(true); JSAutoCompartment comp(cx, globalObj); JS::Rooted<JS::Value> unused(cx); if (!JS::Evaluate(cx, compileOptions, buffer, &unused)) { ErrorResult error; error.MightThrowJSException();
--- a/dom/xbl/nsXBLProtoImplField.cpp +++ b/dom/xbl/nsXBLProtoImplField.cpp @@ -422,24 +422,29 @@ nsXBLProtoImplField::InstallField(JS::Ha JS::Rooted<JSObject*> scopeObject(cx, xpc::GetScopeForXBLExecution(cx, aBoundNode, addonId)); NS_ENSURE_TRUE(scopeObject, NS_ERROR_OUT_OF_MEMORY); JSAutoCompartment ac(cx, scopeObject); JS::Rooted<JS::Value> result(cx); JS::CompileOptions options(cx); options.setFileAndLine(uriSpec.get(), mLineNumber) .setVersion(JSVERSION_LATEST); - nsJSUtils::EvaluateOptions evalOptions(cx); - if (!nsJSUtils::GetScopeChainForElement(cx, boundElement, - evalOptions.scopeChain)) { + JS::AutoObjectVector scopeChain(cx); + if (!nsJSUtils::GetScopeChainForElement(cx, boundElement, scopeChain)) { return NS_ERROR_OUT_OF_MEMORY; } - rv = nsJSUtils::EvaluateString(cx, nsDependentString(mFieldText, - mFieldTextLength), - scopeObject, options, evalOptions, &result); + rv = NS_OK; + { + nsJSUtils::ExecutionContext exec(cx, scopeObject); + exec.SetScopeChain(scopeChain); + exec.CompileAndExec(options, nsDependentString(mFieldText, + mFieldTextLength)); + rv = exec.ExtractReturnValue(&result); + } + if (NS_FAILED(rv)) { return rv; } if (rv == NS_SUCCESS_DOM_SCRIPT_EVALUATION_THREW) { // Report the exception now, before we try using the JSContext for // the JS_DefineUCProperty call. aes.ReportException();
--- a/extensions/gio/nsGIOProtocolHandler.cpp +++ b/extensions/gio/nsGIOProtocolHandler.cpp @@ -19,17 +19,17 @@ #include "nsNetCID.h" #include "nsNetUtil.h" #include "nsServiceManagerUtils.h" #include "nsIURI.h" #include "nsIAuthPrompt.h" #include "nsIChannel.h" #include "nsIInputStream.h" #include "nsIProtocolHandler.h" -#include "nsNullPrincipal.h" +#include "NullPrincipal.h" #include "mozilla/Monitor.h" #include "plstr.h" #include "prtime.h" #include <gio/gio.h> #include <algorithm> #define MOZ_GIO_SCHEME "moz-gio" #define MOZ_GIO_SUPPORTED_PROTOCOLS "network.gio.supported-protocols"
--- a/gfx/2d/RecordedEvent.cpp +++ b/gfx/2d/RecordedEvent.cpp @@ -1294,41 +1294,50 @@ RecordedSourceSurfaceCreation::~Recorded if (mDataOwned) { delete [] mData; } } bool RecordedSourceSurfaceCreation::PlayEvent(Translator *aTranslator) const { + if (!mData) { + return false; + } + RefPtr<SourceSurface> src = aTranslator->GetReferenceDrawTarget()-> CreateSourceSurfaceFromData(mData, mSize, mSize.width * BytesPerPixel(mFormat), mFormat); aTranslator->AddSourceSurface(mRefPtr, src); return true; } void RecordedSourceSurfaceCreation::RecordToStream(ostream &aStream) const { WriteElement(aStream, mRefPtr); WriteElement(aStream, mSize); WriteElement(aStream, mFormat); + MOZ_ASSERT(mData); for (int y = 0; y < mSize.height; y++) { aStream.write((const char*)mData + y * mStride, BytesPerPixel(mFormat) * mSize.width); } } RecordedSourceSurfaceCreation::RecordedSourceSurfaceCreation(istream &aStream) : RecordedEvent(SOURCESURFACECREATION), mDataOwned(true) { ReadElement(aStream, mRefPtr); ReadElement(aStream, mSize); ReadElement(aStream, mFormat); - mData = (uint8_t*)new char[mSize.width * mSize.height * BytesPerPixel(mFormat)]; - aStream.read((char*)mData, mSize.width * mSize.height * BytesPerPixel(mFormat)); + mData = (uint8_t*)new (fallible) char[mSize.width * mSize.height * BytesPerPixel(mFormat)]; + if (!mData) { + gfxWarning() << "RecordedSourceSurfaceCreation failed to allocate data"; + } else { + aStream.read((char*)mData, mSize.width * mSize.height * BytesPerPixel(mFormat)); + } } void RecordedSourceSurfaceCreation::OutputSimpleEventInfo(stringstream &aStringStream) const { aStringStream << "[" << mRefPtr << "] SourceSurface created (Size: " << mSize.width << "x" << mSize.height << ")"; }
--- a/gfx/skia/skia/src/core/SkScan_Path.cpp +++ b/gfx/skia/skia/src/core/SkScan_Path.cpp @@ -587,39 +587,45 @@ static bool clip_to_limit(const SkRegion if (limitR.contains(orig.getBounds())) { return false; } reduced->op(orig, limitR, SkRegion::kIntersect_Op); return true; } /** - * Variant of SkScalarRoundToInt, identical to SkDScalarRoundToInt except when the input fraction - * is 0.5. In this case only, round the value down. This is used to round the top and left - * of a rectangle, and corresponds to the way the scan converter treats the top and left edges. + * Variants of SkScalarRoundToInt, identical to SkDScalarRoundToInt except when the input fraction + * is 0.5. When SK_RASTERIZE_EVEN_ROUNDING is enabled, we must bias the result before rounding to + * account for potential FDot6 rounding edge-cases. + */ +#ifdef SK_RASTERIZE_EVEN_ROUNDING +static const double kRoundBias = 0.5 / SK_FDot6One; +#else +static const double kRoundBias = 0.0; +#endif + +/** + * Round the value down. This is used to round the top and left of a rectangle, + * and corresponds to the way the scan converter treats the top and left edges. */ static inline int round_down_to_int(SkScalar x) { double xx = x; - xx += 0.5; - double floorXX = floor(xx); - return (int)floorXX - (xx == floorXX); + xx -= 0.5 + kRoundBias; + return (int)ceil(xx); } -#ifdef SK_RASTERIZE_EVEN_ROUNDING /** - * Variant of SkDScalarRoundToInt that allows offseting the input by a small fraction - * while trying to preserve intermediate double-precision (rather than directly adding - * the bias to the input at lower single-precision). + * Round the value up. This is used to round the bottom and right of a rectangle, + * and corresponds to the way the scan converter treats the bottom and right edges. */ -static inline int round_biased_to_int(SkScalar x, SkScalar bias) { +static inline int round_up_to_int(SkScalar x) { double xx = x; - xx += 0.5 + bias; + xx += 0.5 + kRoundBias; return (int)floor(xx); } -#endif /** * Variant of SkRect::round() that explicitly performs the rounding step (i.e. floor(x + 0.5)) * using double instead of SkScalar (float). It does this by calling SkDScalarRoundToInt(), * which may be slower than calling SkScalarRountToInt(), but gives slightly more accurate * results. Also rounds top and left using double, flooring when the fraction is exactly 0.5f. * * e.g. @@ -630,36 +636,31 @@ static inline int round_biased_to_int(Sk * SkASSERT(0 == ileft); // <--- succeeds * SkScalar right = 0.49999997f; * int iright = SkScalarRoundToInt(right); * SkASSERT(0 == iright); // <--- fails * iright = SkDScalarRoundToInt(right); * SkASSERT(0 == iright); // <--- succeeds * * - * If using SK_RASTERIZE_EVEN_ROUNDING, we need to ensure that bottom and right account for - * edges bounded by this rect being rounded to FDot6 format before being later rounded to an - * integer. For example, a value like 0.499 can be below 0.5, but round to 0.5 as FDot6, which - * would finally round to the integer 1, instead of just rounding to 0. + * If using SK_RASTERIZE_EVEN_ROUNDING, we need to ensure we account for edges bounded by this + * rect being rounded to FDot6 format before being later rounded to an integer. For example, a + * value like 0.499 can be below 0.5, but round to 0.5 as FDot6, which would finally round to + * the integer 1, instead of just rounding to 0. * * To handle this, a small bias of half an FDot6 increment is added before actually rounding to * an integer value. This simulates the rounding of SkScalarRoundToFDot6 without incurring the * range loss of converting to FDot6 format first, preserving the integer range for the SkIRect. - * Thus, bottom and right are rounded in this manner (biased up), ensuring the rect is large enough. - * Top and left can round as normal since they will round (biased down) to values less or equal - * to the desired rect origin. + * Thus, bottom and right are rounded in this manner (biased up), ensuring the rect is large + * enough. */ static void round_asymmetric_to_int(const SkRect& src, SkIRect* dst) { SkASSERT(dst); dst->set(round_down_to_int(src.fLeft), round_down_to_int(src.fTop), -#ifdef SK_RASTERIZE_EVEN_ROUNDING - round_biased_to_int(src.fRight, 0.5f / SK_FDot6One), round_biased_to_int(src.fBottom, 0.5f / SK_FDot6One)); -#else - SkDScalarRoundToInt(src.fRight), SkDScalarRoundToInt(src.fBottom)); -#endif + round_up_to_int(src.fRight), round_up_to_int(src.fBottom)); } void SkScan::FillPath(const SkPath& path, const SkRegion& origClip, SkBlitter* blitter) { if (origClip.isEmpty()) { return; }
deleted file mode 100644 --- a/gfx/thebes/gfxFontconfigFonts.cpp +++ /dev/null @@ -1,2262 +0,0 @@ -/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "prlink.h" -#include "gfxTypes.h" - -#include "nsTArray.h" - -#include "gfxContext.h" -#ifdef MOZ_WIDGET_GTK -#include "gfxPlatformGtk.h" -#endif -#include "gfxFontconfigFonts.h" -#include "gfxFT2FontBase.h" -#include "gfxFT2Utils.h" -#include "harfbuzz/hb.h" -#include "harfbuzz/hb-glib.h" -#include "harfbuzz/hb-ot.h" -#include "nsUnicodeProperties.h" -#include "nsUnicodeScriptCodes.h" -#include "gfxFontconfigUtils.h" -#include "gfxUserFontSet.h" -#include "gfxFontConstants.h" -#include "nsGkAtoms.h" -#include "nsILanguageAtomService.h" -#include "nsServiceManagerUtils.h" - -#include <cairo.h> -#include <cairo-ft.h> -#include "mozilla/gfx/HelpersCairo.h" - -#include <fontconfig/fcfreetype.h> -#include <pango/pango.h> - -#include FT_TRUETYPE_TABLES_H - -#ifdef MOZ_WIDGET_GTK -#include <gdk/gdk.h> -#endif - -#include <math.h> - -using namespace mozilla; -using namespace mozilla::unicode; - -#define PRINTING_FC_PROPERTY "gfx.printing" - -static PangoLanguage *GuessPangoLanguage(nsIAtom *aLanguage); - -static cairo_scaled_font_t * -CreateScaledFont(FcPattern *aPattern, cairo_font_face_t *aFace); - -static FT_Library gFTLibrary; - -// FC_FAMILYLANG and FC_FULLNAME were introduced in fontconfig-2.2.97 -// and so fontconfig-2.3.0 (2005). -#ifndef FC_FAMILYLANG -#define FC_FAMILYLANG "familylang" -#endif -#ifndef FC_FULLNAME -#define FC_FULLNAME "fullname" -#endif - -static PRFuncPtr -FindFunctionSymbol(const char *name) -{ - PRLibrary *lib = nullptr; - PRFuncPtr result = PR_FindFunctionSymbolAndLibrary(name, &lib); - if (lib) { - PR_UnloadLibrary(lib); - } - - return result; -} - -static bool HasChar(FcPattern *aFont, FcChar32 wc) -{ - FcCharSet *charset = nullptr; - FcPatternGetCharSet(aFont, FC_CHARSET, 0, &charset); - - return charset && FcCharSetHasChar(charset, wc); -} - -/** - * gfxFcFontEntry: - * - * An abstract base class of for gfxFontEntry implementations used by - * gfxFcFont and gfxUserFontSet. - */ - -class gfxFcFontEntry : public gfxFontEntry { -public: - // For all FontEntrys attached to gfxFcFonts, there will be only one - // pattern in this array. This is always a font pattern, not a fully - // resolved pattern. gfxFcFont only uses this to construct a PangoFont. - // - // FontEntrys for src:local() fonts in gfxUserFontSet may return more than - // one pattern. (See comment in gfxUserFcFontEntry.) - const nsTArray< nsCountedRef<FcPattern> >& GetPatterns() - { - return mPatterns; - } - - static gfxFcFontEntry *LookupFontEntry(cairo_font_face_t *aFace) - { - return static_cast<gfxFcFontEntry*> - (cairo_font_face_get_user_data(aFace, &sFontEntryKey)); - } - - // override the gfxFontEntry impl to read the name from fontconfig - // instead of trying to get the 'name' table, as we don't implement - // GetFontTable() here - virtual nsString RealFaceName(); - - // This is needed to make gfxFontEntry::HasCharacter(aCh) work. - virtual bool TestCharacterMap(uint32_t aCh) - { - for (uint32_t i = 0; i < mPatterns.Length(); ++i) { - if (HasChar(mPatterns[i], aCh)) { - return true; - } - } - return false; - } - -protected: - explicit gfxFcFontEntry(const nsAString& aName) - : gfxFontEntry(aName) - { - } - - // One pattern is the common case and some subclasses rely on successful - // addition of the first element to the array. - AutoTArray<nsCountedRef<FcPattern>,1> mPatterns; - - static cairo_user_data_key_t sFontEntryKey; -}; - -cairo_user_data_key_t gfxFcFontEntry::sFontEntryKey; - -nsString -gfxFcFontEntry::RealFaceName() -{ - FcChar8 *name; - if (!mPatterns.IsEmpty()) { - if (FcPatternGetString(mPatterns[0], - FC_FULLNAME, 0, &name) == FcResultMatch) { - return NS_ConvertUTF8toUTF16((const char*)name); - } - if (FcPatternGetString(mPatterns[0], - FC_FAMILY, 0, &name) == FcResultMatch) { - NS_ConvertUTF8toUTF16 result((const char*)name); - if (FcPatternGetString(mPatterns[0], - FC_STYLE, 0, &name) == FcResultMatch) { - result.Append(' '); - AppendUTF8toUTF16((const char*)name, result); - } - return result; - } - } - // fall back to gfxFontEntry implementation (only works for sfnt fonts) - return gfxFontEntry::RealFaceName(); -} - -/** - * gfxSystemFcFontEntry: - * - * An implementation of gfxFcFontEntry used by gfxFcFonts for system fonts, - * including those from regular family-name based font selection as well as - * those from src:local(). - * - * All gfxFcFonts using the same cairo_font_face_t share the same FontEntry. - */ - -class gfxSystemFcFontEntry : public gfxFcFontEntry { -public: - // For memory efficiency, aFontPattern should be a font pattern, - // not a fully resolved pattern. - gfxSystemFcFontEntry(cairo_font_face_t *aFontFace, - FcPattern *aFontPattern, - const nsAString& aName) - : gfxFcFontEntry(aName), mFontFace(aFontFace), - mFTFace(nullptr), mFTFaceInitialized(false) - { - cairo_font_face_reference(mFontFace); - cairo_font_face_set_user_data(mFontFace, &sFontEntryKey, this, nullptr); - - // mPatterns is an AutoTArray with 1 space always available, so the - // AppendElement always succeeds. - // FIXME: Make this infallible after bug 968520 is done. - MOZ_ALWAYS_TRUE(mPatterns.AppendElement(fallible)); - mPatterns[0] = aFontPattern; - - FcChar8 *name; - if (FcPatternGetString(aFontPattern, - FC_FAMILY, 0, &name) == FcResultMatch) { - mFamilyName = NS_ConvertUTF8toUTF16((const char*)name); - } - } - - ~gfxSystemFcFontEntry() - { - cairo_font_face_set_user_data(mFontFace, - &sFontEntryKey, - nullptr, - nullptr); - cairo_font_face_destroy(mFontFace); - } - - virtual void ForgetHBFace() override; - virtual void ReleaseGrFace(gr_face* aFace) override; - -protected: - virtual nsresult - CopyFontTable(uint32_t aTableTag, nsTArray<uint8_t>& aBuffer) override; - - void MaybeReleaseFTFace(); - -private: - cairo_font_face_t *mFontFace; - FT_Face mFTFace; - bool mFTFaceInitialized; -}; - -nsresult -gfxSystemFcFontEntry::CopyFontTable(uint32_t aTableTag, - nsTArray<uint8_t>& aBuffer) -{ - if (!mFTFaceInitialized) { - mFTFaceInitialized = true; - FcChar8 *filename; - if (FcPatternGetString(mPatterns[0], FC_FILE, 0, &filename) != FcResultMatch) { - return NS_ERROR_FAILURE; - } - int index; - if (FcPatternGetInteger(mPatterns[0], FC_INDEX, 0, &index) != FcResultMatch) { - index = 0; // default to 0 if not found in pattern - } - if (FT_New_Face(gfxPangoFontGroup::GetFTLibrary(), - (const char*)filename, index, &mFTFace) != 0) { - return NS_ERROR_FAILURE; - } - } - - if (!mFTFace) { - return NS_ERROR_NOT_AVAILABLE; - } - - FT_ULong length = 0; - if (FT_Load_Sfnt_Table(mFTFace, aTableTag, 0, nullptr, &length) != 0) { - return NS_ERROR_NOT_AVAILABLE; - } - if (!aBuffer.SetLength(length, fallible)) { - return NS_ERROR_OUT_OF_MEMORY; - } - if (FT_Load_Sfnt_Table(mFTFace, aTableTag, 0, aBuffer.Elements(), &length) != 0) { - aBuffer.Clear(); - return NS_ERROR_FAILURE; - } - - return NS_OK; -} - -void -gfxSystemFcFontEntry::MaybeReleaseFTFace() -{ - // don't release if either HB or Gr face still exists - if (mHBFace || mGrFace) { - return; - } - if (mFTFace) { - FT_Done_Face(mFTFace); - mFTFace = nullptr; - } - mFTFaceInitialized = false; -} - -void -gfxSystemFcFontEntry::ForgetHBFace() -{ - gfxFontEntry::ForgetHBFace(); - MaybeReleaseFTFace(); -} - -void -gfxSystemFcFontEntry::ReleaseGrFace(gr_face* aFace) -{ - gfxFontEntry::ReleaseGrFace(aFace); - MaybeReleaseFTFace(); -} - -// A namespace for @font-face family names in FcPatterns so that fontconfig -// aliases do not pick up families from @font-face rules and so that -// fontconfig rules can distinguish between web fonts and platform fonts. -// http://lists.freedesktop.org/archives/fontconfig/2008-November/003037.html -#define FONT_FACE_FAMILY_PREFIX "@font-face:" - -/** - * gfxUserFcFontEntry: - * - * An abstract class for objects in a gfxUserFontSet that can provide - * FcPattern* handles to fonts. - * - * Separate implementations of this class support local fonts from src:local() - * and web fonts from src:url(). - */ - -// There is a one-to-one correspondence between gfxUserFcFontEntry objects and -// @font-face rules, but sometimes a one-to-many correspondence between font -// entries and font patterns. -// -// http://www.w3.org/TR/2002/WD-css3-webfonts-20020802#font-descriptions -// provided a font-size descriptor to specify the sizes supported by the face, -// but the "Editor's Draft 27 June 2008" -// http://dev.w3.org/csswg/css3-fonts/#font-resources does not provide such a -// descriptor, and Mozilla does not recognize such a descriptor. -// -// Font face names used in src:local() also do not usually specify a size. -// -// PCF format fonts have each size in a different file, and each of these -// files is referenced by its own pattern, but really these are each -// different sizes of one face with one name. -// -// Multiple patterns in an entry also effectively deals with a set of -// PostScript Type 1 font files that all have the same face name but are in -// several files because of the limit on the number of glyphs in a Type 1 font -// file. (e.g. Computer Modern.) - -class gfxUserFcFontEntry : public gfxFcFontEntry { -protected: - explicit gfxUserFcFontEntry(const nsAString& aFontName, - uint16_t aWeight, - int16_t aStretch, - uint8_t aStyle) - : gfxFcFontEntry(aFontName) - { - mStyle = aStyle; - mWeight = aWeight; - mStretch = aStretch; - } - - // Helper function to change a pattern so that it matches the CSS style - // descriptors and so gets properly sorted in font selection. This also - // avoids synthetic style effects being added by the renderer when the - // style of the font itself does not match the descriptor provided by the - // author. - void AdjustPatternToCSS(FcPattern *aPattern); -}; - -void -gfxUserFcFontEntry::AdjustPatternToCSS(FcPattern *aPattern) -{ - int fontWeight = -1; - FcPatternGetInteger(aPattern, FC_WEIGHT, 0, &fontWeight); - int cssWeight = gfxFontconfigUtils::FcWeightForBaseWeight(mWeight / 100); - if (cssWeight != fontWeight) { - FcPatternDel(aPattern, FC_WEIGHT); - FcPatternAddInteger(aPattern, FC_WEIGHT, cssWeight); - } - - int fontSlant; - FcResult res = FcPatternGetInteger(aPattern, FC_SLANT, 0, &fontSlant); - // gfxFontEntry doesn't understand the difference between oblique - // and italic. - if (res != FcResultMatch || - IsItalic() != (fontSlant != FC_SLANT_ROMAN)) { - FcPatternDel(aPattern, FC_SLANT); - FcPatternAddInteger(aPattern, FC_SLANT, - IsItalic() ? FC_SLANT_OBLIQUE : FC_SLANT_ROMAN); - } - - int fontWidth = -1; - FcPatternGetInteger(aPattern, FC_WIDTH, 0, &fontWidth); - int cssWidth = gfxFontconfigUtils::FcWidthForThebesStretch(mStretch); - if (cssWidth != fontWidth) { - FcPatternDel(aPattern, FC_WIDTH); - FcPatternAddInteger(aPattern, FC_WIDTH, cssWidth); - } - - // Ensure that there is a fullname property (if there is a family - // property) so that fontconfig rules can identify the real name of the - // font, because the family property will be replaced. - FcChar8 *unused; - if (FcPatternGetString(aPattern, - FC_FULLNAME, 0, &unused) == FcResultNoMatch) { - nsAutoCString fullname; - if (gfxFontconfigUtils::GetFullnameFromFamilyAndStyle(aPattern, - &fullname)) { - FcPatternAddString(aPattern, FC_FULLNAME, - gfxFontconfigUtils::ToFcChar8(fullname)); - } - } - - nsAutoCString family; - family.Append(FONT_FACE_FAMILY_PREFIX); - AppendUTF16toUTF8(Name(), family); - - FcPatternDel(aPattern, FC_FAMILY); - FcPatternDel(aPattern, FC_FAMILYLANG); - FcPatternAddString(aPattern, FC_FAMILY, - gfxFontconfigUtils::ToFcChar8(family)); -} - -/** - * gfxLocalFcFontEntry: - * - * An implementation of gfxUserFcFontEntry for local fonts from src:local(). - * - * This class is used only in gfxUserFontSet and for providing FcPattern* - * handles to system fonts for font selection. gfxFcFonts created from these - * patterns will use gfxSystemFcFontEntrys, which may be shared with - * gfxFcFonts from regular family-name based font selection. - */ - -class gfxLocalFcFontEntry : public gfxUserFcFontEntry { -public: - gfxLocalFcFontEntry(const nsAString& aFontName, - uint16_t aWeight, - int16_t aStretch, - uint8_t aStyle, - const nsTArray< nsCountedRef<FcPattern> >& aPatterns) - : gfxUserFcFontEntry(aFontName, aWeight, aStretch, aStyle) - { - if (!mPatterns.SetCapacity(aPatterns.Length(), fallible)) - return; // OOM - - for (uint32_t i = 0; i < aPatterns.Length(); ++i) { - FcPattern *pattern = FcPatternDuplicate(aPatterns.ElementAt(i)); - if (!pattern) - return; // OOM - - AdjustPatternToCSS(pattern); - - // FIXME: Make this infallible after bug 968520 is done. - MOZ_ALWAYS_TRUE(mPatterns.AppendElement(fallible)); - mPatterns[i].own(pattern); - } - mIsLocalUserFont = true; - } -}; - -/** - * gfxDownloadedFcFontEntry: - * - * An implementation of gfxFcFontEntry for web fonts from src:url(). - * - * When a cairo_font_face_t is created for these fonts, the cairo_font_face_t - * keeps a reference to the FontEntry to keep the font data alive. - */ - -class gfxDownloadedFcFontEntry : public gfxUserFcFontEntry { -public: - // This takes ownership of the face and its underlying data - gfxDownloadedFcFontEntry(const nsAString& aFontName, - uint16_t aWeight, - int16_t aStretch, - uint8_t aStyle, - const uint8_t *aData, FT_Face aFace) - : gfxUserFcFontEntry(aFontName, aWeight, aStretch, aStyle), - mFontData(aData), mFace(aFace) - { - NS_PRECONDITION(aFace != nullptr, "aFace is NULL!"); - mIsDataUserFont = true; - InitPattern(); - } - - virtual ~gfxDownloadedFcFontEntry(); - - // Returns true on success - bool SetCairoFace(cairo_font_face_t *aFace); - - virtual hb_blob_t* GetFontTable(uint32_t aTableTag) override; - -protected: - void InitPattern(); - - // mFontData holds the data used to instantiate the FT_Face; - // this has to persist until we are finished with the face, - // then be released with free(). - const uint8_t* mFontData; - - FT_Face mFace; -}; - -// A property for recording gfxDownloadedFcFontEntrys on FcPatterns. -static const char *kFontEntryFcProp = "-moz-font-entry"; - -static FcBool AddDownloadedFontEntry(FcPattern *aPattern, - gfxDownloadedFcFontEntry *aFontEntry) -{ - FcValue value; - value.type = FcTypeFTFace; // void* field of union - value.u.f = aFontEntry; - - return FcPatternAdd(aPattern, kFontEntryFcProp, value, FcFalse); -} - -static FcBool DelDownloadedFontEntry(FcPattern *aPattern) -{ - return FcPatternDel(aPattern, kFontEntryFcProp); -} - -static gfxDownloadedFcFontEntry *GetDownloadedFontEntry(FcPattern *aPattern) -{ - FcValue value; - if (FcPatternGet(aPattern, kFontEntryFcProp, 0, &value) != FcResultMatch) - return nullptr; - - if (value.type != FcTypeFTFace) { - NS_NOTREACHED("Wrong type for -moz-font-entry font property"); - return nullptr; - } - - return static_cast<gfxDownloadedFcFontEntry*>(value.u.f); -} - -gfxDownloadedFcFontEntry::~gfxDownloadedFcFontEntry() -{ - if (mPatterns.Length() != 0) { - // Remove back reference to this font entry and the face in case - // anyone holds a reference to the pattern. - NS_ASSERTION(mPatterns.Length() == 1, - "More than one pattern in gfxDownloadedFcFontEntry!"); - DelDownloadedFontEntry(mPatterns[0]); - FcPatternDel(mPatterns[0], FC_FT_FACE); - } - FT_Done_Face(mFace); - free((void*)mFontData); -} - -typedef FcPattern* (*QueryFaceFunction)(const FT_Face face, - const FcChar8 *file, int id, - FcBlanks *blanks); - -void -gfxDownloadedFcFontEntry::InitPattern() -{ - static QueryFaceFunction sQueryFacePtr = - reinterpret_cast<QueryFaceFunction> - (FindFunctionSymbol("FcFreeTypeQueryFace")); - FcPattern *pattern; - - // FcFreeTypeQueryFace is the same function used to construct patterns for - // system fonts and so is the preferred function to use for this purpose. - // This will set up the langset property, which helps with sorting, and - // the foundry, fullname, and fontversion properties, which properly - // identify the font to fontconfig rules. However, FcFreeTypeQueryFace is - // available only from fontconfig-2.4.2 (December 2006). (CentOS 5.0 has - // fontconfig-2.4.1.) - if (sQueryFacePtr) { - // The "file" argument cannot be nullptr (in fontconfig-2.6.0 at - // least). The dummy file passed here is removed below. - // - // When fontconfig scans the system fonts, FcConfigGetBlanks(nullptr) - // is passed as the "blanks" argument, which provides that unexpectedly - // blank glyphs are elided. Here, however, we pass nullptr for - // "blanks", effectively assuming that, if the font has a blank glyph, - // then the author intends any associated character to be rendered - // blank. - pattern = - (*sQueryFacePtr)(mFace, - gfxFontconfigUtils::ToFcChar8(""), - 0, - nullptr); - if (!pattern) - // Either OOM, or fontconfig chose to skip this font because it - // has "no encoded characters", which I think means "BDF and PCF - // fonts which are not in Unicode (or the effectively equivalent - // ISO Latin-1) encoding". - return; - - // These properties don't make sense for this face without a file. - FcPatternDel(pattern, FC_FILE); - FcPatternDel(pattern, FC_INDEX); - - } else { - // Do the minimum necessary to construct a pattern for sorting. - - // FC_CHARSET is vital to determine which characters are supported. - nsAutoRef<FcCharSet> charset(FcFreeTypeCharSet(mFace, nullptr)); - // If there are no characters then assume we don't know how to read - // this font. - if (!charset || FcCharSetCount(charset) == 0) - return; - - pattern = FcPatternCreate(); - FcPatternAddCharSet(pattern, FC_CHARSET, charset); - - // FC_PIXEL_SIZE can be important for font selection of fixed-size - // fonts. - if (!(mFace->face_flags & FT_FACE_FLAG_SCALABLE)) { - for (FT_Int i = 0; i < mFace->num_fixed_sizes; ++i) { -#if HAVE_FT_BITMAP_SIZE_Y_PPEM - double size = FLOAT_FROM_26_6(mFace->available_sizes[i].y_ppem); -#else - double size = mFace->available_sizes[i].height; -#endif - FcPatternAddDouble (pattern, FC_PIXEL_SIZE, size); - } - - // Not sure whether this is important; - // imitating FcFreeTypeQueryFace: - FcPatternAddBool (pattern, FC_ANTIALIAS, FcFalse); - } - - // Setting up the FC_LANGSET property is very difficult with the APIs - // available prior to FcFreeTypeQueryFace. Having no FC_LANGSET - // property seems better than having a property with an empty LangSet. - // With no FC_LANGSET property, fontconfig sort functions will - // consider this face to have the same priority as (otherwise equal) - // faces that have support for the primary requested language, but - // will not consider any language to have been satisfied (and so will - // continue to look for a face with language support in fallback - // fonts). - } - - AdjustPatternToCSS(pattern); - - FcPatternAddFTFace(pattern, FC_FT_FACE, mFace); - AddDownloadedFontEntry(pattern, this); - - // There is never more than one pattern - // FIXME: Make this infallible after bug 968520 is done. - MOZ_ALWAYS_TRUE(mPatterns.AppendElement(fallible)); - mPatterns[0].own(pattern); -} - -static void ReleaseDownloadedFontEntry(void *data) -{ - gfxDownloadedFcFontEntry *downloadedFontEntry = - static_cast<gfxDownloadedFcFontEntry*>(data); - NS_RELEASE(downloadedFontEntry); -} - -bool gfxDownloadedFcFontEntry::SetCairoFace(cairo_font_face_t *aFace) -{ - if (CAIRO_STATUS_SUCCESS != - cairo_font_face_set_user_data(aFace, &sFontEntryKey, this, - ReleaseDownloadedFontEntry)) - return false; - - // Hold a reference to this font entry to keep the font face data. - NS_ADDREF(this); - return true; -} - -hb_blob_t * -gfxDownloadedFcFontEntry::GetFontTable(uint32_t aTableTag) -{ - // The entry already owns the (sanitized) sfnt data in mFontData, - // so we can just return a blob that "wraps" the appropriate chunk of it. - // The blob should not attempt to free its data, as the entire sfnt data - // will be freed when the font entry is deleted. - return gfxFontUtils::GetTableFromFontData(mFontData, aTableTag); -} - -/* - * gfxFcFont - * - * This is a gfxFont implementation using a CAIRO_FONT_TYPE_FT - * cairo_scaled_font created from an FcPattern. - */ - -class gfxFcFont : public gfxFontconfigFontBase { -public: - virtual ~gfxFcFont(); - static already_AddRefed<gfxFcFont> - GetOrMakeFont(FcPattern *aRequestedPattern, FcPattern *aFontPattern, - const gfxFontStyle *aFontStyle); - - // return a cloned font resized and offset to simulate sub/superscript glyphs - virtual already_AddRefed<gfxFont> - GetSubSuperscriptFont(int32_t aAppUnitsPerDevPixel) override; - -protected: - virtual already_AddRefed<gfxFont> MakeScaledFont(gfxFontStyle *aFontStyle, - gfxFloat aFontScale); - virtual already_AddRefed<gfxFont> GetSmallCapsFont() override; - -private: - gfxFcFont(cairo_scaled_font_t *aCairoFont, - FcPattern *aPattern, - gfxFcFontEntry *aFontEntry, - const gfxFontStyle *aFontStyle); - - // key for locating a gfxFcFont corresponding to a cairo_scaled_font - static cairo_user_data_key_t sGfxFontKey; -}; - -/** - * gfxFcFontSet: - * - * Translation from a desired FcPattern to a sorted set of font references - * (fontconfig cache data) and (when needed) fonts. - */ - -class gfxFcFontSet final { -public: - NS_INLINE_DECL_REFCOUNTING(gfxFcFontSet) - - explicit gfxFcFontSet(FcPattern *aPattern, - gfxUserFontSet *aUserFontSet) - : mSortPattern(aPattern), mUserFontSet(aUserFontSet), - mFcFontsTrimmed(0), - mHaveFallbackFonts(false) - { - bool waitForUserFont; - mFcFontSet = SortPreferredFonts(waitForUserFont); - mWaitingForUserFont = waitForUserFont; - } - - // A reference is held by the FontSet. - // The caller may add a ref to keep the font alive longer than the FontSet. - gfxFcFont *GetFontAt(uint32_t i, const gfxFontStyle *aFontStyle) - { - if (i >= mFonts.Length() || !mFonts[i].mFont) { - // GetFontPatternAt sets up mFonts - FcPattern *fontPattern = GetFontPatternAt(i); - if (!fontPattern) - return nullptr; - - mFonts[i].mFont = - gfxFcFont::GetOrMakeFont(mSortPattern, fontPattern, - aFontStyle); - } - return mFonts[i].mFont; - } - - FcPattern *GetFontPatternAt(uint32_t i); - - bool WaitingForUserFont() const { - return mWaitingForUserFont; - } - -private: - // Private destructor, to discourage deletion outside of Release(): - ~gfxFcFontSet() - { - } - - nsReturnRef<FcFontSet> SortPreferredFonts(bool& aWaitForUserFont); - nsReturnRef<FcFontSet> SortFallbackFonts(); - - struct FontEntry { - explicit FontEntry(FcPattern *aPattern) : mPattern(aPattern) {} - nsCountedRef<FcPattern> mPattern; - RefPtr<gfxFcFont> mFont; - }; - - struct LangSupportEntry { - LangSupportEntry(FcChar8 *aLang, FcLangResult aSupport) : - mLang(aLang), mBestSupport(aSupport) {} - FcChar8 *mLang; - FcLangResult mBestSupport; - }; - -public: - // public for nsTArray - class LangComparator { - public: - bool Equals(const LangSupportEntry& a, const FcChar8 *b) const - { - return FcStrCmpIgnoreCase(a.mLang, b) == 0; - } - }; - -private: - // The requested pattern - nsCountedRef<FcPattern> mSortPattern; - // Fonts from @font-face rules - RefPtr<gfxUserFontSet> mUserFontSet; - // A (trimmed) list of font patterns and fonts that is built up as - // required. - nsTArray<FontEntry> mFonts; - // Holds a list of font patterns that will be trimmed. This is first set - // to a list of preferred fonts. Then, if/when all the preferred fonts - // have been trimmed and added to mFonts, this is set to a list of - // fallback fonts. - nsAutoRef<FcFontSet> mFcFontSet; - // The set of characters supported by the fonts in mFonts. - nsAutoRef<FcCharSet> mCharSet; - // The index of the next font in mFcFontSet that has not yet been - // considered for mFonts. - int mFcFontsTrimmed; - // True iff fallback fonts are either stored in mFcFontSet or have been - // trimmed and added to mFonts (so that mFcFontSet is nullptr). - bool mHaveFallbackFonts; - // True iff there was a user font set with pending downloads, - // so the set may be updated when downloads complete - bool mWaitingForUserFont; -}; - -// Find the FcPattern for an @font-face font suitable for CSS family |aFamily| -// and style |aStyle| properties. -static const nsTArray< nsCountedRef<FcPattern> >* -FindFontPatterns(gfxUserFontSet *mUserFontSet, - const nsACString &aFamily, uint8_t aStyle, - uint16_t aWeight, int16_t aStretch, - bool& aWaitForUserFont) -{ - // Convert to UTF16 - NS_ConvertUTF8toUTF16 utf16Family(aFamily); - - // needsBold is not used here. Instead synthetic bold is enabled through - // FcFontRenderPrepare when the weight in the requested pattern is - // compared against the weight in the font pattern. - bool needsBold; - - gfxFontStyle style; - style.style = aStyle; - style.weight = aWeight; - style.stretch = aStretch; - - gfxUserFcFontEntry *fontEntry = nullptr; - gfxFontFamily *family = mUserFontSet->LookupFamily(utf16Family); - if (family) { - gfxUserFontEntry* userFontEntry = - mUserFontSet->FindUserFontEntryAndLoad(family, style, needsBold, - aWaitForUserFont); - if (userFontEntry) { - fontEntry = static_cast<gfxUserFcFontEntry*> - (userFontEntry->GetPlatformFontEntry()); - } - - // Accept synthetic oblique for italic and oblique. - // xxx - this isn't really ideal behavior, for docs that only use a - // single italic face it will also pull down the normal face - // and probably never use it - if (!fontEntry && aStyle != NS_FONT_STYLE_NORMAL) { - style.style = NS_FONT_STYLE_NORMAL; - userFontEntry = - mUserFontSet->FindUserFontEntryAndLoad(family, style, - needsBold, - aWaitForUserFont); - if (userFontEntry) { - fontEntry = static_cast<gfxUserFcFontEntry*> - (userFontEntry->GetPlatformFontEntry()); - } - } - } - - if (!fontEntry) { - return nullptr; - } - - return &fontEntry->GetPatterns(); -} - -typedef FcBool (*FcPatternRemoveFunction)(FcPattern *p, const char *object, - int id); - -// FcPatternRemove is available in fontconfig-2.3.0 (2005) -static FcBool -moz_FcPatternRemove(FcPattern *p, const char *object, int id) -{ - static FcPatternRemoveFunction sFcPatternRemovePtr = - reinterpret_cast<FcPatternRemoveFunction> - (FindFunctionSymbol("FcPatternRemove")); - - if (!sFcPatternRemovePtr) - return FcFalse; - - return (*sFcPatternRemovePtr)(p, object, id); -} - -// fontconfig prefers a matching family or lang to pixelsize of bitmap -// fonts. CSS suggests a tolerance of 20% on pixelsize. -static bool -SizeIsAcceptable(FcPattern *aFont, double aRequestedSize) -{ - double size; - int v = 0; - while (FcPatternGetDouble(aFont, - FC_PIXEL_SIZE, v, &size) == FcResultMatch) { - ++v; - if (5.0 * fabs(size - aRequestedSize) < aRequestedSize) - return true; - } - - // No size means scalable - return v == 0; -} - -// Sorting only the preferred fonts first usually saves having to sort through -// every font on the system. -nsReturnRef<FcFontSet> -gfxFcFontSet::SortPreferredFonts(bool &aWaitForUserFont) -{ - aWaitForUserFont = false; - - gfxFontconfigUtils *utils = gfxFontconfigUtils::GetFontconfigUtils(); - if (!utils) - return nsReturnRef<FcFontSet>(); - - // The list of families in mSortPattern has values with both weak and - // strong bindings. Values with strong bindings should be preferred. - // Values with weak bindings are default fonts that should be considered - // only when the font provides the best support for a requested language - // or after other fonts have satisfied all the requested languages. - // - // There are no direct fontconfig APIs to get the binding type. The - // binding only takes effect in the sort and match functions. - - // |requiredLangs| is a list of requested languages that have not yet been - // satisfied. gfxFontconfigUtils only sets one FC_LANG property value, - // but FcConfigSubstitute may add more values (e.g. prepending "en" to - // "ja" will use western fonts to render Latin/Arabic numerals in Japanese - // text.) - AutoTArray<LangSupportEntry,10> requiredLangs; - for (int v = 0; ; ++v) { - FcChar8 *lang; - FcResult result = FcPatternGetString(mSortPattern, FC_LANG, v, &lang); - if (result != FcResultMatch) { - // No need to check FcPatternGetLangSet() because - // gfxFontconfigUtils sets only a string value for FC_LANG and - // FcConfigSubstitute cannot add LangSets. - NS_ASSERTION(result != FcResultTypeMismatch, - "Expected a string for FC_LANG"); - break; - } - - if (!requiredLangs.Contains(lang, LangComparator())) { - FcLangResult bestLangSupport = utils->GetBestLangSupport(lang); - if (bestLangSupport != FcLangDifferentLang) { - requiredLangs. - AppendElement(LangSupportEntry(lang, bestLangSupport)); - } - } - } - - nsAutoRef<FcFontSet> fontSet(FcFontSetCreate()); - if (!fontSet) - return fontSet.out(); - - // FcDefaultSubstitute() ensures a slant on mSortPattern, but, if that ever - // doesn't happen, Roman will be used. - int requestedSlant = FC_SLANT_ROMAN; - FcPatternGetInteger(mSortPattern, FC_SLANT, 0, &requestedSlant); - double requestedSize = -1.0; - FcPatternGetDouble(mSortPattern, FC_PIXEL_SIZE, 0, &requestedSize); - - nsTHashtable<gfxFontconfigUtils::DepFcStrEntry> existingFamilies(32); - FcChar8 *family; - for (int v = 0; - FcPatternGetString(mSortPattern, - FC_FAMILY, v, &family) == FcResultMatch; ++v) { - const nsTArray< nsCountedRef<FcPattern> > *familyFonts = nullptr; - - // Is this an @font-face family? - bool isUserFont = false; - if (mUserFontSet) { - // Have some @font-face definitions - - nsDependentCString cFamily(gfxFontconfigUtils::ToCString(family)); - NS_NAMED_LITERAL_CSTRING(userPrefix, FONT_FACE_FAMILY_PREFIX); - - if (StringBeginsWith(cFamily, userPrefix)) { - isUserFont = true; - - // Trim off the prefix - nsDependentCSubstring cssFamily(cFamily, userPrefix.Length()); - - uint8_t thebesStyle = - gfxFontconfigUtils::FcSlantToThebesStyle(requestedSlant); - uint16_t thebesWeight = - gfxFontconfigUtils::GetThebesWeight(mSortPattern); - int16_t thebesStretch = - gfxFontconfigUtils::GetThebesStretch(mSortPattern); - - bool waitForUserFont; - familyFonts = FindFontPatterns(mUserFontSet, cssFamily, - thebesStyle, - thebesWeight, thebesStretch, - waitForUserFont); - if (waitForUserFont) { - aWaitForUserFont = true; - } - } - } - - if (!isUserFont) { - familyFonts = &utils->GetFontsForFamily(family); - } - - if (!familyFonts || familyFonts->Length() == 0) { - // There are no fonts matching this family, so there is no point - // in searching for this family in the FontSort. - // - // Perhaps the original pattern should be retained for - // FcFontRenderPrepare. However, the only a useful config - // substitution test against missing families that i can imagine - // would only be interested in the preferred family - // (qual="first"), so always keep the first family and use the - // same pattern for Sort and RenderPrepare. - if (v != 0 && moz_FcPatternRemove(mSortPattern, FC_FAMILY, v)) { - --v; - } - continue; - } - - // Aliases seem to often end up occurring more than once, but - // duplicate families can't be removed from the sort pattern without - // knowing whether duplicates have the same binding. - gfxFontconfigUtils::DepFcStrEntry *familyEntry = - existingFamilies.PutEntry(family); - if (familyEntry) { - if (familyEntry->mKey) // old entry - continue; - - familyEntry->mKey = family; // initialize new entry - } - - for (uint32_t f = 0; f < familyFonts->Length(); ++f) { - FcPattern *font = familyFonts->ElementAt(f); - - // Fix up the family name of user-font patterns, as the same - // font entry may be used (via the UserFontCache) for multiple - // CSS family names - if (isUserFont) { - font = FcPatternDuplicate(font); - FcPatternDel(font, FC_FAMILY); - FcPatternAddString(font, FC_FAMILY, family); - } - - // User fonts are already filtered by slant (but not size) in - // mUserFontSet->FindUserFontEntry(). - if (requestedSize != -1.0 && !SizeIsAcceptable(font, requestedSize)) - continue; - - for (uint32_t r = 0; r < requiredLangs.Length(); ++r) { - const LangSupportEntry& langEntry = requiredLangs[r]; - FcLangResult support = - gfxFontconfigUtils::GetLangSupport(font, langEntry.mLang); - if (support <= langEntry.mBestSupport) { // lower is better - requiredLangs.RemoveElementAt(r); - --r; - } - } - - // FcFontSetDestroy will remove a reference but FcFontSetAdd - // does _not_ take a reference! - if (FcFontSetAdd(fontSet, font)) { - // We don't add a reference here for user fonts, because we're - // using a local clone of the pattern (see above) in order to - // override the family name - if (!isUserFont) { - FcPatternReference(font); - } - } - } - } - - FcPattern *truncateMarker = nullptr; - for (uint32_t r = 0; r < requiredLangs.Length(); ++r) { - const nsTArray< nsCountedRef<FcPattern> >& langFonts = - utils->GetFontsForLang(requiredLangs[r].mLang); - - bool haveLangFont = false; - for (uint32_t f = 0; f < langFonts.Length(); ++f) { - FcPattern *font = langFonts[f]; - if (requestedSize != -1.0 && !SizeIsAcceptable(font, requestedSize)) - continue; - - haveLangFont = true; - if (FcFontSetAdd(fontSet, font)) { - FcPatternReference(font); - } - } - - if (!haveLangFont && langFonts.Length() > 0) { - // There is a font that supports this language but it didn't pass - // the slant and size criteria. Weak default font families should - // not be considered until the language has been satisfied. - // - // Insert a font that supports the language so that it will mark - // the position of fonts from weak families in the sorted set and - // they can be removed. The language and weak families will be - // considered in the fallback fonts, which use fontconfig's - // algorithm. - // - // Of the fonts that don't meet slant and size criteria, strong - // default font families should be considered before (other) fonts - // for this language, so this marker font will be removed (as well - // as the fonts from weak families), and strong families will be - // reconsidered in the fallback fonts. - FcPattern *font = langFonts[0]; - if (FcFontSetAdd(fontSet, font)) { - FcPatternReference(font); - truncateMarker = font; - } - break; - } - } - - FcFontSet *sets[1] = { fontSet }; - FcResult result; -#ifdef SOLARIS - // Get around a crash of FcFontSetSort when FcConfig is nullptr - // Solaris's FcFontSetSort needs an FcConfig (bug 474758) - fontSet.own(FcFontSetSort(FcConfigGetCurrent(), sets, 1, mSortPattern, - FcFalse, nullptr, &result)); -#else - fontSet.own(FcFontSetSort(nullptr, sets, 1, mSortPattern, - FcFalse, nullptr, &result)); -#endif - - if (truncateMarker != nullptr && fontSet) { - nsAutoRef<FcFontSet> truncatedSet(FcFontSetCreate()); - - for (int f = 0; f < fontSet->nfont; ++f) { - FcPattern *font = fontSet->fonts[f]; - if (font == truncateMarker) - break; - - if (FcFontSetAdd(truncatedSet, font)) { - FcPatternReference(font); - } - } - - fontSet.steal(truncatedSet); - } - - return fontSet.out(); -} - -nsReturnRef<FcFontSet> -gfxFcFontSet::SortFallbackFonts() -{ - // Setting trim to FcTrue would provide a much smaller (~ 1/10) FcFontSet, - // but would take much longer due to comparing all the character sets. - // - // The references to fonts in this FcFontSet are almost free - // as they are pointers into mmaped cache files. - // - // GetFontPatternAt() will trim lazily if and as needed, which will also - // remove duplicates of preferred fonts. - FcResult result; - return nsReturnRef<FcFontSet>(FcFontSort(nullptr, mSortPattern, - FcFalse, nullptr, &result)); -} - -// GetFontAt relies on this setting up all patterns up to |i|. -FcPattern * -gfxFcFontSet::GetFontPatternAt(uint32_t i) -{ - while (i >= mFonts.Length()) { - while (!mFcFontSet) { - if (mHaveFallbackFonts) - return nullptr; - - mFcFontSet = SortFallbackFonts(); - mHaveFallbackFonts = true; - mFcFontsTrimmed = 0; - // Loop to test that mFcFontSet is non-nullptr. - } - - while (mFcFontsTrimmed < mFcFontSet->nfont) { - FcPattern *font = mFcFontSet->fonts[mFcFontsTrimmed]; - ++mFcFontsTrimmed; - - if (mFonts.Length() != 0) { - // See if the next font provides support for any extra - // characters. Most often the next font is not going to - // support more characters so check for a SubSet first before - // allocating a new CharSet with Union. - FcCharSet *supportedChars = mCharSet; - if (!supportedChars) { - FcPatternGetCharSet(mFonts[mFonts.Length() - 1].mPattern, - FC_CHARSET, 0, &supportedChars); - } - - if (supportedChars) { - FcCharSet *newChars = nullptr; - FcPatternGetCharSet(font, FC_CHARSET, 0, &newChars); - if (newChars) { - if (FcCharSetIsSubset(newChars, supportedChars)) - continue; - - mCharSet.own(FcCharSetUnion(supportedChars, newChars)); - } else if (!mCharSet) { - mCharSet.own(FcCharSetCopy(supportedChars)); - } - } - } - - mFonts.AppendElement(font); - if (mFonts.Length() >= i) - break; - } - - if (mFcFontsTrimmed == mFcFontSet->nfont) { - // finished with this font set - mFcFontSet.reset(); - } - } - - return mFonts[i].mPattern; -} - -#ifdef MOZ_WIDGET_GTK -static void ApplyGdkScreenFontOptions(FcPattern *aPattern); -#endif - -// Apply user settings and defaults to pattern in preparation for matching. -static void -PrepareSortPattern(FcPattern *aPattern, double aFallbackSize, - double aSizeAdjustFactor, bool aIsPrinterFont) -{ - FcConfigSubstitute(nullptr, aPattern, FcMatchPattern); - - // This gets cairo_font_options_t for the Screen. We should have - // different font options for printing (no hinting) but we are not told - // what we are measuring for. - // - // If cairo adds support for lcd_filter, gdk will not provide the default - // setting for that option. We could get the default setting by creating - // an xlib surface once, recording its font_options, and then merging the - // gdk options. - // - // Using an xlib surface would also be an option to get Screen font - // options for non-GTK X11 toolkits, but less efficient than using GDK to - // pick up dynamic changes. - if(aIsPrinterFont) { - cairo_font_options_t *options = cairo_font_options_create(); - cairo_font_options_set_hint_style (options, CAIRO_HINT_STYLE_NONE); - cairo_font_options_set_antialias (options, CAIRO_ANTIALIAS_GRAY); - cairo_ft_font_options_substitute(options, aPattern); - cairo_font_options_destroy(options); - FcPatternAddBool(aPattern, PRINTING_FC_PROPERTY, FcTrue); - } else { -#ifdef MOZ_WIDGET_GTK - ApplyGdkScreenFontOptions(aPattern); -#endif - } - - // Protect against any fontconfig settings that may have incorrectly - // modified the pixelsize, and consider aSizeAdjustFactor. - double size = aFallbackSize; - if (FcPatternGetDouble(aPattern, FC_PIXEL_SIZE, 0, &size) != FcResultMatch - || aSizeAdjustFactor != 1.0) { - FcPatternDel(aPattern, FC_PIXEL_SIZE); - FcPatternAddDouble(aPattern, FC_PIXEL_SIZE, size * aSizeAdjustFactor); - } - - FcDefaultSubstitute(aPattern); -} - -/** - ** gfxPangoFontGroup - **/ - -gfxPangoFontGroup::gfxPangoFontGroup(const FontFamilyList& aFontFamilyList, - const gfxFontStyle *aStyle, - gfxUserFontSet *aUserFontSet, - gfxFloat aDevToCssSize) - : gfxFontGroup(aFontFamilyList, aStyle, nullptr, aUserFontSet, aDevToCssSize), - mPangoLanguage(GuessPangoLanguage(aStyle->language)) -{ - // This language is passed to the font for shaping. - // Shaping doesn't know about lang groups so make it a real language. - if (mPangoLanguage) { - mStyle.language = NS_Atomize(pango_language_to_string(mPangoLanguage)); - } - - // dummy entry, will be replaced when actually needed - mFonts.AppendElement(FamilyFace()); - mSkipUpdateUserFonts = true; -} - -gfxPangoFontGroup::~gfxPangoFontGroup() -{ -} - -gfxFontGroup * -gfxPangoFontGroup::Copy(const gfxFontStyle *aStyle) -{ - return new gfxPangoFontGroup(mFamilyList, aStyle, mUserFontSet, mDevToCssSize); -} - -void -gfxPangoFontGroup::FindGenericFontsPFG(FontFamilyType aGenericType, - nsIAtom *aLanguage, - void *aClosure) -{ - AutoTArray<nsString, 5> resolvedGenerics; - ResolveGenericFontNamesPFG(aGenericType, aLanguage, resolvedGenerics); - uint32_t g = 0, numGenerics = resolvedGenerics.Length(); - for (g = 0; g < numGenerics; g++) { - FindPlatformFontPFG(resolvedGenerics[g], false, aClosure); - } -} - -/* static */ void -gfxPangoFontGroup::ResolveGenericFontNamesPFG(FontFamilyType aGenericType, - nsIAtom *aLanguage, - nsTArray<nsString>& aGenericFamilies) -{ - static const char kGeneric_serif[] = "serif"; - static const char kGeneric_sans_serif[] = "sans-serif"; - static const char kGeneric_monospace[] = "monospace"; - static const char kGeneric_cursive[] = "cursive"; - static const char kGeneric_fantasy[] = "fantasy"; - - // treat -moz-fixed as monospace - if (aGenericType == eFamily_moz_fixed) { - aGenericType = eFamily_monospace; - } - - // type should be standard generic type at this point - NS_ASSERTION(aGenericType >= eFamily_serif && - aGenericType <= eFamily_fantasy, - "standard generic font family type required"); - - // create the lang string - nsIAtom *langGroupAtom = nullptr; - nsAutoCString langGroupString; - if (aLanguage) { - if (!gLangService) { - CallGetService(NS_LANGUAGEATOMSERVICE_CONTRACTID, &gLangService); - } - if (gLangService) { - nsresult rv; - langGroupAtom = gLangService->GetLanguageGroup(aLanguage, &rv); - } - } - if (!langGroupAtom) { - langGroupAtom = nsGkAtoms::Unicode; - } - langGroupAtom->ToUTF8String(langGroupString); - - // map generic type to string - const char *generic = nullptr; - switch (aGenericType) { - case eFamily_serif: - generic = kGeneric_serif; - break; - case eFamily_sans_serif: - generic = kGeneric_sans_serif; - break; - case eFamily_monospace: - generic = kGeneric_monospace; - break; - case eFamily_cursive: - generic = kGeneric_cursive; - break; - case eFamily_fantasy: - generic = kGeneric_fantasy; - break; - default: - break; - } - - if (!generic) { - return; - } - - aGenericFamilies.Clear(); - - // load family for "font.name.generic.lang" - nsAutoCString prefFontName("font.name."); - prefFontName.Append(generic); - prefFontName.Append('.'); - prefFontName.Append(langGroupString); - gfxFontUtils::AppendPrefsFontList(prefFontName.get(), - aGenericFamilies); - - // if lang has pref fonts, also load fonts for "font.name-list.generic.lang" - if (!aGenericFamilies.IsEmpty()) { - nsAutoCString prefFontListName("font.name-list."); - prefFontListName.Append(generic); - prefFontListName.Append('.'); - prefFontListName.Append(langGroupString); - gfxFontUtils::AppendPrefsFontList(prefFontListName.get(), - aGenericFamilies); - } - -#if 0 // dump out generic mappings - printf("%s ===> ", prefFontName.get()); - for (uint32_t k = 0; k < aGenericFamilies.Length(); k++) { - if (k > 0) printf(", "); - printf("%s", NS_ConvertUTF16toUTF8(aGenericFamilies[k]).get()); - } - printf("\n"); -#endif -} - -void gfxPangoFontGroup::EnumerateFontListPFG(nsIAtom *aLanguage, void *aClosure) -{ - // initialize fonts in the font family list - const nsTArray<FontFamilyName>& fontlist = mFamilyList.GetFontlist(); - - // lookup fonts in the fontlist - uint32_t i, numFonts = fontlist.Length(); - for (i = 0; i < numFonts; i++) { - const FontFamilyName& name = fontlist[i]; - if (name.IsNamed()) { - FindPlatformFontPFG(name.mName, true, aClosure); - } else { - FindGenericFontsPFG(name.mType, aLanguage, aClosure); - } - } - - // if necessary, append default generic onto the end - if (mFamilyList.GetDefaultFontType() != eFamily_none && - !mFamilyList.HasDefaultGeneric()) { - FindGenericFontsPFG(mFamilyList.GetDefaultFontType(), - aLanguage, aClosure); - } -} - -void -gfxPangoFontGroup::FindPlatformFontPFG(const nsAString& fontName, - bool aUseFontSet, - void *aClosure) -{ - nsTArray<nsString> *list = static_cast<nsTArray<nsString>*>(aClosure); - - if (!list->Contains(fontName)) { - // names present in the user fontset are not matched against system fonts - if (aUseFontSet && mUserFontSet && mUserFontSet->HasFamily(fontName)) { - nsAutoString userFontName = - NS_LITERAL_STRING(FONT_FACE_FAMILY_PREFIX) + fontName; - list->AppendElement(userFontName); - } else { - list->AppendElement(fontName); - } - } -} - -gfxFcFont * -gfxPangoFontGroup::GetBaseFont() -{ - if (mFonts[0].Font() == nullptr) { - gfxFont* font = GetBaseFontSet()->GetFontAt(0, GetStyle()); - mFonts[0] = FamilyFace(nullptr, font); - } - - return static_cast<gfxFcFont*>(mFonts[0].Font()); -} - -gfxFont* -gfxPangoFontGroup::GetFirstValidFont(uint32_t aCh) -{ - return GetFontAt(0); -} - -gfxFont * -gfxPangoFontGroup::GetFontAt(int32_t i, uint32_t aCh) -{ - // If it turns out to be hard for all clients that cache font - // groups to call UpdateUserFonts at appropriate times, we could - // instead consider just calling UpdateUserFonts from someplace - // more central (such as here). - NS_ASSERTION(!mUserFontSet || mCurrGeneration == GetGeneration(), - "Whoever was caching this font group should have " - "called UpdateUserFonts on it"); - - NS_PRECONDITION(i == 0, "Only have one font"); - - return GetBaseFont(); -} - -void -gfxPangoFontGroup::UpdateUserFonts() -{ - uint64_t newGeneration = GetGeneration(); - if (newGeneration == mCurrGeneration) - return; - - mFonts[0] = FamilyFace(); - mFontSets.Clear(); - ClearCachedData(); - mCurrGeneration = newGeneration; -} - -already_AddRefed<gfxFcFontSet> -gfxPangoFontGroup::MakeFontSet(PangoLanguage *aLang, gfxFloat aSizeAdjustFactor, - nsAutoRef<FcPattern> *aMatchPattern) -{ - const char *lang = pango_language_to_string(aLang); - - RefPtr<nsIAtom> langGroup; - if (aLang != mPangoLanguage) { - // Set up langGroup for Mozilla's font prefs. - langGroup = NS_Atomize(lang); - } - - AutoTArray<nsString, 20> fcFamilyList; - EnumerateFontListPFG(langGroup ? langGroup.get() : mStyle.language.get(), - &fcFamilyList); - - // To consider: A fontset cache here could be helpful. - - // Get a pattern suitable for matching. - nsAutoRef<FcPattern> pattern - (gfxFontconfigUtils::NewPattern(fcFamilyList, mStyle, lang)); - - PrepareSortPattern(pattern, mStyle.size, aSizeAdjustFactor, mStyle.printerFont); - - RefPtr<gfxFcFontSet> fontset = - new gfxFcFontSet(pattern, mUserFontSet); - - mSkipDrawing = fontset->WaitingForUserFont(); - - if (aMatchPattern) - aMatchPattern->steal(pattern); - - return fontset.forget(); -} - -gfxPangoFontGroup:: -FontSetByLangEntry::FontSetByLangEntry(PangoLanguage *aLang, - gfxFcFontSet *aFontSet) - : mLang(aLang), mFontSet(aFontSet) -{ -} - -gfxFcFontSet * -gfxPangoFontGroup::GetFontSet(PangoLanguage *aLang) -{ - GetBaseFontSet(); // sets mSizeAdjustFactor and mFontSets[0] - - if (!aLang) - return mFontSets[0].mFontSet; - - for (uint32_t i = 0; i < mFontSets.Length(); ++i) { - if (mFontSets[i].mLang == aLang) - return mFontSets[i].mFontSet; - } - - RefPtr<gfxFcFontSet> fontSet = - MakeFontSet(aLang, mSizeAdjustFactor); - mFontSets.AppendElement(FontSetByLangEntry(aLang, fontSet)); - - return fontSet; -} - -already_AddRefed<gfxFont> -gfxPangoFontGroup::FindFontForChar(uint32_t aCh, uint32_t aPrevCh, - uint32_t aNextCh, Script aRunScript, - gfxFont *aPrevMatchedFont, - uint8_t *aMatchType) -{ - if (aPrevMatchedFont) { - // Don't switch fonts for control characters, regardless of - // whether they are present in the current font, as they won't - // actually be rendered (see bug 716229) - uint8_t category = GetGeneralCategory(aCh); - if (category == HB_UNICODE_GENERAL_CATEGORY_CONTROL) { - return RefPtr<gfxFont>(aPrevMatchedFont).forget(); - } - - // if this character is a join-control or the previous is a join-causer, - // use the same font as the previous range if we can - if (gfxFontUtils::IsJoinControl(aCh) || - gfxFontUtils::IsJoinCauser(aPrevCh)) { - if (aPrevMatchedFont->HasCharacter(aCh)) { - return RefPtr<gfxFont>(aPrevMatchedFont).forget(); - } - } - } - - // if this character is a variation selector, - // use the previous font regardless of whether it supports VS or not. - // otherwise the text run will be divided. - if (gfxFontUtils::IsVarSelector(aCh)) { - if (aPrevMatchedFont) { - return RefPtr<gfxFont>(aPrevMatchedFont).forget(); - } - // VS alone. it's meaningless to search different fonts - return nullptr; - } - - // The real fonts that fontconfig provides for generic/fallback families - // depend on the language used, so a different FontSet is used for each - // language (except for the variation below). - // - // With most fontconfig configurations any real family names prior to a - // fontconfig generic with corresponding fonts installed will still lead - // to the same leading fonts in each FontSet. - // - // There is an inefficiency here therefore because the same base FontSet - // could often be used if these real families support the character. - // However, with fontconfig aliases, it is difficult to distinguish - // where exactly alias fonts end and generic/fallback fonts begin. - // - // The variation from pure language-based matching used here is that the - // same primary/base font is always used irrespective of the language. - // This provides that SCRIPT_COMMON characters are consistently rendered - // with the same font (bug 339513 and bug 416725). This is particularly - // important with the word cache as script can't be reliably determined - // from surrounding words. It also often avoids the unnecessary extra - // FontSet efficiency mentioned above. - // - // However, in two situations, the base font is not checked before the - // language-specific FontSet. - // - // 1. When we don't have a language to make a good choice for - // the base font. - // - // 2. For system fonts, use the default Pango behavior to give - // consistency with other apps. This is relevant when un-localized - // builds are run in non-Latin locales. This special-case probably - // wouldn't be necessary but for bug 91190. - - gfxFcFontSet *fontSet = GetBaseFontSet(); - uint32_t nextFont = 0; - FcPattern *basePattern = nullptr; - if (!mStyle.systemFont && mPangoLanguage) { - basePattern = fontSet->GetFontPatternAt(0); - if (HasChar(basePattern, aCh)) { - *aMatchType = gfxTextRange::kFontGroup; - return RefPtr<gfxFont>(GetBaseFont()).forget(); - } - - nextFont = 1; - } - - // Our MOZ_SCRIPT_* codes may not match the PangoScript enumeration values - // (if we're using ICU's codes), so convert by mapping through ISO 15924 tag. - // Note that PangoScript is defined to be compatible with GUnicodeScript: - // https://developer.gnome.org/pango/stable/pango-Scripts-and-Languages.html#PangoScript - const hb_tag_t scriptTag = GetScriptTagForCode(aRunScript); - const PangoScript script = - (const PangoScript)hb_glib_script_from_script(hb_script_from_iso15924_tag(scriptTag)); - - // Might be nice to call pango_language_includes_script only once for the - // run rather than for each character. - PangoLanguage *scriptLang; - if ((!basePattern || - !pango_language_includes_script(mPangoLanguage, script)) && - (scriptLang = pango_script_get_sample_language(script))) { - fontSet = GetFontSet(scriptLang); - nextFont = 0; - } - - for (uint32_t i = nextFont; - FcPattern *pattern = fontSet->GetFontPatternAt(i); - ++i) { - if (pattern == basePattern) { - continue; // already checked basePattern - } - - if (HasChar(pattern, aCh)) { - *aMatchType = gfxTextRange::kFontGroup; - return RefPtr<gfxFont>(fontSet->GetFontAt(i, GetStyle())).forget(); - } - } - - return nullptr; -} - -/** - ** gfxFcFont - **/ - -cairo_user_data_key_t gfxFcFont::sGfxFontKey; - -gfxFcFont::gfxFcFont(cairo_scaled_font_t *aCairoFont, - FcPattern *aPattern, - gfxFcFontEntry *aFontEntry, - const gfxFontStyle *aFontStyle) - : gfxFontconfigFontBase(aCairoFont, aPattern, aFontEntry, aFontStyle) -{ - cairo_scaled_font_set_user_data(mScaledFont, &sGfxFontKey, this, nullptr); -} - -gfxFcFont::~gfxFcFont() -{ - cairo_scaled_font_set_user_data(mScaledFont, - &sGfxFontKey, - nullptr, - nullptr); -} - -already_AddRefed<gfxFont> -gfxFcFont::GetSubSuperscriptFont(int32_t aAppUnitsPerDevPixel) -{ - gfxFontStyle style(*GetStyle()); - style.AdjustForSubSuperscript(aAppUnitsPerDevPixel); - return MakeScaledFont(&style, style.size / GetStyle()->size); -} - -already_AddRefed<gfxFont> -gfxFcFont::MakeScaledFont(gfxFontStyle *aFontStyle, gfxFloat aScaleFactor) -{ - gfxFcFontEntry* fe = static_cast<gfxFcFontEntry*>(GetFontEntry()); - RefPtr<gfxFont> font = - gfxFontCache::GetCache()->Lookup(fe, aFontStyle, nullptr); - if (font) { - return font.forget(); - } - - cairo_matrix_t fontMatrix; - cairo_scaled_font_get_font_matrix(mScaledFont, &fontMatrix); - cairo_matrix_scale(&fontMatrix, aScaleFactor, aScaleFactor); - - cairo_matrix_t ctm; - cairo_scaled_font_get_ctm(mScaledFont, &ctm); - - cairo_font_options_t *options = cairo_font_options_create(); - cairo_scaled_font_get_font_options(mScaledFont, options); - - cairo_scaled_font_t *newFont = - cairo_scaled_font_create(cairo_scaled_font_get_font_face(mScaledFont), - &fontMatrix, &ctm, options); - cairo_font_options_destroy(options); - - font = new gfxFcFont(newFont, GetPattern(), fe, aFontStyle); - gfxFontCache::GetCache()->AddNew(font); - cairo_scaled_font_destroy(newFont); - - return font.forget(); -} - -already_AddRefed<gfxFont> -gfxFcFont::GetSmallCapsFont() -{ - gfxFontStyle style(*GetStyle()); - style.size *= SMALL_CAPS_SCALE_FACTOR; - style.variantCaps = NS_FONT_VARIANT_CAPS_NORMAL; - return MakeScaledFont(&style, SMALL_CAPS_SCALE_FACTOR); -} - -/* static */ void -gfxPangoFontGroup::Shutdown() -{ - // Resetting gFTLibrary in case this is wanted again after a - // cairo_debug_reset_static_data. - gFTLibrary = nullptr; -} - -/* static */ gfxFontEntry * -gfxPangoFontGroup::NewFontEntry(const nsAString& aFontName, - uint16_t aWeight, - int16_t aStretch, - uint8_t aStyle) -{ - gfxFontconfigUtils *utils = gfxFontconfigUtils::GetFontconfigUtils(); - if (!utils) - return nullptr; - - // The font face name from @font-face { src: local() } is not well - // defined. - // - // On MS Windows, this name gets compared with - // ENUMLOGFONTEXW::elfFullName, which for OpenType fonts seems to be the - // full font name from the name table. For CFF OpenType fonts this is the - // same as the PostScript name, but for TrueType fonts it is usually - // different. - // - // On Mac, the font face name is compared with the PostScript name, even - // for TrueType fonts. - // - // Fontconfig only records the full font names, so the behavior here - // follows that on MS Windows. However, to provide the possibility - // of aliases to compensate for variations, the font face name is passed - // through FcConfigSubstitute. - - nsAutoRef<FcPattern> pattern(FcPatternCreate()); - if (!pattern) - return nullptr; - - NS_ConvertUTF16toUTF8 fullname(aFontName); - FcPatternAddString(pattern, FC_FULLNAME, - gfxFontconfigUtils::ToFcChar8(fullname)); - FcConfigSubstitute(nullptr, pattern, FcMatchPattern); - - FcChar8 *name; - for (int v = 0; - FcPatternGetString(pattern, FC_FULLNAME, v, &name) == FcResultMatch; - ++v) { - const nsTArray< nsCountedRef<FcPattern> >& fonts = - utils->GetFontsForFullname(name); - - if (fonts.Length() != 0) - return new gfxLocalFcFontEntry(aFontName, - aWeight, - aStretch, - aStyle, - fonts); - } - - return nullptr; -} - -/* static */ FT_Library -gfxPangoFontGroup::GetFTLibrary() -{ - if (!gFTLibrary) { - // Use cairo's FT_Library so that cairo takes care of shutdown of the - // FT_Library after it has destroyed its font_faces, and FT_Done_Face - // has been called on each FT_Face, at least until this bug is fixed: - // https://bugs.freedesktop.org/show_bug.cgi?id=18857 - // - // Cairo's FT_Library can be obtained from any cairo_scaled_font. The - // font properties requested here are chosen to get an FT_Face that is - // likely to be also used elsewhere. - gfxFontStyle style; - RefPtr<gfxPangoFontGroup> fontGroup = - new gfxPangoFontGroup(FontFamilyList(eFamily_sans_serif), - &style, nullptr, 1.0); - - gfxFcFont *font = fontGroup->GetBaseFont(); - if (!font) - return nullptr; - - gfxFT2LockedFace face(font); - if (!face.get()) - return nullptr; - - gFTLibrary = face.get()->glyph->library; - } - - return gFTLibrary; -} - -/* static */ gfxFontEntry * -gfxPangoFontGroup::NewFontEntry(const nsAString& aFontName, - uint16_t aWeight, - int16_t aStretch, - uint8_t aStyle, - const uint8_t* aFontData, - uint32_t aLength) -{ - // Ownership of aFontData is passed in here, and transferred to the - // new fontEntry, which will release it when no longer needed. - - // Using face_index = 0 for the first face in the font, as we have no - // other information. FT_New_Memory_Face checks for a nullptr FT_Library. - FT_Face face; - FT_Error error = - FT_New_Memory_Face(GetFTLibrary(), aFontData, aLength, 0, &face); - if (error != 0) { - free((void*)aFontData); - return nullptr; - } - - return new gfxDownloadedFcFontEntry(aFontName, aWeight, - aStretch, aStyle, - aFontData, face); -} - - -static double -GetPixelSize(FcPattern *aPattern) -{ - double size; - if (FcPatternGetDouble(aPattern, - FC_PIXEL_SIZE, 0, &size) == FcResultMatch) - return size; - - NS_NOTREACHED("No size on pattern"); - return 0.0; -} - -/** - * The following gfxFcFonts are accessed from the cairo_scaled_font or created - * from the FcPattern, not from the gfxFontCache hash table. The gfxFontCache - * hash table is keyed by desired family and style, whereas here we only know - * actual family and style. There may be more than one of these fonts with - * the same family and style, but different PangoFont and actual font face. - * - * The point of this is to record the exact font face for gfxTextRun glyph - * indices. The style of this font does not necessarily represent the exact - * gfxFontStyle used to build the text run. Notably, the language is not - * recorded. - */ - -/* static */ -already_AddRefed<gfxFcFont> -gfxFcFont::GetOrMakeFont(FcPattern *aRequestedPattern, FcPattern *aFontPattern, - const gfxFontStyle *aFontStyle) -{ - nsAutoRef<FcPattern> renderPattern - (FcFontRenderPrepare(nullptr, aRequestedPattern, aFontPattern)); - - // If synthetic bold/italic is not allowed by the style, adjust the - // resulting pattern to match the actual properties of the font. - if (!aFontStyle->allowSyntheticWeight) { - int weight; - if (FcPatternGetInteger(aFontPattern, FC_WEIGHT, 0, - &weight) == FcResultMatch) { - FcPatternDel(renderPattern, FC_WEIGHT); - FcPatternAddInteger(renderPattern, FC_WEIGHT, weight); - } - } - if (!aFontStyle->allowSyntheticStyle) { - int slant; - if (FcPatternGetInteger(aFontPattern, FC_SLANT, 0, - &slant) == FcResultMatch) { - FcPatternDel(renderPattern, FC_SLANT); - FcPatternAddInteger(renderPattern, FC_SLANT, slant); - } - } - - cairo_font_face_t *face = - cairo_ft_font_face_create_for_pattern(renderPattern); - - // Reuse an existing font entry if available. - RefPtr<gfxFcFontEntry> fe = gfxFcFontEntry::LookupFontEntry(face); - if (!fe) { - gfxDownloadedFcFontEntry *downloadedFontEntry = - GetDownloadedFontEntry(aFontPattern); - if (downloadedFontEntry) { - // Web font - fe = downloadedFontEntry; - if (cairo_font_face_status(face) == CAIRO_STATUS_SUCCESS) { - // cairo_font_face_t is using the web font data. - // Hold a reference to the font entry to keep the font face - // data. - if (!downloadedFontEntry->SetCairoFace(face)) { - // OOM. Let cairo pick a fallback font - cairo_font_face_destroy(face); - face = cairo_ft_font_face_create_for_pattern(aRequestedPattern); - fe = gfxFcFontEntry::LookupFontEntry(face); - } - } - } - if (!fe) { - // Get a unique name for the font face from the file and id. - nsAutoString name; - FcChar8 *fc_file; - if (FcPatternGetString(renderPattern, - FC_FILE, 0, &fc_file) == FcResultMatch) { - int index; - if (FcPatternGetInteger(renderPattern, - FC_INDEX, 0, &index) != FcResultMatch) { - // cairo defaults to 0. - index = 0; - } - - AppendUTF8toUTF16(gfxFontconfigUtils::ToCString(fc_file), name); - if (index != 0) { - name.Append('/'); - name.AppendInt(index); - } - } - - fe = new gfxSystemFcFontEntry(face, aFontPattern, name); - } - } - - gfxFontStyle style(*aFontStyle); - style.size = GetPixelSize(renderPattern); - style.style = gfxFontconfigUtils::GetThebesStyle(renderPattern); - style.weight = gfxFontconfigUtils::GetThebesWeight(renderPattern); - - RefPtr<gfxFont> font = - gfxFontCache::GetCache()->Lookup(fe, &style, nullptr); - if (!font) { - // Note that a file/index pair (or FT_Face) and the gfxFontStyle are - // not necessarily enough to provide a key that will describe a unique - // font. cairoFont contains information from renderPattern, which is a - // fully resolved pattern from FcFontRenderPrepare. - // FcFontRenderPrepare takes the requested pattern and the face - // pattern as input and can modify elements of the resulting pattern - // that affect rendering but are not included in the gfxFontStyle. - cairo_scaled_font_t *cairoFont = CreateScaledFont(renderPattern, face); - font = new gfxFcFont(cairoFont, renderPattern, fe, &style); - gfxFontCache::GetCache()->AddNew(font); - cairo_scaled_font_destroy(cairoFont); - } - - cairo_font_face_destroy(face); - - RefPtr<gfxFcFont> retval(static_cast<gfxFcFont*>(font.get())); - return retval.forget(); -} - -gfxFcFontSet * -gfxPangoFontGroup::GetBaseFontSet() -{ - if (mFontSets.Length() > 0) - return mFontSets[0].mFontSet; - - mSizeAdjustFactor = 1.0; // will be adjusted below if necessary - nsAutoRef<FcPattern> pattern; - RefPtr<gfxFcFontSet> fontSet = - MakeFontSet(mPangoLanguage, mSizeAdjustFactor, &pattern); - - double size = GetPixelSize(pattern); - if (size != 0.0 && mStyle.sizeAdjust > 0.0) { - gfxFcFont *font = fontSet->GetFontAt(0, GetStyle()); - if (font) { - const gfxFont::Metrics& metrics = - font->GetMetrics(gfxFont::eHorizontal); // XXX vertical? - - // The factor of 0.1 ensures that xHeight is sane so fonts don't - // become huge. Strictly ">" ensures that xHeight and emHeight are - // not both zero. - if (metrics.xHeight > 0.1 * metrics.emHeight) { - mSizeAdjustFactor = - mStyle.sizeAdjust * metrics.emHeight / metrics.xHeight; - - size *= mSizeAdjustFactor; - FcPatternDel(pattern, FC_PIXEL_SIZE);