mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-05-26 14:30:27 +00:00
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:
@@ -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();
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 =
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -377,10 +377,4 @@ DispatchStatusChangedEvent(const nsAString& aType,
|
||||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
IsMainProcess()
|
||||
{
|
||||
return XRE_GetProcessType() == GeckoProcessType_Default;
|
||||
}
|
||||
|
||||
END_BLUETOOTH_NAMESPACE
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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();
|
||||
|
||||
Vendored
+88
-113
@@ -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) {
|
||||
|
||||
Vendored
+13
-5
@@ -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:
|
||||
|
||||
Vendored
+56
@@ -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,
|
||||
|
||||
Vendored
+7
@@ -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,
|
||||
|
||||
Vendored
+130
-8
@@ -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
|
||||
|
||||
Vendored
+6
@@ -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
|
||||
|
||||
Vendored
+145
-28
@@ -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)
|
||||
{
|
||||
|
||||
Vendored
+5
-1
@@ -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;
|
||||
|
||||
Vendored
+6
-13
@@ -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);
|
||||
}
|
||||
|
||||
Vendored
+4
-24
@@ -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)
|
||||
|
||||
Vendored
-135
@@ -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
|
||||
Vendored
-48
@@ -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
|
||||
Vendored
+20
-50
@@ -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
|
||||
|
||||
Vendored
-1
@@ -33,7 +33,6 @@ struct QuotaInfo
|
||||
nsCOMPtr<nsIFile> mDir;
|
||||
nsCString mGroup;
|
||||
nsCString mOrigin;
|
||||
nsCString mStorageId;
|
||||
bool mIsApp;
|
||||
};
|
||||
|
||||
|
||||
Vendored
-2
@@ -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
@@ -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]
|
||||
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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!");
|
||||
|
||||
|
||||
@@ -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 =
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -65,12 +65,5 @@ FileSystemUtils::IsDescendantPath(const nsAString& aPath,
|
||||
return true;
|
||||
}
|
||||
|
||||
// static
|
||||
bool
|
||||
FileSystemUtils::IsParentProcess()
|
||||
{
|
||||
return XRE_GetProcessType() == GeckoProcessType_Default;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
@@ -41,9 +41,6 @@ public:
|
||||
static bool
|
||||
IsDescendantPath(const nsAString& aPath, const nsAString& aDescendantPath);
|
||||
|
||||
static bool
|
||||
IsParentProcess();
|
||||
|
||||
static const char16_t kSeparatorChar = char16_t('/');
|
||||
};
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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!");
|
||||
|
||||
|
||||
@@ -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!");
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
+2449
-690
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
{
|
||||
|
||||
@@ -83,7 +83,7 @@ BlobImplSnapshot::~BlobImplSnapshot()
|
||||
void
|
||||
BlobImplSnapshot::AssertSanity()
|
||||
{
|
||||
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 +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
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
|
||||
@@ -96,4 +96,5 @@ LOCAL_INCLUDES += [
|
||||
'/dom/workers',
|
||||
'/ipc/glue',
|
||||
'/xpcom/build',
|
||||
'/xpcom/threads',
|
||||
]
|
||||
|
||||
@@ -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.
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]
|
||||
|
||||
@@ -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
@@ -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();
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user