From 48c0c2b431cdf01176ea6306bdd610a15270a735 Mon Sep 17 00:00:00 2001 From: Michael Layzell Date: Tue, 16 Jun 2015 15:27:45 -0400 Subject: [PATCH] Bug 1165263 - Part 1: Update nsPermissionManager to use origins instead of hosts internally, r=ehsan --- browser/app/permissions | 18 +- extensions/cookie/nsPermission.cpp | 67 +- extensions/cookie/nsPermissionManager.cpp | 741 +++++++++++++++------- extensions/cookie/nsPermissionManager.h | 41 +- 4 files changed, 560 insertions(+), 307 deletions(-) diff --git a/browser/app/permissions b/browser/app/permissions index bc3cddbbf43..cc37101dd37 100644 --- a/browser/app/permissions +++ b/browser/app/permissions @@ -1,21 +1,21 @@ # This file has default permissions for the permission manager. # The file-format is strict: # * matchtype \t type \t permission \t host -# * Only "host" is supported for matchtype +# * "origin" should be used for matchtype, "host" is supported for legacy reasons # * type is a string that identifies the type of permission (e.g. "cookie") # * permission is an integer between 1 and 15 # See nsPermissionManager.cpp for more... # UITour -host uitour 1 www.mozilla.org -host uitour 1 self-repair.mozilla.org -host uitour 1 support.mozilla.org -host uitour 1 about:home +origin uitour 1 https://www.mozilla.org +origin uitour 1 https://self-repair.mozilla.org +origin uitour 1 https://support.mozilla.org +origin uitour 1 about:home # XPInstall -host install 1 addons.mozilla.org -host install 1 marketplace.firefox.com +origin install 1 https://addons.mozilla.org +origin install 1 https://marketplace.firefox.com # Remote troubleshooting -host remote-troubleshooting 1 input.mozilla.org -host remote-troubleshooting 1 support.mozilla.org +origin remote-troubleshooting 1 https://input.mozilla.org +origin remote-troubleshooting 1 https://support.mozilla.org diff --git a/extensions/cookie/nsPermission.cpp b/extensions/cookie/nsPermission.cpp index a84a4180a9b..8398b7584e8 100644 --- a/extensions/cookie/nsPermission.cpp +++ b/extensions/cookie/nsPermission.cpp @@ -1,4 +1,4 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* -*- 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/. */ @@ -8,6 +8,7 @@ #include "nsIClassInfoImpl.h" #include "nsIEffectiveTLDService.h" #include "nsIScriptSecurityManager.h" +#include "mozilla/BasePrincipal.h" // nsPermission Implementation @@ -77,29 +78,55 @@ nsPermission::Matches(nsIPrincipal* aPrincipal, bool aExactHost, bool* aMatches) return NS_OK; } - // Make sure that the OriginAttributes of the two entries are the same - nsAutoCString theirSuffix; - nsresult rv = aPrincipal->GetOriginSuffix(theirSuffix); - NS_ENSURE_SUCCESS(rv, rv); - - nsAutoCString ourSuffix; - rv = mPrincipal->GetOriginSuffix(ourSuffix); - NS_ENSURE_SUCCESS(rv, rv); - - if (theirSuffix != ourSuffix) { - return NS_OK; + // If we are matching with an exact host, we're done now - the permissions don't match + // otherwise, we need to start comparing subdomains! + if (aExactHost) { + return NS_OK; + } + + // Compare their OriginAttributes + const mozilla::OriginAttributes& theirAttrs = mozilla::BasePrincipal::Cast(aPrincipal)->OriginAttributesRef(); + const mozilla::OriginAttributes& ourAttrs = mozilla::BasePrincipal::Cast(mPrincipal)->OriginAttributesRef(); + + if (theirAttrs != ourAttrs) { + return NS_OK; } - // Right now, we only care about the hosts nsCOMPtr theirURI; - rv = aPrincipal->GetURI(getter_AddRefs(theirURI)); + nsresult rv = aPrincipal->GetURI(getter_AddRefs(theirURI)); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr ourURI; rv = mPrincipal->GetURI(getter_AddRefs(ourURI)); NS_ENSURE_SUCCESS(rv, rv); - // Get the hosts so we can compare them + // Compare schemes + nsAutoCString theirScheme; + rv = theirURI->GetScheme(theirScheme); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoCString ourScheme; + rv = ourURI->GetScheme(ourScheme); + NS_ENSURE_SUCCESS(rv, rv); + + if (theirScheme != ourScheme) { + return NS_OK; + } + + // Compare ports + int32_t theirPort; + rv = theirURI->GetPort(&theirPort); + NS_ENSURE_SUCCESS(rv, rv); + + int32_t ourPort; + rv = ourURI->GetPort(&ourPort); + NS_ENSURE_SUCCESS(rv, rv); + + if (theirPort != ourPort) { + return NS_OK; + } + + // Check if the host or any subdomain of their host matches. nsAutoCString theirHost; rv = theirURI->GetHost(theirHost); if (NS_FAILED(rv) || theirHost.IsEmpty()) { @@ -112,11 +139,6 @@ nsPermission::Matches(nsIPrincipal* aPrincipal, bool aExactHost, bool* aMatches) return NS_OK; } - if (aExactHost) { // If we only care about the exact host, we compare them and are done - *aMatches = theirHost == ourHost; - return NS_OK; - } - nsCOMPtr tldService = do_GetService(NS_EFFECTIVETLDSERVICE_CONTRACTID); if (!tldService) { @@ -124,9 +146,8 @@ nsPermission::Matches(nsIPrincipal* aPrincipal, bool aExactHost, bool* aMatches) return NS_ERROR_FAILURE; } - // Check if the host or any subdomain of the host matches. This loop will - // not loop forever, as GetNextSubDomain will eventually fail with - // NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS. + // This loop will not loop forever, as GetNextSubDomain will eventually fail + // with NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS. while (theirHost != ourHost) { rv = tldService->GetNextSubDomain(theirHost, theirHost); if (NS_FAILED(rv)) { diff --git a/extensions/cookie/nsPermissionManager.cpp b/extensions/cookie/nsPermissionManager.cpp index 654a0e03a2a..3594d6afb17 100644 --- a/extensions/cookie/nsPermissionManager.cpp +++ b/extensions/cookie/nsPermissionManager.cpp @@ -40,6 +40,8 @@ #include "nsReadLine.h" #include "mozilla/Telemetry.h" #include "nsIConsoleService.h" +#include "nsINavHistoryService.h" +#include "nsToolkitCompsCID.h" static nsPermissionManager *gPermissionManager = nullptr; @@ -102,29 +104,31 @@ LogToConsole(const nsAString& aMsg) namespace { nsresult -GetPrincipal(const nsACString& aHost, uint32_t aAppId, bool aIsInBrowserElement, - nsIPrincipal** aPrincipal) +GetPrincipalFromOrigin(const nsACString& aOrigin, nsIPrincipal** aPrincipal) +{ + nsAutoCString originNoSuffix; + mozilla::OriginAttributes attrs; + if (!attrs.PopulateFromOrigin(aOrigin, originNoSuffix)) { + return NS_ERROR_FAILURE; + } + + nsCOMPtr uri; + nsresult rv = NS_NewURI(getter_AddRefs(uri), originNoSuffix); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr principal = mozilla::BasePrincipal::CreateCodebasePrincipal(uri, attrs); + principal.forget(aPrincipal); + return NS_OK; +} + + +nsresult +GetPrincipal(nsIURI* aURI, uint32_t aAppId, bool aIsInBrowserElement, nsIPrincipal** aPrincipal) { nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager(); NS_ENSURE_TRUE(secMan, NS_ERROR_FAILURE); - nsCOMPtr uri; - nsresult rv = NS_NewURI(getter_AddRefs(uri), aHost); - if (NS_FAILED(rv)) { - // NOTE: most callers will end up here because we don't append "http://" for - // hosts. It's fine to arbitrary use "http://" because, for those entries, - // we will actually just use the host. If we end up here, but the host looks - // like an email address, we use mailto: instead. - nsCString scheme; - if (aHost.FindChar('@') == -1) - scheme = NS_LITERAL_CSTRING("http://"); - else - scheme = NS_LITERAL_CSTRING("mailto:"); - rv = NS_NewURI(getter_AddRefs(uri), scheme + aHost); - NS_ENSURE_SUCCESS(rv, rv); - } - - return secMan->GetAppCodebasePrincipal(uri, aAppId, aIsInBrowserElement, aPrincipal); + return secMan->GetAppCodebasePrincipal(aURI, aAppId, aIsInBrowserElement, aPrincipal); } nsresult @@ -136,50 +140,6 @@ GetPrincipal(nsIURI* aURI, nsIPrincipal** aPrincipal) return secMan->GetNoAppCodebasePrincipal(aURI, aPrincipal); } -nsresult -GetPrincipal(const nsACString& aHost, nsIPrincipal** aPrincipal) -{ - return GetPrincipal(aHost, nsIScriptSecurityManager::NO_APP_ID, false, aPrincipal); -} - -nsresult -GetHostForPrincipal(nsIPrincipal* aPrincipal, nsACString& aHost) -{ - nsCOMPtr uri; - nsresult rv = aPrincipal->GetURI(getter_AddRefs(uri)); - NS_ENSURE_SUCCESS(rv, rv); - - uri = NS_GetInnermostURI(uri); - NS_ENSURE_TRUE(uri, NS_ERROR_FAILURE); - - rv = uri->GetAsciiHost(aHost); - if (NS_SUCCEEDED(rv) && !aHost.IsEmpty()) { - return NS_OK; - } - - // For the mailto scheme, we use the path of the URI. We have to chop off the - // query part if one exists, so we eliminate everything after a ?. - bool isMailTo = false; - if (NS_SUCCEEDED(uri->SchemeIs("mailto", &isMailTo)) && isMailTo) { - rv = uri->GetPath(aHost); - NS_ENSURE_SUCCESS(rv, rv); - - int32_t spart = aHost.FindChar('?', 0); - if (spart >= 0) { - aHost.Cut(spart, aHost.Length() - spart); - } - return NS_OK; - } - - // Some entries like "file://" uses the origin. - rv = aPrincipal->GetOriginNoSuffix(aHost); - if (NS_SUCCEEDED(rv) && !aHost.IsEmpty()) { - return NS_OK; - } - - return NS_ERROR_UNEXPECTED; -} - nsCString GetNextSubDomainForHost(const nsACString& aHost) { @@ -235,6 +195,265 @@ public: NS_IMPL_ISUPPORTS(AppClearDataObserver, nsIObserver) +class MOZ_STACK_CLASS UpgradeHostToOriginHelper { +public: + virtual nsresult Insert(nsIPrincipal* aPrincipal, const nsAFlatCString& aType, + uint32_t aPermission, uint32_t aExpireType, int64_t aExpireTime, + int64_t aModificationTime) = 0; +}; + +class UpgradeHostToOriginDBMigration final : public UpgradeHostToOriginHelper { +public: + UpgradeHostToOriginDBMigration(mozIStorageConnection* aDBConn, int64_t* aID) : mDBConn(aDBConn) + , mID(aID) + { + mDBConn->CreateStatement(NS_LITERAL_CSTRING( + "INSERT INTO moz_hosts_new " + "(id, origin, type, permission, expireType, expireTime, modificationTime) " + "VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7)"), getter_AddRefs(mInsertStmt)); + + mDBConn->CreateStatement(NS_LITERAL_CSTRING("SELECT id FROM moz_hosts_new WHERE origin = ?1"), + getter_AddRefs(mLookupStmt)); + } + + nsresult + Insert(nsIPrincipal* aPrincipal, const nsAFlatCString& aType, + uint32_t aPermission, uint32_t aExpireType, int64_t aExpireTime, + int64_t aModificationTime) final + { + nsAutoCString origin; + nsresult rv = aPrincipal->GetOrigin(origin); + NS_ENSURE_SUCCESS(rv, rv); + + rv = mLookupStmt->Reset(); + NS_ENSURE_SUCCESS(rv, rv); + + rv = mLookupStmt->BindUTF8StringByIndex(0, origin); + NS_ENSURE_SUCCESS(rv, rv); + + // Check to see if the origin already exists in the database + bool hasResult = false; + if (NS_SUCCEEDED(mLookupStmt->ExecuteStep(&hasResult)) && hasResult) { + mLookupStmt->Reset(); + return NS_OK; + } + + rv = mInsertStmt->BindInt64ByIndex(0, *mID); + NS_ENSURE_SUCCESS(rv, rv); + + rv = mInsertStmt->BindUTF8StringByIndex(1, origin); + NS_ENSURE_SUCCESS(rv, rv); + + rv = mInsertStmt->BindUTF8StringByIndex(2, aType); + NS_ENSURE_SUCCESS(rv, rv); + + rv = mInsertStmt->BindInt32ByIndex(3, aPermission); + NS_ENSURE_SUCCESS(rv, rv); + + rv = mInsertStmt->BindInt32ByIndex(4, aExpireType); + NS_ENSURE_SUCCESS(rv, rv); + + rv = mInsertStmt->BindInt64ByIndex(5, aExpireTime); + NS_ENSURE_SUCCESS(rv, rv); + + rv = mInsertStmt->BindInt64ByIndex(6, aModificationTime); + NS_ENSURE_SUCCESS(rv, rv); + + // Increment the working identifier, as we are about to use this one + (*mID)++; + + rv = mInsertStmt->Execute(); + NS_ENSURE_SUCCESS(rv, rv); + + return NS_OK; + } + +private: + nsCOMPtr mLookupStmt; + nsCOMPtr mInsertStmt; + nsCOMPtr mDBConn; + int64_t* mID; +}; + +class UpgradeHostToOriginHostfileImport final : public UpgradeHostToOriginHelper { +public: + UpgradeHostToOriginHostfileImport(nsPermissionManager* aPm, + nsPermissionManager::DBOperationType aOperation, + int64_t aID) : mPm(aPm) + , mOperation(aOperation) + , mID(aID) + {} + + nsresult + Insert(nsIPrincipal* aPrincipal, const nsAFlatCString& aType, + uint32_t aPermission, uint32_t aExpireType, int64_t aExpireTime, + int64_t aModificationTime) final + { + // AddInternal won't do anything if the permission already exists + return mPm->AddInternal(aPrincipal, aType, aPermission, mID, + aExpireType, aExpireTime, aModificationTime, + nsPermissionManager::eDontNotify, mOperation); + } + +private: + nsRefPtr mPm; + nsPermissionManager::DBOperationType mOperation; + int64_t mID; +}; + +nsresult +UpgradeHostToOriginAndInsert(const nsACString& aHost, const nsAFlatCString& aType, + uint32_t aPermission, uint32_t aExpireType, int64_t aExpireTime, + int64_t aModificationTime, uint32_t aAppId, bool aIsInBrowserElement, + UpgradeHostToOriginHelper* aHelper) +{ + if (aHost.EqualsLiteral("")) { + // We no longer support the magic host + NS_WARNING("The magic host is no longer supported. " + "It is being removed from the permissions database."); + return NS_OK; + } + + // First, we check to see if the host is a valid URI. If it is, it can be imported directly + nsCOMPtr uri; + nsresult rv = NS_NewURI(getter_AddRefs(uri), aHost); + if (NS_SUCCEEDED(rv)) { + // It was previously possible to insert useless entries to your permissions database + // for URIs which have a null principal. This acts as a cleanup, getting rid of + // these useless database entries + bool nullpScheme = false; + if (NS_SUCCEEDED(uri->SchemeIs("moz-nullprincipal", &nullpScheme)) && nullpScheme) { + NS_WARNING("A moz-nullprincipal: permission is being discarded."); + return NS_OK; + } + + nsCOMPtr principal; + rv = GetPrincipal(uri, aAppId, aIsInBrowserElement, getter_AddRefs(principal)); + NS_ENSURE_SUCCESS(rv, rv); + + return aHelper->Insert(principal, aType, aPermission, + aExpireType, aExpireTime, aModificationTime); + return NS_OK; + } + + // The user may use this host at non-standard ports or protocols, we can use their history + // to guess what ports and protocols we want to add permissions for. + // We find every URI which they have visited with this host (or a subdomain of this host), + // and try to add it as a principal. + nsCOMPtr histSrv = do_GetService(NS_NAVHISTORYSERVICE_CONTRACTID); + + nsCOMPtr histQuery; + rv = histSrv->GetNewQuery(getter_AddRefs(histQuery)); + NS_ENSURE_SUCCESS(rv, rv); + + // We want to only find history items for this particular host, and subdomains + rv = histQuery->SetDomain(aHost); + NS_ENSURE_SUCCESS(rv, rv); + + rv = histQuery->SetDomainIsHost(false); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr histQueryOpts; + rv = histSrv->GetNewQueryOptions(getter_AddRefs(histQueryOpts)); + NS_ENSURE_SUCCESS(rv, rv); + + // We want to get the URIs for every item in the user's history with the given host + rv = histQueryOpts->SetResultType(nsINavHistoryQueryOptions::RESULTS_AS_URI); + NS_ENSURE_SUCCESS(rv, rv); + + // We only search history, because searching both bookmarks and history + // is not supported, and history tends to be more comprehensive. + rv = histQueryOpts->SetQueryType(nsINavHistoryQueryOptions::QUERY_TYPE_HISTORY); + NS_ENSURE_SUCCESS(rv, rv); + + // We include hidden URIs (such as those visited via iFrames) as they may have permissions too + rv = histQueryOpts->SetIncludeHidden(true); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr histResult; + rv = histSrv->ExecuteQuery(histQuery, histQueryOpts, getter_AddRefs(histResult)); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr histResultContainer; + rv = histResult->GetRoot(getter_AddRefs(histResultContainer)); + NS_ENSURE_SUCCESS(rv, rv); + + rv = histResultContainer->SetContainerOpen(true); + NS_ENSURE_SUCCESS(rv, rv); + + uint32_t childCount = 0; + rv = histResultContainer->GetChildCount(&childCount); + NS_ENSURE_SUCCESS(rv, rv); + + bool foundHistory = false; + for (uint32_t i = 0; i < childCount; i++) { + nsCOMPtr child; + histResultContainer->GetChild(i, getter_AddRefs(child)); + if (NS_FAILED(rv)) continue; + + uint32_t type; + rv = child->GetType(&type); + if (NS_FAILED(rv) || type != nsINavHistoryResultNode::RESULT_TYPE_URI) { + NS_WARNING("Unexpected non-RESULT_TYPE_URI node in " + "UpgradeHostToOriginAndInsert()"); + continue; + } + + nsAutoCString uriSpec; + rv = child->GetUri(uriSpec); + if (NS_FAILED(rv)) continue; + + nsCOMPtr uri; + rv = NS_NewURI(getter_AddRefs(uri), uriSpec); + if (NS_FAILED(rv)) continue; + + // Use the provided host - this URI may be for a subdomain, rather than the host we care about. + rv = uri->SetHost(aHost); + if (NS_FAILED(rv)) continue; + + // We now have a URI which we can make a nsIPrincipal out of + nsCOMPtr principal; + rv = GetPrincipal(uri, aAppId, aIsInBrowserElement, getter_AddRefs(principal)); + if (NS_FAILED(rv)) continue; + + // Insert it! (The backend should be able to deal with us inserting the same origin repeatedly) + foundHistory = true; + rv = aHelper->Insert(principal, aType, aPermission, + aExpireType, aExpireTime, aModificationTime); + NS_WARN_IF(NS_FAILED(rv)); + } + + rv = histResultContainer->SetContainerOpen(false); + NS_ENSURE_SUCCESS(rv, rv); + + // If we didn't find any origins for this host in the poermissions database, + // we can insert the default http:// and https:// permissions into the database. + // This has a relatively high liklihood of applying the permission to the correct + // origin. + if (!foundHistory) { + rv = NS_NewURI(getter_AddRefs(uri), NS_LITERAL_CSTRING("http://") + aHost); + if (NS_SUCCEEDED(rv)) { + nsCOMPtr principal; + rv = GetPrincipal(uri, aAppId, aIsInBrowserElement, getter_AddRefs(principal)); + NS_ENSURE_SUCCESS(rv, rv); + + aHelper->Insert(principal, aType, aPermission, + aExpireType, aExpireTime, aModificationTime); + } + rv = NS_NewURI(getter_AddRefs(uri), NS_LITERAL_CSTRING("https://") + aHost); + if (NS_SUCCEEDED(rv)) { + nsCOMPtr principal; + rv = GetPrincipal(uri, aAppId, aIsInBrowserElement, getter_AddRefs(principal)); + NS_ENSURE_SUCCESS(rv, rv); + + aHelper->Insert(principal, aType, aPermission, + aExpireType, aExpireTime, aModificationTime); + } + } + + return NS_OK; +} + static bool IsExpandedPrincipal(nsIPrincipal* aPrincipal) { @@ -248,9 +467,7 @@ IsExpandedPrincipal(nsIPrincipal* aPrincipal) nsPermissionManager::PermissionKey::PermissionKey(nsIPrincipal* aPrincipal) { - MOZ_ALWAYS_TRUE(NS_SUCCEEDED(GetHostForPrincipal(aPrincipal, mHost))); - MOZ_ALWAYS_TRUE(NS_SUCCEEDED(aPrincipal->GetAppId(&mAppId))); - MOZ_ALWAYS_TRUE(NS_SUCCEEDED(aPrincipal->GetIsInBrowserElement(&mIsInBrowserElement))); + MOZ_ALWAYS_TRUE(NS_SUCCEEDED(aPrincipal->GetOrigin(mOrigin))); } /** @@ -373,7 +590,7 @@ nsPermissionManager::AppClearDataObserverInit() // nsPermissionManager Implementation #define PERMISSIONS_FILE_NAME "permissions.sqlite" -#define HOSTS_SCHEMA_VERSION 4 +#define HOSTS_SCHEMA_VERSION 5 #define HOSTPERM_FILE_NAME "hostperm.1" @@ -617,6 +834,89 @@ nsPermissionManager::InitDB(bool aRemoveFile) // fall through to the next upgrade + // Version 4->5 is the merging of host, appId, and isInBrowserElement into origin + case 4: + { + bool tableExists = false; + mDBConn->TableExists(NS_LITERAL_CSTRING("moz_hosts_new"), &tableExists); + if (tableExists) { + rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING("DROP TABLE moz_hosts_new")); + NS_ENSURE_SUCCESS(rv, rv); + } + rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING( + "CREATE TABLE moz_hosts_new (" + " id INTEGER PRIMARY KEY" + ",origin TEXT" + ",type TEXT" + ",permission INTEGER" + ",expireType INTEGER" + ",expireTime INTEGER" + ",modificationTime INTEGER" + ")")); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr stmt; + rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING( + "SELECT host, type, permission, expireType, expireTime, modificationTime, appId, isInBrowserElement " + "FROM moz_hosts"), getter_AddRefs(stmt)); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr pending; + + int64_t id = 0; + nsAutoCString host, type; + uint32_t permission; + uint32_t expireType; + int64_t expireTime; + int64_t modificationTime; + uint32_t appId; + bool isInBrowserElement; + bool hasResult; + + while (NS_SUCCEEDED(stmt->ExecuteStep(&hasResult)) && hasResult) { + // Read in the old row + rv = stmt->GetUTF8String(0, host); + if (NS_FAILED(rv)) { + continue; + } + rv = stmt->GetUTF8String(1, type); + if (NS_FAILED(rv)) { + continue; + } + permission = stmt->AsInt32(2); + expireType = stmt->AsInt32(3); + expireTime = stmt->AsInt64(4); + modificationTime = stmt->AsInt64(5); + if (stmt->AsInt64(6) < 0) { + continue; + } + appId = static_cast(stmt->AsInt64(6)); + isInBrowserElement = static_cast(stmt->AsInt32(7)); + + UpgradeHostToOriginDBMigration upHelper(mDBConn, &id); + rv = UpgradeHostToOriginAndInsert(host, type, permission, + expireType, expireTime, + modificationTime, appId, + isInBrowserElement, + &upHelper); + if (NS_FAILED(rv)) { + NS_WARNING("Unexpected failure when upgrading migrating permission from host to origin"); + } + } + + // We rename the old table to moz_hosts_v4 instead of dropping it, such that if + // we discover that there was a problem with our migration code in the future, we have information + // to roll-back with. + rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING("ALTER TABLE moz_hosts RENAME TO moz_hosts_v4")); + NS_ENSURE_SUCCESS(rv, rv); + + rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING("ALTER TABLE moz_hosts_new RENAME TO moz_hosts")); + NS_ENSURE_SUCCESS(rv, rv); + + rv = mDBConn->SetSchemaVersion(HOSTS_SCHEMA_VERSION); + NS_ENSURE_SUCCESS(rv, rv); + } + // current version. case HOSTS_SCHEMA_VERSION: break; @@ -632,7 +932,7 @@ nsPermissionManager::InitDB(bool aRemoveFile) // check if all the expected columns exist nsCOMPtr stmt; rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING( - "SELECT host, type, permission, expireType, expireTime, modificationTime, appId, isInBrowserElement FROM moz_hosts"), + "SELECT origin, type, permission, expireType, expireTime, modificationTime FROM moz_hosts"), getter_AddRefs(stmt)); if (NS_SUCCEEDED(rv)) break; @@ -651,8 +951,8 @@ nsPermissionManager::InitDB(bool aRemoveFile) // cache frequently used statements (for insertion, deletion, and updating) rv = mDBConn->CreateAsyncStatement(NS_LITERAL_CSTRING( "INSERT INTO moz_hosts " - "(id, host, type, permission, expireType, expireTime, modificationTime, appId, isInBrowserElement) " - "VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9)"), getter_AddRefs(mStmtInsert)); + "(id, origin, type, permission, expireType, expireTime, modificationTime) " + "VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7)"), getter_AddRefs(mStmtInsert)); NS_ENSURE_SUCCESS(rv, rv); rv = mDBConn->CreateAsyncStatement(NS_LITERAL_CSTRING( @@ -689,14 +989,12 @@ nsPermissionManager::CreateTable() return mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING( "CREATE TABLE moz_hosts (" " id INTEGER PRIMARY KEY" - ",host TEXT" + ",origin TEXT" ",type TEXT" ",permission INTEGER" ",expireType INTEGER" ",expireTime INTEGER" ",modificationTime INTEGER" - ",appId INTEGER" - ",isInBrowserElement INTEGER" ")")); } @@ -776,15 +1074,11 @@ nsPermissionManager::AddInternal(nsIPrincipal* aPrincipal, DBOperationType aDBOperation, const bool aIgnoreSessionPermissions) { - nsAutoCString host; - nsresult rv = GetHostForPrincipal(aPrincipal, host); + nsAutoCString origin; + nsresult rv = aPrincipal->GetOrigin(origin); NS_ENSURE_SUCCESS(rv, rv); if (!IsChildProcess()) { - nsAutoCString origin; - rv = aPrincipal->GetOrigin(origin); - NS_ENSURE_SUCCESS(rv, rv); - IPC::Permission permission(origin, aType, aPermission, aExpireType, aExpireTime); @@ -898,21 +1192,11 @@ nsPermissionManager::AddInternal(nsIPrincipal* aPrincipal, aModificationTime)); if (aDBOperation == eWriteToDB && aExpireType != nsIPermissionManager::EXPIRE_SESSION) { - uint32_t appId; - rv = aPrincipal->GetAppId(&appId); - NS_ENSURE_SUCCESS(rv, rv); - - bool isInBrowserElement; - rv = aPrincipal->GetIsInBrowserElement(&isInBrowserElement); - NS_ENSURE_SUCCESS(rv, rv); - - UpdateDB(op, mStmtInsert, id, host, aType, aPermission, aExpireType, aExpireTime, aModificationTime, appId, isInBrowserElement); + UpdateDB(op, mStmtInsert, id, origin, aType, aPermission, aExpireType, aExpireTime, aModificationTime); } if (aNotifyOperation == eNotify) { - NotifyObserversWithPermission(host, - entry->GetKey()->mAppId, - entry->GetKey()->mIsInBrowserElement, + NotifyObserversWithPermission(aPrincipal, mTypeArray[typeIndex], aPermission, aExpireType, @@ -933,12 +1217,10 @@ nsPermissionManager::AddInternal(nsIPrincipal* aPrincipal, // We care only about the id here so we pass dummy values for all other // parameters. UpdateDB(op, mStmtDelete, id, EmptyCString(), EmptyCString(), 0, - nsIPermissionManager::EXPIRE_NEVER, 0, 0, 0, false); + nsIPermissionManager::EXPIRE_NEVER, 0, 0); if (aNotifyOperation == eNotify) { - NotifyObserversWithPermission(host, - entry->GetKey()->mAppId, - entry->GetKey()->mIsInBrowserElement, + NotifyObserversWithPermission(aPrincipal, mTypeArray[typeIndex], oldPermissionEntry.mPermission, oldPermissionEntry.mExpireType, @@ -981,12 +1263,10 @@ nsPermissionManager::AddInternal(nsIPrincipal* aPrincipal, // We care only about the id, the permission and expireType/expireTime/modificationTime here. // We pass dummy values for all other parameters. UpdateDB(op, mStmtUpdate, id, EmptyCString(), EmptyCString(), - aPermission, aExpireType, aExpireTime, aModificationTime, 0, false); + aPermission, aExpireType, aExpireTime, aModificationTime); if (aNotifyOperation == eNotify) { - NotifyObserversWithPermission(host, - entry->GetKey()->mAppId, - entry->GetKey()->mIsInBrowserElement, + NotifyObserversWithPermission(aPrincipal, mTypeArray[typeIndex], aPermission, aExpireType, @@ -1037,14 +1317,12 @@ nsPermissionManager::AddInternal(nsIPrincipal* aPrincipal, rv = aPrincipal->GetIsInBrowserElement(&isInBrowserElement); NS_ENSURE_SUCCESS(rv, rv); - UpdateDB(eOperationAdding, mStmtInsert, id, host, aType, aPermission, - aExpireType, aExpireTime, aModificationTime, appId, isInBrowserElement); + UpdateDB(eOperationAdding, mStmtInsert, id, origin, aType, aPermission, + aExpireType, aExpireTime, aModificationTime); } if (aNotifyOperation == eNotify) { - NotifyObserversWithPermission(host, - entry->GetKey()->mAppId, - entry->GetKey()->mIsInBrowserElement, + NotifyObserversWithPermission(aPrincipal, mTypeArray[typeIndex], aPermission, aExpireType, @@ -1273,25 +1551,12 @@ nsPermissionManager::GetPermissionObject(nsIPrincipal* aPrincipal, return NS_ERROR_INVALID_ARG; } - nsAutoCString host; - nsresult rv = GetHostForPrincipal(aPrincipal, host); - NS_ENSURE_SUCCESS(rv, rv); - int32_t typeIndex = GetTypeIndex(aType, false); // If type == -1, the type isn't known, // so just return NS_OK if (typeIndex == -1) return NS_OK; - uint32_t appId; - rv = aPrincipal->GetAppId(&appId); - NS_ENSURE_SUCCESS(rv, rv); - - bool isInBrowserElement; - rv = aPrincipal->GetIsInBrowserElement(&isInBrowserElement); - NS_ENSURE_SUCCESS(rv, rv); - - PermissionHashKey* entry = GetPermissionHashKey(host, appId, isInBrowserElement, - typeIndex, aExactHostMatch); + PermissionHashKey* entry = GetPermissionHashKey(aPrincipal, typeIndex, aExactHostMatch); if (!entry) { return NS_OK; } @@ -1303,14 +1568,11 @@ nsPermissionManager::GetPermissionObject(nsIPrincipal* aPrincipal, return NS_OK; } - PermissionEntry& perm = entry->GetPermissions()[idx]; nsCOMPtr principal; - rv = GetPrincipal(entry->GetKey()->mHost, - entry->GetKey()->mAppId, - entry->GetKey()->mIsInBrowserElement, - getter_AddRefs(principal)); + nsresult rv = GetPrincipalFromOrigin(entry->GetKey()->mOrigin, getter_AddRefs(principal)); NS_ENSURE_SUCCESS(rv, rv); + PermissionEntry& perm = entry->GetPermissions()[idx]; nsCOMPtr r = new nsPermission(principal, mTypeArray.ElementAt(perm.mType), perm.mPermission, @@ -1363,25 +1625,12 @@ nsPermissionManager::CommonTestPermission(nsIPrincipal* aPrincipal, return NS_OK; } - nsAutoCString host; - nsresult rv = GetHostForPrincipal(aPrincipal, host); - NS_ENSURE_SUCCESS(rv, rv); - int32_t typeIndex = GetTypeIndex(aType, false); // If type == -1, the type isn't known, // so just return NS_OK if (typeIndex == -1) return NS_OK; - uint32_t appId; - rv = aPrincipal->GetAppId(&appId); - NS_ENSURE_SUCCESS(rv, rv); - - bool isInBrowserElement; - rv = aPrincipal->GetIsInBrowserElement(&isInBrowserElement); - NS_ENSURE_SUCCESS(rv, rv); - - PermissionHashKey* entry = GetPermissionHashKey(host, appId, isInBrowserElement, - typeIndex, aExactHostMatch); + PermissionHashKey* entry = GetPermissionHashKey(aPrincipal, typeIndex, aExactHostMatch); if (!entry || (!aIncludingSession && entry->GetPermission(typeIndex).mNonSessionExpireType == @@ -1403,15 +1652,13 @@ nsPermissionManager::CommonTestPermission(nsIPrincipal* aPrincipal, // Also accepts host on the format "". This will perform an exact match // lookup as the string doesn't contain any dots. nsPermissionManager::PermissionHashKey* -nsPermissionManager::GetPermissionHashKey(const nsACString& aHost, - uint32_t aAppId, - bool aIsInBrowserElement, +nsPermissionManager::GetPermissionHashKey(nsIPrincipal* aPrincipal, uint32_t aType, bool aExactHostMatch) { PermissionHashKey* entry = nullptr; - nsRefPtr key = new PermissionKey(aHost, aAppId, aIsInBrowserElement); + nsRefPtr key = new PermissionKey(aPrincipal); entry = mPermissionTable.GetEntry(key); if (entry) { @@ -1423,13 +1670,8 @@ nsPermissionManager::GetPermissionHashKey(const nsACString& aHost, (permEntry.mExpireType == nsIPermissionManager::EXPIRE_SESSION && permEntry.mExpireTime != 0)) && permEntry.mExpireTime <= (PR_Now() / 1000)) { - nsCOMPtr principal; - if (NS_FAILED(GetPrincipal(aHost, aAppId, aIsInBrowserElement, getter_AddRefs(principal)))) { - return nullptr; - } - entry = nullptr; - RemoveFromPrincipal(principal, mTypeArray[aType].get()); + RemoveFromPrincipal(aPrincipal, mTypeArray[aType].get()); } else if (permEntry.mPermission == nsIPermissionManager::UNKNOWN_ACTION) { entry = nullptr; } @@ -1441,10 +1683,40 @@ nsPermissionManager::GetPermissionHashKey(const nsACString& aHost, // If aExactHostMatch wasn't true, we can check if the base domain has a permission entry. if (!aExactHostMatch) { - nsCString domain = GetNextSubDomainForHost(aHost); - if (!domain.IsEmpty()) { - return GetPermissionHashKey(domain, aAppId, aIsInBrowserElement, aType, aExactHostMatch); + nsCOMPtr uri; + nsresult rv = aPrincipal->GetURI(getter_AddRefs(uri)); + if (NS_FAILED(rv)) { + return nullptr; } + + nsAutoCString host; + rv = uri->GetHost(host); + if (NS_FAILED(rv)) { + return nullptr; + } + + nsCString domain = GetNextSubDomainForHost(host); + if (domain.IsEmpty()) { + return nullptr; + } + + // Create a new principal which is identical to the current one, but with the new host + nsCOMPtr newURI; + rv = uri->Clone(getter_AddRefs(newURI)); + if (NS_FAILED(rv)) { + return nullptr; + } + + rv = newURI->SetHost(domain); + if (NS_FAILED(rv)) { + return nullptr; + } + + // Copy the attributes over + mozilla::OriginAttributes attrs = mozilla::BasePrincipal::Cast(aPrincipal)->OriginAttributesRef(); + nsCOMPtr principal = mozilla::BasePrincipal::CreateCodebasePrincipal(newURI, attrs); + + return GetPermissionHashKey(principal, aType, aExactHostMatch); } // No entry, really... @@ -1467,10 +1739,9 @@ NS_IMETHODIMP nsPermissionManager::GetEnumerator(nsISimpleEnumerator **aEnum) } nsCOMPtr principal; - if (NS_FAILED(GetPrincipal(entry->GetKey()->mHost, - entry->GetKey()->mAppId, - entry->GetKey()->mIsInBrowserElement, - getter_AddRefs(principal)))) { + nsresult rv = GetPrincipalFromOrigin(entry->GetKey()->mOrigin, + getter_AddRefs(principal)); + if (NS_FAILED(rv)) { continue; } @@ -1520,10 +1791,9 @@ nsPermissionManager::RemoveAllModifiedSince(int64_t aModificationTime) } nsCOMPtr principal; - if (NS_FAILED(GetPrincipal(entry->GetKey()->mHost, - entry->GetKey()->mAppId, - entry->GetKey()->mIsInBrowserElement, - getter_AddRefs(principal)))) { + nsresult rv = GetPrincipalFromOrigin(entry->GetKey()->mOrigin, + getter_AddRefs(principal)); + if (NS_FAILED(rv)) { continue; } @@ -1601,16 +1871,20 @@ nsPermissionManager::RemovePermissionsForApp(uint32_t aAppId, bool aBrowserOnly) nsCOMArray permissions; for (auto iter = mPermissionTable.Iter(); !iter.Done(); iter.Next()) { PermissionHashKey* entry = iter.Get(); - if (entry->GetKey()->mAppId != aAppId || - (aBrowserOnly && !entry->GetKey()->mIsInBrowserElement)) { + + nsCOMPtr principal; + nsresult rv = GetPrincipalFromOrigin(entry->GetKey()->mOrigin, + getter_AddRefs(principal)); + if (NS_FAILED(rv)) { continue; } - nsCOMPtr principal; - if (NS_FAILED(GetPrincipal(entry->GetKey()->mHost, - entry->GetKey()->mAppId, - entry->GetKey()->mIsInBrowserElement, - getter_AddRefs(principal)))) { + uint32_t appId; + bool isInBrowserElement; + principal->GetAppId(&appId); + principal->GetIsInBrowserElement(&isInBrowserElement); + + if (appId != aAppId || (aBrowserOnly && !isInBrowserElement)) { continue; } @@ -1639,7 +1913,7 @@ nsPermissionManager::RemovePermissionsForApp(uint32_t aAppId, bool aBrowserOnly) 0, 0, nsPermissionManager::eNotify, - nsPermissionManager::eNoDBOperation); + nsPermissionManager::eWriteToDB); } return NS_OK; @@ -1656,7 +1930,13 @@ nsPermissionManager::RemoveExpiredPermissionsForApp(uint32_t aAppId) for (auto iter = mPermissionTable.Iter(); !iter.Done(); iter.Next()) { PermissionHashKey* entry = iter.Get(); - if (entry->GetKey()->mAppId != aAppId) { + nsCOMPtr principal; + GetPrincipalFromOrigin(entry->GetKey()->mOrigin, getter_AddRefs(principal)); + + uint32_t appId; + principal->GetAppId(&appId); + + if (appId != aAppId) { continue; } @@ -1672,9 +1952,7 @@ nsPermissionManager::RemoveExpiredPermissionsForApp(uint32_t aAppId) entry->GetPermissions().RemoveElementAt(i); - NotifyObserversWithPermission(entry->GetKey()->mHost, - entry->GetKey()->mAppId, - entry->GetKey()->mIsInBrowserElement, + NotifyObserversWithPermission(principal, mTypeArray.ElementAt(oldPermEntry.mType), oldPermEntry.mPermission, oldPermEntry.mExpireType, @@ -1689,9 +1967,7 @@ nsPermissionManager::RemoveExpiredPermissionsForApp(uint32_t aAppId) permEntry.mExpireType = permEntry.mNonSessionExpireType; permEntry.mExpireTime = permEntry.mNonSessionExpireTime; - NotifyObserversWithPermission(entry->GetKey()->mHost, - entry->GetKey()->mAppId, - entry->GetKey()->mIsInBrowserElement, + NotifyObserversWithPermission(principal, mTypeArray.ElementAt(permEntry.mType), permEntry.mPermission, permEntry.mExpireType, @@ -1744,20 +2020,15 @@ nsPermissionManager::GetTypeIndex(const char *aType, // wrapper function for mangling (host,type,perm,expireType,expireTime) // set into an nsIPermission. void -nsPermissionManager::NotifyObserversWithPermission(const nsACString &aHost, - uint32_t aAppId, - bool aIsInBrowserElement, +nsPermissionManager::NotifyObserversWithPermission(nsIPrincipal* aPrincipal, const nsCString &aType, uint32_t aPermission, uint32_t aExpireType, int64_t aExpireTime, const char16_t *aData) { - nsCOMPtr principal; - GetPrincipal(aHost, aAppId, aIsInBrowserElement, getter_AddRefs(principal)); - nsCOMPtr permission = - new nsPermission(principal, aType, aPermission, + new nsPermission(aPrincipal, aType, aPermission, aExpireType, aExpireTime); if (permission) NotifyObservers(permission, aData); @@ -1808,18 +2079,16 @@ nsPermissionManager::Read() nsCOMPtr stmt; rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING( - "SELECT id, host, type, permission, expireType, expireTime, modificationTime, appId, isInBrowserElement " + "SELECT id, origin, type, permission, expireType, expireTime, modificationTime " "FROM moz_hosts"), getter_AddRefs(stmt)); NS_ENSURE_SUCCESS(rv, rv); int64_t id; - nsAutoCString host, type; + nsAutoCString origin, type; uint32_t permission; uint32_t expireType; int64_t expireTime; int64_t modificationTime; - uint32_t appId; - bool isInBrowserElement; bool hasResult; bool readError = false; @@ -1830,7 +2099,7 @@ nsPermissionManager::Read() if (id > mLargestID) mLargestID = id; - rv = stmt->GetUTF8String(1, host); + rv = stmt->GetUTF8String(1, origin); if (NS_FAILED(rv)) { readError = true; continue; @@ -1849,16 +2118,8 @@ nsPermissionManager::Read() expireTime = stmt->AsInt64(5); modificationTime = stmt->AsInt64(6); - if (stmt->AsInt64(7) < 0) { - readError = true; - continue; - } - - appId = static_cast(stmt->AsInt64(7)); - isInBrowserElement = static_cast(stmt->AsInt32(8)); - nsCOMPtr principal; - nsresult rv = GetPrincipal(host, appId, isInBrowserElement, getter_AddRefs(principal)); + nsresult rv = GetPrincipalFromOrigin(origin, getter_AddRefs(principal)); if (NS_FAILED(rv)) { readError = true; continue; @@ -1881,6 +2142,7 @@ nsPermissionManager::Read() } static const char kMatchTypeHost[] = "host"; +static const char kMatchTypeOrigin[] = "origin"; // Import() will read a file from the profile directory and add them to the // database before deleting the file - ie, this is a one-shot operation that @@ -1990,32 +2252,48 @@ nsPermissionManager::_DoImport(nsIInputStream *inputStream, mozIStorageConnectio if (lineArray[0].EqualsLiteral(kMatchTypeHost) && lineArray.Length() == 4) { - - nsresult error; + nsresult error = NS_OK; uint32_t permission = lineArray[2].ToInteger(&error); if (NS_FAILED(error)) continue; - // hosts might be encoded in UTF8; switch them to ACE to be consistent - if (!IsASCII(lineArray[3])) { - rv = NormalizeToACE(lineArray[3]); - if (NS_FAILED(rv)) - continue; - } - - nsCOMPtr principal; - nsresult rv = GetPrincipal(lineArray[3], getter_AddRefs(principal)); - NS_ENSURE_SUCCESS(rv, rv); - // the import file format doesn't handle modification times, so we use // 0, which AddInternal will convert to now() int64_t modificationTime = 0; - rv = AddInternal(principal, lineArray[1], permission, id, - nsIPermissionManager::EXPIRE_NEVER, 0, - modificationTime, - eDontNotify, operation); - NS_ENSURE_SUCCESS(rv, rv); + UpgradeHostToOriginHostfileImport upHelper(this, operation, id); + error = UpgradeHostToOriginAndInsert(lineArray[3], lineArray[1], permission, + nsIPermissionManager::EXPIRE_NEVER, 0, + modificationTime, nsIScriptSecurityManager::NO_APP_ID, + false, &upHelper); + if (NS_FAILED(error)) { + NS_WARNING("There was a problem importing a host permission"); + } + } else if (lineArray[0].EqualsLiteral(kMatchTypeOrigin) && + lineArray.Length() == 4) { + nsresult error = NS_OK; + uint32_t permission = lineArray[2].ToInteger(&error); + if (NS_FAILED(error)) + continue; + + nsCOMPtr principal; + error = GetPrincipalFromOrigin(lineArray[3], getter_AddRefs(principal)); + if (NS_FAILED(error)) { + NS_WARNING("Couldn't import an origin permission - malformed origin"); + continue; + } + + // the import file format doesn't handle modification times, so we use + // 0, which AddInternal will convert to now() + int64_t modificationTime = 0; + + error = AddInternal(principal, lineArray[1], permission, id, + nsIPermissionManager::EXPIRE_NEVER, 0, + modificationTime, + eDontNotify, operation); + if (NS_FAILED(error)) { + NS_WARNING("There was a problem importing an origin permission"); + } } } while (isMore); @@ -2040,14 +2318,12 @@ void nsPermissionManager::UpdateDB(OperationType aOp, mozIStorageAsyncStatement* aStmt, int64_t aID, - const nsACString &aHost, + const nsACString &aOrigin, const nsACString &aType, uint32_t aPermission, uint32_t aExpireType, int64_t aExpireTime, - int64_t aModificationTime, - uint32_t aAppId, - bool aIsInBrowserElement) + int64_t aModificationTime) { ENSURE_NOT_CHILD_PROCESS_NORET; @@ -2063,7 +2339,7 @@ nsPermissionManager::UpdateDB(OperationType aOp, rv = aStmt->BindInt64ByIndex(0, aID); if (NS_FAILED(rv)) break; - rv = aStmt->BindUTF8StringByIndex(1, aHost); + rv = aStmt->BindUTF8StringByIndex(1, aOrigin); if (NS_FAILED(rv)) break; rv = aStmt->BindUTF8StringByIndex(2, aType); @@ -2079,12 +2355,6 @@ nsPermissionManager::UpdateDB(OperationType aOp, if (NS_FAILED(rv)) break; rv = aStmt->BindInt64ByIndex(6, aModificationTime); - if (NS_FAILED(rv)) break; - - rv = aStmt->BindInt64ByIndex(7, aAppId); - if (NS_FAILED(rv)) break; - - rv = aStmt->BindInt64ByIndex(8, aIsInBrowserElement); break; } @@ -2203,25 +2473,12 @@ nsPermissionManager::UpdateExpireTime(nsIPrincipal* aPrincipal, return NS_ERROR_INVALID_ARG; } - nsAutoCString host; - nsresult rv = GetHostForPrincipal(aPrincipal, host); - NS_ENSURE_SUCCESS(rv, rv); - int32_t typeIndex = GetTypeIndex(aType, false); // If type == -1, the type isn't known, // so just return NS_OK if (typeIndex == -1) return NS_OK; - uint32_t appId; - rv = aPrincipal->GetAppId(&appId); - NS_ENSURE_SUCCESS(rv, rv); - - bool isInBrowserElement; - rv = aPrincipal->GetIsInBrowserElement(&isInBrowserElement); - NS_ENSURE_SUCCESS(rv, rv); - - PermissionHashKey* entry = GetPermissionHashKey(host, appId, isInBrowserElement, - typeIndex, aExactHostMatch); + PermissionHashKey* entry = GetPermissionHashKey(aPrincipal, typeIndex, aExactHostMatch); if (!entry) { return NS_OK; } @@ -2250,16 +2507,10 @@ nsPermissionManager::FetchPermissions() { for (uint32_t i = 0; i < perms.Length(); i++) { const IPC::Permission &perm = perms[i]; - nsAutoCString originNoSuffix; - mozilla::OriginAttributes attrs; - attrs.PopulateFromOrigin(perm.origin, originNoSuffix); - - nsCOMPtr uri; - nsresult rv = NS_NewURI(getter_AddRefs(uri), originNoSuffix); + nsCOMPtr principal; + nsresult rv = GetPrincipalFromOrigin(perm.origin, getter_AddRefs(principal)); NS_ENSURE_SUCCESS(rv, rv); - nsCOMPtr principal = mozilla::BasePrincipal::CreateCodebasePrincipal(uri, attrs); - // The child process doesn't care about modification times - it neither // reads nor writes, nor removes them based on the date - so 0 (which // will end up as now()) is fine. diff --git a/extensions/cookie/nsPermissionManager.h b/extensions/cookie/nsPermissionManager.h index 080bffa3f49..3b855b544bc 100644 --- a/extensions/cookie/nsPermissionManager.h +++ b/extensions/cookie/nsPermissionManager.h @@ -71,35 +71,22 @@ public: { public: explicit PermissionKey(nsIPrincipal* aPrincipal); - PermissionKey(const nsACString& aHost, - uint32_t aAppId, - bool aIsInBrowserElement) - : mHost(aHost) - , mAppId(aAppId) - , mIsInBrowserElement(aIsInBrowserElement) + explicit PermissionKey(const nsACString& aOrigin) + : mOrigin(aOrigin) { } bool operator==(const PermissionKey& aKey) const { - return mHost.Equals(aKey.mHost) && - mAppId == aKey.mAppId && - mIsInBrowserElement == aKey.mIsInBrowserElement; + return mOrigin.Equals(aKey.mOrigin); } PLDHashNumber GetHashCode() const { - nsAutoCString str; - str.Assign(mHost); - str.AppendInt(mAppId); - str.AppendInt(static_cast(mIsInBrowserElement)); - - return mozilla::HashString(str); + return mozilla::HashString(mOrigin); } NS_INLINE_DECL_THREADSAFE_REFCOUNTING(PermissionKey) - nsCString mHost; - uint32_t mAppId; - bool mIsInBrowserElement; + nsCString mOrigin; private: // Default ctor shouldn't be used. @@ -222,11 +209,9 @@ private: int32_t GetTypeIndex(const char *aTypeString, bool aAdd); - PermissionHashKey* GetPermissionHashKey(const nsACString& aHost, - uint32_t aAppId, - bool aIsInBrowserElement, - uint32_t aType, - bool aExactHostMatch); + PermissionHashKey* GetPermissionHashKey(nsIPrincipal* aPrincipal, + uint32_t aType, + bool aExactHostMatch); nsresult CommonTestPermission(nsIPrincipal* aPrincipal, const char *aType, @@ -241,9 +226,7 @@ private: nsresult ImportDefaults(); nsresult _DoImport(nsIInputStream *inputStream, mozIStorageConnection *aConn); nsresult Read(); - void NotifyObserversWithPermission(const nsACString &aHost, - uint32_t aAppId, - bool aIsInBrowserElement, + void NotifyObserversWithPermission(nsIPrincipal* aPrincipal, const nsCString &aType, uint32_t aPermission, uint32_t aExpireType, @@ -261,14 +244,12 @@ private: static void UpdateDB(OperationType aOp, mozIStorageAsyncStatement* aStmt, int64_t aID, - const nsACString& aHost, + const nsACString& aOrigin, const nsACString& aType, uint32_t aPermission, uint32_t aExpireType, int64_t aExpireTime, - int64_t aModificationTime, - uint32_t aAppId, - bool aIsInBrowserElement); + int64_t aModificationTime); nsresult RemoveExpiredPermissionsForApp(uint32_t aAppId);