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 1173051 - Minor optimizations for device storage enumerate on parent and child. r=dhylands (31037e471a) - Bug 1020179 followup: Mark DeviceStorageRequest::GetRequester as override (and use NS_IMETHOD instead of NS_IMETHODIMP inside of class definition). rs=ehsan (b2a0808c21) - Bug 1171170 - Consolidate/cache access to permissions, cycle collected objects in device storage. r=dhylands (8eddc30aed) - Bug 1204618 - Add a field to the DeviceStorage object holding the low-disk-space status. r=dhylands, r=bzbarsky (52257b821f) - Bug 1128505 - Preload Webapps.js for faster mozApps instantiation. r=fabrice (d540be89af) - Bug 1166207 - Load preload.js in the Nuwa process. r=khuey (1310da32df) - MOZ_FINAL -> final (887f351669) - Bug 1200922: Add the ability to shut down a thread asynchronously. r=froydnj (b09ea156b6) - Bug 1195767 - part 1 - remove nsCOMPtr temporary from nsEventQueue::PtEvent; r=gerald (fed354ffb7) - Bug 1195767 - part 2 - create an nsEventQueueBase templated over the monitor type; r=gerald (ede20ac6f4) - Bug 1202497 - part 1 - switch nsEventQueue to use a non-reentrant Monitor; r=gerald (cd043d1267) - Bug 1195767 - part 3 - modify nsThreadPool to use a non-reentrant monitor; r=gerald (52eec3d125) - Bug 1202497 - part 2 - remove ReentrantMonitor specializations for nsEventQueueBase; r=gerald (ceb1a9e63e) - Bug 1202497 - part 3 - remove nsThread::GetEvent; r=gerald (ef9a5924fe) - Bug 1202828 - use nsEventQueue::HasPendingEvent in nsThread.cpp; r=mccr8 nsEventQueue's HasPending event is defined to simply: (2e7a6ebcd2) - Bug 1202497 - part 4 - lock around call to nsChainedEventQueue::HasPendingEvent; r=gerald (bc69bb30db) - Bug 1202497 - part 5 - make the locking requirements of nsChainedEventQueue explicit; r=gerald (fbd73f2b0c) - Bug 1195767 - part 4 - remove nsEventQueue::GetReentrantMonitor; r=gerald (1dfa6b186a) - Bug 1195767 - part 5 - use signaling instead of broadcast when work items are placed in nsEventQueue; r=gerald (1f01f6198a) - Bug 1202497 - part 6 - make the locking requirements of nsEventQueue explicit; r=gerald (7aaf4eb9cd) - Bug 1202497 - part 7 - make nsEventQueue use external locking; r=gerald (2b31ff22f0) - Bug 1202497 - follow-up - fix static analysis bustage; r=me (b7997e75f5) - Bug 1197672 - s/_sendPromise/createPromiseWithId/ in mozInputMethod.addInput(). r=kchen (fb8e91e67e) - Bug 1132349 - Test for focus removal after pagehide/submit/beforeload. r=janjongboom (a9adc87bb5) - Bug 1137557 - Part 3: Allow content to pass a dict representing the property of the keyboard event to send. r=masayuki, sr=smaug (4e27b2bfc9) - Bug 895274 part.18 Rename NS_PLUGIN_ACTIVATE to ePluginActivate r=smaug (6ad79fee12) - Bug 1167069 - Watch out for deletion of current frame. r=jmathies (2868b2689d) - Bug 895274 part.19 Rename NS_PLUGIN_FOCUS to ePluginFocus r=smaug (792d1d41d8) - Bug 895274 part.20 Rename NS_OFFLINE to eOffline r=smaug (6eab162432) - Bug 895274 part.21 Rename NS_ONLINE to eOnline r=smaug (91fb9aea87) - Bug 895274 part.22 Get rid of NS_MOZ_USER_* since nobody is using them r=smaug (a46848bfc5) - Bug 895274 part.23 Rename NS_LANGUAGECHANGE to eLanguageChange r=smaug (11ee7a6511) - Bug 895274 part.24 Rename NS_MOUSE_MESSAGE_START to eMouseEventFirst r=smaug (52168d3374)
This commit is contained in:
@@ -1622,5 +1622,13 @@ BrowserElementChild.prototype = {
|
||||
}
|
||||
};
|
||||
|
||||
var api = new BrowserElementChild();
|
||||
|
||||
var api = null;
|
||||
if ('DoPreloadPostfork' in this && typeof this.DoPreloadPostfork === 'function') {
|
||||
// If we are preloaded, instantiate BrowserElementChild after a content
|
||||
// process is forked.
|
||||
this.DoPreloadPostfork(function() {
|
||||
api = new BrowserElementChild();
|
||||
});
|
||||
} else {
|
||||
api = new BrowserElementChild();
|
||||
}
|
||||
|
||||
@@ -41,9 +41,15 @@ class DeviceStorageFileSystem;
|
||||
} // namespace dom
|
||||
namespace ipc {
|
||||
class FileDescriptor;
|
||||
class PrincipalInfo;
|
||||
} // namespace ipc
|
||||
} // namespace mozilla
|
||||
|
||||
class DeviceStorageRequest;
|
||||
class DeviceStorageCursorRequest;
|
||||
class DeviceStorageRequestManager;
|
||||
class nsDOMDeviceStorageCursor;
|
||||
|
||||
class DeviceStorageFile final
|
||||
: public nsISupports {
|
||||
public:
|
||||
@@ -197,10 +203,6 @@ public:
|
||||
AppendNamed(mozilla::dom::Blob* aBlob, const nsAString& aPath,
|
||||
ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<DOMRequest>
|
||||
AddOrAppendNamed(mozilla::dom::Blob* aBlob, const nsAString& aPath,
|
||||
const int32_t aRequestType, ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<DOMRequest>
|
||||
Get(const nsAString& aPath, ErrorResult& aRv)
|
||||
{
|
||||
@@ -247,6 +249,7 @@ public:
|
||||
bool CanBeFormatted();
|
||||
bool CanBeShared();
|
||||
bool IsRemovable();
|
||||
bool LowDiskSpace();
|
||||
bool Default();
|
||||
void GetStorageName(nsAString& aStorageName);
|
||||
|
||||
@@ -290,16 +293,32 @@ public:
|
||||
void OnVolumeStateChanged(nsIVolume* aVolume);
|
||||
#endif
|
||||
|
||||
uint32_t CreateDOMRequest(DOMRequest** aRequest, ErrorResult& aRv);
|
||||
uint32_t CreateDOMCursor(DeviceStorageCursorRequest* aRequest,
|
||||
nsDOMDeviceStorageCursor** aCursor,
|
||||
ErrorResult& aRv);
|
||||
already_AddRefed<DOMRequest> CreateAndRejectDOMRequest(const char *aReason,
|
||||
ErrorResult& aRv);
|
||||
|
||||
nsresult CheckPermission(DeviceStorageRequest* aRequest);
|
||||
void StorePermission(DeviceStorageRequest* aRequest, bool aAllow);
|
||||
|
||||
bool IsOwningThread();
|
||||
nsresult DispatchToOwningThread(nsIRunnable* aRunnable);
|
||||
|
||||
private:
|
||||
~nsDOMDeviceStorage();
|
||||
|
||||
static nsresult CheckPrincipal(nsPIDOMWindow* aWindow, bool aIsAppsStorage,
|
||||
nsIPrincipal** aPrincipal);
|
||||
|
||||
already_AddRefed<DOMRequest>
|
||||
AddOrAppendNamed(mozilla::dom::Blob* aBlob, const nsAString& aPath,
|
||||
bool aCreate, ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<DOMRequest>
|
||||
GetInternal(const nsAString& aPath, bool aEditable, ErrorResult& aRv);
|
||||
|
||||
void
|
||||
GetInternal(nsPIDOMWindow* aWin, const nsAString& aPath, DOMRequest* aRequest,
|
||||
bool aEditable);
|
||||
|
||||
void
|
||||
DeleteInternal(nsPIDOMWindow* aWin, const nsAString& aPath,
|
||||
DOMRequest* aRequest);
|
||||
@@ -327,10 +346,6 @@ private:
|
||||
const nsAString& aStorageName,
|
||||
const nsAString& aType);
|
||||
|
||||
nsCOMPtr<nsIPrincipal> mPrincipal;
|
||||
|
||||
bool mIsWatchingFile;
|
||||
bool mAllowedToWatchFile;
|
||||
bool mIsDefaultLocation;
|
||||
|
||||
nsresult Notify(const char* aReason, class DeviceStorageFile* aFile);
|
||||
@@ -347,7 +362,11 @@ private:
|
||||
void DispatchStorageStatusChangeEvent(nsAString& aStorageStatus);
|
||||
#endif
|
||||
|
||||
uint64_t mInnerWindowID;
|
||||
nsRefPtr<DeviceStorageFileSystem> mFileSystem;
|
||||
nsRefPtr<DeviceStorageRequestManager> mManager;
|
||||
nsAutoPtr<mozilla::ipc::PrincipalInfo> mPrincipalInfo;
|
||||
nsCOMPtr<nsIThread> mOwningThread;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsDOMDeviceStorage, NS_DOM_DEVICE_STORAGE_CID)
|
||||
|
||||
@@ -16,33 +16,14 @@ namespace dom {
|
||||
namespace devicestorage {
|
||||
|
||||
DeviceStorageRequestChild::DeviceStorageRequestChild()
|
||||
: mCallback(nullptr)
|
||||
{
|
||||
MOZ_COUNT_CTOR(DeviceStorageRequestChild);
|
||||
}
|
||||
|
||||
DeviceStorageRequestChild::DeviceStorageRequestChild(DOMRequest* aRequest,
|
||||
DeviceStorageFile* aDSFile)
|
||||
DeviceStorageRequestChild::DeviceStorageRequestChild(DeviceStorageRequest* aRequest)
|
||||
: mRequest(aRequest)
|
||||
, mDSFile(aDSFile)
|
||||
, mCallback(nullptr)
|
||||
{
|
||||
MOZ_ASSERT(aRequest);
|
||||
MOZ_ASSERT(aDSFile);
|
||||
MOZ_COUNT_CTOR(DeviceStorageRequestChild);
|
||||
}
|
||||
|
||||
DeviceStorageRequestChild::DeviceStorageRequestChild(DOMRequest* aRequest,
|
||||
DeviceStorageFile* aDSFile,
|
||||
DeviceStorageFileDescriptor* aDSFileDescriptor)
|
||||
: mRequest(aRequest)
|
||||
, mDSFile(aDSFile)
|
||||
, mDSFileDescriptor(aDSFileDescriptor)
|
||||
, mCallback(nullptr)
|
||||
{
|
||||
MOZ_ASSERT(aRequest);
|
||||
MOZ_ASSERT(aDSFile);
|
||||
MOZ_ASSERT(aDSFileDescriptor);
|
||||
MOZ_COUNT_CTOR(DeviceStorageRequestChild);
|
||||
}
|
||||
|
||||
@@ -54,159 +35,126 @@ bool
|
||||
DeviceStorageRequestChild::
|
||||
Recv__delete__(const DeviceStorageResponseValue& aValue)
|
||||
{
|
||||
if (mCallback) {
|
||||
mCallback->RequestComplete();
|
||||
mCallback = nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> window = mRequest->GetOwner();
|
||||
if (!window) {
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (aValue.type()) {
|
||||
|
||||
case DeviceStorageResponseValue::TErrorResponse:
|
||||
{
|
||||
DS_LOG_INFO("error %u", mRequest->GetId());
|
||||
ErrorResponse r = aValue;
|
||||
mRequest->FireError(r.error());
|
||||
mRequest->Reject(r.error());
|
||||
break;
|
||||
}
|
||||
|
||||
case DeviceStorageResponseValue::TSuccessResponse:
|
||||
{
|
||||
DS_LOG_INFO("success %u", mRequest->GetId());
|
||||
nsString fullPath;
|
||||
mDSFile->GetFullPath(fullPath);
|
||||
AutoJSContext cx;
|
||||
JS::Rooted<JS::Value> result(cx);
|
||||
StringToJsval(window, fullPath, &result);
|
||||
mRequest->FireSuccess(result);
|
||||
mRequest->GetFile()->GetFullPath(fullPath);
|
||||
mRequest->Resolve(fullPath);
|
||||
break;
|
||||
}
|
||||
|
||||
case DeviceStorageResponseValue::TFileDescriptorResponse:
|
||||
{
|
||||
DS_LOG_INFO("fd %u", mRequest->GetId());
|
||||
FileDescriptorResponse r = aValue;
|
||||
|
||||
DeviceStorageFile* file = mRequest->GetFile();
|
||||
DeviceStorageFileDescriptor* descriptor = mRequest->GetFileDescriptor();
|
||||
nsString fullPath;
|
||||
mDSFile->GetFullPath(fullPath);
|
||||
AutoJSContext cx;
|
||||
JS::Rooted<JS::Value> result(cx);
|
||||
StringToJsval(window, fullPath, &result);
|
||||
|
||||
mDSFileDescriptor->mDSFile = mDSFile;
|
||||
mDSFileDescriptor->mFileDescriptor = r.fileDescriptor();
|
||||
mRequest->FireSuccess(result);
|
||||
file->GetFullPath(fullPath);
|
||||
descriptor->mDSFile = file;
|
||||
descriptor->mFileDescriptor = r.fileDescriptor();
|
||||
mRequest->Resolve(fullPath);
|
||||
break;
|
||||
}
|
||||
|
||||
case DeviceStorageResponseValue::TBlobResponse:
|
||||
{
|
||||
DS_LOG_INFO("blob %u", mRequest->GetId());
|
||||
BlobResponse r = aValue;
|
||||
BlobChild* actor = static_cast<BlobChild*>(r.blobChild());
|
||||
nsRefPtr<BlobImpl> bloblImpl = actor->GetBlobImpl();
|
||||
nsRefPtr<Blob> blob = Blob::Create(mRequest->GetParentObject(),
|
||||
bloblImpl);
|
||||
|
||||
AutoJSContext cx;
|
||||
|
||||
JS::Rooted<JSObject*> obj(cx, blob->WrapObject(cx, nullptr));
|
||||
MOZ_ASSERT(obj);
|
||||
|
||||
JS::Rooted<JS::Value> result(cx, JS::ObjectValue(*obj));
|
||||
mRequest->FireSuccess(result);
|
||||
nsRefPtr<BlobImpl> blobImpl = actor->GetBlobImpl();
|
||||
mRequest->Resolve(blobImpl.get());
|
||||
break;
|
||||
}
|
||||
|
||||
case DeviceStorageResponseValue::TFreeSpaceStorageResponse:
|
||||
{
|
||||
DS_LOG_INFO("free %u", mRequest->GetId());
|
||||
FreeSpaceStorageResponse r = aValue;
|
||||
AutoJSContext cx;
|
||||
JS::Rooted<JS::Value> result(cx, JS_NumberValue(double(r.freeBytes())));
|
||||
mRequest->FireSuccess(result);
|
||||
mRequest->Resolve(r.freeBytes());
|
||||
break;
|
||||
}
|
||||
|
||||
case DeviceStorageResponseValue::TUsedSpaceStorageResponse:
|
||||
{
|
||||
DS_LOG_INFO("used %u", mRequest->GetId());
|
||||
UsedSpaceStorageResponse r = aValue;
|
||||
AutoJSContext cx;
|
||||
JS::Rooted<JS::Value> result(cx, JS_NumberValue(double(r.usedBytes())));
|
||||
mRequest->FireSuccess(result);
|
||||
mRequest->Resolve(r.usedBytes());
|
||||
break;
|
||||
}
|
||||
|
||||
case DeviceStorageResponseValue::TAvailableStorageResponse:
|
||||
{
|
||||
DS_LOG_INFO("available %u", mRequest->GetId());
|
||||
AvailableStorageResponse r = aValue;
|
||||
AutoJSContext cx;
|
||||
JS::Rooted<JS::Value> result(cx);
|
||||
StringToJsval(window, r.mountState(), &result);
|
||||
mRequest->FireSuccess(result);
|
||||
mRequest->Resolve(r.mountState());
|
||||
break;
|
||||
}
|
||||
|
||||
case DeviceStorageResponseValue::TStorageStatusResponse:
|
||||
{
|
||||
DS_LOG_INFO("status %u", mRequest->GetId());
|
||||
StorageStatusResponse r = aValue;
|
||||
AutoJSContext cx;
|
||||
JS::Rooted<JS::Value> result(cx);
|
||||
StringToJsval(window, r.storageStatus(), &result);
|
||||
mRequest->FireSuccess(result);
|
||||
mRequest->Resolve(r.storageStatus());
|
||||
break;
|
||||
}
|
||||
|
||||
case DeviceStorageResponseValue::TFormatStorageResponse:
|
||||
{
|
||||
DS_LOG_INFO("format %u", mRequest->GetId());
|
||||
FormatStorageResponse r = aValue;
|
||||
AutoJSContext cx;
|
||||
JS::Rooted<JS::Value> result(cx);
|
||||
StringToJsval(window, r.mountState(), &result);
|
||||
mRequest->FireSuccess(result);
|
||||
mRequest->Resolve(r.mountState());
|
||||
break;
|
||||
}
|
||||
|
||||
case DeviceStorageResponseValue::TMountStorageResponse:
|
||||
{
|
||||
DS_LOG_INFO("mount %u", mRequest->GetId());
|
||||
MountStorageResponse r = aValue;
|
||||
AutoJSContext cx;
|
||||
JS::Rooted<JS::Value> result(cx);
|
||||
StringToJsval(window, r.storageStatus(), &result);
|
||||
mRequest->FireSuccess(result);
|
||||
mRequest->Resolve(r.storageStatus());
|
||||
break;
|
||||
}
|
||||
|
||||
case DeviceStorageResponseValue::TUnmountStorageResponse:
|
||||
{
|
||||
DS_LOG_INFO("unmount %u", mRequest->GetId());
|
||||
UnmountStorageResponse r = aValue;
|
||||
AutoJSContext cx;
|
||||
JS::Rooted<JS::Value> result(cx);
|
||||
StringToJsval(window, r.storageStatus(), &result);
|
||||
mRequest->FireSuccess(result);
|
||||
mRequest->Resolve(r.storageStatus());
|
||||
break;
|
||||
}
|
||||
|
||||
case DeviceStorageResponseValue::TEnumerationResponse:
|
||||
{
|
||||
DS_LOG_INFO("enumerate %u", mRequest->GetId());
|
||||
EnumerationResponse r = aValue;
|
||||
nsDOMDeviceStorageCursor* cursor
|
||||
= static_cast<nsDOMDeviceStorageCursor*>(mRequest.get());
|
||||
|
||||
auto request = static_cast<DeviceStorageCursorRequest*>(mRequest.get());
|
||||
uint32_t count = r.paths().Length();
|
||||
request->AddFiles(count);
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
nsRefPtr<DeviceStorageFile> dsf
|
||||
= new DeviceStorageFile(r.type(), r.paths()[i].storageName(),
|
||||
r.rootdir(), r.paths()[i].name());
|
||||
cursor->mFiles.AppendElement(dsf);
|
||||
request->AddFile(dsf.forget());
|
||||
}
|
||||
|
||||
nsRefPtr<ContinueCursorEvent> event = new ContinueCursorEvent(cursor);
|
||||
event->Continue();
|
||||
request->Continue();
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
DS_LOG_ERROR("unknown %u", mRequest->GetId());
|
||||
NS_RUNTIMEABORT("not reached");
|
||||
break;
|
||||
}
|
||||
@@ -214,13 +162,6 @@ DeviceStorageRequestChild::
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
DeviceStorageRequestChild::
|
||||
SetCallback(DeviceStorageRequestChildCallback *aCallback)
|
||||
{
|
||||
mCallback = aCallback;
|
||||
}
|
||||
|
||||
} // namespace devicestorage
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
@@ -10,13 +10,12 @@
|
||||
#include "mozilla/dom/devicestorage/PDeviceStorageRequestChild.h"
|
||||
|
||||
class DeviceStorageFile;
|
||||
class DeviceStorageRequest;
|
||||
struct DeviceStorageFileDescriptor;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class DOMRequest;
|
||||
|
||||
namespace devicestorage {
|
||||
|
||||
class DeviceStorageRequestChildCallback
|
||||
@@ -29,21 +28,13 @@ class DeviceStorageRequestChild : public PDeviceStorageRequestChild
|
||||
{
|
||||
public:
|
||||
DeviceStorageRequestChild();
|
||||
DeviceStorageRequestChild(DOMRequest* aRequest, DeviceStorageFile* aFile);
|
||||
DeviceStorageRequestChild(DOMRequest* aRequest, DeviceStorageFile* aFile,
|
||||
DeviceStorageFileDescriptor* aFileDescrptor);
|
||||
explicit DeviceStorageRequestChild(DeviceStorageRequest* aRequest);
|
||||
~DeviceStorageRequestChild();
|
||||
|
||||
void SetCallback(class DeviceStorageRequestChildCallback *aCallback);
|
||||
|
||||
virtual bool Recv__delete__(const DeviceStorageResponseValue& value);
|
||||
|
||||
private:
|
||||
nsRefPtr<DOMRequest> mRequest;
|
||||
nsRefPtr<DeviceStorageFile> mDSFile;
|
||||
nsRefPtr<DeviceStorageFileDescriptor> mDSFileDescriptor;
|
||||
|
||||
DeviceStorageRequestChildCallback* mCallback;
|
||||
nsRefPtr<DeviceStorageRequest> mRequest;
|
||||
};
|
||||
|
||||
} // namespace devicestorage
|
||||
|
||||
@@ -72,6 +72,7 @@ DeviceStorageStatics::InitializeDirs()
|
||||
DeviceStorageStatics::DeviceStorageStatics()
|
||||
: mInitialized(false)
|
||||
, mPromptTesting(false)
|
||||
, mLowDiskSpace(false)
|
||||
{
|
||||
DS_LOG_INFO("");
|
||||
}
|
||||
@@ -358,6 +359,16 @@ DeviceStorageStatics::IsPromptTesting()
|
||||
return sInstance->mPromptTesting;
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
DeviceStorageStatics::LowDiskSpace()
|
||||
{
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
if (NS_WARN_IF(!sInstance)) {
|
||||
return false;
|
||||
}
|
||||
return sInstance->mLowDiskSpace;
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
DeviceStorageStatics::GetWritableName(nsString& aName)
|
||||
{
|
||||
@@ -605,27 +616,29 @@ DeviceStorageStatics::Observe(nsISupports* aSubject,
|
||||
}
|
||||
|
||||
if (!strcmp(aTopic, kDiskSpaceWatcher)) {
|
||||
// 'disk-space-watcher' notifications are sent when there is a modification
|
||||
// of a file in a specific location while a low device storage situation
|
||||
// exists or after recovery of a low storage situation. For Firefox OS,
|
||||
// these notifications are specific for apps storage.
|
||||
bool lowDiskSpace = false;
|
||||
if (!NS_strcmp(aData, MOZ_UTF16("full"))) {
|
||||
lowDiskSpace = true;
|
||||
} else if (NS_strcmp(aData, MOZ_UTF16("free"))) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
if (NS_WARN_IF(!sInstance)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// 'disk-space-watcher' notifications are sent when there is a modification
|
||||
// of a file in a specific location while a low device storage situation
|
||||
// exists or after recovery of a low storage situation. For Firefox OS,
|
||||
// these notifications are specific for apps storage.
|
||||
if (!NS_strcmp(aData, MOZ_UTF16("full"))) {
|
||||
sInstance->mLowDiskSpace = true;
|
||||
} else if (!NS_strcmp(aData, MOZ_UTF16("free"))) {
|
||||
sInstance->mLowDiskSpace = false;
|
||||
} else {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
uint32_t i = mListeners.Length();
|
||||
DS_LOG_INFO("disk space %d (%u)", lowDiskSpace, i);
|
||||
DS_LOG_INFO("disk space %d (%u)", sInstance->mLowDiskSpace, i);
|
||||
while (i > 0) {
|
||||
--i;
|
||||
mListeners[i]->OnDiskSpaceWatcher(lowDiskSpace);
|
||||
mListeners[i]->OnDiskSpaceWatcher(sInstance->mLowDiskSpace);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ public:
|
||||
static void AddListener(nsDOMDeviceStorage* aListener);
|
||||
static void RemoveListener(nsDOMDeviceStorage* aListener);
|
||||
|
||||
static bool LowDiskSpace();
|
||||
static bool IsPromptTesting();
|
||||
static void GetWritableName(nsString& aName);
|
||||
static void SetWritableName(const nsAString& aName);
|
||||
@@ -92,6 +93,7 @@ private:
|
||||
|
||||
bool mInitialized;
|
||||
bool mPromptTesting;
|
||||
bool mLowDiskSpace;
|
||||
nsString mWritableName;
|
||||
|
||||
static StaticRefPtr<DeviceStorageStatics> sInstance;
|
||||
|
||||
+1664
-1601
File diff suppressed because it is too large
Load Diff
@@ -8,6 +8,7 @@
|
||||
#define nsDeviceStorage_h
|
||||
|
||||
class nsPIDOMWindow;
|
||||
#include "mozilla/Atomics.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/Logging.h"
|
||||
#include "mozilla/dom/devicestorage/DeviceStorageRequestChild.h"
|
||||
@@ -18,7 +19,6 @@ class nsPIDOMWindow;
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsDOMClassInfoID.h"
|
||||
#include "nsIClassInfo.h"
|
||||
#include "nsIContentPermissionPrompt.h"
|
||||
#include "nsIDOMWindow.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsIPrincipal.h"
|
||||
@@ -36,13 +36,18 @@ namespace mozilla {
|
||||
class ErrorResult;
|
||||
|
||||
namespace dom {
|
||||
class Blob;
|
||||
class BlobImpl;
|
||||
class DeviceStorageParams;
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
class nsDOMDeviceStorage;
|
||||
class DeviceStorageCursorRequest;
|
||||
|
||||
//#define DS_LOGGING 1
|
||||
|
||||
#ifdef DS_LOGGING
|
||||
// FIXME -- use MOZ_LOG and set to warn by default
|
||||
#define DS_LOG_DEBUG(msg, ...) printf_stderr("[%s:%d] " msg "\n", __func__, __LINE__, ##__VA_ARGS__)
|
||||
#define DS_LOG_INFO DS_LOG_DEBUG
|
||||
#define DS_LOG_WARN DS_LOG_DEBUG
|
||||
@@ -62,20 +67,29 @@ class Blob;
|
||||
#define POST_ERROR_EVENT_UNKNOWN "Unknown"
|
||||
|
||||
enum DeviceStorageRequestType {
|
||||
DEVICE_STORAGE_REQUEST_READ,
|
||||
DEVICE_STORAGE_REQUEST_WRITE,
|
||||
DEVICE_STORAGE_REQUEST_APPEND,
|
||||
DEVICE_STORAGE_REQUEST_CREATE,
|
||||
DEVICE_STORAGE_REQUEST_DELETE,
|
||||
DEVICE_STORAGE_REQUEST_WATCH,
|
||||
DEVICE_STORAGE_REQUEST_FREE_SPACE,
|
||||
DEVICE_STORAGE_REQUEST_USED_SPACE,
|
||||
DEVICE_STORAGE_REQUEST_AVAILABLE,
|
||||
DEVICE_STORAGE_REQUEST_STATUS,
|
||||
DEVICE_STORAGE_REQUEST_FORMAT,
|
||||
DEVICE_STORAGE_REQUEST_MOUNT,
|
||||
DEVICE_STORAGE_REQUEST_UNMOUNT,
|
||||
DEVICE_STORAGE_REQUEST_CREATEFD
|
||||
DEVICE_STORAGE_REQUEST_READ,
|
||||
DEVICE_STORAGE_REQUEST_WRITE,
|
||||
DEVICE_STORAGE_REQUEST_APPEND,
|
||||
DEVICE_STORAGE_REQUEST_CREATE,
|
||||
DEVICE_STORAGE_REQUEST_DELETE,
|
||||
DEVICE_STORAGE_REQUEST_WATCH,
|
||||
DEVICE_STORAGE_REQUEST_FREE_SPACE,
|
||||
DEVICE_STORAGE_REQUEST_USED_SPACE,
|
||||
DEVICE_STORAGE_REQUEST_AVAILABLE,
|
||||
DEVICE_STORAGE_REQUEST_STATUS,
|
||||
DEVICE_STORAGE_REQUEST_FORMAT,
|
||||
DEVICE_STORAGE_REQUEST_MOUNT,
|
||||
DEVICE_STORAGE_REQUEST_UNMOUNT,
|
||||
DEVICE_STORAGE_REQUEST_CREATEFD,
|
||||
DEVICE_STORAGE_REQUEST_CURSOR
|
||||
};
|
||||
|
||||
enum DeviceStorageAccessType {
|
||||
DEVICE_STORAGE_ACCESS_READ,
|
||||
DEVICE_STORAGE_ACCESS_WRITE,
|
||||
DEVICE_STORAGE_ACCESS_CREATE,
|
||||
DEVICE_STORAGE_ACCESS_UNDEFINED,
|
||||
DEVICE_STORAGE_ACCESS_COUNT
|
||||
};
|
||||
|
||||
class DeviceStorageUsedSpaceCache final
|
||||
@@ -176,14 +190,17 @@ public:
|
||||
|
||||
void InitFromBundle(nsIStringBundle* aBundle);
|
||||
|
||||
bool Check(const nsAString& aType, mozilla::dom::Blob* aBlob);
|
||||
bool Check(const nsAString& aType, mozilla::dom::BlobImpl* aBlob);
|
||||
bool Check(const nsAString& aType, nsIFile* aFile);
|
||||
bool Check(const nsAString& aType, const nsString& aPath);
|
||||
void GetTypeFromFile(nsIFile* aFile, nsAString& aType);
|
||||
void GetTypeFromFileName(const nsAString& aFileName, nsAString& aType);
|
||||
|
||||
static nsresult GetPermissionForType(const nsAString& aType, nsACString& aPermissionResult);
|
||||
static nsresult GetAccessForRequest(const DeviceStorageRequestType aRequestType, nsACString& aAccessResult);
|
||||
static nsresult GetPermissionForType(const nsAString& aType,
|
||||
nsACString& aPermissionResult);
|
||||
static nsresult GetAccessForRequest(const DeviceStorageRequestType aRequestType,
|
||||
nsACString& aAccessResult);
|
||||
static nsresult GetAccessForIndex(size_t aAccessIndex, nsACString& aAccessResult);
|
||||
static size_t GetAccessIndexForRequest(const DeviceStorageRequestType aRequestType);
|
||||
static bool IsVolumeBased(const nsAString& aType);
|
||||
static bool IsSharedMediaRoot(const nsAString& aType);
|
||||
|
||||
@@ -195,64 +212,224 @@ private:
|
||||
static mozilla::StaticAutoPtr<DeviceStorageTypeChecker> sDeviceStorageTypeChecker;
|
||||
};
|
||||
|
||||
class ContinueCursorEvent final : public nsRunnable
|
||||
{
|
||||
public:
|
||||
explicit ContinueCursorEvent(already_AddRefed<mozilla::dom::DOMRequest> aRequest);
|
||||
explicit ContinueCursorEvent(mozilla::dom::DOMRequest* aRequest);
|
||||
~ContinueCursorEvent();
|
||||
void Continue();
|
||||
|
||||
NS_IMETHOD Run() override;
|
||||
private:
|
||||
already_AddRefed<DeviceStorageFile> GetNextFile();
|
||||
nsRefPtr<mozilla::dom::DOMRequest> mRequest;
|
||||
};
|
||||
|
||||
class nsDOMDeviceStorageCursor final
|
||||
: public mozilla::dom::DOMCursor
|
||||
, public nsIContentPermissionRequest
|
||||
, public mozilla::dom::devicestorage::DeviceStorageRequestChildCallback
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSICONTENTPERMISSIONREQUEST
|
||||
NS_FORWARD_NSIDOMDOMCURSOR(mozilla::dom::DOMCursor::)
|
||||
|
||||
// DOMCursor
|
||||
virtual void Continue(mozilla::ErrorResult& aRv) override;
|
||||
|
||||
nsDOMDeviceStorageCursor(nsPIDOMWindow* aWindow,
|
||||
nsIPrincipal* aPrincipal,
|
||||
DeviceStorageFile* aFile,
|
||||
PRTime aSince);
|
||||
nsDOMDeviceStorageCursor(nsIGlobalObject* aGlobal,
|
||||
DeviceStorageCursorRequest* aRequest);
|
||||
|
||||
|
||||
nsTArray<nsRefPtr<DeviceStorageFile> > mFiles;
|
||||
bool mOkToCallContinue;
|
||||
PRTime mSince;
|
||||
|
||||
void GetStorageType(nsAString & aType);
|
||||
|
||||
void RequestComplete() override;
|
||||
void FireSuccess(JS::Handle<JS::Value> aResult);
|
||||
void FireError(const nsString& aReason);
|
||||
void FireDone();
|
||||
|
||||
private:
|
||||
~nsDOMDeviceStorageCursor();
|
||||
virtual ~nsDOMDeviceStorageCursor();
|
||||
|
||||
nsRefPtr<DeviceStorageFile> mFile;
|
||||
nsCOMPtr<nsIPrincipal> mPrincipal;
|
||||
nsCOMPtr<nsIContentPermissionRequester> mRequester;
|
||||
bool mOkToCallContinue;
|
||||
nsRefPtr<DeviceStorageCursorRequest> mRequest;
|
||||
};
|
||||
|
||||
//helpers
|
||||
bool
|
||||
StringToJsval(nsPIDOMWindow* aWindow, nsAString& aString,
|
||||
JS::MutableHandle<JS::Value> result);
|
||||
class DeviceStorageRequestManager final
|
||||
{
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DeviceStorageRequestManager)
|
||||
|
||||
JS::Value
|
||||
nsIFileToJsval(nsPIDOMWindow* aWindow, DeviceStorageFile* aFile);
|
||||
static const uint32_t INVALID_ID = 0;
|
||||
|
||||
JS::Value
|
||||
InterfaceToJsval(nsPIDOMWindow* aWindow, nsISupports* aObject, const nsIID* aIID);
|
||||
DeviceStorageRequestManager();
|
||||
|
||||
bool IsOwningThread();
|
||||
nsresult DispatchToOwningThread(nsIRunnable* aRunnable);
|
||||
|
||||
void StorePermission(size_t aAccess, bool aAllow);
|
||||
uint32_t CheckPermission(size_t aAccess);
|
||||
|
||||
/* These must be called on the owning thread context of the device
|
||||
storage object. It will hold onto a device storage reference until
|
||||
all of the pending requests are completed or shutdown is called. */
|
||||
uint32_t Create(nsDOMDeviceStorage* aDeviceStorage,
|
||||
mozilla::dom::DOMRequest** aRequest);
|
||||
uint32_t Create(nsDOMDeviceStorage* aDeviceStorage,
|
||||
DeviceStorageCursorRequest* aRequest,
|
||||
nsDOMDeviceStorageCursor** aCursor);
|
||||
|
||||
/* These may be called from any thread context and post a request
|
||||
to the owning thread to resolve the underlying DOMRequest or
|
||||
DOMCursor. In order to trigger FireDone for a DOMCursor, one
|
||||
should call Resolve with only the request ID. */
|
||||
nsresult Resolve(uint32_t aId, bool aForceDispatch);
|
||||
nsresult Resolve(uint32_t aId, const nsString& aValue, bool aForceDispatch);
|
||||
nsresult Resolve(uint32_t aId, uint64_t aValue, bool aForceDispatch);
|
||||
nsresult Resolve(uint32_t aId, DeviceStorageFile* aValue, bool aForceDispatch);
|
||||
nsresult Resolve(uint32_t aId, mozilla::dom::BlobImpl* aValue, bool aForceDispatch);
|
||||
nsresult Reject(uint32_t aId, const nsString& aReason);
|
||||
nsresult Reject(uint32_t aId, const char* aReason);
|
||||
|
||||
void Shutdown();
|
||||
|
||||
private:
|
||||
DeviceStorageRequestManager(const DeviceStorageRequestManager&) = delete;
|
||||
DeviceStorageRequestManager& operator=(const DeviceStorageRequestManager&) = delete;
|
||||
|
||||
struct ListEntry {
|
||||
nsRefPtr<mozilla::dom::DOMRequest> mRequest;
|
||||
uint32_t mId;
|
||||
bool mCursor;
|
||||
};
|
||||
|
||||
typedef nsTArray<ListEntry> ListType;
|
||||
typedef ListType::index_type ListIndex;
|
||||
|
||||
virtual ~DeviceStorageRequestManager();
|
||||
uint32_t CreateInternal(mozilla::dom::DOMRequest* aRequest, bool aCursor);
|
||||
nsresult ResolveInternal(ListIndex aIndex, JS::HandleValue aResult);
|
||||
nsresult RejectInternal(ListIndex aIndex, const nsString& aReason);
|
||||
nsresult DispatchOrAbandon(uint32_t aId, nsIRunnable* aRunnable);
|
||||
ListType::index_type Find(uint32_t aId);
|
||||
|
||||
nsCOMPtr<nsIThread> mOwningThread;
|
||||
ListType mPending; // owning thread or destructor only
|
||||
|
||||
mozilla::Mutex mMutex;
|
||||
uint32_t mPermissionCache[DEVICE_STORAGE_ACCESS_COUNT];
|
||||
bool mShutdown;
|
||||
|
||||
static mozilla::Atomic<uint32_t> sLastRequestId;
|
||||
};
|
||||
|
||||
class DeviceStorageRequest
|
||||
: public nsRunnable
|
||||
{
|
||||
protected:
|
||||
DeviceStorageRequest();
|
||||
|
||||
public:
|
||||
virtual void Initialize(DeviceStorageRequestManager* aManager,
|
||||
DeviceStorageFile* aFile,
|
||||
uint32_t aRequest);
|
||||
|
||||
virtual void Initialize(DeviceStorageRequestManager* aManager,
|
||||
DeviceStorageFile* aFile,
|
||||
uint32_t aRequest,
|
||||
mozilla::dom::BlobImpl* aBlob);
|
||||
|
||||
virtual void Initialize(DeviceStorageRequestManager* aManager,
|
||||
DeviceStorageFile* aFile,
|
||||
uint32_t aRequest,
|
||||
DeviceStorageFileDescriptor* aDSFileDescriptor);
|
||||
|
||||
DeviceStorageAccessType GetAccess() const;
|
||||
void GetStorageType(nsAString& aType) const;
|
||||
DeviceStorageFile* GetFile() const;
|
||||
DeviceStorageFileDescriptor* GetFileDescriptor() const;
|
||||
DeviceStorageRequestManager* GetManager() const;
|
||||
|
||||
uint32_t GetId() const
|
||||
{
|
||||
return mId;
|
||||
}
|
||||
|
||||
void PermissionCacheMissed()
|
||||
{
|
||||
mPermissionCached = false;
|
||||
}
|
||||
|
||||
nsresult Cancel();
|
||||
nsresult Allow();
|
||||
|
||||
nsresult Resolve()
|
||||
{
|
||||
/* Always dispatch an empty resolve because that signals a cursor end
|
||||
and should not be executed directly from the caller's context due
|
||||
to the object potentially getting freed before we return. */
|
||||
uint32_t id = mId;
|
||||
mId = DeviceStorageRequestManager::INVALID_ID;
|
||||
return mManager->Resolve(id, true);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
nsresult Resolve(T aValue)
|
||||
{
|
||||
uint32_t id = mId;
|
||||
if (!mMultipleResolve) {
|
||||
mId = DeviceStorageRequestManager::INVALID_ID;
|
||||
}
|
||||
return mManager->Resolve(id, aValue, ForceDispatch());
|
||||
}
|
||||
|
||||
template<class T>
|
||||
nsresult Reject(T aReason)
|
||||
{
|
||||
uint32_t id = mId;
|
||||
mId = DeviceStorageRequestManager::INVALID_ID;
|
||||
return mManager->Reject(id, aReason);
|
||||
}
|
||||
|
||||
protected:
|
||||
bool ForceDispatch() const
|
||||
{
|
||||
return !mSendToParent && mPermissionCached;
|
||||
}
|
||||
|
||||
virtual ~DeviceStorageRequest();
|
||||
virtual void Prepare();
|
||||
virtual nsresult CreateSendParams(mozilla::dom::DeviceStorageParams& aParams);
|
||||
nsresult AllowInternal();
|
||||
nsresult SendToParentProcess();
|
||||
|
||||
nsRefPtr<DeviceStorageRequestManager> mManager;
|
||||
nsRefPtr<DeviceStorageFile> mFile;
|
||||
uint32_t mId;
|
||||
nsRefPtr<mozilla::dom::BlobImpl> mBlob;
|
||||
nsRefPtr<DeviceStorageFileDescriptor> mDSFileDescriptor;
|
||||
DeviceStorageAccessType mAccess;
|
||||
bool mSendToParent;
|
||||
bool mUseStreamTransport;
|
||||
bool mCheckFile;
|
||||
bool mCheckBlob;
|
||||
bool mMultipleResolve;
|
||||
bool mPermissionCached;
|
||||
|
||||
private:
|
||||
DeviceStorageRequest(const DeviceStorageRequest&) = delete;
|
||||
DeviceStorageRequest& operator=(const DeviceStorageRequest&) = delete;
|
||||
};
|
||||
|
||||
class DeviceStorageCursorRequest final
|
||||
: public DeviceStorageRequest
|
||||
{
|
||||
public:
|
||||
DeviceStorageCursorRequest();
|
||||
|
||||
using DeviceStorageRequest::Initialize;
|
||||
|
||||
virtual void Initialize(DeviceStorageRequestManager* aManager,
|
||||
DeviceStorageFile* aFile,
|
||||
uint32_t aRequest,
|
||||
PRTime aSince);
|
||||
|
||||
void AddFiles(size_t aSize);
|
||||
void AddFile(already_AddRefed<DeviceStorageFile> aFile);
|
||||
nsresult Continue();
|
||||
NS_IMETHOD Run() override;
|
||||
|
||||
protected:
|
||||
virtual ~DeviceStorageCursorRequest()
|
||||
{ };
|
||||
|
||||
nsresult SendContinueToParentProcess();
|
||||
nsresult CreateSendParams(mozilla::dom::DeviceStorageParams& aParams) override;
|
||||
|
||||
size_t mIndex;
|
||||
PRTime mSince;
|
||||
nsString mStorageType;
|
||||
nsTArray<nsRefPtr<DeviceStorageFile> > mFiles;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -2298,11 +2298,7 @@ ContentChild::RecvAppInit()
|
||||
// PreloadSlowThings() may set the docshell of the first TabChild
|
||||
// inactive, and we can only safely restore it to active from
|
||||
// BrowserElementChild.js.
|
||||
if ((mIsForApp || mIsForBrowser)
|
||||
#ifdef MOZ_NUWA_PROCESS
|
||||
&& !IsNuwaProcess()
|
||||
#endif
|
||||
) {
|
||||
if (mIsForApp || mIsForBrowser) {
|
||||
PreloadSlowThings();
|
||||
}
|
||||
|
||||
|
||||
+78
-1
@@ -23,6 +23,9 @@
|
||||
#include "mozilla/plugins/PluginWidgetChild.h"
|
||||
#include "mozilla/IMEStateManager.h"
|
||||
#include "mozilla/ipc/DocumentRendererChild.h"
|
||||
#ifdef MOZ_NUWA_PROCESS
|
||||
#include "ipc/Nuwa.h"
|
||||
#endif
|
||||
#include "mozilla/ipc/FileDescriptorUtils.h"
|
||||
#include "mozilla/layers/APZCCallbackHelper.h"
|
||||
#include "mozilla/layers/APZCTreeManager.h"
|
||||
@@ -479,10 +482,67 @@ TabChild::FindTabChild(const TabId& aTabId)
|
||||
return tabChild.forget();
|
||||
}
|
||||
|
||||
static void
|
||||
PreloadSlowThingsPostFork(void* aUnused)
|
||||
{
|
||||
nsCOMPtr<nsIObserverService> observerService =
|
||||
mozilla::services::GetObserverService();
|
||||
observerService->NotifyObservers(nullptr, "preload-postfork", nullptr);
|
||||
}
|
||||
|
||||
#ifdef MOZ_NUWA_PROCESS
|
||||
class MessageChannelAutoBlock MOZ_STACK_CLASS
|
||||
{
|
||||
public:
|
||||
MessageChannelAutoBlock()
|
||||
{
|
||||
SetMessageChannelBlocked(true);
|
||||
}
|
||||
|
||||
~MessageChannelAutoBlock()
|
||||
{
|
||||
SetMessageChannelBlocked(false);
|
||||
}
|
||||
|
||||
private:
|
||||
void SetMessageChannelBlocked(bool aBlock)
|
||||
{
|
||||
if (!IsNuwaProcess()) {
|
||||
return;
|
||||
}
|
||||
|
||||
mozilla::dom::ContentChild* content =
|
||||
mozilla::dom::ContentChild::GetSingleton();
|
||||
if (aBlock) {
|
||||
content->GetIPCChannel()->Block();
|
||||
} else {
|
||||
content->GetIPCChannel()->Unblock();
|
||||
}
|
||||
|
||||
nsTArray<IToplevelProtocol*> actors;
|
||||
content->GetOpenedActors(actors);
|
||||
for (size_t j = 0; j < actors.Length(); j++) {
|
||||
IToplevelProtocol* actor = actors[j];
|
||||
if (aBlock) {
|
||||
actor->GetIPCChannel()->Block();
|
||||
} else {
|
||||
actor->GetIPCChannel()->Unblock();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
static bool sPreloaded = false;
|
||||
|
||||
/*static*/ void
|
||||
TabChild::PreloadSlowThings()
|
||||
{
|
||||
MOZ_ASSERT(!sPreallocatedTab);
|
||||
if (sPreloaded) {
|
||||
// If we are alredy initialized in Nuwa, don't redo preloading.
|
||||
return;
|
||||
}
|
||||
sPreloaded = true;
|
||||
|
||||
// Pass nullptr to aManager since at this point the TabChild is
|
||||
// not connected to any manager. Any attempt to use the TabChild
|
||||
@@ -494,6 +554,13 @@ TabChild::PreloadSlowThings()
|
||||
!tab->InitTabChildGlobal(DONT_LOAD_SCRIPTS)) {
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef MOZ_NUWA_PROCESS
|
||||
// Temporarily block the IPC channels to the chrome process when we are
|
||||
// preloading.
|
||||
MessageChannelAutoBlock autoblock;
|
||||
#endif
|
||||
|
||||
// Just load and compile these scripts, but don't run them.
|
||||
tab->TryCacheLoadAndCompileScript(BROWSER_ELEMENT_CHILD_SCRIPT, true);
|
||||
// Load, compile, and run these scripts.
|
||||
@@ -501,6 +568,16 @@ TabChild::PreloadSlowThings()
|
||||
NS_LITERAL_STRING("chrome://global/content/preload.js"),
|
||||
true);
|
||||
|
||||
#ifdef MOZ_NUWA_PROCESS
|
||||
if (IsNuwaProcess()) {
|
||||
NuwaAddFinalConstructor(PreloadSlowThingsPostFork, nullptr);
|
||||
} else {
|
||||
PreloadSlowThingsPostFork(nullptr);
|
||||
}
|
||||
#else
|
||||
PreloadSlowThingsPostFork(nullptr);
|
||||
#endif
|
||||
|
||||
nsCOMPtr<nsIDocShell> docShell = do_GetInterface(tab->WebNavigation());
|
||||
if (nsIPresShell* presShell = docShell->GetPresShell()) {
|
||||
// Initialize and do an initial reflow of the about:blank
|
||||
|
||||
+50
-7
@@ -9,6 +9,17 @@
|
||||
|
||||
const BrowserElementIsPreloaded = true;
|
||||
|
||||
const DoPreloadPostfork = function(aCallback) {
|
||||
Services.obs.addObserver({
|
||||
_callback: aCallback,
|
||||
|
||||
observe: function() {
|
||||
this._callback();
|
||||
Services.obs.removeObserver(this, "preload-postfork");
|
||||
}
|
||||
}, "preload-postfork", false);
|
||||
};
|
||||
|
||||
(function (global) {
|
||||
"use strict";
|
||||
|
||||
@@ -16,7 +27,6 @@ const BrowserElementIsPreloaded = true;
|
||||
let Cc = Components.classes;
|
||||
let Ci = Components.interfaces;
|
||||
|
||||
Cu.import("resource://gre/modules/AppsServiceChild.jsm");
|
||||
Cu.import("resource://gre/modules/AppsUtils.jsm");
|
||||
Cu.import("resource://gre/modules/BrowserElementPromptService.jsm");
|
||||
Cu.import("resource://gre/modules/DOMRequestHelper.jsm");
|
||||
@@ -35,12 +45,10 @@ const BrowserElementIsPreloaded = true;
|
||||
|
||||
Cc["@mozilla.org/appshell/appShellService;1"].getService(Ci["nsIAppShellService"]);
|
||||
Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci["nsIWindowMediator"]);
|
||||
Cc["@mozilla.org/AppsService;1"].getService(Ci["nsIAppsService"]);
|
||||
Cc["@mozilla.org/base/telemetry;1"].getService(Ci["nsITelemetry"]);
|
||||
Cc["@mozilla.org/categorymanager;1"].getService(Ci["nsICategoryManager"]);
|
||||
Cc["@mozilla.org/childprocessmessagemanager;1"].getService(Ci["nsIMessageSender"]);
|
||||
Cc["@mozilla.org/consoleservice;1"].getService(Ci["nsIConsoleService"]);
|
||||
Cc["@mozilla.org/cookieService;1"].getService(Ci["nsICookieService"]);
|
||||
Cc["@mozilla.org/docshell/urifixup;1"].getService(Ci["nsIURIFixup"]);
|
||||
Cc["@mozilla.org/dom/dom-request-service;1"].getService(Ci["nsIDOMRequestService"]);
|
||||
Cc["@mozilla.org/embedcomp/prompt-service;1"].getService(Ci["nsIPromptService"]);
|
||||
@@ -58,14 +66,12 @@ const BrowserElementIsPreloaded = true;
|
||||
Cc["@mozilla.org/network/idn-service;1"].getService(Ci["nsIIDNService"]);
|
||||
Cc["@mozilla.org/network/io-service;1"].getService(Ci["nsIIOService2"]);
|
||||
Cc["@mozilla.org/network/mime-hdrparam;1"].getService(Ci["nsIMIMEHeaderParam"]);
|
||||
Cc["@mozilla.org/network/protocol-proxy-service;1"].getService(Ci["nsIProtocolProxyService"]);
|
||||
Cc["@mozilla.org/network/socket-transport-service;1"].getService(Ci["nsISocketTransportService"]);
|
||||
Cc["@mozilla.org/network/stream-transport-service;1"].getService(Ci["nsIStreamTransportService"]);
|
||||
Cc["@mozilla.org/network/url-parser;1?auth=maybe"].getService(Ci["nsIURLParser"]);
|
||||
Cc["@mozilla.org/network/url-parser;1?auth=no"].getService(Ci["nsIURLParser"]);
|
||||
Cc["@mozilla.org/network/url-parser;1?auth=yes"].getService(Ci["nsIURLParser"]);
|
||||
Cc["@mozilla.org/observer-service;1"].getService(Ci["nsIObserverService"]);
|
||||
Cc["@mozilla.org/permissionmanager;1"].getService(Ci["nsIPermissionManager"]);
|
||||
Cc["@mozilla.org/preferences-service;1"].getService(Ci["nsIPrefBranch"]);
|
||||
Cc["@mozilla.org/scriptsecuritymanager;1"].getService(Ci["nsIScriptSecurityManager"]);
|
||||
Cc["@mozilla.org/storage/service;1"].getService(Ci["mozIStorageService"]);
|
||||
@@ -108,7 +114,44 @@ const BrowserElementIsPreloaded = true;
|
||||
Services.io.getProtocolHandler("app");
|
||||
Services.io.getProtocolHandler("default");
|
||||
|
||||
docShell.isActive = false;
|
||||
docShell.createAboutBlankContentViewer(null);
|
||||
// Register an observer for topic "preload_postfork" after we fork a content
|
||||
// process.
|
||||
DoPreloadPostfork(function () {
|
||||
// Load AppsServiceChild.jsm after fork since it sends an async message to
|
||||
// the chrome process in its init() function.
|
||||
Cu.import("resource://gre/modules/AppsServiceChild.jsm");
|
||||
|
||||
// Load UserCustomizations.jsm after fork since it sends an async message to
|
||||
// the chrome process in its init() function.
|
||||
try {
|
||||
if (Services.prefs.getBoolPref("dom.apps.customization.enabled")) {
|
||||
Cu.import("resource://gre/modules/UserCustomizations.jsm");
|
||||
}
|
||||
} catch(e) {}
|
||||
|
||||
// Load nsIAppsService after fork since its implementation loads
|
||||
// AppsServiceChild.jsm
|
||||
Cc["@mozilla.org/AppsService;1"].getService(Ci["nsIAppsService"]);
|
||||
|
||||
// Load nsICookieService after fork since it sends an IPC constructor
|
||||
// message to the chrome process.
|
||||
Cc["@mozilla.org/cookieService;1"].getService(Ci["nsICookieService"]);
|
||||
|
||||
// Load nsIPermissionManager after fork since it sends a message to the
|
||||
// chrome process to read permissions.
|
||||
Cc["@mozilla.org/permissionmanager;1"].getService(Ci["nsIPermissionManager"]);
|
||||
|
||||
// Create this instance after fork since it loads AppsServiceChild.jsm
|
||||
Cc["@mozilla.org/webapps;1"].createInstance(Ci["nsISupports"]);
|
||||
|
||||
// Load nsIProtocolProxyService after fork since it asynchronously accesses
|
||||
// the "Proxy Resolution" thread after it's frozen.
|
||||
Cc["@mozilla.org/network/protocol-proxy-service;1"].getService(Ci["nsIProtocolProxyService"]);
|
||||
|
||||
// Call docShell.createAboutBlankContentViewer() after fork since it has IPC
|
||||
// activity in the PCompositor protocol.
|
||||
docShell.createAboutBlankContentViewer(null);
|
||||
docShell.isActive = false;
|
||||
});
|
||||
})(this);
|
||||
|
||||
|
||||
@@ -86,6 +86,9 @@ interface DeviceStorage : EventTarget {
|
||||
// Indicates if the storage area denoted by storageName is removable
|
||||
readonly attribute boolean isRemovable;
|
||||
|
||||
// True if the storage area is close to being full
|
||||
readonly attribute boolean lowDiskSpace;
|
||||
|
||||
[NewObject]
|
||||
// XXXbz what type does this really return?
|
||||
Promise<any> getRoot();
|
||||
|
||||
@@ -170,6 +170,16 @@ class MessageChannel : HasResultCodes
|
||||
sIsPumpingMessages = aIsPumping;
|
||||
}
|
||||
|
||||
#ifdef MOZ_NUWA_PROCESS
|
||||
void Block() {
|
||||
mLink->Block();
|
||||
}
|
||||
|
||||
void Unblock() {
|
||||
mLink->Unblock();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef OS_WIN
|
||||
struct MOZ_STACK_CLASS SyncStackFrame
|
||||
{
|
||||
|
||||
@@ -16,6 +16,10 @@
|
||||
#include "mozilla/dom/PContent.h"
|
||||
#include "mozilla/dom/PNuwa.h"
|
||||
#include "mozilla/hal_sandbox/PHal.h"
|
||||
#if defined(DEBUG) || defined(ENABLE_TESTS)
|
||||
#include "jsprf.h"
|
||||
extern "C" char* PrintJSStack();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
@@ -75,6 +79,7 @@ ProcessLink::ProcessLink(MessageChannel *aChan)
|
||||
, mExistingListener(nullptr)
|
||||
#ifdef MOZ_NUWA_PROCESS
|
||||
, mIsToNuwaProcess(false)
|
||||
, mIsBlocked(false)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
@@ -175,6 +180,8 @@ ProcessLink::SendMessage(Message *msg)
|
||||
mChan->mMonitor->AssertCurrentThreadOwns();
|
||||
|
||||
#ifdef MOZ_NUWA_PROCESS
|
||||
// Parent to child: check whether we are sending some unexpected message to
|
||||
// the Nuwa process.
|
||||
if (mIsToNuwaProcess && mozilla::dom::ContentParent::IsNuwaReady()) {
|
||||
switch (msg->type()) {
|
||||
case mozilla::dom::PNuwa::Msg_Fork__ID:
|
||||
@@ -194,6 +201,19 @@ ProcessLink::SendMessage(Message *msg)
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// Nuwa to parent: check whether we are currently blocked.
|
||||
if (IsNuwaProcess() && mIsBlocked) {
|
||||
#if defined(ENABLE_TESTS) || defined(DEBUG)
|
||||
char* jsstack = PrintJSStack();
|
||||
printf_stderr("Fatal error: sending a message to the chrome process"
|
||||
"with a blocked IPC channel from \n%s",
|
||||
jsstack ? jsstack : "<no JS stack>");
|
||||
JS_smprintf_free(jsstack);
|
||||
MOZ_CRASH();
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
mIOLoop->PostTask(
|
||||
|
||||
@@ -128,6 +128,12 @@ class MessageLink
|
||||
virtual bool Unsound_IsClosed() const = 0;
|
||||
virtual uint32_t Unsound_NumQueuedMessages() const = 0;
|
||||
|
||||
#ifdef MOZ_NUWA_PROCESS
|
||||
// To be overridden by ProcessLink.
|
||||
virtual void Block() {}
|
||||
virtual void Unblock() {}
|
||||
#endif
|
||||
|
||||
protected:
|
||||
MessageChannel *mChan;
|
||||
};
|
||||
@@ -175,12 +181,22 @@ class ProcessLink
|
||||
virtual bool Unsound_IsClosed() const override;
|
||||
virtual uint32_t Unsound_NumQueuedMessages() const override;
|
||||
|
||||
#ifdef MOZ_NUWA_PROCESS
|
||||
void Block() override {
|
||||
mIsBlocked = true;
|
||||
}
|
||||
void Unblock() override {
|
||||
mIsBlocked = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
protected:
|
||||
Transport* mTransport;
|
||||
MessageLoop* mIOLoop; // thread where IO happens
|
||||
Transport::Listener* mExistingListener; // channel's previous listener
|
||||
#ifdef MOZ_NUWA_PROCESS
|
||||
bool mIsToNuwaProcess;
|
||||
bool mIsBlocked;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@@ -239,6 +239,8 @@ public:
|
||||
|
||||
void GetOpenedActors(nsTArray<IToplevelProtocol*>& aActors);
|
||||
|
||||
virtual MessageChannel* GetIPCChannel() = 0;
|
||||
|
||||
// This Unsafe version should only be used when all other threads are
|
||||
// frozen, since it performs no locking. It also takes a stack-allocated
|
||||
// array and its size (number of elements) rather than an nsTArray. The Nuwa
|
||||
|
||||
@@ -1923,4 +1923,28 @@ IsNuwaReady() {
|
||||
return sNuwaReady;
|
||||
}
|
||||
|
||||
#if defined(DEBUG) || defined(ENABLE_TESTS)
|
||||
MFBT_API void
|
||||
NuwaAssertNotFrozen(unsigned int aThread, const char* aThreadName) {
|
||||
if (!sIsNuwaProcess || !sIsFreezing) {
|
||||
return;
|
||||
}
|
||||
|
||||
thread_info_t *tinfo = GetThreadInfo(static_cast<pthread_t>(aThread));
|
||||
if (!tinfo) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((tinfo->flags & TINFO_FLAG_NUWA_SUPPORT) &&
|
||||
!(tinfo->flags & TINFO_FLAG_NUWA_EXPLICIT_CHECKPOINT)) {
|
||||
__android_log_print(ANDROID_LOG_FATAL, "Nuwa",
|
||||
"Fatal error: the Nuwa process is about to deadlock in "
|
||||
"accessing a frozen thread (%s, tid=%d).",
|
||||
aThreadName ? aThreadName : "(unnamed)",
|
||||
tinfo->origNativeThreadID);
|
||||
abort();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
} // extern "C"
|
||||
|
||||
@@ -186,6 +186,16 @@ MFBT_API bool IsNuwaProcess();
|
||||
* @return If the Nuwa process is ready for spawning new processes.
|
||||
*/
|
||||
MFBT_API bool IsNuwaReady();
|
||||
|
||||
#if defined(DEBUG) || defined(ENABLE_TESTS)
|
||||
/**
|
||||
* Asserts that aThread is not frozen.
|
||||
*/
|
||||
MFBT_API void NuwaAssertNotFrozen(unsigned int aThread,
|
||||
const char* aThreadName);
|
||||
#else
|
||||
#define NuwaAssertNotFrozen(aThread, aThreadName) do {} while(0);
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif /* __NUWA_H_ */
|
||||
|
||||
@@ -36,6 +36,15 @@
|
||||
#include "mozilla/ChaosMode.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsICrashReporter.h"
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_NUWA_PROCESS
|
||||
#include "private/pprthred.h"
|
||||
#endif
|
||||
|
||||
#ifdef XP_LINUX
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
@@ -478,6 +487,12 @@ nsThread::PutEvent(already_AddRefed<nsIRunnable>&& aEvent, nsNestedEventTarget*
|
||||
{
|
||||
nsCOMPtr<nsIThreadObserver> obs;
|
||||
|
||||
#ifdef MOZ_NUWA_PROCESS
|
||||
// On debug build or when tests are enabled, assert that we are not about to
|
||||
// create a deadlock in the Nuwa process.
|
||||
NuwaAssertNotFrozen(PR_GetThreadID(mThread), PR_GetThreadName(mThread));
|
||||
#endif
|
||||
|
||||
{
|
||||
MutexAutoLock lock(mLock);
|
||||
nsChainedEventQueue* queue = aTarget ? aTarget->mQueue : &mEventsRoot;
|
||||
|
||||
Reference in New Issue
Block a user