import changes from `dev' branch of rmottola/Arctic-Fox:

- Bug 1110446 P2 Cleanup stale caches/bodies if last session didn't shutdown cleanly. r=ehsan (7925cf5fa)
- Bug 1110446 P3 Add a test that forces a Cache object to be orphaned and reclaimed. r=ehsan (c61409240)
- Bug 1110446 P4 Add a test that orphanes Cache API body files. r=ehsan (97e0a6f73)
- Bug 1157670 - Fixing an incorrect assertion in QuotaManager.cpp leads to an assertion failure; r=bent (0a19eac66)
- Bug 1165119 Remove corrupt morgue directories polluting nightly profiles. r=janv (d148170d8)
- Bug 1165119 - Follow-up to address review feedback accidentally left out of last push. r=me (f7ef96873)
- Fixup to make bug 1165119 ride the trains properly. r=trivial,DONTBUILD (87d186da4)
- Bug 1162624 - Add support for restoring corrupted or missing metadata files; r=bent (57e4341e6)
- Bug 1174113 - QuotaManager: Origin initialization fails on moz-safe-about+++home; r=bent (b7673128c)
- Bug 1142694 - QuotaManager default/temporary initialization fails on some profiles; r=bent (29a286137)
- Bug 1166871 - Always force a repaint before handling a wheel event so that we don't untransform it into some other scrollframe. r=botond (28e56646d)
- Don't vertically scroll APZCs that have less than one pixel of vertical scroll range. (bug 1154134, r=kats) (1bac9c054)
- Bug 1166871 - Add a test. r=botond (45d398bb6)
- Bug 1164557 - Do not start an overscroll animation if one is already running. r=kats (287a27910)
- Bug 1163832 - Add an API to flush pending APZ repaint requests and dispatch a notification upon completion. r=botond (8b3f9e06f)
- Bug 858680 - Part 1: Perform incremental_vacuum on open databases while idle, r=janv. (715f77ad6)
- Bug 858680 - Part 2: Add idle notifications to QuotaClient, r=janv. (9f245b1bb)
- Bug 1135166 - Initialize Telemetry histogram id cache early to avoid races. r=froydnj,vladan (f0bd8278c)
- Bug 1162176, Part 1. r=mak. (f92ba4061)
- Bug 1162176, Part 2. r=janv. (f313e1cf3)
- Bug 1155634 - Move ConnectionPool creation closer to where we actually use it and at a point guaranteed to be after QuotaManager has been started. r=khuey relanding CLOSED TREE (ce489e8f4)
- Bug 1155652 - Fix two incorrect assertions r=janv (2417d91ed)
- Bug 1156063 - Intermittent application crashed [@ mozilla::dom::indexedDB::::ConnectionPool::Start] in various tests. r=janv (b1126ac71)
- Bug 1157029 - More changes to bulletproof shutdown of failed connections, r=janv. (93a425abb)
- Bug 858680 - Part 4: Perform maintenance on databases while idle, r=janv. (017d536fe)
- Bug 1130775 - Convert synchronized ops and storage registration into unified directory locks; r=bent (300f635f7)
- Bug 1130775 followup: Add missing 'override' keyword to SendResults() methods in QuotaManager.cpp. rs=ehsan (397338f5b)
- Bug 1170021 - Part 1: Merge QuotaManager with QuotaObject; r=bent (168264350)
- Bug 1170021 - Part 2: Move DirectoryLock out of QuotaManager class; r=bent (278964f88)
- pointer style (99453953c)
- Bug 1171931 - Refactor duplicated code using XRE_IsParent/ContentProcess. r=froydnj (6d1ddbff1)
This commit is contained in:
2021-02-23 12:01:40 +08:00
parent 13b1aeb09f
commit 3909bb5fb8
271 changed files with 7550 additions and 4762 deletions
+3 -3
View File
@@ -1239,7 +1239,7 @@ nsAccessibilityService::Init()
logging::CheckEnv();
#endif
if (XRE_GetProcessType() == GeckoProcessType_Default)
if (XRE_IsParentProcess())
gApplicationAccessible = new ApplicationAccessibleWrap();
else
gApplicationAccessible = new ApplicationAccessible();
@@ -1254,7 +1254,7 @@ nsAccessibilityService::Init()
gIsShutdown = false;
// Now its safe to start platform accessibility.
if (XRE_GetProcessType() == GeckoProcessType_Default)
if (XRE_IsParentProcess())
PlatformInit();
return true;
@@ -1297,7 +1297,7 @@ nsAccessibilityService::Shutdown()
gIsShutdown = true;
if (XRE_GetProcessType() == GeckoProcessType_Default)
if (XRE_IsParentProcess())
PlatformShutdown();
gApplicationAccessible->Shutdown();
+1 -1
View File
@@ -282,7 +282,7 @@ IPCAccessibilityActive()
#ifdef MOZ_B2G
return false;
#else
return XRE_GetProcessType() == GeckoProcessType_Content &&
return XRE_IsContentProcess() &&
mozilla::Preferences::GetBool("accessibility.ipc_architecture.enabled", true);
#endif
}
+1 -1
View File
@@ -425,7 +425,7 @@ nsCoreUtils::IsTabDocument(nsIDocument* aDocumentNode)
treeItem->GetParent(getter_AddRefs(parentTreeItem));
// Tab document running in own process doesn't have parent.
if (XRE_GetProcessType() == GeckoProcessType_Content)
if (XRE_IsContentProcess())
return !parentTreeItem;
// Parent of docshell for tab document running in chrome process is root.
+1 -1
View File
@@ -64,7 +64,7 @@ nsWinUtils::MaybeStartWindowEmulation()
if (Compatibility::IsJAWS() || Compatibility::IsWE() ||
Compatibility::IsDolphin() ||
XRE_GetProcessType() == GeckoProcessType_Content) {
XRE_IsContentProcess()) {
RegisterNativeWindow(kClassNameTabContent);
sHWNDCache = new nsRefPtrHashtable<nsPtrHashKey<void>, DocAccessible>(2);
return true;
@@ -52,8 +52,6 @@ add_test(function setup_sdcard() {
let vol = volumeService.getVolumeByName(volName);
ok(vol, "volume shouldn't be null");
equal(volName, vol.name, "name");
volumeService.SetFakeVolumeState(volName, Ci.nsIVolume.STATE_MOUNTED);
equal(Ci.nsIVolume.STATE_MOUNTED, vol.state, "state");
run_next_test();
+6 -6
View File
@@ -22,7 +22,7 @@ static nsresult
BroadcastDomainSetChange(DomainSetType aSetType, DomainSetChangeType aChangeType,
nsIURI* aDomain = nullptr)
{
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default,
MOZ_ASSERT(XRE_IsParentProcess(),
"DomainPolicy should only be exposed to the chrome process.");
nsTArray<ContentParent*> parents;
@@ -45,7 +45,7 @@ DomainPolicy::DomainPolicy() : mBlacklist(new DomainSet(BLACKLIST))
, mWhitelist(new DomainSet(WHITELIST))
, mSuperWhitelist(new DomainSet(SUPER_WHITELIST))
{
if (XRE_GetProcessType() == GeckoProcessType_Default) {
if (XRE_IsParentProcess()) {
BroadcastDomainSetChange(NO_TYPE, ACTIVATE_POLICY);
}
}
@@ -112,7 +112,7 @@ DomainPolicy::Deactivate()
if (ssm) {
ssm->DeactivateDomainPolicy();
}
if (XRE_GetProcessType() == GeckoProcessType_Default) {
if (XRE_IsParentProcess()) {
BroadcastDomainSetChange(NO_TYPE, DEACTIVATE_POLICY);
}
return NS_OK;
@@ -170,7 +170,7 @@ DomainSet::Add(nsIURI* aDomain)
nsCOMPtr<nsIURI> clone = GetCanonicalClone(aDomain);
NS_ENSURE_TRUE(clone, NS_ERROR_FAILURE);
mHashTable.PutEntry(clone);
if (XRE_GetProcessType() == GeckoProcessType_Default)
if (XRE_IsParentProcess())
return BroadcastDomainSetChange(mType, ADD_DOMAIN, aDomain);
return NS_OK;
@@ -182,7 +182,7 @@ DomainSet::Remove(nsIURI* aDomain)
nsCOMPtr<nsIURI> clone = GetCanonicalClone(aDomain);
NS_ENSURE_TRUE(clone, NS_ERROR_FAILURE);
mHashTable.RemoveEntry(clone);
if (XRE_GetProcessType() == GeckoProcessType_Default)
if (XRE_IsParentProcess())
return BroadcastDomainSetChange(mType, REMOVE_DOMAIN, aDomain);
return NS_OK;
@@ -192,7 +192,7 @@ NS_IMETHODIMP
DomainSet::Clear()
{
mHashTable.Clear();
if (XRE_GetProcessType() == GeckoProcessType_Default)
if (XRE_IsParentProcess())
return BroadcastDomainSetChange(mType, CLEAR_DOMAINS);
return NS_OK;
+2 -2
View File
@@ -1273,7 +1273,7 @@ nsScriptSecurityManager::~nsScriptSecurityManager(void)
// ContentChild might hold a reference to the domain policy,
// and it might release it only after the security manager is
// gone. But we can still assert this for the main process.
MOZ_ASSERT_IF(XRE_GetProcessType() == GeckoProcessType_Default,
MOZ_ASSERT_IF(XRE_IsParentProcess(),
!mDomainPolicy);
}
@@ -1490,7 +1490,7 @@ nsScriptSecurityManager::GetDomainPolicyActive(bool *aRv)
NS_IMETHODIMP
nsScriptSecurityManager::ActivateDomainPolicy(nsIDomainPolicy** aRv)
{
if (XRE_GetProcessType() != GeckoProcessType_Default) {
if (!XRE_IsParentProcess()) {
return NS_ERROR_SERVICE_NOT_AVAILABLE;
}
+1
View File
@@ -51,6 +51,7 @@ EXPORTS
sqlite3_create_function16
sqlite3_create_module
sqlite3_data_count
sqlite3_db_filename
sqlite3_db_handle
sqlite3_db_mutex
sqlite3_db_status
+1 -1
View File
@@ -448,7 +448,7 @@ nsDefaultURIFixup::KeywordToURI(const nsACString& aKeyword,
}
keyword.Trim(" ");
if (XRE_GetProcessType() == GeckoProcessType_Content) {
if (XRE_IsContentProcess()) {
dom::ContentChild* contentChild = dom::ContentChild::GetSingleton();
if (!contentChild) {
return NS_ERROR_NOT_AVAILABLE;
+5 -5
View File
@@ -816,7 +816,7 @@ IncreasePrivateDocShellCount()
{
gNumberOfPrivateDocShells++;
if (gNumberOfPrivateDocShells > 1 ||
XRE_GetProcessType() != GeckoProcessType_Content) {
!XRE_IsContentProcess()) {
return;
}
@@ -830,7 +830,7 @@ DecreasePrivateDocShellCount()
MOZ_ASSERT(gNumberOfPrivateDocShells > 0);
gNumberOfPrivateDocShells--;
if (!gNumberOfPrivateDocShells) {
if (XRE_GetProcessType() == GeckoProcessType_Content) {
if (XRE_IsContentProcess()) {
dom::ContentChild* cc = dom::ContentChild::GetSingleton();
cc->SendPrivateDocShellsExist(false);
return;
@@ -5028,7 +5028,7 @@ nsDocShell::DisplayLoadError(nsresult aError, nsIURI* aURI,
mInPrivateBrowsing ? nsISocketProvider::NO_PERMANENT_STORAGE : 0;
bool isStsHost = false;
bool isPinnedHost = false;
if (XRE_GetProcessType() == GeckoProcessType_Default) {
if (XRE_IsParentProcess()) {
nsCOMPtr<nsISiteSecurityService> sss =
do_GetService(NS_SSSERVICE_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
@@ -9487,7 +9487,7 @@ nsDocShell::CopyFavicon(nsIURI* aOldURI,
nsIURI* aNewURI,
bool aInPrivateBrowsing)
{
if (XRE_GetProcessType() == GeckoProcessType_Content) {
if (XRE_IsContentProcess()) {
dom::ContentChild* contentChild = dom::ContentChild::GetSingleton();
if (contentChild) {
mozilla::ipc::URIParams oldURI, newURI;
@@ -14199,7 +14199,7 @@ nsDocShell::MaybeNotifyKeywordSearchLoading(const nsString& aProvider,
return;
}
if (XRE_GetProcessType() == GeckoProcessType_Content) {
if (XRE_IsContentProcess()) {
dom::ContentChild* contentChild = dom::ContentChild::GetSingleton();
if (contentChild) {
contentChild->SendNotifyKeywordSearchLoading(aProvider, aKeyword);
+75 -56
View File
@@ -17,7 +17,6 @@
#include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/PermissionMessageUtils.h"
#include "mozilla/dom/quota/Client.h"
#include "mozilla/dom/quota/OriginOrPatternString.h"
#include "mozilla/dom/quota/QuotaManager.h"
#include "mozilla/dom/quota/QuotaObject.h"
#include "mozilla/dom/quota/UsageInfo.h"
@@ -42,7 +41,6 @@
#define ASMJSCACHE_ENTRY_FILE_NAME_BASE "module"
using mozilla::dom::quota::AssertIsOnIOThread;
using mozilla::dom::quota::OriginOrPatternString;
using mozilla::dom::quota::PersistenceType;
using mozilla::dom::quota::QuotaManager;
using mozilla::dom::quota::QuotaObject;
@@ -59,12 +57,6 @@ namespace asmjscache {
namespace {
bool
IsMainProcess()
{
return XRE_GetProcessType() == GeckoProcessType_Default;
}
// Anything smaller should compile fast enough that caching will just add
// overhead.
static const size_t sMinCachedModuleLength = 10000;
@@ -298,8 +290,8 @@ public:
}
protected:
// This method must be called before AllowNextSynchronizedOp (which releases
// the lock protecting these resources). It is idempotent, so it is ok to call
// This method must be called before the directory lock is released (the lock
// is protecting these resources). It is idempotent, so it is ok to call
// multiple times (or before the file has been fully opened).
void
Finish()
@@ -482,8 +474,12 @@ private:
// MainProcessRunnable is a base class shared by (Single|Parent)ProcessRunnable
// that factors out the runnable state machine required to open a cache entry
// that runs in the main process.
class MainProcessRunnable : public virtual FileDescriptorHolder
class MainProcessRunnable
: public virtual FileDescriptorHolder
, public quota::OpenDirectoryListener
{
typedef mozilla::dom::quota::DirectoryLock DirectoryLock;
public:
NS_DECL_NSIRUNNABLE
@@ -496,20 +492,19 @@ public:
: mPrincipal(aPrincipal),
mOpenMode(aOpenMode),
mWriteParams(aWriteParams),
mNeedAllowNextSynchronizedOp(false),
mPersistence(quota::PERSISTENCE_TYPE_INVALID),
mState(eInitial),
mResult(JS::AsmJSCache_InternalError),
mIsApp(false),
mEnforcingQuota(true)
{
MOZ_ASSERT(IsMainProcess());
MOZ_ASSERT(XRE_IsParentProcess());
}
virtual ~MainProcessRunnable()
{
MOZ_ASSERT(mState == eFinished);
MOZ_ASSERT(!mNeedAllowNextSynchronizedOp);
MOZ_ASSERT(!mDirectoryLock);
}
protected:
@@ -637,16 +632,22 @@ private:
}
}
// OpenDirectoryListener overrides.
virtual void
DirectoryLockAcquired(DirectoryLock* aLock) override;
virtual void
DirectoryLockFailed() override;
nsIPrincipal* const mPrincipal;
const OpenMode mOpenMode;
const WriteParams mWriteParams;
// State initialized during eInitial:
bool mNeedAllowNextSynchronizedOp;
quota::PersistenceType mPersistence;
nsCString mGroup;
nsCString mOrigin;
nsCString mStorageId;
nsRefPtr<DirectoryLock> mDirectoryLock;
// State initialized during eReadyToReadMetadata
nsCOMPtr<nsIFile> mDirectory;
@@ -741,9 +742,6 @@ MainProcessRunnable::InitOnMainThread()
mEnforcingQuota =
QuotaManager::IsQuotaEnforced(mPersistence, mOrigin, mIsApp);
QuotaManager::GetStorageId(mPersistence, mOrigin, quota::Client::ASMJS,
NS_LITERAL_STRING("asmjs"), mStorageId);
return NS_OK;
}
@@ -918,18 +916,10 @@ MainProcessRunnable::FinishOnMainThread()
MOZ_ASSERT(NS_IsMainThread());
// Per FileDescriptorHolder::Finish()'s comment, call before
// AllowNextSynchronizedOp.
// releasing the directory lock.
FileDescriptorHolder::Finish();
if (mNeedAllowNextSynchronizedOp) {
mNeedAllowNextSynchronizedOp = false;
QuotaManager* qm = QuotaManager::Get();
if (qm) {
qm->AllowNextSynchronizedOp(OriginOrPatternString::FromOrigin(mOrigin),
Nullable<PersistenceType>(mPersistence),
mStorageId);
}
}
mDirectoryLock = nullptr;
}
NS_IMETHODIMP
@@ -950,24 +940,16 @@ MainProcessRunnable::Run()
}
mState = eWaitingToOpenMetadata;
rv = QuotaManager::Get()->WaitForOpenAllowed(
OriginOrPatternString::FromOrigin(mOrigin),
Nullable<PersistenceType>(mPersistence),
mStorageId, this);
if (NS_FAILED(rv)) {
Fail();
return NS_OK;
}
mNeedAllowNextSynchronizedOp = true;
return NS_OK;
}
// XXX The exclusive lock shouldn't be needed for read operations.
QuotaManager::Get()->OpenDirectory(mPersistence,
mGroup,
mOrigin,
mIsApp,
quota::Client::ASMJS,
/* aExclusive */ true,
this);
case eWaitingToOpenMetadata: {
MOZ_ASSERT(NS_IsMainThread());
mState = eReadyToReadMetadata;
DispatchToIOThread();
return NS_OK;
}
@@ -1053,6 +1035,7 @@ MainProcessRunnable::Run()
return NS_OK;
}
case eWaitingToOpenMetadata:
case eWaitingToOpenCacheFileForRead:
case eOpened:
case eFinished: {
@@ -1064,6 +1047,29 @@ MainProcessRunnable::Run()
return NS_OK;
}
void
MainProcessRunnable::DirectoryLockAcquired(DirectoryLock* aLock)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mState == eWaitingToOpenMetadata);
MOZ_ASSERT(!mDirectoryLock);
mDirectoryLock = aLock;
mState = eReadyToReadMetadata;
DispatchToIOThread();
}
void
MainProcessRunnable::DirectoryLockFailed()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mState == eWaitingToOpenMetadata);
MOZ_ASSERT(!mDirectoryLock);
Fail();
}
bool
FindHashMatch(const Metadata& aMetadata, const ReadParams& aReadParams,
unsigned* aModuleIndex)
@@ -1113,6 +1119,8 @@ class SingleProcessRunnable final : public File,
private MainProcessRunnable
{
public:
NS_DECL_ISUPPORTS_INHERITED
// In the single-process case, the calling JS compilation thread holds the
// nsIPrincipal alive indirectly (via the global object -> compartment ->
// principal) so we don't have to ref-count it here. This is fortunate since
@@ -1125,7 +1133,7 @@ public:
: MainProcessRunnable(aPrincipal, aOpenMode, aWriteParams),
mReadParams(aReadParams)
{
MOZ_ASSERT(IsMainProcess());
MOZ_ASSERT(XRE_IsParentProcess());
MOZ_ASSERT(!NS_IsMainThread());
MOZ_COUNT_CTOR(SingleProcessRunnable);
}
@@ -1184,6 +1192,8 @@ private:
ReadParams mReadParams;
};
NS_IMPL_ISUPPORTS_INHERITED0(SingleProcessRunnable, File)
// A runnable that executes in a parent process for a cache access originating
// in the content process. This runnable gets registered as an IPDL subprotocol
// actor so that it can communicate with the corresponding ChildProcessRunnable.
@@ -1191,6 +1201,8 @@ class ParentProcessRunnable final : public PAsmJSCacheEntryParent,
public MainProcessRunnable
{
public:
NS_DECL_ISUPPORTS_INHERITED
// The given principal comes from an IPC::Principal which will be dec-refed
// at the end of the message, so we must ref-count it here. Fortunately, we
// are on the main thread (where PContent messages are delivered).
@@ -1203,7 +1215,7 @@ public:
mOpened(false),
mFinished(false)
{
MOZ_ASSERT(IsMainProcess());
MOZ_ASSERT(XRE_IsParentProcess());
MOZ_ASSERT(NS_IsMainThread());
MOZ_COUNT_CTOR(ParentProcessRunnable);
}
@@ -1331,6 +1343,8 @@ private:
bool mFinished;
};
NS_IMPL_ISUPPORTS_INHERITED0(ParentProcessRunnable, FileDescriptorHolder)
} // unnamed namespace
PAsmJSCacheEntryParent*
@@ -1380,7 +1394,7 @@ public:
mActorDestroyed(false),
mState(eInitial)
{
MOZ_ASSERT(!IsMainProcess());
MOZ_ASSERT(!XRE_IsParentProcess());
MOZ_ASSERT(!NS_IsMainThread());
MOZ_COUNT_CTOR(ChildProcessRunnable);
}
@@ -1512,8 +1526,8 @@ ChildProcessRunnable::Run()
MOZ_ASSERT(NS_IsMainThread());
// Per FileDescriptorHolder::Finish()'s comment, call before
// AllowNextSynchronizedOp (which happens in the parent upon receipt of
// the Send__delete__ message).
// releasing the directory lock (which happens in the parent upon receipt
// of the Send__delete__ message).
File::OnClose();
if (!mActorDestroyed) {
@@ -1576,7 +1590,7 @@ OpenFile(nsIPrincipal* aPrincipal,
// parent process to open the file and interact with the QuotaManager. The
// child can then map the file into its address space to perform I/O.
nsRefPtr<File> file;
if (IsMainProcess()) {
if (XRE_IsParentProcess()) {
file = new SingleProcessRunnable(aPrincipal, aOpenMode, aWriteParams,
aReadParams);
} else {
@@ -1836,11 +1850,16 @@ public:
{ }
virtual void
WaitForStoragesToComplete(nsTArray<nsIOfflineStorage*>& aStorages,
nsIRunnable* aCallback) override
{
MOZ_ASSERT_UNREACHABLE("There are no storages");
}
AbortOperations(const nsACString& aOrigin) override
{ }
virtual void
AbortOperationsForProcess(ContentParentId aContentParentId) override
{ }
virtual void
PerformIdleMaintenance() override
{ }
virtual void
ShutdownWorkThreads() override
+9 -9
View File
@@ -57,7 +57,7 @@ AudioChannelService::GetAudioChannelService()
{
MOZ_ASSERT(NS_IsMainThread());
if (XRE_GetProcessType() != GeckoProcessType_Default) {
if (!XRE_IsParentProcess()) {
return AudioChannelServiceChild::GetAudioChannelService();
}
@@ -71,7 +71,7 @@ AudioChannelService::GetOrCreateAudioChannelService()
{
MOZ_ASSERT(NS_IsMainThread());
if (XRE_GetProcessType() != GeckoProcessType_Default) {
if (!XRE_IsParentProcess()) {
return AudioChannelServiceChild::GetOrCreateAudioChannelService();
}
@@ -91,7 +91,7 @@ AudioChannelService::GetOrCreateAudioChannelService()
void
AudioChannelService::Shutdown()
{
if (XRE_GetProcessType() != GeckoProcessType_Default) {
if (!XRE_IsParentProcess()) {
return AudioChannelServiceChild::Shutdown();
}
@@ -109,7 +109,7 @@ AudioChannelService::AudioChannelService()
, mDisabled(false)
, mDefChannelChildID(CONTENT_PROCESS_ID_UNKNOWN)
{
if (XRE_GetProcessType() == GeckoProcessType_Default) {
if (XRE_IsParentProcess()) {
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
if (obs) {
obs->AddObserver(this, "ipc:content-shutdown", false);
@@ -167,7 +167,7 @@ AudioChannelService::RegisterType(AudioChannel aChannel, uint64_t aChildID,
AudioChannelInternalType type = GetInternalType(aChannel, true);
mChannelCounters[type].AppendElement(aChildID);
if (XRE_GetProcessType() == GeckoProcessType_Default) {
if (XRE_IsParentProcess()) {
// We must keep the childIds in order to decide which app is allowed to play
// with then telephony channel.
@@ -259,7 +259,7 @@ AudioChannelService::UnregisterType(AudioChannel aChannel,
// There are two reasons to defer the decrease of telephony channel.
// 1. User can have time to remove device from his ear before music resuming.
// 2. Give BT SCO to be disconnected before starting to connect A2DP.
if (XRE_GetProcessType() == GeckoProcessType_Default) {
if (XRE_IsParentProcess()) {
if (aChannel == AudioChannel::Telephony) {
UnregisterTelephonyChild(aChildID);
@@ -293,7 +293,7 @@ AudioChannelService::UnregisterTypeInternal(AudioChannel aChannel,
// In order to avoid race conditions, it's safer to notify any existing
// agent any time a new one is registered.
if (XRE_GetProcessType() == GeckoProcessType_Default) {
if (XRE_IsParentProcess()) {
// No hidden content channel is playable if the original playable hidden
// process does not need to play audio from background anymore.
if (aChannel == AudioChannel::Content &&
@@ -518,7 +518,7 @@ AudioChannelService::SetDefaultVolumeControlChannelInternal(int32_t aChannel,
bool aVisible,
uint64_t aChildID)
{
if (XRE_GetProcessType() != GeckoProcessType_Default) {
if (!XRE_IsParentProcess()) {
return;
}
@@ -561,7 +561,7 @@ AudioChannelService::SetDefaultVolumeControlChannelInternal(int32_t aChannel,
void
AudioChannelService::SendAudioChannelChangedNotification(uint64_t aChildID)
{
if (XRE_GetProcessType() != GeckoProcessType_Default) {
if (!XRE_IsParentProcess()) {
return;
}
+1 -1
View File
@@ -91,7 +91,7 @@ Crypto::GetRandomValues(JSContext* aCx, const ArrayBufferView& aArray,
uint8_t* data = aArray.Data();
if (XRE_GetProcessType() != GeckoProcessType_Default) {
if (!XRE_IsParentProcess()) {
InfallibleTArray<uint8_t> randomValues;
// Tell the parent process to generate random values via PContent
ContentChild* cc = ContentChild::GetSingleton();
+2 -2
View File
@@ -1479,7 +1479,7 @@ Navigator::GetFeature(const nsAString& aName, ErrorResult& aRv)
#if defined(XP_LINUX)
if (aName.EqualsLiteral("hardware.memory")) {
// with seccomp enabled, fopen() should be in a non-sandboxed process
if (XRE_GetProcessType() == GeckoProcessType_Default) {
if (XRE_IsParentProcess()) {
uint32_t memLevel = mozilla::hal::GetTotalSystemMemoryLevel();
if (memLevel == 0) {
p->MaybeReject(NS_ERROR_NOT_AVAILABLE);
@@ -2530,7 +2530,7 @@ Navigator::HasTVSupport(JSContext* aCx, JSObject* aGlobal)
bool
Navigator::IsE10sEnabled(JSContext* aCx, JSObject* aGlobal)
{
return XRE_GetProcessType() == GeckoProcessType_Content;
return XRE_IsContentProcess();
}
bool
+1 -1
View File
@@ -140,7 +140,7 @@ static void
MarkMessageManagers()
{
// The global message manager only exists in the root process.
if (XRE_GetProcessType() != GeckoProcessType_Default) {
if (!XRE_IsParentProcess()) {
return;
}
nsCOMPtr<nsIMessageBroadcaster> strongGlobalMM =
+1 -1
View File
@@ -335,7 +335,7 @@ nsContentPermissionUtils::AskPermission(nsIContentPermissionRequest* aRequest, n
NS_ENSURE_STATE(aWindow && aWindow->IsCurrentInnerWindow());
// for content process
if (XRE_GetProcessType() == GeckoProcessType_Content) {
if (XRE_IsContentProcess()) {
nsRefPtr<RemotePermissionRequest> req =
new RemotePermissionRequest(aRequest, aWindow);
+47
View File
@@ -24,6 +24,7 @@
#include "nsIObjectLoadingContent.h"
#include "nsFrame.h"
#include "mozilla/layers/ShadowLayers.h"
#include "mozilla/layers/APZCCallbackHelper.h"
#include "ClientLayerManager.h"
#include "nsQueryObject.h"
#ifdef MOZ_FMP4
@@ -2487,6 +2488,34 @@ nsDOMWindowUtils::SetAsyncZoom(nsIDOMNode* aRootElement, float aValue)
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::FlushApzRepaints(bool* aOutResult)
{
nsIWidget* widget = GetWidget();
if (!widget) {
*aOutResult = false;
return NS_OK;
}
// If APZ is not enabled, this function is a no-op.
if (!widget->AsyncPanZoomEnabled()) {
*aOutResult = false;
return NS_OK;
}
LayerManager* manager = widget->GetLayerManager();
if (!manager) {
*aOutResult = false;
return NS_OK;
}
ShadowLayerForwarder* forwarder = manager->AsShadowForwarder();
if (!forwarder || !forwarder->HasShadowManager()) {
*aOutResult = false;
return NS_OK;
}
forwarder->GetShadowManager()->SendFlushApzRepaints();
*aOutResult = true;
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::ComputeAnimationDistance(nsIDOMElement* aElement,
const nsAString& aProperty,
@@ -2949,6 +2978,24 @@ nsDOMWindowUtils::GetFileReferences(const nsAString& aDatabaseName, int64_t aId,
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::FlushPendingFileDeletions()
{
MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome());
using mozilla::dom::indexedDB::IndexedDatabaseManager;
nsRefPtr<IndexedDatabaseManager> mgr = IndexedDatabaseManager::Get();
if (mgr) {
nsresult rv = mgr->FlushPendingFileDeletions();
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::IsIncrementalGCEnabled(JSContext* cx, bool* aResult)
{
+1 -1
View File
@@ -10593,7 +10593,7 @@ PLDHashOperator UnlockEnumerator(imgIRequest* aKey,
nsresult
nsDocument::SetImageLockingState(bool aLocked)
{
if (XRE_GetProcessType() == GeckoProcessType_Content &&
if (XRE_IsContentProcess() &&
!Preferences::GetBool("image.mem.allow_locking_in_content_processes", true)) {
return NS_OK;
}
+2 -2
View File
@@ -704,7 +704,7 @@ nsFocusManager::WindowRaised(nsIDOMWindow* aWindow)
// If this is a parent or single process window, send the activate event.
// Events for child process windows will be sent when ParentActivated
// is called.
if (XRE_GetProcessType() == GeckoProcessType_Default) {
if (XRE_IsParentProcess()) {
ActivateOrDeactivate(window, true);
}
@@ -767,7 +767,7 @@ nsFocusManager::WindowLowered(nsIDOMWindow* aWindow)
// If this is a parent or single process window, send the deactivate event.
// Events for child process windows will be sent when ParentActivated
// is called.
if (XRE_GetProcessType() == GeckoProcessType_Default) {
if (XRE_IsParentProcess()) {
ActivateOrDeactivate(window, false);
}
+3 -3
View File
@@ -1630,12 +1630,12 @@ nsFrameLoader::ShouldUseRemoteProcess()
// Don't try to launch nested children if we don't have OMTC.
// They won't render!
if (XRE_GetProcessType() == GeckoProcessType_Content &&
if (XRE_IsContentProcess() &&
!CompositorChild::ChildProcessHasCompositor()) {
return false;
}
if (XRE_GetProcessType() == GeckoProcessType_Content &&
if (XRE_IsContentProcess() &&
!(PR_GetEnv("MOZ_NESTED_OOP_TABS") ||
Preferences::GetBool("dom.ipc.tabs.nested.enabled", false))) {
return false;
@@ -2678,7 +2678,7 @@ nsFrameLoader::ResetPermissionManagerStatus()
{
// The resetting of the permissions status can run only
// in the main process.
if (XRE_GetProcessType() == GeckoProcessType_Content) {
if (XRE_IsContentProcess()) {
return;
}
+4 -4
View File
@@ -892,7 +892,7 @@ nsFrameMessageManager::Dump(const nsAString& aStr)
NS_IMETHODIMP
nsFrameMessageManager::PrivateNoteIntentionalCrash()
{
if (XRE_GetProcessType() == GeckoProcessType_Content) {
if (XRE_IsContentProcess()) {
mozilla::NoteIntentionalCrash("tab");
return NS_OK;
} else {
@@ -1566,7 +1566,7 @@ MessageManagerReporter::CollectReports(nsIMemoryReporterCallback* aCb,
{
nsresult rv;
if (XRE_GetProcessType() == GeckoProcessType_Default) {
if (XRE_IsParentProcess()) {
nsCOMPtr<nsIMessageBroadcaster> globalmm =
do_GetService("@mozilla.org/globalmessagemanager;1");
if (globalmm) {
@@ -1602,7 +1602,7 @@ MessageManagerReporter::CollectReports(nsIMemoryReporterCallback* aCb,
nsresult
NS_NewGlobalMessageManager(nsIMessageBroadcaster** aResult)
{
NS_ENSURE_TRUE(XRE_GetProcessType() == GeckoProcessType_Default,
NS_ENSURE_TRUE(XRE_IsParentProcess(),
NS_ERROR_NOT_AVAILABLE);
nsRefPtr<nsFrameMessageManager> mm = new nsFrameMessageManager(nullptr,
nullptr,
@@ -2131,7 +2131,7 @@ NS_NewChildProcessMessageManager(nsISyncMessageSender** aResult)
"Re-creating sChildProcessManager");
MessageManagerCallback* cb;
if (XRE_GetProcessType() == GeckoProcessType_Default) {
if (XRE_IsParentProcess()) {
cb = new SameChildProcessMessageManagerCallback();
} else {
cb = new ChildProcessMessageManagerCallback();
+2 -2
View File
@@ -9457,7 +9457,7 @@ nsGlobalWindow::ShowModalDialog(const nsAString& aUrl, nsIVariant* aArgument,
(aUrl, aArgument, aOptions, aError), aError,
nullptr);
if (!IsShowModalDialogEnabled() || XRE_GetProcessType() == GeckoProcessType_Content) {
if (!IsShowModalDialogEnabled() || XRE_IsContentProcess()) {
aError.Throw(NS_ERROR_NOT_AVAILABLE);
return nullptr;
}
@@ -11244,7 +11244,7 @@ nsGlobalWindow::ShowSlowScriptDialog()
unsigned lineno;
bool hasFrame = JS::DescribeScriptedCaller(cx, &filename, &lineno);
if (XRE_GetProcessType() == GeckoProcessType_Content &&
if (XRE_IsContentProcess() &&
ProcessHangMonitor::Get()) {
ProcessHangMonitor::SlowScriptAction action;
nsRefPtr<ProcessHangMonitor> monitor = ProcessHangMonitor::Get();
+1 -1
View File
@@ -3197,7 +3197,7 @@ nsObjectLoadingContent::ShouldPlay(FallbackType &aReason, bool aIgnoreCurrentTyp
sPrefsInitialized = true;
}
if (XRE_GetProcessType() == GeckoProcessType_Default &&
if (XRE_IsParentProcess() &&
BrowserTabsRemoteAutostart()) {
// Plugins running OOP from the chrome process along with plugins running
// OOP from the content process will hang. Let's prevent that situation.
+1 -1
View File
@@ -529,7 +529,7 @@ nsWindowMemoryReporter::CollectReports(nsIMemoryReporterCallback* aCb,
// Collect window memory usage.
nsWindowSizes windowTotalSizes(nullptr);
nsCOMPtr<amIAddonManager> addonManager;
if (XRE_GetProcessType() == GeckoProcessType_Default) {
if (XRE_IsParentProcess()) {
// Only try to access the service from the main process.
addonManager = do_GetService("@mozilla.org/addons/integration;1");
}
+1 -1
View File
@@ -3042,7 +3042,7 @@ nsXMLHttpRequest::Send(nsIVariant* aVariant, const Nullable<RequestBody>& aBody)
if (scheme.LowerCaseEqualsLiteral("app") ||
scheme.LowerCaseEqualsLiteral("jar")) {
mIsMappedArrayBuffer = true;
if (XRE_GetProcessType() != GeckoProcessType_Default) {
if (!XRE_IsParentProcess()) {
nsCOMPtr<nsIJARChannel> jarChannel = do_QueryInterface(mChannel);
// For memory mapping from child process, we need to get file
// descriptor of the JAR file opened remotely on the parent proess.
-6
View File
@@ -377,10 +377,4 @@ DispatchStatusChangedEvent(const nsAString& aType,
#endif
}
bool
IsMainProcess()
{
return XRE_GetProcessType() == GeckoProcessType_Default;
}
END_BLUETOOTH_NAMESPACE
-8
View File
@@ -191,14 +191,6 @@ DispatchStatusChangedEvent(const nsAString& aType,
const nsAString& aDeviceAddress,
bool aStatus);
/**
* Check whether the caller runs at B2G process.
*
* @return true if the caller runs at B2G process, false otherwise.
*/
bool
IsMainProcess();
END_BLUETOOTH_NAMESPACE
#endif
@@ -238,7 +238,7 @@ bool
BluetoothHfpManager::Init()
{
// The function must run at b2g process since it would access SettingsService.
MOZ_ASSERT(IsMainProcess());
MOZ_ASSERT(XRE_IsParentProcess());
MOZ_ASSERT(NS_IsMainThread());
@@ -784,7 +784,7 @@ BluetoothAdapter::SendFile(const nsAString& aDeviceAddress,
return nullptr;
}
if (XRE_GetProcessType() == GeckoProcessType_Default) {
if (XRE_IsParentProcess()) {
// In-process transfer
bs->SendFile(aDeviceAddress, &aBlob, results);
} else {
@@ -98,12 +98,6 @@ StaticRefPtr<BluetoothService> sBluetoothService;
bool sInShutdown = false;
bool sToggleInProgress = false;
bool
IsMainProcess()
{
return XRE_GetProcessType() == GeckoProcessType_Default;
}
void
ShutdownTimeExceeded(nsITimer* aTimer, void* aClosure)
{
@@ -217,7 +211,7 @@ BluetoothService*
BluetoothService::Create()
{
#if defined(MOZ_B2G_BT)
if (!IsMainProcess()) {
if (!XRE_IsParentProcess()) {
return BluetoothServiceChildProcess::Create();
}
@@ -251,7 +245,7 @@ BluetoothService::Init()
}
// Only the main process should observe bluetooth settings changes.
if (IsMainProcess() &&
if (XRE_IsParentProcess() &&
NS_FAILED(obs->AddObserver(this, MOZSETTINGS_CHANGED_ID, false))) {
BT_WARNING("Failed to add settings change observer!");
return false;
@@ -1272,7 +1272,7 @@ BluetoothAdapter::SendFile(const nsAString& aDeviceAddress,
return nullptr;
}
if (XRE_GetProcessType() == GeckoProcessType_Default) {
if (XRE_IsParentProcess()) {
// In-process transfer
bs->SendFile(aDeviceAddress, &aBlob, results);
} else {
@@ -192,7 +192,7 @@ BluetoothService*
BluetoothService::Create()
{
#if defined(MOZ_B2G_BT)
if (!IsMainProcess()) {
if (!XRE_IsParentProcess()) {
return BluetoothServiceChildProcess::Create();
}
@@ -226,7 +226,7 @@ BluetoothService::Init()
}
// Only the main process should observe bluetooth settings changes.
if (IsMainProcess() &&
if (XRE_IsParentProcess() &&
NS_FAILED(obs->AddObserver(this, MOZSETTINGS_CHANGED_ID, false))) {
BT_WARNING("Failed to add settings change observer!");
return false;
@@ -268,7 +268,7 @@ BluetoothService::RegisterBluetoothSignalHandler(
// Distribute pending pairing requests when pairing listener has been added
// to signal observer table.
if (IsMainProcess() &&
if (XRE_IsParentProcess() &&
!mPendingPairReqSignals.IsEmpty() &&
aNodeName.EqualsLiteral(KEY_PAIRING_LISTENER)) {
for (uint32_t i = 0; i < mPendingPairReqSignals.Length(); ++i) {
+1 -1
View File
@@ -443,7 +443,7 @@ bool
BluetoothHfpManager::Init()
{
// The function must run at b2g process since it would access SettingsService.
MOZ_ASSERT(IsMainProcess());
MOZ_ASSERT(XRE_IsParentProcess());
MOZ_ASSERT(NS_IsMainThread());
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
+88 -113
View File
@@ -12,8 +12,6 @@
#include "mozilla/dom/cache/FileUtils.h"
#include "mozilla/dom/cache/Manager.h"
#include "mozilla/dom/cache/ManagerId.h"
#include "mozilla/dom/cache/OfflineStorage.h"
#include "mozilla/dom/quota/OriginOrPatternString.h"
#include "mozilla/dom/quota/QuotaManager.h"
#include "mozIStorageConnection.h"
#include "nsIFile.h"
@@ -23,39 +21,8 @@
namespace {
using mozilla::dom::Nullable;
using mozilla::dom::cache::Action;
using mozilla::dom::cache::QuotaInfo;
using mozilla::dom::quota::Client;
using mozilla::dom::quota::OriginOrPatternString;
using mozilla::dom::quota::QuotaManager;
using mozilla::dom::quota::PERSISTENCE_TYPE_DEFAULT;
using mozilla::dom::quota::PersistenceType;
// Release our lock on the QuotaManager directory asynchronously.
class QuotaReleaseRunnable final : public nsRunnable
{
public:
explicit QuotaReleaseRunnable(const QuotaInfo& aQuotaInfo)
: mQuotaInfo(aQuotaInfo)
{ }
NS_IMETHOD Run() override
{
MOZ_ASSERT(NS_IsMainThread());
QuotaManager* qm = QuotaManager::Get();
MOZ_ASSERT(qm);
qm->AllowNextSynchronizedOp(OriginOrPatternString::FromOrigin(mQuotaInfo.mOrigin),
Nullable<PersistenceType>(PERSISTENCE_TYPE_DEFAULT),
mQuotaInfo.mStorageId);
return NS_OK;
}
private:
~QuotaReleaseRunnable() { }
const QuotaInfo mQuotaInfo;
};
class NullAction final : public Action
{
@@ -80,7 +47,8 @@ namespace dom {
namespace cache {
using mozilla::DebugOnly;
using mozilla::dom::quota::OriginOrPatternString;
using mozilla::dom::quota::AssertIsOnIOThread;
using mozilla::dom::quota::OpenDirectoryListener;
using mozilla::dom::quota::QuotaManager;
using mozilla::dom::quota::PERSISTENCE_TYPE_DEFAULT;
using mozilla::dom::quota::PersistenceType;
@@ -132,6 +100,7 @@ private:
// the QuotaManager. This must be performed for each origin before any disk
// IO occurrs.
class Context::QuotaInitRunnable final : public nsIRunnable
, public OpenDirectoryListener
{
public:
QuotaInitRunnable(Context* aContext,
@@ -149,7 +118,6 @@ public:
, mResult(NS_OK)
, mState(STATE_INIT)
, mCanceled(false)
, mNeedsQuotaRelease(false)
{
MOZ_ASSERT(mContext);
MOZ_ASSERT(mManager);
@@ -164,7 +132,7 @@ public:
NS_ASSERT_OWNINGTHREAD(QuotaInitRunnable);
MOZ_ASSERT(mState == STATE_INIT);
mState = STATE_CALL_WAIT_FOR_OPEN_ALLOWED;
mState = STATE_OPEN_DIRECTORY;
nsresult rv = NS_DispatchToMainThread(this, nsIThread::DISPATCH_NORMAL);
if (NS_WARN_IF(NS_FAILED(rv))) {
mState = STATE_COMPLETE;
@@ -181,6 +149,13 @@ public:
mInitAction->CancelOnInitiatingThread();
}
// OpenDirectoryListener methods
virtual void
DirectoryLockAcquired(DirectoryLock* aLock) override;
virtual void
DirectoryLockFailed() override;
private:
class SyncResolver final : public Action::Resolver
{
@@ -220,8 +195,8 @@ private:
enum State
{
STATE_INIT,
STATE_CALL_WAIT_FOR_OPEN_ALLOWED,
STATE_WAIT_FOR_OPEN_ALLOWED,
STATE_OPEN_DIRECTORY,
STATE_WAIT_FOR_DIRECTORY_LOCK,
STATE_ENSURE_ORIGIN_INITIALIZED,
STATE_RUN_ON_TARGET,
STATE_RUNNING,
@@ -229,6 +204,18 @@ private:
STATE_COMPLETE
};
void Complete(nsresult aResult)
{
MOZ_ASSERT(mState == STATE_RUNNING || NS_FAILED(aResult));
MOZ_ASSERT(NS_SUCCEEDED(mResult));
mResult = aResult;
mState = STATE_COMPLETING;
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(
mInitiatingThread->Dispatch(this, nsIThread::DISPATCH_NORMAL)));
}
void Clear()
{
NS_ASSERT_OWNINGTHREAD(QuotaInitRunnable);
@@ -247,16 +234,52 @@ private:
nsCOMPtr<nsIThread> mInitiatingThread;
nsresult mResult;
QuotaInfo mQuotaInfo;
nsMainThreadPtrHandle<OfflineStorage> mOfflineStorage;
nsMainThreadPtrHandle<DirectoryLock> mDirectoryLock;
State mState;
Atomic<bool> mCanceled;
bool mNeedsQuotaRelease;
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIRUNNABLE
};
void
Context::QuotaInitRunnable::DirectoryLockAcquired(DirectoryLock* aLock)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mState == STATE_WAIT_FOR_DIRECTORY_LOCK);
MOZ_ASSERT(!mDirectoryLock);
mDirectoryLock = new nsMainThreadPtrHolder<DirectoryLock>(aLock);
if (mCanceled) {
Complete(NS_ERROR_ABORT);
return;
}
QuotaManager* qm = QuotaManager::Get();
MOZ_ASSERT(qm);
mState = STATE_ENSURE_ORIGIN_INITIALIZED;
nsresult rv = qm->IOThread()->Dispatch(this, nsIThread::DISPATCH_NORMAL);
if (NS_WARN_IF(NS_FAILED(rv))) {
Complete(rv);
return;
}
}
void
Context::QuotaInitRunnable::DirectoryLockFailed()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mState == STATE_WAIT_FOR_DIRECTORY_LOCK);
MOZ_ASSERT(!mDirectoryLock);
NS_WARNING("Failed to acquire a directory lock!");
Complete(NS_ERROR_FAILURE);
}
NS_IMPL_ISUPPORTS(mozilla::dom::cache::Context::QuotaInitRunnable, nsIRunnable);
// The QuotaManager init state machine is represented in the following diagram:
@@ -267,14 +290,14 @@ NS_IMPL_ISUPPORTS(mozilla::dom::cache::Context::QuotaInitRunnable, nsIRunnable);
// +-------+-------+ |
// | |
// +----------v-----------+ |
// |CallWaitForOpenAllowed| Resolve(error) |
// | OpenDirectory | Resolve(error) |
// | (Main Thread) +-----------------+
// +----------+-----------+ |
// | |
// +--------v---------+ |
// |WaitForOpenAllowed| Resolve(error) |
// | (Main Thread) +-------------------+
// +--------+---------+ |
// +----------v-----------+ |
// | WaitForDirectoryLock | Resolve(error) |
// | (Main Thread) +-----------------+
// +----------+-----------+ |
// | |
// +----------v------------+ |
// |EnsureOriginInitialized| Resolve(error) |
@@ -307,7 +330,7 @@ Context::QuotaInitRunnable::Run()
switch(mState) {
// -----------------------------------
case STATE_CALL_WAIT_FOR_OPEN_ALLOWED:
case STATE_OPEN_DIRECTORY:
{
MOZ_ASSERT(NS_IsMainThread());
@@ -333,59 +356,23 @@ Context::QuotaInitRunnable::Run()
break;
}
QuotaManager::GetStorageId(PERSISTENCE_TYPE_DEFAULT,
mQuotaInfo.mOrigin,
Client::DOMCACHE,
NS_LITERAL_STRING("cache"),
mQuotaInfo.mStorageId);
// QuotaManager::WaitForOpenAllowed() will hold a reference to us as
// a callback. We will then get executed again on the main thread when
// it is safe to open the quota directory.
mState = STATE_WAIT_FOR_OPEN_ALLOWED;
rv = qm->WaitForOpenAllowed(OriginOrPatternString::FromOrigin(mQuotaInfo.mOrigin),
Nullable<PersistenceType>(PERSISTENCE_TYPE_DEFAULT),
mQuotaInfo.mStorageId, this);
if (NS_FAILED(rv)) {
resolver->Resolve(rv);
break;
}
break;
}
// ------------------------------
case STATE_WAIT_FOR_OPEN_ALLOWED:
{
MOZ_ASSERT(NS_IsMainThread());
mNeedsQuotaRelease = true;
if (mCanceled) {
resolver->Resolve(NS_ERROR_ABORT);
break;
}
QuotaManager* qm = QuotaManager::Get();
MOZ_ASSERT(qm);
nsRefPtr<OfflineStorage> offlineStorage =
OfflineStorage::Register(mThreadsafeHandle, mQuotaInfo);
mOfflineStorage = new nsMainThreadPtrHolder<OfflineStorage>(offlineStorage);
mState = STATE_ENSURE_ORIGIN_INITIALIZED;
nsresult rv = qm->IOThread()->Dispatch(this, nsIThread::DISPATCH_NORMAL);
if (NS_WARN_IF(NS_FAILED(rv))) {
resolver->Resolve(rv);
break;
}
// QuotaManager::OpenDirectory() will hold a reference to us as
// a listener. We will then get DirectoryLockAcquired() on the main
// thread when it is safe to access our storage directory.
mState = STATE_WAIT_FOR_DIRECTORY_LOCK;
qm->OpenDirectory(PERSISTENCE_TYPE_DEFAULT,
mQuotaInfo.mGroup,
mQuotaInfo.mOrigin,
mQuotaInfo.mIsApp,
quota::Client::DOMCACHE,
/* aExclusive */ false,
this);
break;
}
// ----------------------------------
case STATE_ENSURE_ORIGIN_INITIALIZED:
{
// Can't assert quota IO thread because its an idle thread that can get
// recreated. At least assert we're not on main thread or owning thread.
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(_mOwningThread.GetThread() != PR_GetCurrentThread());
AssertIsOnIOThread();
if (mCanceled) {
resolver->Resolve(NS_ERROR_ABORT);
@@ -438,21 +425,16 @@ Context::QuotaInitRunnable::Run()
{
NS_ASSERT_OWNINGTHREAD(QuotaInitRunnable);
mInitAction->CompleteOnInitiatingThread(mResult);
mContext->OnQuotaInit(mResult, mQuotaInfo, mOfflineStorage);
mContext->OnQuotaInit(mResult, mQuotaInfo, mDirectoryLock);
mState = STATE_COMPLETE;
if (mNeedsQuotaRelease) {
// Unlock the quota dir if we locked it previously
nsCOMPtr<nsIRunnable> runnable = new QuotaReleaseRunnable(mQuotaInfo);
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToMainThread(runnable)));
}
// Explicitly cleanup here as the destructor could fire on any of
// the threads we have bounced through.
Clear();
break;
}
// -----
case STATE_WAIT_FOR_DIRECTORY_LOCK:
default:
{
MOZ_CRASH("unexpected state in QuotaInitRunnable");
@@ -460,14 +442,7 @@ Context::QuotaInitRunnable::Run()
}
if (resolver->Resolved()) {
MOZ_ASSERT(mState == STATE_RUNNING || NS_FAILED(resolver->Result()));
MOZ_ASSERT(NS_SUCCEEDED(mResult));
mResult = resolver->Result();
mState = STATE_COMPLETING;
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(
mInitiatingThread->Dispatch(this, nsIThread::DISPATCH_NORMAL)));
Complete(resolver->Result());
}
return NS_OK;
@@ -1007,7 +982,7 @@ Context::DispatchAction(Action* aAction, bool aDoomData)
void
Context::OnQuotaInit(nsresult aRv, const QuotaInfo& aQuotaInfo,
nsMainThreadPtrHandle<OfflineStorage>& aOfflineStorage)
nsMainThreadPtrHandle<DirectoryLock>& aDirectoryLock)
{
NS_ASSERT_OWNINGTHREAD(Context);
@@ -1016,10 +991,10 @@ Context::OnQuotaInit(nsresult aRv, const QuotaInfo& aQuotaInfo,
mQuotaInfo = aQuotaInfo;
// Always save the offline storage to ensure QuotaManager does not shutdown
// Always save the directory lock to ensure QuotaManager does not shutdown
// before the Context has gone away.
MOZ_ASSERT(!mOfflineStorage);
mOfflineStorage = aOfflineStorage;
MOZ_ASSERT(!mDirectoryLock);
mDirectoryLock = aDirectoryLock;
if (mState == STATE_CONTEXT_CANCELED || NS_FAILED(aRv)) {
for (uint32_t i = 0; i < mPendingActions.Length(); ++i) {
+13 -5
View File
@@ -21,11 +21,17 @@ class nsIThread;
namespace mozilla {
namespace dom {
namespace quota {
class DirectoryLock;
} // namespace quota
namespace cache {
class Action;
class Manager;
class OfflineStorage;
// The Context class is RAII-style class for managing IO operations within the
// Cache.
@@ -41,8 +47,8 @@ class OfflineStorage;
// 1) The Manager will call Context::AllowToClose() when all of the actors
// have removed themselves as listener. This means an idle context with
// no active DOM objects will close gracefully.
// 2) The QuotaManager invalidates the storage area so it can delete the
// files. In this case the OfflineStorage calls Cache::Invalidate() which
// 2) The QuotaManager aborts all operations so it can delete the files.
// In this case the QuotaManager calls Client::AbortOperations() which
// in turn cancels all existing Action objects and then marks the Manager
// as invalid.
// 3) Browser shutdown occurs and the Manager calls Context::CancelAll().
@@ -59,6 +65,8 @@ class OfflineStorage;
// via the code in ShutdownObserver.cpp.
class Context final
{
typedef mozilla::dom::quota::DirectoryLock DirectoryLock;
public:
// Define a class allowing other threads to hold the Context alive. This also
// allows these other threads to safely close or cancel the Context.
@@ -182,7 +190,7 @@ private:
void Start();
void DispatchAction(Action* aAction, bool aDoomData = false);
void OnQuotaInit(nsresult aRv, const QuotaInfo& aQuotaInfo,
nsMainThreadPtrHandle<OfflineStorage>& aOfflineStorage);
nsMainThreadPtrHandle<DirectoryLock>& aDirectoryLock);
already_AddRefed<ThreadsafeHandle>
CreateThreadsafeHandle();
@@ -212,7 +220,7 @@ private:
// when ThreadsafeHandle::AllowToClose() is called.
nsRefPtr<ThreadsafeHandle> mThreadsafeHandle;
nsMainThreadPtrHandle<OfflineStorage> mOfflineStorage;
nsMainThreadPtrHandle<DirectoryLock> mDirectoryLock;
nsRefPtr<Context> mNextContext;
public:
+56
View File
@@ -548,6 +548,62 @@ IsCacheOrphaned(mozIStorageConnection* aConn, CacheId aCacheId,
return rv;
}
nsresult
FindOrphanedCacheIds(mozIStorageConnection* aConn,
nsTArray<CacheId>& aOrphanedListOut)
{
nsCOMPtr<mozIStorageStatement> state;
nsresult rv = aConn->CreateStatement(NS_LITERAL_CSTRING(
"SELECT id FROM caches "
"WHERE id NOT IN (SELECT cache_id from storage);"
), getter_AddRefs(state));
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
bool hasMoreData = false;
while (NS_SUCCEEDED(state->ExecuteStep(&hasMoreData)) && hasMoreData) {
CacheId cacheId = INVALID_CACHE_ID;
rv = state->GetInt64(0, &cacheId);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
aOrphanedListOut.AppendElement(cacheId);
}
return rv;
}
nsresult
GetKnownBodyIds(mozIStorageConnection* aConn, nsTArray<nsID>& aBodyIdListOut)
{
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(aConn);
nsCOMPtr<mozIStorageStatement> state;
nsresult rv = aConn->CreateStatement(NS_LITERAL_CSTRING(
"SELECT request_body_id, response_body_id FROM entries;"
), getter_AddRefs(state));
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
bool hasMoreData = false;
while (NS_SUCCEEDED(state->ExecuteStep(&hasMoreData)) && hasMoreData) {
// extract 0 to 2 nsID structs per row
for (uint32_t i = 0; i < 2; ++i) {
bool isNull = false;
rv = state->GetIsNull(i, &isNull);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
if (!isNull) {
nsID id;
rv = ExtractId(state, i, &id);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
aBodyIdListOut.AppendElement(id);
}
}
}
return rv;
}
nsresult
CacheMatch(mozIStorageConnection* aConn, CacheId aCacheId,
const CacheRequest& aRequest,
+7
View File
@@ -48,6 +48,13 @@ nsresult
IsCacheOrphaned(mozIStorageConnection* aConn, CacheId aCacheId,
bool* aOrphanedOut);
nsresult
FindOrphanedCacheIds(mozIStorageConnection* aConn,
nsTArray<CacheId>& aOrphanedListOut);
nsresult
GetKnownBodyIds(mozIStorageConnection* aConn, nsTArray<nsID>& aBodyIdListOut);
nsresult
CacheMatch(mozIStorageConnection* aConn, CacheId aCacheId,
const CacheRequest& aRequest, const CacheQueryParams& aParams,
+130 -8
View File
@@ -320,8 +320,108 @@ BodyIdToFile(nsIFile* aBaseDir, const nsID& aId, BodyFileType aType,
} // namespace
nsresult
CreateMarkerFile(const QuotaInfo& aQuotaInfo)
BodyDeleteOrphanedFiles(nsIFile* aBaseDir, nsTArray<nsID>& aKnownBodyIdList)
{
MOZ_ASSERT(aBaseDir);
// body files are stored in a directory structure like:
//
// /morgue/01/{01fdddb2-884d-4c3d-95ba-0c8062f6c325}.final
// /morgue/02/{02fdddb2-884d-4c3d-95ba-0c8062f6c325}.tmp
nsCOMPtr<nsIFile> dir;
nsresult rv = aBaseDir->Clone(getter_AddRefs(dir));
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
// Add the root morgue directory
rv = dir->Append(NS_LITERAL_STRING("morgue"));
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; }
// Iterate over all the intermediate morgue subdirs
bool hasMore = false;
while (NS_SUCCEEDED(rv = entries->HasMoreElements(&hasMore)) && hasMore) {
nsCOMPtr<nsISupports> entry;
rv = entries->GetNext(getter_AddRefs(entry));
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
nsCOMPtr<nsIFile> subdir = do_QueryInterface(entry);
bool isDir = false;
rv = subdir->IsDirectory(&isDir);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
// If a file got in here somehow, try to remove it and move on
if (NS_WARN_IF(!isDir)) {
rv = subdir->Remove(false /* recursive */);
MOZ_ASSERT(NS_SUCCEEDED(rv));
continue;
}
nsCOMPtr<nsISimpleEnumerator> subEntries;
rv = subdir->GetDirectoryEntries(getter_AddRefs(subEntries));
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
// Now iterate over all the files in the subdir
bool subHasMore = false;
while(NS_SUCCEEDED(rv = subEntries->HasMoreElements(&subHasMore)) &&
subHasMore) {
nsCOMPtr<nsISupports> subEntry;
rv = subEntries->GetNext(getter_AddRefs(subEntry));
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
nsCOMPtr<nsIFile> file = do_QueryInterface(subEntry);
nsAutoCString leafName;
rv = file->GetNativeLeafName(leafName);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
// Delete all tmp files regardless of known bodies. These are
// all considered orphans.
if (StringEndsWith(leafName, NS_LITERAL_CSTRING(".tmp"))) {
// remove recursively in case its somehow a directory
rv = file->Remove(true /* recursive */);
MOZ_ASSERT(NS_SUCCEEDED(rv));
continue;
}
nsCString suffix(NS_LITERAL_CSTRING(".final"));
// Otherwise, it must be a .final file. If its not, then just
// skip it.
if (NS_WARN_IF(!StringEndsWith(leafName, suffix) ||
leafName.Length() != NSID_LENGTH - 1 + suffix.Length())) {
continue;
}
// Finally, parse the uuid out of the name. If its fails to parse,
// the ignore the file.
nsID id;
if (NS_WARN_IF(!id.Parse(leafName.BeginReading()))) {
continue;
}
if (!aKnownBodyIdList.Contains(id)) {
// remove recursively in case its somehow a directory
rv = file->Remove(true /* recursive */);
MOZ_ASSERT(NS_SUCCEEDED(rv));
}
}
}
return rv;
}
namespace {
nsresult
GetMarkerFileHandle(const QuotaInfo& aQuotaInfo, nsIFile** aFileOut)
{
MOZ_ASSERT(aFileOut);
nsCOMPtr<nsIFile> marker;
nsresult rv = aQuotaInfo.mDir->Clone(getter_AddRefs(marker));
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
@@ -332,6 +432,20 @@ CreateMarkerFile(const QuotaInfo& aQuotaInfo)
rv = marker->Append(NS_LITERAL_STRING("context_open.marker"));
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
marker.forget(aFileOut);
return rv;
}
} // namespace
nsresult
CreateMarkerFile(const QuotaInfo& aQuotaInfo)
{
nsCOMPtr<nsIFile> marker;
nsresult rv = GetMarkerFileHandle(aQuotaInfo, getter_AddRefs(marker));
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = marker->Create(nsIFile::NORMAL_FILE_TYPE, 0644);
if (rv == NS_ERROR_FILE_ALREADY_EXISTS) {
rv = NS_OK;
@@ -350,13 +464,7 @@ nsresult
DeleteMarkerFile(const QuotaInfo& aQuotaInfo)
{
nsCOMPtr<nsIFile> marker;
nsresult rv = aQuotaInfo.mDir->Clone(getter_AddRefs(marker));
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = marker->Append(NS_LITERAL_STRING("cache"));
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = marker->Append(NS_LITERAL_STRING("context_open.marker"));
nsresult rv = GetMarkerFileHandle(aQuotaInfo, getter_AddRefs(marker));
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = marker->Remove(/* recursive = */ false);
@@ -373,6 +481,20 @@ DeleteMarkerFile(const QuotaInfo& aQuotaInfo)
return NS_OK;
}
bool
MarkerFileExists(const QuotaInfo& aQuotaInfo)
{
nsCOMPtr<nsIFile> marker;
nsresult rv = GetMarkerFileHandle(aQuotaInfo, getter_AddRefs(marker));
if (NS_WARN_IF(NS_FAILED(rv))) { return false; }
bool exists = false;
rv = marker->Exists(&exists);
if (NS_WARN_IF(NS_FAILED(rv))) { return false; }
return exists;
}
} // namespace cache
} // namespace dom
} // namespace mozilla
+6
View File
@@ -50,12 +50,18 @@ BodyOpen(const QuotaInfo& aQuotaInfo, nsIFile* aBaseDir, const nsID& aId,
nsresult
BodyDeleteFiles(nsIFile* aBaseDir, const nsTArray<nsID>& aIdList);
nsresult
BodyDeleteOrphanedFiles(nsIFile* aBaseDir, nsTArray<nsID>& aKnownBodyIdList);
nsresult
CreateMarkerFile(const QuotaInfo& aQuotaInfo);
nsresult
DeleteMarkerFile(const QuotaInfo& aQuotaInfo);
bool
MarkerFileExists(const QuotaInfo& aQuotaInfo);
} // namespace cache
} // namespace dom
} // namespace mozilla
+145 -28
View File
@@ -30,15 +30,12 @@
#include "nsThreadUtils.h"
#include "nsTObserverArray.h"
namespace {
using mozilla::unused;
using mozilla::dom::cache::Action;
using mozilla::dom::cache::BodyCreateDir;
using mozilla::dom::cache::BodyDeleteFiles;
using mozilla::dom::cache::QuotaInfo;
using mozilla::dom::cache::SyncDBAction;
using mozilla::dom::cache::db::CreateSchema;
namespace mozilla {
namespace dom {
namespace cache {
namespace {
// An Action that is executed when a Context is first created. It ensures that
// the directory and database are setup properly. This lets other actions
@@ -54,23 +51,56 @@ public:
RunSyncWithDBOnTarget(const QuotaInfo& aQuotaInfo, nsIFile* aDBDir,
mozIStorageConnection* aConn) override
{
// TODO: init maintainance marker (bug 1110446)
// TODO: perform maintainance if necessary (bug 1110446)
// TODO: find orphaned caches in database (bug 1110446)
// TODO: have Context create/delete marker files in constructor/destructor
// and only do expensive maintenance if that marker is present (bug 1110446)
nsresult rv = BodyCreateDir(aDBDir);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
mozStorageTransaction trans(aConn, false,
mozIStorageConnection::TRANSACTION_IMMEDIATE);
{
mozStorageTransaction trans(aConn, false,
mozIStorageConnection::TRANSACTION_IMMEDIATE);
rv = CreateSchema(aConn);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = db::CreateSchema(aConn);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = trans.Commit();
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = trans.Commit();
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
}
// If the Context marker file exists, then the last session was
// not cleanly shutdown. In these cases sqlite will ensure that
// the database is valid, but we might still orphan data. Both
// Cache objects and body files can be referenced by DOM objects
// after they are "removed" from their parent. So we need to
// look and see if any of these late access objects have been
// orphaned.
//
// Note, this must be done after any schema version updates to
// ensure our DBSchema methods work correctly.
if (MarkerFileExists(aQuotaInfo)) {
NS_WARNING("Cache not shutdown cleanly! Cleaning up stale data...");
mozStorageTransaction trans(aConn, false,
mozIStorageConnection::TRANSACTION_IMMEDIATE);
// Clean up orphaned Cache objects
nsAutoTArray<CacheId, 8> orphanedCacheIdList;
nsresult rv = db::FindOrphanedCacheIds(aConn, orphanedCacheIdList);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
for (uint32_t i = 0; i < orphanedCacheIdList.Length(); ++i) {
nsAutoTArray<nsID, 16> deletedBodyIdList;
rv = db::DeleteCacheId(aConn, orphanedCacheIdList[i], deletedBodyIdList);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
rv = BodyDeleteFiles(aDBDir, deletedBodyIdList);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
}
// Clean up orphaned body objects
nsAutoTArray<nsID, 64> knownBodyIdList;
rv = db::GetKnownBodyIds(aConn, knownBodyIdList);
rv = BodyDeleteOrphanedFiles(aDBDir, knownBodyIdList);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
}
return rv;
}
@@ -127,14 +157,6 @@ private:
nsTArray<nsID> mDeletedBodyIdList;
};
} // namespace
namespace mozilla {
namespace dom {
namespace cache {
namespace {
bool IsHeadRequest(CacheRequest aRequest, CacheQueryParams aParams)
{
return !aParams.ignoreMethod() && aRequest.method().LowerCaseEqualsLiteral("head");
@@ -229,6 +251,26 @@ public:
MaybeDestroyInstance();
}
static void
StartAbortOnMainThread(const nsACString& aOrigin)
{
MOZ_ASSERT(NS_IsMainThread());
// Lock for sBackgroundThread.
StaticMutexAutoLock lock(sMutex);
if (!sBackgroundThread) {
return;
}
// Guaranteed to succeed because we should get abort only before the
// background thread is destroyed.
nsCOMPtr<nsIRunnable> runnable = new AbortRunnable(aOrigin);
nsresult rv = sBackgroundThread->Dispatch(runnable,
nsIThread::DISPATCH_NORMAL);
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(rv));
}
static void
StartShutdownAllOnMainThread()
{
@@ -338,6 +380,36 @@ private:
sFactory = nullptr;
}
static void
AbortOnBackgroundThread(const nsACString& aOrigin)
{
mozilla::ipc::AssertIsOnBackgroundThread();
// The factory was destroyed between when abort started on main thread and
// when we could start abort on the worker thread. Just declare abort
// complete.
if (!sFactory) {
#ifdef DEBUG
StaticMutexAutoLock lock(sMutex);
MOZ_ASSERT(!sBackgroundThread);
#endif
return;
}
MOZ_ASSERT(!sFactory->mManagerList.IsEmpty());
{
ManagerList::ForwardIterator iter(sFactory->mManagerList);
while (iter.HasMore()) {
nsRefPtr<Manager> manager = iter.GetNext();
if (aOrigin.IsVoid() ||
manager->mManagerId->ExtendedOrigin() == aOrigin) {
manager->Abort();
}
}
}
}
static void
ShutdownAllOnBackgroundThread()
{
@@ -374,6 +446,26 @@ private:
MaybeDestroyInstance();
}
class AbortRunnable final : public nsRunnable
{
public:
explicit AbortRunnable(const nsACString& aOrigin)
: mOrigin(aOrigin)
{ }
NS_IMETHOD
Run() override
{
mozilla::ipc::AssertIsOnBackgroundThread();
AbortOnBackgroundThread(mOrigin);
return NS_OK;
}
private:
~AbortRunnable() { }
const nsCString mOrigin;
};
class ShutdownAllRunnable final : public nsRunnable
{
public:
@@ -1463,6 +1555,15 @@ Manager::ShutdownAllOnMainThread()
}
}
// static
void
Manager::AbortOnMainThread(const nsACString& aOrigin)
{
MOZ_ASSERT(NS_IsMainThread());
Factory::StartAbortOnMainThread(aOrigin);
}
void
Manager::RemoveListener(Listener* aListener)
{
@@ -1838,6 +1939,22 @@ Manager::Shutdown()
}
}
void
Manager::Abort()
{
NS_ASSERT_OWNINGTHREAD(Manager);
MOZ_ASSERT(mContext);
// Note that we are closing to prevent any new requests from coming in and
// creating a new Context. We must ensure all Contexts and IO operations are
// complete before origin clear proceeds.
NoteClosing();
// Cancel and only note that we are done after the context is cleaned up.
nsRefPtr<Context> context = mContext;
context->CancelAll();
}
Manager::ListenerId
Manager::SaveListener(Listener* aListener)
{
+5 -1
View File
@@ -134,6 +134,9 @@ public:
// Synchronously shutdown from main thread. This spins the event loop.
static void ShutdownAllOnMainThread();
// Cancel actions for given origin or all actions if passed string is null.
static void AbortOnMainThread(const nsACString& aOrigin);
// Must be called by Listener objects before they are destroyed.
void RemoveListener(Listener* aListener);
@@ -197,7 +200,8 @@ private:
~Manager();
void Init(Manager* aOldManager);
void Shutdown();
already_AddRefed<Context> CurrentContext();
void Abort();
ListenerId SaveListener(Listener* aListener);
Listener* GetListener(ListenerId aListenerId) const;
+6 -13
View File
@@ -32,20 +32,15 @@ ManagerId::Create(nsIPrincipal* aPrincipal, ManagerId** aManagerIdOut)
//
// TODO: consider using QuotaManager's modified origin here (bug 1112071)
nsAutoCString origin;
nsCString origin;
nsresult rv = aPrincipal->GetOrigin(origin);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
uint32_t appId;
rv = aPrincipal->GetAppId(&appId);
nsCString jarPrefix;
rv = aPrincipal->GetJarPrefix(jarPrefix);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
bool inBrowserElement;
rv = aPrincipal->GetIsInBrowserElement(&inBrowserElement);
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
nsRefPtr<ManagerId> ref = new ManagerId(aPrincipal, origin, appId,
inBrowserElement);
nsRefPtr<ManagerId> ref = new ManagerId(aPrincipal, origin, jarPrefix);
ref.forget(aManagerIdOut);
return NS_OK;
@@ -60,11 +55,9 @@ ManagerId::Principal() const
}
ManagerId::ManagerId(nsIPrincipal* aPrincipal, const nsACString& aOrigin,
uint32_t aAppId, bool aInBrowserElement)
const nsACString& aJarPrefix)
: mPrincipal(aPrincipal)
, mOrigin(aOrigin)
, mAppId(aAppId)
, mInBrowserElement(aInBrowserElement)
, mExtendedOrigin(aJarPrefix + aOrigin)
{
MOZ_ASSERT(mPrincipal);
}
+4 -24
View File
@@ -23,40 +23,22 @@ namespace cache {
class ManagerId final
{
public:
// nsTArray comparator that compares by value instead of pointer values.
class MOZ_STACK_CLASS Comparator final
{
public:
bool Equals(ManagerId *aA, ManagerId* aB) const { return *aA == *aB; }
bool LessThan(ManagerId *aA, ManagerId* aB) const { return *aA < *aB; }
};
// Main thread only
static nsresult Create(nsIPrincipal* aPrincipal, ManagerId** aManagerIdOut);
// Main thread only
already_AddRefed<nsIPrincipal> Principal() const;
const nsACString& Origin() const { return mOrigin; }
const nsACString& ExtendedOrigin() const { return mExtendedOrigin; }
bool operator==(const ManagerId& aOther) const
{
return mOrigin == aOther.mOrigin &&
mAppId == aOther.mAppId &&
mInBrowserElement == aOther.mInBrowserElement;
}
bool operator<(const ManagerId& aOther) const
{
return mOrigin < aOther.mOrigin ||
(mOrigin == aOther.mOrigin && mAppId < aOther.mAppId) ||
(mOrigin == aOther.mOrigin && mAppId == aOther.mAppId &&
mInBrowserElement < aOther.mInBrowserElement);
return mExtendedOrigin == aOther.mExtendedOrigin;
}
private:
ManagerId(nsIPrincipal* aPrincipal, const nsACString& aOrigin,
uint32_t aAppId, bool aInBrowserElement);
const nsACString& aJarPrefix);
~ManagerId();
ManagerId(const ManagerId&) = delete;
@@ -66,9 +48,7 @@ private:
nsCOMPtr<nsIPrincipal> mPrincipal;
// immutable to allow threadsfe access
const nsCString mOrigin;
const uint32_t mAppId;
const bool mInBrowserElement;
const nsCString mExtendedOrigin;
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(mozilla::dom::cache::ManagerId)
-135
View File
@@ -1,135 +0,0 @@
/* -*- 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 "mozilla/dom/cache/OfflineStorage.h"
#include "mozilla/dom/cache/Context.h"
#include "mozilla/dom/cache/QuotaClient.h"
#include "mozilla/dom/quota/QuotaManager.h"
#include "nsThreadUtils.h"
namespace mozilla {
namespace dom {
namespace cache {
using mozilla::dom::quota::Client;
using mozilla::dom::quota::PERSISTENCE_TYPE_DEFAULT;
using mozilla::dom::quota::QuotaManager;
NS_IMPL_ISUPPORTS(OfflineStorage, nsIOfflineStorage);
// static
already_AddRefed<OfflineStorage>
OfflineStorage::Register(Context::ThreadsafeHandle* aContext,
const QuotaInfo& aQuotaInfo)
{
MOZ_ASSERT(NS_IsMainThread());
QuotaManager* qm = QuotaManager::Get();
if (NS_WARN_IF(!qm)) {
return nullptr;
}
nsRefPtr<Client> client = qm->GetClient(Client::DOMCACHE);
nsRefPtr<OfflineStorage> storage =
new OfflineStorage(aContext, aQuotaInfo, client);
if (NS_WARN_IF(!qm->RegisterStorage(storage))) {
return nullptr;
}
return storage.forget();
}
void
OfflineStorage::AddDestroyCallback(nsIRunnable* aCallback)
{
MOZ_ASSERT(aCallback);
MOZ_ASSERT(!mDestroyCallbacks.Contains(aCallback));
mDestroyCallbacks.AppendElement(aCallback);
}
OfflineStorage::OfflineStorage(Context::ThreadsafeHandle* aContext,
const QuotaInfo& aQuotaInfo,
Client* aClient)
: mContext(aContext)
, mQuotaInfo(aQuotaInfo)
, mClient(aClient)
{
MOZ_ASSERT(mContext);
MOZ_ASSERT(mClient);
mPersistenceType = PERSISTENCE_TYPE_DEFAULT;
mGroup = mQuotaInfo.mGroup;
}
OfflineStorage::~OfflineStorage()
{
MOZ_ASSERT(NS_IsMainThread());
QuotaManager* qm = QuotaManager::Get();
MOZ_ASSERT(qm);
qm->UnregisterStorage(this);
for (uint32_t i = 0; i < mDestroyCallbacks.Length(); ++i) {
mDestroyCallbacks[i]->Run();
}
}
NS_IMETHODIMP_(const nsACString&)
OfflineStorage::Id()
{
MOZ_ASSERT(NS_IsMainThread());
return mQuotaInfo.mStorageId;
}
NS_IMETHODIMP_(Client*)
OfflineStorage::GetClient()
{
MOZ_ASSERT(NS_IsMainThread());
return mClient;
}
NS_IMETHODIMP_(bool)
OfflineStorage::IsOwnedByProcess(ContentParent* aOwner)
{
MOZ_ASSERT(NS_IsMainThread());
// The Cache and Context can be shared by multiple client processes. They
// are not exclusively owned by a single process.
//
// As far as I can tell this is used by QuotaManager to shutdown storages
// when a particular process goes away. We definitely don't want this
// since we are shared. Also, the Cache actor code already properly
// handles asynchronous actor destruction when the child process dies.
//
// Therefore, always return false here.
return false;
}
NS_IMETHODIMP_(const nsACString&)
OfflineStorage::Origin()
{
MOZ_ASSERT(NS_IsMainThread());
return mQuotaInfo.mOrigin;
}
NS_IMETHODIMP_(nsresult)
OfflineStorage::Close()
{
MOZ_ASSERT(NS_IsMainThread());
mContext->AllowToClose();
return NS_OK;
}
NS_IMETHODIMP_(void)
OfflineStorage::Invalidate()
{
MOZ_ASSERT(NS_IsMainThread());
mContext->InvalidateAndAllowToClose();
}
} // namespace cache
} // namespace dom
} // namespace mozilla
-48
View File
@@ -1,48 +0,0 @@
/* -*- 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_cache_QuotaOfflineStorage_h
#define mozilla_dom_cache_QuotaOfflineStorage_h
#include "nsISupportsImpl.h"
#include "mozilla/AlreadyAddRefed.h"
#include "mozilla/dom/cache/Context.h"
#include "nsIOfflineStorage.h"
#include "nsTArray.h"
namespace mozilla {
namespace dom {
namespace cache {
class OfflineStorage final : public nsIOfflineStorage
{
public:
static already_AddRefed<OfflineStorage>
Register(Context::ThreadsafeHandle* aContext, const QuotaInfo& aQuotaInfo);
void
AddDestroyCallback(nsIRunnable* aCallback);
private:
OfflineStorage(Context::ThreadsafeHandle* aContext,
const QuotaInfo& aQuotaInfo,
Client* aClient);
~OfflineStorage();
nsRefPtr<Context::ThreadsafeHandle> mContext;
const QuotaInfo mQuotaInfo;
nsRefPtr<Client> mClient;
nsTArray<nsCOMPtr<nsIRunnable>> mDestroyCallbacks;
NS_DECL_ISUPPORTS
NS_DECL_NSIOFFLINESTORAGE
};
} // namespace cache
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_cache_QuotaOfflineStorage_h
+20 -50
View File
@@ -8,7 +8,6 @@
#include "mozilla/DebugOnly.h"
#include "mozilla/dom/cache/Manager.h"
#include "mozilla/dom/cache/OfflineStorage.h"
#include "mozilla/dom/quota/QuotaManager.h"
#include "mozilla/dom/quota/UsageInfo.h"
#include "nsIFile.h"
@@ -18,8 +17,8 @@
namespace {
using mozilla::DebugOnly;
using mozilla::dom::ContentParentId;
using mozilla::dom::cache::Manager;
using mozilla::dom::cache::OfflineStorage;
using mozilla::dom::quota::Client;
using mozilla::dom::quota::PersistenceType;
using mozilla::dom::quota::QuotaManager;
@@ -62,41 +61,6 @@ GetBodyUsage(nsIFile* aDir, UsageInfo* aUsageInfo)
return NS_OK;
}
class StoragesDestroyedRunnable final : public nsRunnable
{
uint32_t mExpectedCalls;
nsCOMPtr<nsIRunnable> mCallback;
public:
StoragesDestroyedRunnable(uint32_t aExpectedCalls, nsIRunnable* aCallback)
: mExpectedCalls(aExpectedCalls)
, mCallback(aCallback)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mExpectedCalls);
MOZ_ASSERT(mCallback);
}
NS_IMETHOD Run() override
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mExpectedCalls);
mExpectedCalls -= 1;
if (!mExpectedCalls) {
mCallback->Run();
}
return NS_OK;
}
private:
~StoragesDestroyedRunnable()
{
// This is a callback runnable and not used for thread dispatch. It should
// always be destroyed on the main thread.
MOZ_ASSERT(NS_IsMainThread());
}
};
class CacheQuotaClient final : public Client
{
public:
@@ -209,24 +173,30 @@ public:
}
virtual void
WaitForStoragesToComplete(nsTArray<nsIOfflineStorage*>& aStorages,
nsIRunnable* aCallback) override
AbortOperations(const nsACString& aOrigin) override
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!aStorages.IsEmpty());
nsCOMPtr<nsIRunnable> callback =
new StoragesDestroyedRunnable(aStorages.Length(), aCallback);
for (uint32_t i = 0; i < aStorages.Length(); ++i) {
MOZ_ASSERT(aStorages[i]->GetClient());
MOZ_ASSERT(aStorages[i]->GetClient()->GetType() == Client::DOMCACHE);
nsRefPtr<OfflineStorage> storage =
static_cast<OfflineStorage*>(aStorages[i]);
storage->AddDestroyCallback(callback);
}
Manager::AbortOnMainThread(aOrigin);
}
virtual void
AbortOperationsForProcess(ContentParentId aContentParentId) override
{
// The Cache and Context can be shared by multiple client processes. They
// are not exclusively owned by a single process.
//
// As far as I can tell this is used by QuotaManager to abort operations
// when a particular process goes away. We definitely don't want this
// since we are shared. Also, the Cache actor code already properly
// handles asynchronous actor destruction when the child process dies.
//
// Therefore, do nothing here.
}
virtual void
PerformIdleMaintenance() override
{ }
virtual void
ShutdownWorkThreads() override
-1
View File
@@ -33,7 +33,6 @@ struct QuotaInfo
nsCOMPtr<nsIFile> mDir;
nsCString mGroup;
nsCString mOrigin;
nsCString mStorageId;
bool mIsApp;
};
-2
View File
@@ -30,7 +30,6 @@ EXPORTS.mozilla.dom.cache += [
'IPCUtils.h',
'Manager.h',
'ManagerId.h',
'OfflineStorage.h',
'PrincipalVerifier.h',
'QuotaClient.h',
'ReadStream.h',
@@ -65,7 +64,6 @@ UNIFIED_SOURCES += [
'FileUtils.cpp',
'Manager.cpp',
'ManagerId.cpp',
'OfflineStorage.cpp',
'PrincipalVerifier.cpp',
'QuotaClient.cpp',
'ReadStream.cpp',
+2
View File
@@ -39,3 +39,5 @@ support-files =
skip-if = buildapp == 'b2g' # bug 1162353
[test_cache_restart.html]
[test_cache_shrink.html]
[test_cache_orphaned_cache.html]
[test_cache_orphaned_body.html]
+178
View File
@@ -0,0 +1,178 @@
<!-- Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ -->
<!DOCTYPE HTML>
<html>
<head>
<title>Test Cache with QuotaManager Restart</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="large_url_list.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<script class="testbody" type="text/javascript">
function setupTestIframe() {
return new Promise(function(resolve) {
var iframe = document.createElement("iframe");
iframe.src = "empty.html";
iframe.onload = function() {
window.caches = iframe.contentWindow.caches;
resolve();
};
document.body.appendChild(iframe);
});
}
function clearStorage() {
return new Promise(function(resolve, reject) {
var principal = SpecialPowers.wrap(document).nodePrincipal;
var appId, inBrowser;
var nsIPrincipal = SpecialPowers.Components.interfaces.nsIPrincipal;
if (principal.appId != nsIPrincipal.UNKNOWN_APP_ID &&
principal.appId != nsIPrincipal.NO_APP_ID) {
appId = principal.appId;
inBrowser = principal.isInBrowserElement;
}
SpecialPowers.clearStorageForURI(document.documentURI, resolve, appId,
inBrowser);
});
}
function storageUsage() {
return new Promise(function(resolve, reject) {
var principal = SpecialPowers.wrap(document).nodePrincipal;
var appId, inBrowser;
var nsIPrincipal = SpecialPowers.Components.interfaces.nsIPrincipal;
if (principal.appId != nsIPrincipal.UNKNOWN_APP_ID &&
principal.appId != nsIPrincipal.NO_APP_ID) {
appId = principal.appId;
inBrowser = principal.isInBrowserElement;
}
SpecialPowers.getStorageUsageForURI(document.documentURI, resolve, appId,
inBrowser);
});
}
function resetStorage() {
return new Promise(function(resolve, reject) {
var principal = SpecialPowers.wrap(document).nodePrincipal;
var appId, inBrowser;
var nsIPrincipal = SpecialPowers.Components.interfaces.nsIPrincipal;
if (principal.appId != nsIPrincipal.UNKNOWN_APP_ID &&
principal.appId != nsIPrincipal.NO_APP_ID) {
appId = principal.appId;
inBrowser = principal.isInBrowserElement;
}
SpecialPowers.resetStorageForURI(document.documentURI, resolve, appId,
inBrowser);
});
}
function gc() {
return new Promise(function(resolve, reject) {
SpecialPowers.exactGC(window, resolve);
});
}
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({
"set": [["dom.caches.enabled", true],
["dom.quotaManager.testing", true]],
}, function() {
var name = 'orphanedBodyOwner';
var cache = null;
var response = null;
var initialUsage = 0;
var fullUsage = 0;
var resetUsage = 0;
var endUsage = 0;
var url = 'cache_add.js';
// start from a fresh origin directory so other tests do not influence our
// results
setupTestIframe().then(function() {
return clearStorage();
}).then(function() {
return storageUsage();
}).then(function(usage) {
is(0, usage, 'disk usage should be zero to start');
})
// Initialize and populate an initial cache to get the base sqlite pages
// and directory structure allocated.
.then(function() {
return caches.open(name);
}).then(function(c) {
return c.add(url);
}).then(function() {
return gc();
}).then(function() {
return caches.delete(name);
}).then(function(deleted) {
ok(deleted, 'cache should be deleted');
})
// Now measure initial disk usage
.then(function() {
return resetStorage();
}).then(function() {
return storageUsage();
}).then(function(usage) {
initialUsage = usage;
})
// Now re-populate the Cache object
.then(function() {
return caches.open(name);
}).then(function(c) {
cache = c;
return cache.add(url);
})
// Get a reference to the body we've stored in the Cache.
.then(function() {
return cache.match(url);
}).then(function(r) {
response = r;
return cache.delete(url);
}).then(function(result) {
ok(result, "Cache entry should be deleted");
})
// Reset the quota dir while the cache entry is deleted, but still referenced
// from the DOM. This forces the body to be orphaned.
.then(function() {
return resetStorage();
}).then(function() {
return storageUsage();
}).then(function(usage) {
fullUsage = usage;
ok(fullUsage > initialUsage, 'disk usage should have grown');
})
// Now perform a new Cache operation that will reopen the origin. This
// should clean up the orphaned body.
.then(function() {
return caches.match(url);
}).then(function(r) {
ok(!r, 'response should not exist in storage');
})
// Finally, verify orphaned data was cleaned up by re-checking the disk
// usage. Reset the storage first to ensure any WAL transaction files
// are flushed before measuring the usage.
.then(function() {
return resetStorage();
}).then(function() {
return storageUsage();
}).then(function(usage) {
endUsage = usage;
dump("### ### initial:" + initialUsage + ", full:" + fullUsage +
", end:" + endUsage + "\n");
ok(endUsage < fullUsage, 'disk usage should have shrank');
is(endUsage, initialUsage, 'disk usage should return to original');
SimpleTest.finish();
});
});
</script>
</body>
</html>
+171
View File
@@ -0,0 +1,171 @@
<!-- Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ -->
<!DOCTYPE HTML>
<html>
<head>
<title>Test Cache with QuotaManager Restart</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="large_url_list.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<script class="testbody" type="text/javascript">
function setupTestIframe() {
return new Promise(function(resolve) {
var iframe = document.createElement("iframe");
iframe.src = "empty.html";
iframe.onload = function() {
window.caches = iframe.contentWindow.caches;
resolve();
};
document.body.appendChild(iframe);
});
}
function clearStorage() {
return new Promise(function(resolve, reject) {
var principal = SpecialPowers.wrap(document).nodePrincipal;
var appId, inBrowser;
var nsIPrincipal = SpecialPowers.Components.interfaces.nsIPrincipal;
if (principal.appId != nsIPrincipal.UNKNOWN_APP_ID &&
principal.appId != nsIPrincipal.NO_APP_ID) {
appId = principal.appId;
inBrowser = principal.isInBrowserElement;
}
SpecialPowers.clearStorageForURI(document.documentURI, resolve, appId,
inBrowser);
});
}
function storageUsage() {
return new Promise(function(resolve, reject) {
var principal = SpecialPowers.wrap(document).nodePrincipal;
var appId, inBrowser;
var nsIPrincipal = SpecialPowers.Components.interfaces.nsIPrincipal;
if (principal.appId != nsIPrincipal.UNKNOWN_APP_ID &&
principal.appId != nsIPrincipal.NO_APP_ID) {
appId = principal.appId;
inBrowser = principal.isInBrowserElement;
}
SpecialPowers.getStorageUsageForURI(document.documentURI, resolve, appId,
inBrowser);
});
}
function resetStorage() {
return new Promise(function(resolve, reject) {
var principal = SpecialPowers.wrap(document).nodePrincipal;
var appId, inBrowser;
var nsIPrincipal = SpecialPowers.Components.interfaces.nsIPrincipal;
if (principal.appId != nsIPrincipal.UNKNOWN_APP_ID &&
principal.appId != nsIPrincipal.NO_APP_ID) {
appId = principal.appId;
inBrowser = principal.isInBrowserElement;
}
SpecialPowers.resetStorageForURI(document.documentURI, resolve, appId,
inBrowser);
});
}
function gc() {
return new Promise(function(resolve, reject) {
SpecialPowers.exactGC(window, resolve);
});
}
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({
"set": [["dom.caches.enabled", true],
["dom.quotaManager.testing", true]],
}, function() {
var name = 'toBeOrphaned';
var cache = null;
var initialUsage = 0;
var fullUsage = 0;
var resetUsage = 0;
var endUsage = 0;
var url = 'cache_add.js';
// start from a fresh origin directory so other tests do not influence our
// results
setupTestIframe().then(function() {
return clearStorage();
}).then(function() {
return storageUsage();
}).then(function(usage) {
is(0, usage, 'disk usage should be zero to start');
})
// Initialize and populate an initial cache to get the base sqlite pages
// and directory structure allocated.
.then(function() {
return caches.open(name);
}).then(function(c) {
return c.add(url);
}).then(function() {
return gc();
}).then(function() {
return caches.delete(name);
}).then(function(deleted) {
ok(deleted, 'cache should be deleted');
})
// Now measure initial disk usage
.then(function() {
return resetStorage();
}).then(function() {
return storageUsage();
}).then(function(usage) {
initialUsage = usage;
})
// Now re-populate the Cache object
.then(function() {
return caches.open(name);
}).then(function(c) {
cache = c;
return cache.add(url);
}).then(function() {
return caches.delete(name);
}).then(function(deleted) {
ok(deleted, 'cache should be deleted');
})
// Reset the quota dir while the cache is deleted, but still referenced
// from the DOM. This forces it to be orphaned.
.then(function() {
return resetStorage();
}).then(function() {
return storageUsage();
}).then(function(usage) {
fullUsage = usage;
ok(fullUsage > initialUsage, 'disk usage should have grown');
})
// Now perform a new Cache operation that will reopen the origin. This
// should clean up the orphaned Cache data.
.then(function() {
return caches.has(name);
}).then(function(result) {
ok(!result, 'cache should not exist in storage');
})
// Finally, verify orphaned data was cleaned up by re-checking the disk
// usage. Reset the storage first to ensure any WAL transaction files
// are flushed before measuring the usage.
.then(function() {
return resetStorage();
}).then(function() {
return storageUsage();
}).then(function(usage) {
endUsage = usage;
dump("### ### initial:" + initialUsage + ", full:" + fullUsage +
", end:" + endUsage + "\n");
ok(endUsage < fullUsage, 'disk usage should have shrank');
is(endUsage, initialUsage, 'disk usage should return to original');
SimpleTest.finish();
});
});
</script>
</body>
</html>
+1 -1
View File
@@ -152,7 +152,7 @@ NS_CreateCellBroadcastService()
{
nsCOMPtr<nsICellBroadcastService> service;
if (XRE_GetProcessType() == GeckoProcessType_Content) {
if (XRE_IsContentProcess()) {
service = new mozilla::dom::cellbroadcast::CellBroadcastIPCService();
#if defined(MOZ_WIDGET_GONK) && defined(MOZ_B2G_RIL)
} else {
+26 -60
View File
@@ -51,8 +51,8 @@
#include "nsXULAppAPI.h"
#define ASSERT_PARENT_PROCESS() \
AssertIsInMainProcess(); \
if (NS_WARN_IF(!IsMainProcess())) { \
MOZ_ASSERT(XRE_IsParentProcess()); \
if (NS_WARN_IF(!XRE_IsParentProcess())) { \
return NS_ERROR_FAILURE; \
}
@@ -125,20 +125,6 @@ static uint64_t gCounterID = 0;
typedef nsClassHashtable<nsUint32HashKey, DataStoreInfo> HashApp;
bool
IsMainProcess()
{
static const bool isMainProcess =
XRE_GetProcessType() == GeckoProcessType_Default;
return isMainProcess;
}
void
AssertIsInMainProcess()
{
MOZ_ASSERT(IsMainProcess());
}
void
RejectPromise(nsPIDOMWindow* aWindow, Promise* aPromise, nsresult aRv)
{
@@ -161,8 +147,7 @@ void
DeleteDatabase(const nsAString& aName,
const nsAString& aManifestURL)
{
AssertIsInMainProcess();
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(XRE_IsParentProcess() && NS_IsMainThread());
nsRefPtr<DataStoreDB> db = new DataStoreDB(aManifestURL, aName);
db->Delete();
@@ -174,8 +159,7 @@ DeleteDataStoresAppEnumerator(
nsAutoPtr<DataStoreInfo>& aInfo,
void* aUserData)
{
AssertIsInMainProcess();
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(XRE_IsParentProcess() && NS_IsMainThread());
auto* appId = static_cast<uint32_t*>(aUserData);
if (*appId != aAppId) {
@@ -191,8 +175,7 @@ DeleteDataStoresEnumerator(const nsAString& aName,
nsAutoPtr<HashApp>& aApps,
void* aUserData)
{
AssertIsInMainProcess();
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(XRE_IsParentProcess() && NS_IsMainThread());
aApps->Enumerate(DeleteDataStoresAppEnumerator, aUserData);
return aApps->Count() ? PL_DHASH_NEXT : PL_DHASH_REMOVE;
@@ -215,8 +198,7 @@ ResetPermission(uint32_t aAppId, const nsAString& aOriginURL,
const nsAString& aPermission,
bool aReadOnly)
{
AssertIsInMainProcess();
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(XRE_IsParentProcess() && NS_IsMainThread());
nsresult rv;
nsCOMPtr<nsIIOService> ioService(do_GetService(NS_IOSERVICE_CONTRACTID, &rv));
@@ -347,8 +329,7 @@ GetDataStoreInfosEnumerator(const uint32_t& aAppId,
DataStoreInfo* aInfo,
void* aUserData)
{
AssertIsInMainProcess();
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(XRE_IsParentProcess() && NS_IsMainThread());
auto* data = static_cast<GetDataStoreInfosData*>(aUserData);
if (aAppId == data->mAppId) {
@@ -384,8 +365,7 @@ GetAppManifestURLsEnumerator(const uint32_t& aAppId,
DataStoreInfo* aInfo,
void* aUserData)
{
AssertIsInMainProcess();
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(XRE_IsParentProcess() && NS_IsMainThread());
auto* manifestURLs = static_cast<nsIMutableArray*>(aUserData);
nsCOMPtr<nsISupportsString> manifestURL(do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID));
@@ -417,8 +397,7 @@ AddPermissionsEnumerator(const uint32_t& aAppId,
DataStoreInfo* aInfo,
void* userData)
{
AssertIsInMainProcess();
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(XRE_IsParentProcess() && NS_IsMainThread());
auto* data = static_cast<AddPermissionsData*>(userData);
@@ -457,8 +436,7 @@ AddAccessPermissionsEnumerator(const uint32_t& aAppId,
DataStoreInfo* aInfo,
void* userData)
{
AssertIsInMainProcess();
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(XRE_IsParentProcess() && NS_IsMainThread());
auto* data = static_cast<AddAccessPermissionsData*>(userData);
@@ -517,15 +495,13 @@ public:
, mName(aName)
, mManifestURL(aManifestURL)
{
AssertIsInMainProcess();
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(XRE_IsParentProcess() && NS_IsMainThread());
}
void
Run(const nsAString& aRevisionId)
{
AssertIsInMainProcess();
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(XRE_IsParentProcess() && NS_IsMainThread());
nsRefPtr<DataStoreService> service = DataStoreService::Get();
MOZ_ASSERT(service);
@@ -553,15 +529,13 @@ public:
, mName(aName)
, mManifestURL(aManifestURL)
{
AssertIsInMainProcess();
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(XRE_IsParentProcess() && NS_IsMainThread());
}
void
Run(DataStoreDB* aDb, RunStatus aStatus) override
{
AssertIsInMainProcess();
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(XRE_IsParentProcess() && NS_IsMainThread());
MOZ_ASSERT(aDb);
if (aStatus == Error) {
@@ -642,8 +616,7 @@ public:
NS_IMETHOD
HandleEvent(nsIDOMEvent* aEvent) override
{
AssertIsInMainProcess();
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(XRE_IsParentProcess() && NS_IsMainThread());
nsRefPtr<IDBRequest> request;
request.swap(mRequest);
@@ -830,7 +803,7 @@ DataStoreService::Shutdown()
MOZ_ASSERT(NS_IsMainThread());
if (gDataStoreService) {
if (IsMainProcess()) {
if (XRE_IsParentProcess()) {
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
if (obs) {
obs->RemoveObserver(gDataStoreService, "webapps-clear-data");
@@ -863,7 +836,7 @@ DataStoreService::~DataStoreService()
nsresult
DataStoreService::Init()
{
if (!IsMainProcess()) {
if (!XRE_IsParentProcess()) {
return NS_OK;
}
@@ -973,7 +946,7 @@ DataStoreService::GetDataStores(nsIDOMWindow* aWindow,
// If this request comes from the main process, we have access to the
// window, so we can skip the ipc communication.
if (IsMainProcess()) {
if (XRE_IsParentProcess()) {
uint32_t appId;
nsresult rv = principal->GetAppId(&appId);
if (NS_FAILED(rv)) {
@@ -1132,8 +1105,7 @@ DataStoreService::GetDataStoreInfos(const nsAString& aName,
nsIPrincipal* aPrincipal,
nsTArray<DataStoreInfo>& aStores)
{
AssertIsInMainProcess();
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(XRE_IsParentProcess() && NS_IsMainThread());
nsCOMPtr<nsIAppsService> appsService =
do_GetService("@mozilla.org/AppsService;1");
@@ -1242,8 +1214,7 @@ DataStoreService::CheckPermission(nsIPrincipal* aPrincipal,
void
DataStoreService::DeleteDataStores(uint32_t aAppId)
{
AssertIsInMainProcess();
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(XRE_IsParentProcess() && NS_IsMainThread());
mStores.Enumerate(DeleteDataStoresEnumerator, &aAppId);
mAccessStores.Enumerate(DeleteDataStoresEnumerator, &aAppId);
@@ -1254,8 +1225,7 @@ DataStoreService::Observe(nsISupports* aSubject,
const char* aTopic,
const char16_t* aData)
{
AssertIsInMainProcess();
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(XRE_IsParentProcess() && NS_IsMainThread());
if (strcmp(aTopic, "webapps-clear-data")) {
return NS_OK;
@@ -1294,8 +1264,7 @@ DataStoreService::AddPermissions(uint32_t aAppId,
const nsAString& aManifestURL,
bool aReadOnly)
{
AssertIsInMainProcess();
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(XRE_IsParentProcess() && NS_IsMainThread());
// This is the permission name.
nsString permission;
@@ -1327,8 +1296,7 @@ DataStoreService::AddAccessPermissions(uint32_t aAppId, const nsAString& aName,
const nsAString& aManifestURL,
bool aReadOnly)
{
AssertIsInMainProcess();
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(XRE_IsParentProcess() && NS_IsMainThread());
// When an app wants to have access to a DataStore, the permissions must be
// set.
@@ -1349,8 +1317,7 @@ DataStoreService::CreateFirstRevisionId(uint32_t aAppId,
const nsAString& aName,
const nsAString& aManifestURL)
{
AssertIsInMainProcess();
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(XRE_IsParentProcess() && NS_IsMainThread());
nsRefPtr<DataStoreDB> db = new DataStoreDB(aManifestURL, aName);
@@ -1380,7 +1347,7 @@ DataStoreService::EnableDataStore(uint32_t aAppId, const nsAString& aName,
}
// Notify the child processes.
if (IsMainProcess()) {
if (XRE_IsParentProcess()) {
nsTArray<ContentParent*> children;
ContentParent::GetAll(children);
for (uint32_t i = 0; i < children.Length(); i++) {
@@ -1447,8 +1414,7 @@ DataStoreService::GetDataStoresFromIPC(const nsAString& aName,
nsIPrincipal* aPrincipal,
nsTArray<DataStoreSetting>* aValue)
{
MOZ_ASSERT(IsMainProcess());
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(XRE_IsParentProcess() && NS_IsMainThread());
uint32_t appId;
nsresult rv = aPrincipal->GetAppId(&appId);
+18 -18
View File
@@ -560,7 +560,7 @@ FileUpdateDispatcher::Observe(nsISupports* aSubject,
return NS_OK;
}
if (XRE_GetProcessType() != GeckoProcessType_Default) {
if (!XRE_IsParentProcess()) {
// Child process. Forward the notification to the parent.
ContentChild::GetSingleton()
->SendFilePathUpdateNotify(dsf->mStorageType,
@@ -691,7 +691,7 @@ DeviceStorageFile::Dump(const char* label)
path = NS_LITERAL_STRING("(null)");
}
const char* ptStr;
if (XRE_GetProcessType() == GeckoProcessType_Default) {
if (XRE_IsParentProcess()) {
ptStr = "parent";
} else {
ptStr = "child";
@@ -813,7 +813,7 @@ OverrideRootDir::Init()
}
if (sDirs->overrideRootDir) {
if (XRE_GetProcessType() == GeckoProcessType_Default) {
if (XRE_IsParentProcess()) {
// Only the parent process can create directories. In testing, because
// the preference is updated after startup, its entirely possible that
// the preference updated notification will be received by a child
@@ -935,7 +935,7 @@ InitDirs()
}
#endif
if (XRE_GetProcessType() == GeckoProcessType_Default) {
if (XRE_IsParentProcess()) {
NS_GetSpecialDirectory("UAppData", getter_AddRefs(sDirs->crashes));
if (sDirs->crashes) {
sDirs->crashes->Append(NS_LITERAL_STRING("Crash Reports"));
@@ -2057,7 +2057,7 @@ ContinueCursorEvent::~ContinueCursorEvent() {}
void
ContinueCursorEvent::Continue()
{
if (XRE_GetProcessType() == GeckoProcessType_Default) {
if (XRE_IsParentProcess()) {
DebugOnly<nsresult> rv = NS_DispatchToMainThread(this);
MOZ_ASSERT(NS_SUCCEEDED(rv));
return;
@@ -2242,7 +2242,7 @@ nsDOMDeviceStorageCursor::Allow(JS::HandleValue aChoices)
return NS_DispatchToMainThread(r);
}
if (XRE_GetProcessType() != GeckoProcessType_Default) {
if (!XRE_IsParentProcess()) {
PDeviceStorageRequestChild* child
= new DeviceStorageRequestChild(this, mFile);
DeviceStorageEnumerationParams params(mFile->mStorageType,
@@ -3011,7 +3011,7 @@ public:
return NS_DispatchToCurrentThread(r);
}
if (XRE_GetProcessType() != GeckoProcessType_Default) {
if (!XRE_IsParentProcess()) {
DeviceStorageCreateFdParams params;
params.type() = mFile->mStorageType;
@@ -3051,7 +3051,7 @@ public:
return NS_DispatchToCurrentThread(r);
}
if (XRE_GetProcessType() != GeckoProcessType_Default) {
if (!XRE_IsParentProcess()) {
BlobChild* actor
= ContentChild::GetSingleton()->GetOrCreateActorForBlob(
static_cast<Blob*>(mBlob.get()));
@@ -3097,7 +3097,7 @@ public:
return NS_DispatchToCurrentThread(r);
}
if (XRE_GetProcessType() != GeckoProcessType_Default) {
if (!XRE_IsParentProcess()) {
BlobChild* actor
= ContentChild::GetSingleton()->GetOrCreateActorForBlob(
static_cast<Blob*>(mBlob.get()));
@@ -3143,7 +3143,7 @@ public:
return NS_DispatchToCurrentThread(r);
}
if (XRE_GetProcessType() != GeckoProcessType_Default) {
if (!XRE_IsParentProcess()) {
PDeviceStorageRequestChild* child
= new DeviceStorageRequestChild(mRequest, mFile);
DeviceStorageGetParams params(mFile->mStorageType,
@@ -3177,7 +3177,7 @@ public:
return NS_DispatchToCurrentThread(r);
}
if (XRE_GetProcessType() != GeckoProcessType_Default) {
if (!XRE_IsParentProcess()) {
PDeviceStorageRequestChild* child
= new DeviceStorageRequestChild(mRequest, mFile);
DeviceStorageDeleteParams params(mFile->mStorageType,
@@ -3193,7 +3193,7 @@ public:
case DEVICE_STORAGE_REQUEST_FREE_SPACE:
{
if (XRE_GetProcessType() != GeckoProcessType_Default) {
if (!XRE_IsParentProcess()) {
PDeviceStorageRequestChild* child
= new DeviceStorageRequestChild(mRequest, mFile);
DeviceStorageFreeSpaceParams params(mFile->mStorageType,
@@ -3208,7 +3208,7 @@ public:
case DEVICE_STORAGE_REQUEST_USED_SPACE:
{
if (XRE_GetProcessType() != GeckoProcessType_Default) {
if (!XRE_IsParentProcess()) {
PDeviceStorageRequestChild* child
= new DeviceStorageRequestChild(mRequest, mFile);
DeviceStorageUsedSpaceParams params(mFile->mStorageType,
@@ -3229,7 +3229,7 @@ public:
case DEVICE_STORAGE_REQUEST_AVAILABLE:
{
if (XRE_GetProcessType() != GeckoProcessType_Default) {
if (!XRE_IsParentProcess()) {
PDeviceStorageRequestChild* child
= new DeviceStorageRequestChild(mRequest, mFile);
DeviceStorageAvailableParams params(mFile->mStorageType,
@@ -3244,7 +3244,7 @@ public:
case DEVICE_STORAGE_REQUEST_STATUS:
{
if (XRE_GetProcessType() != GeckoProcessType_Default) {
if (!XRE_IsParentProcess()) {
PDeviceStorageRequestChild* child
= new DeviceStorageRequestChild(mRequest, mFile);
DeviceStorageStatusParams params(mFile->mStorageType,
@@ -3265,7 +3265,7 @@ public:
case DEVICE_STORAGE_REQUEST_FORMAT:
{
if (XRE_GetProcessType() != GeckoProcessType_Default) {
if (!XRE_IsParentProcess()) {
PDeviceStorageRequestChild* child
= new DeviceStorageRequestChild(mRequest, mFile);
DeviceStorageFormatParams params(mFile->mStorageType,
@@ -3280,7 +3280,7 @@ public:
case DEVICE_STORAGE_REQUEST_MOUNT:
{
if (XRE_GetProcessType() != GeckoProcessType_Default) {
if (!XRE_IsParentProcess()) {
PDeviceStorageRequestChild* child
= new DeviceStorageRequestChild(mRequest, mFile);
DeviceStorageMountParams params(mFile->mStorageType,
@@ -3295,7 +3295,7 @@ public:
case DEVICE_STORAGE_REQUEST_UNMOUNT:
{
if (XRE_GetProcessType() != GeckoProcessType_Default) {
if (!XRE_IsParentProcess()) {
PDeviceStorageRequestChild* child
= new DeviceStorageRequestChild(mRequest, mFile);
DeviceStorageUnmountParams params(mFile->mStorageType,
+1 -1
View File
@@ -607,7 +607,7 @@ EventStateManager::PreHandleEvent(nsPresContext* aPresContext,
// window edge) wont update the cursor if the cached value and the current
// cursor match. So when the mouse exits a remote frame, clear the cached
// widget cursor so a proper update will occur when the mouse re-enters.
if (XRE_GetProcessType() == GeckoProcessType_Content) {
if (XRE_IsContentProcess()) {
ClearCachedWidgetCursor(mCurrentTarget);
}
+1 -1
View File
@@ -892,7 +892,7 @@ IMEStateManager::SetIMEState(const IMEState& aState,
// XXX I think that we should use nsContentUtils::IsCallerChrome() instead
// of the process type.
if (aAction.mCause == InputContextAction::CAUSE_UNKNOWN &&
XRE_GetProcessType() != GeckoProcessType_Content) {
!XRE_IsContentProcess()) {
aAction.mCause = InputContextAction::CAUSE_UNKNOWN_CHROME;
}
+1 -1
View File
@@ -242,7 +242,7 @@ void
FileInputStreamWrapper::Serialize(InputStreamParams& aParams,
FileDescriptorArray& /* aFDs */)
{
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
MOZ_ASSERT(XRE_IsParentProcess());
MOZ_ASSERT(NS_IsMainThread());
nsCOMPtr<nsIInputStream> thisStream = do_QueryObject(this);
+2 -2
View File
@@ -39,7 +39,7 @@ CreateDirectoryTask::CreateDirectoryTask(
FileSystemRequestParent* aParent)
: FileSystemTaskBase(aFileSystem, aParam, aParent)
{
MOZ_ASSERT(FileSystemUtils::IsParentProcess(),
MOZ_ASSERT(XRE_IsParentProcess(),
"Only call from parent process!");
MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
MOZ_ASSERT(aFileSystem);
@@ -84,7 +84,7 @@ CreateDirectoryTask::SetSuccessRequestResult(const FileSystemResponseValue& aVal
nsresult
CreateDirectoryTask::Work()
{
MOZ_ASSERT(FileSystemUtils::IsParentProcess(),
MOZ_ASSERT(XRE_IsParentProcess(),
"Only call from parent process!");
MOZ_ASSERT(!NS_IsMainThread(), "Only call on worker thread!");
+4 -4
View File
@@ -39,7 +39,7 @@ CreateFileTask::CreateFileTask(FileSystemBase* aFileSystem,
MOZ_ASSERT(aFileSystem);
GetOutputBufferSize();
if (aBlobData) {
if (FileSystemUtils::IsParentProcess()) {
if (XRE_IsParentProcess()) {
aBlobData->GetInternalStream(getter_AddRefs(mBlobStream), aRv);
NS_WARN_IF(aRv.Failed());
} else {
@@ -61,7 +61,7 @@ CreateFileTask::CreateFileTask(FileSystemBase* aFileSystem,
: FileSystemTaskBase(aFileSystem, aParam, aParent)
, mReplace(false)
{
MOZ_ASSERT(FileSystemUtils::IsParentProcess(),
MOZ_ASSERT(XRE_IsParentProcess(),
"Only call from parent process!");
MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
MOZ_ASSERT(aFileSystem);
@@ -168,7 +168,7 @@ CreateFileTask::Work()
nsCOMPtr<nsIOutputStream> mStream;
};
MOZ_ASSERT(FileSystemUtils::IsParentProcess(),
MOZ_ASSERT(XRE_IsParentProcess(),
"Only call from parent process!");
MOZ_ASSERT(!NS_IsMainThread(), "Only call on worker thread!");
@@ -324,7 +324,7 @@ CreateFileTask::GetPermissionAccessType(nsCString& aAccess) const
void
CreateFileTask::GetOutputBufferSize() const
{
if (sOutputBufferSize || !FileSystemUtils::IsParentProcess()) {
if (sOutputBufferSize || !XRE_IsParentProcess()) {
return;
}
sOutputBufferSize =
+4 -4
View File
@@ -47,7 +47,7 @@ DeviceStorageFileSystem::DeviceStorageFileSystem(
// Get the local path of the file system root.
// Since the child process is not allowed to access the file system, we only
// do this from the parent process.
if (!FileSystemUtils::IsParentProcess()) {
if (!XRE_IsParentProcess()) {
return;
}
nsCOMPtr<nsIFile> rootFile;
@@ -100,7 +100,7 @@ DeviceStorageFileSystem::GetWindow() const
already_AddRefed<nsIFile>
DeviceStorageFileSystem::GetLocalFile(const nsAString& aRealPath) const
{
MOZ_ASSERT(FileSystemUtils::IsParentProcess(),
MOZ_ASSERT(XRE_IsParentProcess(),
"Should be on parent process!");
nsAutoString localPath;
FileSystemUtils::NormalizedPathToLocalPath(aRealPath, localPath);
@@ -116,7 +116,7 @@ DeviceStorageFileSystem::GetLocalFile(const nsAString& aRealPath) const
bool
DeviceStorageFileSystem::GetRealPath(BlobImpl* aFile, nsAString& aRealPath) const
{
MOZ_ASSERT(FileSystemUtils::IsParentProcess(),
MOZ_ASSERT(XRE_IsParentProcess(),
"Should be on parent process!");
MOZ_ASSERT(aFile, "aFile Should not be null.");
@@ -141,7 +141,7 @@ DeviceStorageFileSystem::GetRootName() const
bool
DeviceStorageFileSystem::IsSafeFile(nsIFile* aFile) const
{
MOZ_ASSERT(FileSystemUtils::IsParentProcess(),
MOZ_ASSERT(XRE_IsParentProcess(),
"Should be on parent process!");
MOZ_ASSERT(aFile);
+5 -5
View File
@@ -35,7 +35,7 @@ FileSystemTaskBase::FileSystemTaskBase(FileSystemBase* aFileSystem,
, mFileSystem(aFileSystem)
, mRequestParent(aParent)
{
MOZ_ASSERT(FileSystemUtils::IsParentProcess(),
MOZ_ASSERT(XRE_IsParentProcess(),
"Only call from parent process!");
MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
MOZ_ASSERT(aFileSystem, "aFileSystem should not be null.");
@@ -61,7 +61,7 @@ FileSystemTaskBase::Start()
return;
}
if (FileSystemUtils::IsParentProcess()) {
if (XRE_IsParentProcess()) {
// Run in parent process.
// Start worker thread.
nsCOMPtr<nsIEventTarget> target
@@ -121,7 +121,7 @@ FileSystemTaskBase::HandleResult()
FileSystemResponseValue
FileSystemTaskBase::GetRequestResult() const
{
MOZ_ASSERT(FileSystemUtils::IsParentProcess(),
MOZ_ASSERT(XRE_IsParentProcess(),
"Only call from parent process!");
MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
if (HasError()) {
@@ -134,7 +134,7 @@ FileSystemTaskBase::GetRequestResult() const
void
FileSystemTaskBase::SetRequestResult(const FileSystemResponseValue& aValue)
{
MOZ_ASSERT(!FileSystemUtils::IsParentProcess(),
MOZ_ASSERT(!XRE_IsParentProcess(),
"Only call from child process!");
MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
if (aValue.type() == FileSystemResponseValue::TFileSystemErrorResponse) {
@@ -156,7 +156,7 @@ FileSystemTaskBase::Recv__delete__(const FileSystemResponseValue& aValue)
BlobParent*
FileSystemTaskBase::GetBlobParent(BlobImpl* aFile) const
{
MOZ_ASSERT(FileSystemUtils::IsParentProcess(),
MOZ_ASSERT(XRE_IsParentProcess(),
"Only call from parent process!");
MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
MOZ_ASSERT(aFile);
-7
View File
@@ -65,12 +65,5 @@ FileSystemUtils::IsDescendantPath(const nsAString& aPath,
return true;
}
// static
bool
FileSystemUtils::IsParentProcess()
{
return XRE_GetProcessType() == GeckoProcessType_Default;
}
} // namespace dom
} // namespace mozilla
-3
View File
@@ -41,9 +41,6 @@ public:
static bool
IsDescendantPath(const nsAString& aPath, const nsAString& aDescendantPath);
static bool
IsParentProcess();
static const char16_t kSeparatorChar = char16_t('/');
};
+3 -3
View File
@@ -42,7 +42,7 @@ GetDirectoryListingTask::GetDirectoryListingTask(FileSystemBase* aFileSystem,
FileSystemRequestParent* aParent)
: FileSystemTaskBase(aFileSystem, aParam, aParent)
{
MOZ_ASSERT(FileSystemUtils::IsParentProcess(),
MOZ_ASSERT(XRE_IsParentProcess(),
"Only call from parent process!");
MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
MOZ_ASSERT(aFileSystem);
@@ -105,7 +105,7 @@ GetDirectoryListingTask::SetSuccessRequestResult(const FileSystemResponseValue&
nsresult
GetDirectoryListingTask::Work()
{
MOZ_ASSERT(FileSystemUtils::IsParentProcess(),
MOZ_ASSERT(XRE_IsParentProcess(),
"Only call from parent process!");
MOZ_ASSERT(!NS_IsMainThread(), "Only call on worker thread!");
@@ -222,7 +222,7 @@ GetDirectoryListingTask::HandlerCallback()
path.AppendLiteral(FILESYSTEM_DOM_PATH_SEPARATOR);
path.Append(name);
#ifdef DEBUG
if (FileSystemUtils::IsParentProcess()) {
if (XRE_IsParentProcess()) {
nsCOMPtr<nsIFile> file = mFileSystem->GetLocalFile(path);
bool exist;
file->Exists(&exist);
+2 -2
View File
@@ -47,7 +47,7 @@ GetFileOrDirectoryTask::GetFileOrDirectoryTask(
: FileSystemTaskBase(aFileSystem, aParam, aParent)
, mIsDirectory(false)
{
MOZ_ASSERT(FileSystemUtils::IsParentProcess(),
MOZ_ASSERT(XRE_IsParentProcess(),
"Only call from parent process!");
MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
MOZ_ASSERT(aFileSystem);
@@ -119,7 +119,7 @@ GetFileOrDirectoryTask::SetSuccessRequestResult(const FileSystemResponseValue& a
nsresult
GetFileOrDirectoryTask::Work()
{
MOZ_ASSERT(FileSystemUtils::IsParentProcess(),
MOZ_ASSERT(XRE_IsParentProcess(),
"Only call from parent process!");
MOZ_ASSERT(!NS_IsMainThread(), "Only call on worker thread!");
+2 -2
View File
@@ -49,7 +49,7 @@ RemoveTask::RemoveTask(FileSystemBase* aFileSystem,
, mRecursive(false)
, mReturnValue(false)
{
MOZ_ASSERT(FileSystemUtils::IsParentProcess(),
MOZ_ASSERT(XRE_IsParentProcess(),
"Only call from parent process!");
MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
MOZ_ASSERT(aFileSystem);
@@ -123,7 +123,7 @@ RemoveTask::SetSuccessRequestResult(const FileSystemResponseValue& aValue)
nsresult
RemoveTask::Work()
{
MOZ_ASSERT(FileSystemUtils::IsParentProcess(),
MOZ_ASSERT(XRE_IsParentProcess(),
"Only call from parent process!");
MOZ_ASSERT(!NS_IsMainThread(), "Only call on worker thread!");
+2 -2
View File
@@ -42,7 +42,7 @@ BEGIN_FMRADIO_NAMESPACE
IFMRadioService*
IFMRadioService::Singleton()
{
if (XRE_GetProcessType() != GeckoProcessType_Default) {
if (!XRE_IsParentProcess()) {
return FMRadioChild::Singleton();
} else {
return FMRadioService::Singleton();
@@ -1240,7 +1240,7 @@ FMRadioService::UpdateFrequency()
FMRadioService*
FMRadioService::Singleton()
{
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
MOZ_ASSERT(XRE_IsParentProcess());
MOZ_ASSERT(NS_IsMainThread());
if (!sFMRadioService) {
+1 -1
View File
@@ -338,7 +338,7 @@ FMRadioChild::EnableAudio(bool aAudioEnabled)
FMRadioChild*
FMRadioChild::Singleton()
{
MOZ_ASSERT(XRE_GetProcessType() != GeckoProcessType_Default);
MOZ_ASSERT(!XRE_IsParentProcess());
MOZ_ASSERT(NS_IsMainThread());
if (!sFMRadioChild) {
+7 -7
View File
@@ -24,7 +24,7 @@ void
NotifyGamepadChange(const T& aInfo)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
MOZ_ASSERT(XRE_IsParentProcess());
GamepadChangeEvent e(aInfo);
nsTArray<ContentParent*> t;
ContentParent::GetAll(t);
@@ -44,7 +44,7 @@ AddGamepad(const char* aID,
uint32_t aNumButtons, uint32_t aNumAxes)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
MOZ_ASSERT(XRE_IsParentProcess());
int index = gGamepadIndex;
gGamepadIndex++;
@@ -59,7 +59,7 @@ void
RemoveGamepad(uint32_t aIndex)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
MOZ_ASSERT(XRE_IsParentProcess());
GamepadRemoved a(aIndex);
NotifyGamepadChange<GamepadRemoved>(a);
}
@@ -69,7 +69,7 @@ NewButtonEvent(uint32_t aIndex, uint32_t aButton,
bool aPressed, double aValue)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
MOZ_ASSERT(XRE_IsParentProcess());
GamepadButtonInformation a(aIndex, aButton, aPressed, aValue);
NotifyGamepadChange<GamepadButtonInformation>(a);
}
@@ -79,7 +79,7 @@ NewButtonEvent(uint32_t aIndex, uint32_t aButton,
bool aPressed)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
MOZ_ASSERT(XRE_IsParentProcess());
// When only a digital button is available the value will be synthesized.
NewButtonEvent(aIndex, aButton, aPressed, aPressed ? 1.0L : 0.0L);
}
@@ -89,7 +89,7 @@ NewAxisMoveEvent(uint32_t aIndex, uint32_t aAxis,
double aValue)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
MOZ_ASSERT(XRE_IsParentProcess());
GamepadAxisInformation a(aIndex, aAxis, aValue);
NotifyGamepadChange<GamepadAxisInformation>(a);
}
@@ -98,7 +98,7 @@ void
ResetGamepadIndexes()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
MOZ_ASSERT(XRE_IsParentProcess());
gGamepadIndex = 0;
}
+1 -1
View File
@@ -17,7 +17,7 @@ void
MaybeStopGamepadMonitoring()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
MOZ_ASSERT(XRE_IsParentProcess());
nsTArray<ContentParent*> t;
ContentParent::GetAll(t);
for(uint32_t i = 0; i < t.Length(); ++i) {
+3 -3
View File
@@ -85,7 +85,7 @@ GamepadService::BeginShutdown()
mTimer->Cancel();
}
if (mStarted) {
if (XRE_GetProcessType() == GeckoProcessType_Default) {
if (XRE_IsParentProcess()) {
MaybeStopGamepadMonitoring();
} else {
ContentChild::GetSingleton()->SendGamepadListenerRemoved();
@@ -115,7 +115,7 @@ GamepadService::AddListener(nsGlobalWindow* aWindow)
}
if (!mStarted && mEnabled) {
if (XRE_GetProcessType() == GeckoProcessType_Default) {
if (XRE_IsParentProcess()) {
StartGamepadMonitoring();
} else {
ContentChild::GetSingleton()->SendGamepadListenerAdded();
@@ -500,7 +500,7 @@ GamepadService::TimeoutHandler(nsITimer* aTimer, void* aClosure)
}
if (self->mListeners.Length() == 0) {
if (XRE_GetProcessType() == GeckoProcessType_Default) {
if (XRE_IsParentProcess()) {
MaybeStopGamepadMonitoring();
} else {
ContentChild::GetSingleton()->SendGamepadListenerRemoved();
+5 -5
View File
@@ -562,7 +562,7 @@ already_AddRefed<nsIDOMGeoPosition>
nsGeolocationRequest::AdjustedLocation(nsIDOMGeoPosition *aPosition)
{
nsCOMPtr<nsIDOMGeoPosition> pos = aPosition;
if (XRE_GetProcessType() == GeckoProcessType_Content) {
if (XRE_IsContentProcess()) {
GPSLOG("child process just copying position");
return pos.forget();
}
@@ -756,7 +756,7 @@ nsresult nsGeolocationService::Init()
return NS_ERROR_FAILURE;
}
if (XRE_GetProcessType() == GeckoProcessType_Content) {
if (XRE_IsContentProcess()) {
sGeoInitPending = false;
return NS_OK;
}
@@ -1008,7 +1008,7 @@ nsGeolocationService::StartDevice(nsIPrincipal *aPrincipal)
// inactivivity
SetDisconnectTimer();
if (XRE_GetProcessType() == GeckoProcessType_Content) {
if (XRE_IsContentProcess()) {
ContentChild* cpc = ContentChild::GetSingleton();
cpc->SendAddGeolocationListener(IPC::Principal(aPrincipal),
HighAccuracyRequested());
@@ -1071,7 +1071,7 @@ nsGeolocationService::UpdateAccuracy(bool aForceHigh)
{
bool highRequired = aForceHigh || HighAccuracyRequested();
if (XRE_GetProcessType() == GeckoProcessType_Content) {
if (XRE_IsContentProcess()) {
ContentChild* cpc = ContentChild::GetSingleton();
if (cpc->IsAlive()) {
cpc->SendSetGeolocationHigherAccuracy(highRequired);
@@ -1098,7 +1098,7 @@ nsGeolocationService::StopDevice()
mDisconnectTimer = nullptr;
}
if (XRE_GetProcessType() == GeckoProcessType_Content) {
if (XRE_IsContentProcess()) {
ContentChild* cpc = ContentChild::GetSingleton();
cpc->SendRemoveGeolocationListener();
return; // bail early
+1 -1
View File
@@ -49,7 +49,7 @@ already_AddRefed<nsGeolocationSettings>
nsGeolocationSettings::GetGeolocationSettings()
{
// this singleton is only needed in the parent process...
if (XRE_GetProcessType() == GeckoProcessType_Content) {
if (XRE_IsContentProcess()) {
return nullptr;
}
+3 -3
View File
@@ -1058,7 +1058,7 @@ UploadLastDir::FetchDirectoryAndDisplayPicker(nsIDocument* aDoc,
new UploadLastDir::ContentPrefCallback(aFilePicker, aFpCallback);
#ifdef MOZ_B2G
if (XRE_GetProcessType() == GeckoProcessType_Content) {
if (XRE_IsContentProcess()) {
prefCallback->HandleCompletion(nsIContentPrefCallback2::COMPLETE_ERROR);
return NS_OK;
}
@@ -1089,7 +1089,7 @@ UploadLastDir::StoreLastUsedDirectory(nsIDocument* aDoc, nsIFile* aDir)
}
#ifdef MOZ_B2G
if (XRE_GetProcessType() == GeckoProcessType_Content) {
if (XRE_IsContentProcess()) {
return NS_OK;
}
#endif
@@ -2417,7 +2417,7 @@ HTMLInputElement::MozSetFileArray(const Sequence<OwningNonNull<File>>& aFiles)
void
HTMLInputElement::MozSetFileNameArray(const Sequence< nsString >& aFileNames, ErrorResult& aRv)
{
if (XRE_GetProcessType() == GeckoProcessType_Content) {
if (XRE_IsContentProcess()) {
aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
return;
}
+1 -1
View File
@@ -596,7 +596,7 @@ nsGenericHTMLFrameElement::GetAppManifestURL(nsAString& aOut)
// Only allow content process to embed an app when nested content
// process is enabled.
if (XRE_GetProcessType() != GeckoProcessType_Default &&
if (!XRE_IsParentProcess() &&
!(GetBoolAttr(nsGkAtoms::Remote) && NestedEnabled())){
NS_WARNING("Can't embed-apps. Embed-apps is restricted to in-proc apps "
"or content processes with nested pref enabled, see bug 1097479");
+1 -1
View File
@@ -146,7 +146,7 @@ NS_CreateIccService()
{
nsCOMPtr<nsIIccService> service;
if (XRE_GetProcessType() == GeckoProcessType_Content) {
if (XRE_IsContentProcess()) {
service = new mozilla::dom::icc::IccIPCService();
#if defined(MOZ_WIDGET_GONK) && defined(MOZ_B2G_RIL)
} else {
+4 -4
View File
@@ -818,7 +818,7 @@ public:
: PermissionRequestBase(aElement, aPrincipal)
, mChallenge(aChallenge)
{
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
MOZ_ASSERT(XRE_IsParentProcess());
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aChallenge);
}
@@ -844,7 +844,7 @@ public:
WorkerPermissionChallenge* aChallenge)
: mChallenge(aChallenge)
{
MOZ_ASSERT(XRE_GetProcessType() != GeckoProcessType_Default);
MOZ_ASSERT(!XRE_IsParentProcess());
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aChallenge);
}
@@ -950,7 +950,7 @@ private:
return true;
}
if (XRE_GetProcessType() == GeckoProcessType_Default) {
if (XRE_IsParentProcess()) {
nsCOMPtr<Element> ownerElement =
do_QueryInterface(window->GetChromeEventHandler());
if (NS_WARN_IF(!ownerElement)) {
@@ -1387,7 +1387,7 @@ BackgroundFactoryRequestChild::RecvPermissionChallenge(
return false;
}
if (XRE_GetProcessType() == GeckoProcessType_Default) {
if (XRE_IsParentProcess()) {
nsCOMPtr<nsPIDOMWindow> window = mFactory->GetParentObject();
MOZ_ASSERT(window);
File diff suppressed because it is too large Load Diff
+10 -1
View File
@@ -42,6 +42,7 @@ class FileManager final
// Protected by IndexedDatabaseManager::FileMutex()
nsDataHashtable<nsUint64HashKey, FileInfo*> mFileInfos;
const bool mIsApp;
const bool mEnforcingQuota;
bool mInvalidated;
@@ -54,7 +55,8 @@ public:
nsIFile* aDatabaseFile,
PersistenceType aPersistenceType,
const nsACString& aGroup,
const nsACString& aOrigin);
const nsACString& aOrigin,
uint32_t aTelemetryId);
static nsresult
GetUsage(nsIFile* aDirectory, uint64_t* aUsage);
@@ -62,6 +64,7 @@ public:
FileManager(PersistenceType aPersistenceType,
const nsACString& aGroup,
const nsACString& aOrigin,
bool aIsApp,
const nsAString& aDatabaseName,
bool aEnforcingQuota);
@@ -83,6 +86,12 @@ public:
return mOrigin;
}
bool
IsApp() const
{
return mIsApp;
}
const nsAString&
DatabaseName() const
{
+1 -1
View File
@@ -83,7 +83,7 @@ BlobImplSnapshot::~BlobImplSnapshot()
void
BlobImplSnapshot::AssertSanity()
{
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
MOZ_ASSERT(XRE_IsParentProcess());
MOZ_ASSERT(NS_IsMainThread());
}
+6 -2
View File
@@ -168,15 +168,19 @@ IDBMutableFile::Create(IDBDatabase* aDatabase,
const DatabaseSpec* spec = aDatabase->Spec();
MOZ_ASSERT(spec);
PersistenceType persistenceType = spec->metadata().persistenceType();
const DatabaseMetadata& metadata = spec->metadata();
PersistenceType persistenceType = metadata.persistenceType();
nsCString storageId;
QuotaManager::GetStorageId(persistenceType,
origin,
Client::IDB,
aDatabase->Name(),
storageId);
storageId.Append('*');
storageId.Append(NS_ConvertUTF16toUTF8(metadata.name()));
nsCOMPtr<nsIFile> file = GetFileFor(fileInfo);
if (NS_WARN_IF(!file)) {
return nullptr;
+315 -68
View File
@@ -25,13 +25,7 @@
#include "mozilla/dom/DOMError.h"
#include "mozilla/dom/ErrorEvent.h"
#include "mozilla/dom/ErrorEventBinding.h"
#include "mozilla/dom/PBlobChild.h"
#include "mozilla/dom/quota/OriginOrPatternString.h"
#include "mozilla/dom/quota/QuotaManager.h"
#include "mozilla/dom/quota/Utilities.h"
#include "mozilla/dom/TabContext.h"
#include "mozilla/ipc/BackgroundChild.h"
#include "mozilla/ipc/PBackgroundChild.h"
#include "nsContentUtils.h"
#include "nsGlobalWindow.h"
#include "nsThreadUtils.h"
@@ -121,6 +115,8 @@ namespace {
NS_DEFINE_IID(kIDBRequestIID, PRIVATE_IDBREQUEST_IID);
const uint32_t kDeleteTimeoutMs = 1000;
#define IDB_PREF_BRANCH_ROOT "dom.indexedDB."
const char kTestingPref[] = IDB_PREF_BRANCH_ROOT "testing";
@@ -146,19 +142,73 @@ Atomic<bool> gClosed(false);
Atomic<bool> gTestingMode(false);
Atomic<bool> gExperimentalFeaturesEnabled(false);
class AsyncDeleteFileRunnable final : public nsIRunnable
class DeleteFilesRunnable final
: public nsIRunnable
, public OpenDirectoryListener
{
typedef mozilla::dom::quota::DirectoryLock DirectoryLock;
enum State
{
// Just created on the main thread. Next step is State_DirectoryOpenPending.
State_Initial,
// Waiting for directory open allowed on the main thread. The next step is
// State_DatabaseWorkOpen.
State_DirectoryOpenPending,
// Waiting to do/doing work on the QuotaManager IO thread. The next step is
// State_UnblockingOpen.
State_DatabaseWorkOpen,
// Notifying the QuotaManager that it can proceed to the next operation on
// the main thread. Next step is State_Completed.
State_UnblockingOpen,
// All done.
State_Completed
};
nsRefPtr<FileManager> mFileManager;
nsTArray<int64_t> mFileIds;
nsRefPtr<DirectoryLock> mDirectoryLock;
nsCOMPtr<nsIFile> mDirectory;
nsCOMPtr<nsIFile> mJournalDirectory;
State mState;
public:
DeleteFilesRunnable(FileManager* aFileManager,
nsTArray<int64_t>& aFileIds);
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIRUNNABLE
AsyncDeleteFileRunnable(FileManager* aFileManager, int64_t aFileId);
virtual void
DirectoryLockAcquired(DirectoryLock* aLock) override;
virtual void
DirectoryLockFailed() override;
private:
~AsyncDeleteFileRunnable() {}
~DeleteFilesRunnable() {}
nsRefPtr<FileManager> mFileManager;
int64_t mFileId;
nsresult
Open();
nsresult
DeleteFile(int64_t aFileId);
nsresult
DoDatabaseWork();
void
Finish();
void
UnblockOpen();
};
class GetFileReferencesHelper final : public nsIRunnable
@@ -252,7 +302,7 @@ IndexedDatabaseManager::GetOrCreate()
}
if (!gDBManager) {
sIsMainProcess = XRE_GetProcessType() == GeckoProcessType_Default;
sIsMainProcess = XRE_IsParentProcess();
if (!sLoggingModule) {
sLoggingModule = PR_NewLogModule("IndexedDB");
@@ -315,6 +365,9 @@ IndexedDatabaseManager::Init()
nsresult rv =
obs->AddObserver(this, DISKSPACEWATCHER_OBSERVER_TOPIC, false);
NS_ENSURE_SUCCESS(rv, rv);
mDeleteTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
NS_ENSURE_STATE(mDeleteTimer);
}
Preferences::RegisterCallbackAndCall(AtomicBoolPrefChangedCallback,
@@ -353,6 +406,14 @@ IndexedDatabaseManager::Destroy()
NS_ERROR("Shutdown more than once?!");
}
if (sIsMainProcess && mDeleteTimer) {
if (NS_FAILED(mDeleteTimer->Cancel())) {
NS_WARNING("Failed to cancel timer!");
}
mDeleteTimer = nullptr;
}
Preferences::UnregisterCallback(AtomicBoolPrefChangedCallback,
kTestingPref,
&gTestingMode);
@@ -515,25 +576,6 @@ IndexedDatabaseManager::CommonPostHandleEvent(EventChainPostVisitor& aVisitor,
return NS_OK;
}
// static
bool
IndexedDatabaseManager::TabContextMayAccessOrigin(const TabContext& aContext,
const nsACString& aOrigin)
{
NS_ASSERTION(!aOrigin.IsEmpty(), "Empty origin!");
// If aContext is for a browser element, it's allowed only to access other
// browser elements. But if aContext is not for a browser element, it may
// access both browser and non-browser elements.
nsAutoCString pattern;
QuotaManager::GetOriginPatternStringMaybeIgnoreBrowser(
aContext.OwnOrContainingAppId(),
aContext.IsBrowserElement(),
pattern);
return PatternMatchesOrigin(pattern, aOrigin);
}
// static
bool
IndexedDatabaseManager::DefineIndexedDB(JSContext* aCx,
@@ -597,7 +639,7 @@ IndexedDatabaseManager::IsMainProcess()
{
NS_ASSERTION(gDBManager,
"IsMainProcess() called before indexedDB has been initialized!");
NS_ASSERTION((XRE_GetProcessType() == GeckoProcessType_Default) ==
NS_ASSERTION((XRE_IsParentProcess()) ==
sIsMainProcess, "XRE_GetProcessType changed its tune!");
return sIsMainProcess;
}
@@ -733,9 +775,8 @@ IndexedDatabaseManager::InvalidateAllFileManagers()
}
void
IndexedDatabaseManager::InvalidateFileManagers(
PersistenceType aPersistenceType,
const nsACString& aOrigin)
IndexedDatabaseManager::InvalidateFileManagers(PersistenceType aPersistenceType,
const nsACString& aOrigin)
{
AssertIsOnIOThread();
MOZ_ASSERT(!aOrigin.IsEmpty());
@@ -775,27 +816,30 @@ nsresult
IndexedDatabaseManager::AsyncDeleteFile(FileManager* aFileManager,
int64_t aFileId)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
MOZ_ASSERT(IsMainProcess());
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aFileManager);
MOZ_ASSERT(aFileId > 0);
MOZ_ASSERT(mDeleteTimer);
NS_ENSURE_ARG_POINTER(aFileManager);
QuotaManager* quotaManager = QuotaManager::Get();
NS_ASSERTION(quotaManager, "Shouldn't be null!");
// See if we're currently clearing the storages for this origin. If so then
// we pretend that we've already deleted everything.
if (quotaManager->IsClearOriginPending(
aFileManager->Origin(),
Nullable<PersistenceType>(aFileManager->Type()))) {
return NS_OK;
nsresult rv = mDeleteTimer->Cancel();
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
nsRefPtr<AsyncDeleteFileRunnable> runnable =
new AsyncDeleteFileRunnable(aFileManager, aFileId);
rv = mDeleteTimer->InitWithCallback(this, kDeleteTimeoutMs,
nsITimer::TYPE_ONE_SHOT);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
nsresult rv =
quotaManager->IOThread()->Dispatch(runnable, NS_DISPATCH_NORMAL);
NS_ENSURE_SUCCESS(rv, rv);
nsTArray<int64_t>* array;
if (!mPendingDeleteInfos.Get(aFileManager, &array)) {
array = new nsTArray<int64_t>();
mPendingDeleteInfos.Put(aFileManager, array);
}
array->AppendElement(aFileId);
return NS_OK;
}
@@ -811,6 +855,8 @@ IndexedDatabaseManager::BlockAndGetFileReferences(
int32_t* aSliceRefCnt,
bool* aResult)
{
MOZ_ASSERT(NS_IsMainThread());
if (NS_WARN_IF(!InTestingMode())) {
return NS_ERROR_UNEXPECTED;
}
@@ -847,6 +893,39 @@ IndexedDatabaseManager::BlockAndGetFileReferences(
return NS_OK;
}
nsresult
IndexedDatabaseManager::FlushPendingFileDeletions()
{
MOZ_ASSERT(NS_IsMainThread());
if (NS_WARN_IF(!InTestingMode())) {
return NS_ERROR_UNEXPECTED;
}
if (IsMainProcess()) {
nsresult rv = mDeleteTimer->Cancel();
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = Notify(mDeleteTimer);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
} else {
ContentChild* contentChild = ContentChild::GetSingleton();
if (NS_WARN_IF(!contentChild)) {
return NS_ERROR_FAILURE;
}
if (!contentChild->SendFlushPendingFileDeletions()) {
return NS_ERROR_FAILURE;
}
}
return NS_OK;
}
// static
void
IndexedDatabaseManager::LoggingModePrefChangedCallback(
@@ -887,7 +966,7 @@ IndexedDatabaseManager::LoggingModePrefChangedCallback(
NS_IMPL_ADDREF(IndexedDatabaseManager)
NS_IMPL_RELEASE_WITH_DESTROY(IndexedDatabaseManager, Destroy())
NS_IMPL_QUERY_INTERFACE(IndexedDatabaseManager, nsIObserver)
NS_IMPL_QUERY_INTERFACE(IndexedDatabaseManager, nsIObserver, nsITimerCallback)
NS_IMETHODIMP
IndexedDatabaseManager::Observe(nsISupports* aSubject, const char* aTopic,
@@ -916,7 +995,41 @@ IndexedDatabaseManager::Observe(nsISupports* aSubject, const char* aTopic,
NS_NOTREACHED("Unknown topic!");
return NS_ERROR_UNEXPECTED;
}
}
NS_IMETHODIMP
IndexedDatabaseManager::Notify(nsITimer* aTimer)
{
MOZ_ASSERT(IsMainProcess());
MOZ_ASSERT(NS_IsMainThread());
class MOZ_STACK_CLASS Helper final
{
public:
static PLDHashOperator
CreateAndDispatchRunnables(FileManager* aFileManager,
nsTArray<int64_t>* aValue,
void* aClosure)
{
MOZ_ASSERT(!aValue->IsEmpty());
nsRefPtr<DeleteFilesRunnable> runnable =
new DeleteFilesRunnable(aFileManager, *aValue);
MOZ_ASSERT(aValue->IsEmpty());
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToMainThread(runnable)));
return PL_DHASH_NEXT;
}
};
mPendingDeleteInfos.EnumerateRead(Helper::CreateAndDispatchRunnables,
nullptr);
mPendingDeleteInfos.Clear();
return NS_OK;
}
already_AddRefed<FileManager>
FileManagerInfo::GetFileManager(PersistenceType aPersistenceType,
@@ -1022,24 +1135,109 @@ FileManagerInfo::GetArray(PersistenceType aPersistenceType)
}
}
AsyncDeleteFileRunnable::AsyncDeleteFileRunnable(FileManager* aFileManager,
int64_t aFileId)
: mFileManager(aFileManager), mFileId(aFileId)
DeleteFilesRunnable::DeleteFilesRunnable(FileManager* aFileManager,
nsTArray<int64_t>& aFileIds)
: mFileManager(aFileManager)
, mState(State_Initial)
{
mFileIds.SwapElements(aFileIds);
}
NS_IMPL_ISUPPORTS(AsyncDeleteFileRunnable,
nsIRunnable)
NS_IMPL_ISUPPORTS(DeleteFilesRunnable, nsIRunnable)
NS_IMETHODIMP
AsyncDeleteFileRunnable::Run()
DeleteFilesRunnable::Run()
{
AssertIsOnIOThread();
nsresult rv;
nsCOMPtr<nsIFile> directory = mFileManager->GetDirectory();
NS_ENSURE_TRUE(directory, NS_ERROR_FAILURE);
switch (mState) {
case State_Initial:
rv = Open();
break;
nsCOMPtr<nsIFile> file = mFileManager->GetFileForId(directory, mFileId);
case State_DatabaseWorkOpen:
rv = DoDatabaseWork();
break;
case State_UnblockingOpen:
UnblockOpen();
return NS_OK;
case State_DirectoryOpenPending:
default:
MOZ_CRASH("Should never get here!");
}
if (NS_WARN_IF(NS_FAILED(rv)) && mState != State_UnblockingOpen) {
Finish();
}
return NS_OK;
}
void
DeleteFilesRunnable::DirectoryLockAcquired(DirectoryLock* aLock)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mState == State_DirectoryOpenPending);
MOZ_ASSERT(!mDirectoryLock);
mDirectoryLock = aLock;
QuotaManager* quotaManager = QuotaManager::Get();
MOZ_ASSERT(quotaManager);
// Must set this before dispatching otherwise we will race with the IO thread
mState = State_DatabaseWorkOpen;
nsresult rv = quotaManager->IOThread()->Dispatch(this, NS_DISPATCH_NORMAL);
if (NS_WARN_IF(NS_FAILED(rv))) {
Finish();
return;
}
}
void
DeleteFilesRunnable::DirectoryLockFailed()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mState == State_DirectoryOpenPending);
MOZ_ASSERT(!mDirectoryLock);
Finish();
}
nsresult
DeleteFilesRunnable::Open()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mState == State_Initial);
QuotaManager* quotaManager = QuotaManager::Get();
if (NS_WARN_IF(!quotaManager)) {
return NS_ERROR_FAILURE;
}
mState = State_DirectoryOpenPending;
quotaManager->OpenDirectory(mFileManager->Type(),
mFileManager->Group(),
mFileManager->Origin(),
mFileManager->IsApp(),
Client::IDB,
/* aExclusive */ false,
this);
return NS_OK;
}
nsresult
DeleteFilesRunnable::DeleteFile(int64_t aFileId)
{
MOZ_ASSERT(mDirectory);
MOZ_ASSERT(mJournalDirectory);
nsCOMPtr<nsIFile> file = mFileManager->GetFileForId(mDirectory, aFileId);
NS_ENSURE_TRUE(file, NS_ERROR_FAILURE);
nsresult rv;
@@ -1062,10 +1260,7 @@ AsyncDeleteFileRunnable::Run()
mFileManager->Origin(), fileSize);
}
directory = mFileManager->GetJournalDirectory();
NS_ENSURE_TRUE(directory, NS_ERROR_FAILURE);
file = mFileManager->GetFileForId(directory, mFileId);
file = mFileManager->GetFileForId(mJournalDirectory, aFileId);
NS_ENSURE_TRUE(file, NS_ERROR_FAILURE);
rv = file->Remove(false);
@@ -1074,6 +1269,58 @@ AsyncDeleteFileRunnable::Run()
return NS_OK;
}
nsresult
DeleteFilesRunnable::DoDatabaseWork()
{
AssertIsOnIOThread();
MOZ_ASSERT(mState == State_DatabaseWorkOpen);
if (!mFileManager->Invalidated()) {
mDirectory = mFileManager->GetDirectory();
if (NS_WARN_IF(!mDirectory)) {
return NS_ERROR_FAILURE;
}
mJournalDirectory = mFileManager->GetJournalDirectory();
if (NS_WARN_IF(!mJournalDirectory)) {
return NS_ERROR_FAILURE;
}
for (int64_t fileId : mFileIds) {
if (NS_FAILED(DeleteFile(fileId))) {
NS_WARNING("Failed to delete file!");
}
}
}
Finish();
return NS_OK;
}
void
DeleteFilesRunnable::Finish()
{
// Must set mState before dispatching otherwise we will race with the main
// thread.
mState = State_UnblockingOpen;
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToMainThread(this)));
}
void
DeleteFilesRunnable::UnblockOpen()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mState == State_UnblockingOpen);
if (mDirectoryLock) {
mDirectoryLock = nullptr;
}
mState = State_Completed;
}
nsresult
GetFileReferencesHelper::DispatchAndReturnFileReferences(int32_t* aMemRefCnt,
int32_t* aDBRefCnt,
+14 -7
View File
@@ -14,7 +14,9 @@
#include "mozilla/dom/quota/PersistenceType.h"
#include "mozilla/Mutex.h"
#include "nsClassHashtable.h"
#include "nsCOMPtr.h"
#include "nsHashKeys.h"
#include "nsITimer.h"
struct PRLogModuleInfo;
@@ -24,15 +26,15 @@ class EventChainPostVisitor;
namespace dom {
class TabContext;
namespace indexedDB {
class FileManager;
class FileManagerInfo;
class IDBFactory;
class IndexedDatabaseManager final : public nsIObserver
class IndexedDatabaseManager final
: public nsIObserver
, public nsITimerCallback
{
typedef mozilla::dom::quota::PersistenceType PersistenceType;
@@ -48,6 +50,7 @@ public:
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
NS_DECL_NSITIMERCALLBACK
// Returns a non-owning reference.
static IndexedDatabaseManager*
@@ -152,6 +155,9 @@ public:
int32_t* aSliceRefCnt,
bool* aResult);
nsresult
FlushPendingFileDeletions();
static mozilla::Mutex&
FileMutex()
{
@@ -164,10 +170,6 @@ public:
static nsresult
CommonPostHandleEvent(EventChainPostVisitor& aVisitor, IDBFactory* aFactory);
static bool
TabContextMayAccessOrigin(const mozilla::dom::TabContext& aContext,
const nsACString& aOrigin);
static bool
DefineIndexedDB(JSContext* aCx, JS::Handle<JSObject*> aGlobal);
@@ -184,10 +186,15 @@ private:
static void
LoggingModePrefChangedCallback(const char* aPrefName, void* aClosure);
nsCOMPtr<nsITimer> mDeleteTimer;
// Maintains a list of all file managers per origin. This list isn't
// protected by any mutex but it is only ever touched on the IO thread.
nsClassHashtable<nsCStringHashKey, FileManagerInfo> mFileManagerInfos;
nsClassHashtable<nsRefPtrHashKey<FileManager>,
nsTArray<int64_t>> mPendingDeleteInfos;
// Lock protecting FileManager.mFileInfos and BlobImplBase.mFileInfos
// It's s also used to atomically update FileInfo.mRefCnt, FileInfo.mDBRefCnt
// and FileInfo.mSliceRefCnt
+1 -1
View File
@@ -43,7 +43,7 @@ const uint32_t kPermissionDefault = nsIPermissionManager::UNKNOWN_ACTION;
void
AssertSanity()
{
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
MOZ_ASSERT(XRE_IsParentProcess());
MOZ_ASSERT(NS_IsMainThread());
}
+1
View File
@@ -96,4 +96,5 @@ LOCAL_INCLUDES += [
'/dom/workers',
'/ipc/glue',
'/xpcom/build',
'/xpcom/threads',
]
+5
View File
@@ -220,3 +220,8 @@ function getFileDBRefCount(name, id)
utils.getFileReferences(name, id, null, {}, count);
return count.value;
}
function flushPendingFileDeletions()
{
utils.flushPendingFileDeletions();
}
@@ -90,6 +90,9 @@
request.onsuccess = grabEventAndContinueHandler;
yield undefined;
// and also flush pending file deletions before checking usage.
flushPendingFileDeletions();
getUsage(grabFileUsageAndContinueHandler);
let endUsage = yield undefined;
Binary file not shown.
@@ -63,6 +63,18 @@ function testSteps()
// This one lives in storage/default/file++++c++
{ url: "file:///c:/", dbName: "dbQ", dbVersion: 1 },
// This one lives in storage/default/file++++Users+joe+c+++index.html
{ url: "file:///Users/joe/c++/index.html", dbName: "dbR", dbVersion: 1 },
// This one lives in storage/default/file++++Users+joe+c+++index.html
{ url: "file:///Users/joe/c///index.html", dbName: "dbR", dbVersion: 1 },
// This one lives in storage/default/file++++++index.html
{ url: "file:///+/index.html", dbName: "dbS", dbVersion: 1 },
// This one lives in storage/default/file++++++index.html
{ url: "file://///index.html", dbName: "dbS", dbVersion: 1 },
// This one lives in storage/temporary/http+++localhost
{ url: "http://localhost", dbName: "dbZ",
dbOptions: { version: 1, storage: "temporary" } }
@@ -0,0 +1,136 @@
/**
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
var testGenerator = testSteps();
function testSteps()
{
let uri = Cc["@mozilla.org/network/io-service;1"].
getService(Ci.nsIIOService).
newURI("https://www.example.com", null, null);
let principal = Cc["@mozilla.org/scriptsecuritymanager;1"].
getService(Ci.nsIScriptSecurityManager).
getNoAppCodebasePrincipal(uri);
info("Setting permissions");
let permMgr =
Cc["@mozilla.org/permissionmanager;1"].getService(Ci.nsIPermissionManager);
permMgr.add(uri, "indexedDB", Ci.nsIPermissionManager.ALLOW_ACTION);
info("Setting idle preferences to prevent real 'idle-daily' notification");
let prefs =
Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
prefs.setIntPref("idle.lastDailyNotification", (Date.now() / 1000) - 10);
info("Activating real idle service");
do_get_idle();
info("Creating databases");
let quotaManager =
Cc["@mozilla.org/dom/quota/manager;1"].getService(Ci.nsIQuotaManager);
let dbCount = 0;
for (let persistence of ["persistent", "temporary", "default"]) {
for (let i = 1; i <= 5; i++) {
let dbName = "foo-" + i;
let dbPersistence = persistence;
let req = indexedDB.openForPrincipal(principal,
dbName,
{ version: 1,
storage: dbPersistence });
req.onerror = event => {
if (dbPersistence != "persistent") {
errorHandler(event);
return;
}
// Explicit persistence is currently blocked on mobile.
info("Failed to create persistent database '" + dbPersistence + "/" +
dbName + "', hopefully this is on mobile!");
event.preventDefault();
if (!(--dbCount)) {
continueToNextStep();
}
};
req.onupgradeneeded = event => {
let db = event.target.result;
let objectStore = db.createObjectStore("foo");
// Add lots of data...
for (let j = 0; j < 100; j++) {
objectStore.add("abcdefghijklmnopqrstuvwxyz0123456789", j);
}
// And then clear it so that maintenance has some space to reclaim.
objectStore.clear();
};
req.onsuccess = event => {
let db = event.target.result;
ok(db, "Created database '" + dbPersistence + "/" + dbName + "'");
db.close();
if (!(--dbCount)) {
continueToNextStep();
}
};
dbCount++;
}
}
yield undefined;
info("Getting usage before maintenance");
let usageBeforeMaintenance;
quotaManager.getUsageForURI(uri, (url, usage) => {
ok(usage > 0, "Usage is non-zero");
usageBeforeMaintenance = usage;
continueToNextStep();
});
yield undefined;
info("Sending fake 'idle-daily' notification to QuotaManager");
let observer = quotaManager.QueryInterface(Ci.nsIObserver);
observer.observe(null, "idle-daily", "");
info("Waiting for maintenance to start");
// This time is totally arbitrary. Most likely directory scanning will have
// completed, QuotaManager locks will be acquired, and maintenance tasks will
// be scheduled before this time has elapsed, so we will be testing the
// maintenance code. However, if something is slow then this will test
// shutting down in the middle of maintenance.
setTimeout(continueToNextStep, 10000);
yield undefined;
info("Getting usage after maintenance");
let usageAfterMaintenance;
quotaManager.getUsageForURI(uri, (url, usage) => {
ok(usage > 0, "Usage is non-zero");
usageAfterMaintenance = usage;
continueToNextStep();
});
yield undefined;
info("Usage before: " + usageBeforeMaintenance + ". " +
"Usage after: " + usageAfterMaintenance);
ok(usageAfterMaintenance <= usageBeforeMaintenance,
"Maintenance decreased file sizes or left them the same");
finishTest();
yield undefined;
}
@@ -0,0 +1,109 @@
/**
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
var testGenerator = testSteps();
function testSteps()
{
const openParams = [
// This one lives in storage/permanent/chrome
{ dbName: "dbA",
dbOptions: { version: 1, storage: "persistent" } },
// This one lives in storage/temporary/http+++localhost
{ url: "http://localhost", dbName: "dbB",
dbOptions: { version: 1, storage: "temporary" } },
// This one lives in storage/default/http+++localhost+81
{ url: "http://localhost:81", dbName: "dbC",
dbOptions: { version: 1, storage: "default" } },
// This one lives in storage/default/http+++localhost+82
{ url: "http://localhost:82", dbName: "dbD",
dbOptions: { version: 1, storage: "default" } },
// This one lives in storage/default/http+++localhost+83
{ url: "http://localhost:83", dbName: "dbE",
dbOptions: { version: 1, storage: "default" } },
// This one lives in storage/default/http+++localhost+84
{ url: "http://localhost:84", dbName: "dbF",
dbOptions: { version: 1, storage: "default" } },
// This one lives in storage/default/http+++localhost+85
{ url: "http://localhost:85", dbName: "dbG",
dbOptions: { version: 1, storage: "default" } },
// This one lives in storage/default/http+++localhost+86
{ url: "http://localhost:86", dbName: "dbH",
dbOptions: { version: 1, storage: "default" } },
// This one lives in storage/default/http+++localhost+87
{ url: "http://localhost:87", dbName: "dbI",
dbOptions: { version: 1, storage: "default" } },
// This one lives in storage/default/http+++localhost+88
{ url: "http://localhost:88", dbName: "dbJ",
dbOptions: { version: 1, storage: "default" } },
// This one lives in storage/default/http+++localhost+89
{ url: "http://localhost:89", dbName: "dbK",
dbOptions: { version: 1, storage: "default" } },
// This one lives in storage/default/http+++localhost+90
{ url: "http://localhost:90", dbName: "dbL",
dbOptions: { version: 1, storage: "default" } }
];
let ios = SpecialPowers.Cc["@mozilla.org/network/io-service;1"]
.getService(SpecialPowers.Ci.nsIIOService);
let ssm = SpecialPowers.Cc["@mozilla.org/scriptsecuritymanager;1"]
.getService(SpecialPowers.Ci.nsIScriptSecurityManager);
function openDatabase(params) {
let request;
if ("url" in params) {
let uri = ios.newURI(params.url, null, null);
let principal = ssm.getNoAppCodebasePrincipal(uri);
request = indexedDB.openForPrincipal(principal, params.dbName,
params.dbOptions);
} else {
request = indexedDB.open(params.dbName, params.dbOptions);
}
return request;
}
clearAllDatabases(continueToNextStepSync);
yield undefined;
installPackagedProfile("metadataRestore_profile");
for (let params of openParams) {
let request = openDatabase(params);
request.onerror = errorHandler;
request.onupgradeneeded = unexpectedSuccessHandler;
request.onsuccess = grabEventAndContinueHandler;
let event = yield undefined;
is(event.type, "success", "Correct event type");
}
resetAllDatabases(continueToNextStepSync);
yield undefined;
for (let params of openParams) {
let request = openDatabase(params);
request.onerror = errorHandler;
request.onupgradeneeded = unexpectedSuccessHandler;
request.onsuccess = grabEventAndContinueHandler;
let event = yield undefined;
is(event.type, "success", "Correct event type");
}
finishTest();
yield undefined;
}
@@ -15,6 +15,7 @@ support-files =
GlobalObjectsComponent.manifest
GlobalObjectsModule.jsm
GlobalObjectsSandbox.js
metadataRestore_profile.zip
schema18upgrade_profile.zip
xpcshell-shared.ini
@@ -25,10 +26,12 @@ support-files =
[test_defaultStorageUpgrade.js]
[test_globalObjects_ipc.js]
skip-if = toolkit == 'android'
[test_idle_maintenance.js]
[test_invalidate.js]
# disabled for the moment.
skip-if = true
[test_lowDiskSpace.js]
[test_metadataRestore.js]
[test_readwriteflush_disabled.js]
[test_schema18upgrade.js]
[test_temporary_storage.js]
+13 -1
View File
@@ -49,7 +49,7 @@ interface nsIJSRAIIHelper;
interface nsIContentPermissionRequest;
interface nsIObserver;
[scriptable, uuid(ec176f3b-2886-4090-938e-dded103c5f1c)]
[scriptable, uuid(e7b44320-8255-4ad1-bbe9-d78a8a1867c9)]
interface nsIDOMWindowUtils : nsISupports {
/**
@@ -1438,6 +1438,16 @@ interface nsIDOMWindowUtils : nsISupports {
*/
void setAsyncZoom(in nsIDOMNode aRootElement, in float aValue);
/**
* Do a round-trip to the compositor to ensure any pending APZ repaint requests
* get flushed to the main thread. If the function returns true, the flush was
* triggered and an "apz-repaints-flushed" notification will be dispatched via
* the observer service once the flush is complete. If the function returns
* false, an error occurred or a flush is not needed, and the notification
* will not fire. This is intended to be used by test code only!
*/
bool flushApzRepaints();
/**
* Method for testing StyleAnimationValue::ComputeDistance.
*
@@ -1528,6 +1538,8 @@ interface nsIDOMWindowUtils : nsISupports {
[optional] out long aDBRefCnt,
[optional] out long aSliceRefCnt);
void flushPendingFileDeletions();
/**
* Return whether incremental GC has been disabled due to a binary add-on.
*/
+2 -2
View File
@@ -3284,7 +3284,7 @@ BlobChild::AssertIsOnOwningThread() const
void
BlobChild::Startup(const FriendKey& /* aKey */)
{
MOZ_ASSERT(XRE_GetProcessType() != GeckoProcessType_Default);
MOZ_ASSERT(!XRE_IsParentProcess());
CommonStartup();
}
@@ -3812,7 +3812,7 @@ BlobParent::AssertIsOnOwningThread() const
void
BlobParent::Startup(const FriendKey& /* aKey */)
{
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
MOZ_ASSERT(XRE_IsParentProcess());
CommonStartup();
+1 -1
View File
@@ -2808,7 +2808,7 @@ uint64_t
NextWindowID()
{
uint64_t processID = 0;
if (XRE_GetProcessType() == GeckoProcessType_Content) {
if (XRE_IsContentProcess()) {
ContentChild* cc = ContentChild::GetSingleton();
processID = cc->GetID();
}
+28 -8
View File
@@ -762,7 +762,7 @@ ContentParent::StartUp()
// child process
sCanLaunchSubprocesses = true;
if (XRE_GetProcessType() != GeckoProcessType_Default) {
if (!XRE_IsParentProcess()) {
return;
}
@@ -1132,7 +1132,7 @@ ContentParent::CreateBrowserOrApp(const TabContext& aContext,
}
ProcessPriority initialPriority = GetInitialProcessPriority(aFrameElement);
bool isInContentProcess = (XRE_GetProcessType() != GeckoProcessType_Default);
bool isInContentProcess = !XRE_IsParentProcess();
TabId tabId;
nsIDocShell* docShell = GetOpenerDocShellHelper(aFrameElement);
@@ -1692,7 +1692,7 @@ ContentParent::ShutDownProcess(ShutDownMethod aMethod)
using mozilla::dom::quota::QuotaManager;
if (QuotaManager* quotaManager = QuotaManager::Get()) {
quotaManager->AbortCloseStoragesForProcess(this);
quotaManager->AbortOperationsForProcess(mChildID);
}
// If Close() fails with an error, we'll end up back in this function, but
@@ -1810,7 +1810,7 @@ ContentParent::OnChannelError()
void
ContentParent::OnBeginSyncTransaction() {
if (XRE_GetProcessType() == GeckoProcessType_Default) {
if (XRE_IsParentProcess()) {
nsCOMPtr<nsIConsoleService> console(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
JSContext *cx = nsContentUtils::GetCurrentJSContext();
if (!sDisableUnsafeCPOWWarnings) {
@@ -4798,6 +4798,26 @@ ContentParent::RecvGetFileReferences(const PersistenceType& aPersistenceType,
return true;
}
bool
ContentParent::RecvFlushPendingFileDeletions()
{
nsRefPtr<IndexedDatabaseManager> mgr = IndexedDatabaseManager::Get();
if (NS_WARN_IF(!mgr)) {
return false;
}
if (NS_WARN_IF(!mgr->IsMainProcess())) {
return false;
}
nsresult rv = mgr->FlushPendingFileDeletions();
if (NS_WARN_IF(NS_FAILED(rv))) {
return false;
}
return true;
}
bool
ContentParent::IgnoreIPCPrincipal()
{
@@ -4834,7 +4854,7 @@ ContentParent::AllocateTabId(const TabId& aOpenerTabId,
const ContentParentId& aCpId)
{
TabId tabId;
if (XRE_GetProcessType() == GeckoProcessType_Default) {
if (XRE_IsParentProcess()) {
ContentProcessManager *cpm = ContentProcessManager::GetSingleton();
tabId = cpm->AllocateTabId(aOpenerTabId, aContext, aCpId);
}
@@ -4851,7 +4871,7 @@ ContentParent::AllocateTabId(const TabId& aOpenerTabId,
ContentParent::DeallocateTabId(const TabId& aTabId,
const ContentParentId& aCpId)
{
if (XRE_GetProcessType() == GeckoProcessType_Default) {
if (XRE_IsParentProcess()) {
ContentProcessManager::GetSingleton()->DeallocateTabId(aCpId,
aTabId);
}
@@ -5050,7 +5070,7 @@ ContentParent::DeallocPContentPermissionRequestParent(PContentPermissionRequestP
bool
ContentParent::RecvGetBrowserConfiguration(const nsCString& aURI, BrowserConfiguration* aConfig)
{
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
MOZ_ASSERT(XRE_IsParentProcess());
return GetBrowserConfiguration(aURI, *aConfig);;
}
@@ -5058,7 +5078,7 @@ ContentParent::RecvGetBrowserConfiguration(const nsCString& aURI, BrowserConfigu
/*static*/ bool
ContentParent::GetBrowserConfiguration(const nsCString& aURI, BrowserConfiguration& aConfig)
{
if (XRE_GetProcessType() == GeckoProcessType_Default) {
if (XRE_IsParentProcess()) {
nsRefPtr<ServiceWorkerRegistrar> swr = ServiceWorkerRegistrar::Get();
MOZ_ASSERT(swr);
+3
View File
@@ -841,6 +841,9 @@ private:
int32_t* aSliceRefCnt,
bool* aResult) override;
virtual bool
RecvFlushPendingFileDeletions() override;
virtual PWebrtcGlobalParent* AllocPWebrtcGlobalParent() override;
virtual bool DeallocPWebrtcGlobalParent(PWebrtcGlobalParent *aActor) override;
+1 -1
View File
@@ -32,7 +32,7 @@ ContentProcessManager::sSingleton;
/* static */ ContentProcessManager*
ContentProcessManager::GetSingleton()
{
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
MOZ_ASSERT(XRE_IsParentProcess());
if (!sSingleton) {
sSingleton = new ContentProcessManager();
+1
View File
@@ -593,6 +593,7 @@ child:
HandleSingleTap(CSSPoint aPoint, Modifiers aModifiers, ScrollableLayerGuid aGuid);
HandleLongTap(CSSPoint point, Modifiers aModifiers, ScrollableLayerGuid aGuid, uint64_t aInputBlockId);
NotifyAPZStateChange(ViewID aViewId, APZStateChange aChange, int aArg);
NotifyFlushComplete();
/**

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