mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge b2g-inbound to m-c. a=merge
This commit is contained in:
commit
7f2f3a93e8
@ -12,10 +12,10 @@
|
||||
<!--original fetch url was https://git.mozilla.org/releases-->
|
||||
<remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
|
||||
<!-- B2G specific things. -->
|
||||
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
|
||||
<project name="platform_build" path="build" remote="b2g" revision="aacd9b12da7fc3c8f4deaaa8eedfbb158f4fefe7">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="d9d99f32762975a370f1abd34a3512bd6fe29111"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="507ba38fb64b27f87d11f4104dfcc58448e12b1a"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="62cfa11ae7d77f6330de019a5aa79607e35be7d1"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
@ -12,10 +12,10 @@
|
||||
<!--original fetch url was https://git.mozilla.org/releases-->
|
||||
<remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
|
||||
<!-- B2G specific things. -->
|
||||
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
|
||||
<project name="platform_build" path="build" remote="b2g" revision="aacd9b12da7fc3c8f4deaaa8eedfbb158f4fefe7">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="d9d99f32762975a370f1abd34a3512bd6fe29111"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="507ba38fb64b27f87d11f4104dfcc58448e12b1a"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="62cfa11ae7d77f6330de019a5aa79607e35be7d1"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
@ -19,7 +19,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="d9d99f32762975a370f1abd34a3512bd6fe29111"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="507ba38fb64b27f87d11f4104dfcc58448e12b1a"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="62cfa11ae7d77f6330de019a5aa79607e35be7d1"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="2d58f4b9206b50b8fda0d5036da6f0c62608db7c"/>
|
||||
|
@ -17,7 +17,7 @@
|
||||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="d9d99f32762975a370f1abd34a3512bd6fe29111"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="507ba38fb64b27f87d11f4104dfcc58448e12b1a"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="62cfa11ae7d77f6330de019a5aa79607e35be7d1"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="bfdb6348725a33bdcdc4e17999cb500be6beedb5"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="a6f9a1245d98c51172c15afecb9ade1a6ca511e2"/>
|
||||
|
@ -12,10 +12,10 @@
|
||||
<!--original fetch url was https://git.mozilla.org/releases-->
|
||||
<remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
|
||||
<!-- B2G specific things. -->
|
||||
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
|
||||
<project name="platform_build" path="build" remote="b2g" revision="aacd9b12da7fc3c8f4deaaa8eedfbb158f4fefe7">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="d9d99f32762975a370f1abd34a3512bd6fe29111"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="507ba38fb64b27f87d11f4104dfcc58448e12b1a"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="62cfa11ae7d77f6330de019a5aa79607e35be7d1"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
@ -128,8 +128,8 @@
|
||||
<default remote="caf" revision="refs/tags/android-4.4.2_r1" sync-j="4"/>
|
||||
<!-- Emulator specific things -->
|
||||
<project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="72ffdf71c68a96309212eb13d63560d66db14c9e"/>
|
||||
<project name="device_generic_goldfish" path="device/generic/goldfish" remote="b2g" revision="85f6a2e1e638dbc8b119896e61383e973e764ffd"/>
|
||||
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="4bebbe8d92368befc31e8b4a99da2d29cc26bfbc"/>
|
||||
<project name="device_generic_goldfish" path="device/generic/goldfish" remote="b2g" revision="dea95f1a539f037db1b00732048a8722532b4d47"/>
|
||||
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="ef1a0385c3286dc2403c72fdc8092258c20f70d4"/>
|
||||
<project name="platform/external/libnfc-nci" path="external/libnfc-nci" revision="f37bd545063039e30a92f2550ae78c0e6e4e2d08"/>
|
||||
<project name="platform_external_wpa_supplicant_8" path="external/wpa_supplicant_8" remote="b2g" revision="0c6a6547cd1fd302fa2b0f6e375654df36bf0ec4"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd4fc430da93fad3123f0775791a919568aa0ca2"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="05a36844c1046a1eb07d5b1325f85ed741f961ea">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="d9d99f32762975a370f1abd34a3512bd6fe29111"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="507ba38fb64b27f87d11f4104dfcc58448e12b1a"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="62cfa11ae7d77f6330de019a5aa79607e35be7d1"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
@ -19,7 +19,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="d9d99f32762975a370f1abd34a3512bd6fe29111"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="507ba38fb64b27f87d11f4104dfcc58448e12b1a"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="62cfa11ae7d77f6330de019a5aa79607e35be7d1"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="2d58f4b9206b50b8fda0d5036da6f0c62608db7c"/>
|
||||
|
@ -12,10 +12,10 @@
|
||||
<!--original fetch url was https://git.mozilla.org/releases-->
|
||||
<remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
|
||||
<!-- B2G specific things. -->
|
||||
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
|
||||
<project name="platform_build" path="build" remote="b2g" revision="aacd9b12da7fc3c8f4deaaa8eedfbb158f4fefe7">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="d9d99f32762975a370f1abd34a3512bd6fe29111"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="507ba38fb64b27f87d11f4104dfcc58448e12b1a"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="62cfa11ae7d77f6330de019a5aa79607e35be7d1"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
@ -1,9 +1,9 @@
|
||||
{
|
||||
"git": {
|
||||
"git_revision": "d9d99f32762975a370f1abd34a3512bd6fe29111",
|
||||
"git_revision": "507ba38fb64b27f87d11f4104dfcc58448e12b1a",
|
||||
"remote": "https://git.mozilla.org/releases/gaia.git",
|
||||
"branch": ""
|
||||
},
|
||||
"revision": "a1b18f9a9e869b1ae261a064a7dd174d59169fb9",
|
||||
"revision": "8ca4fec22230c6b6d62301261a6fc76a6fa64814",
|
||||
"repo_path": "integration/gaia-central"
|
||||
}
|
||||
|
@ -17,7 +17,7 @@
|
||||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="d9d99f32762975a370f1abd34a3512bd6fe29111"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="507ba38fb64b27f87d11f4104dfcc58448e12b1a"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="62cfa11ae7d77f6330de019a5aa79607e35be7d1"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="bfdb6348725a33bdcdc4e17999cb500be6beedb5"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="a6f9a1245d98c51172c15afecb9ade1a6ca511e2"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="05a36844c1046a1eb07d5b1325f85ed741f961ea">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="d9d99f32762975a370f1abd34a3512bd6fe29111"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="507ba38fb64b27f87d11f4104dfcc58448e12b1a"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="62cfa11ae7d77f6330de019a5aa79607e35be7d1"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
@ -206,7 +206,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Navigator)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCameraManager)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMediaDevices)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMessagesManager)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDeviceStorageStores)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTimeManager)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mServiceWorkerContainer)
|
||||
|
||||
@ -328,7 +327,10 @@ Navigator::Invalidate()
|
||||
|
||||
uint32_t len = mDeviceStorageStores.Length();
|
||||
for (uint32_t i = 0; i < len; ++i) {
|
||||
mDeviceStorageStores[i]->Shutdown();
|
||||
nsRefPtr<nsDOMDeviceStorage> ds = do_QueryReferent(mDeviceStorageStores[i]);
|
||||
if (ds) {
|
||||
ds->Shutdown();
|
||||
}
|
||||
}
|
||||
mDeviceStorageStores.Clear();
|
||||
|
||||
@ -961,7 +963,26 @@ Navigator::GetDeviceStorageAreaListener(ErrorResult& aRv)
|
||||
return mDeviceStorageAreaListener;
|
||||
}
|
||||
|
||||
nsDOMDeviceStorage*
|
||||
already_AddRefed<nsDOMDeviceStorage>
|
||||
Navigator::FindDeviceStorage(const nsAString& aName, const nsAString& aType)
|
||||
{
|
||||
auto i = mDeviceStorageStores.Length();
|
||||
while (i > 0) {
|
||||
--i;
|
||||
nsRefPtr<nsDOMDeviceStorage> storage =
|
||||
do_QueryReferent(mDeviceStorageStores[i]);
|
||||
if (storage) {
|
||||
if (storage->Equals(mWindow, aName, aType)) {
|
||||
return storage.forget();
|
||||
}
|
||||
} else {
|
||||
mDeviceStorageStores.RemoveElementAt(i);
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
already_AddRefed<nsDOMDeviceStorage>
|
||||
Navigator::GetDeviceStorage(const nsAString& aType, ErrorResult& aRv)
|
||||
{
|
||||
if (!mWindow || !mWindow->GetOuterWindow() || !mWindow->GetDocShell()) {
|
||||
@ -969,7 +990,13 @@ Navigator::GetDeviceStorage(const nsAString& aType, ErrorResult& aRv)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsRefPtr<nsDOMDeviceStorage> storage;
|
||||
nsString name;
|
||||
nsDOMDeviceStorage::GetDefaultStorageName(aType, name);
|
||||
nsRefPtr<nsDOMDeviceStorage> storage = FindDeviceStorage(name, aType);
|
||||
if (storage) {
|
||||
return storage.forget();
|
||||
}
|
||||
|
||||
nsDOMDeviceStorage::CreateDeviceStorageFor(mWindow, aType,
|
||||
getter_AddRefs(storage));
|
||||
|
||||
@ -977,8 +1004,9 @@ Navigator::GetDeviceStorage(const nsAString& aType, ErrorResult& aRv)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
mDeviceStorageStores.AppendElement(storage);
|
||||
return storage;
|
||||
mDeviceStorageStores.AppendElement(
|
||||
do_GetWeakReference(static_cast<DOMEventTargetHelper*>(storage)));
|
||||
return storage.forget();
|
||||
}
|
||||
|
||||
void
|
||||
@ -991,12 +1019,31 @@ Navigator::GetDeviceStorages(const nsAString& aType,
|
||||
return;
|
||||
}
|
||||
|
||||
nsDOMDeviceStorage::CreateDeviceStoragesFor(mWindow, aType, aStores);
|
||||
nsDOMDeviceStorage::VolumeNameArray volumes;
|
||||
nsDOMDeviceStorage::GetOrderedVolumeNames(aType, volumes);
|
||||
if (volumes.IsEmpty()) {
|
||||
nsRefPtr<nsDOMDeviceStorage> storage = GetDeviceStorage(aType, aRv);
|
||||
if (storage) {
|
||||
aStores.AppendElement(storage.forget());
|
||||
}
|
||||
} else {
|
||||
uint32_t len = volumes.Length();
|
||||
aStores.SetCapacity(len);
|
||||
for (uint32_t i = 0; i < len; ++i) {
|
||||
nsRefPtr<nsDOMDeviceStorage> storage =
|
||||
GetDeviceStorageByNameAndType(volumes[i], aType, aRv);
|
||||
if (aRv.Failed()) {
|
||||
break;
|
||||
}
|
||||
|
||||
mDeviceStorageStores.AppendElements(aStores);
|
||||
if (storage) {
|
||||
aStores.AppendElement(storage.forget());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsDOMDeviceStorage*
|
||||
already_AddRefed<nsDOMDeviceStorage>
|
||||
Navigator::GetDeviceStorageByNameAndType(const nsAString& aName,
|
||||
const nsAString& aType,
|
||||
ErrorResult& aRv)
|
||||
@ -1006,7 +1053,10 @@ Navigator::GetDeviceStorageByNameAndType(const nsAString& aName,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsRefPtr<nsDOMDeviceStorage> storage;
|
||||
nsRefPtr<nsDOMDeviceStorage> storage = FindDeviceStorage(aName, aType);
|
||||
if (storage) {
|
||||
return storage.forget();
|
||||
}
|
||||
nsDOMDeviceStorage::CreateDeviceStorageByNameAndType(mWindow, aName, aType,
|
||||
getter_AddRefs(storage));
|
||||
|
||||
@ -1014,8 +1064,9 @@ Navigator::GetDeviceStorageByNameAndType(const nsAString& aName,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
mDeviceStorageStores.AppendElement(storage);
|
||||
return storage;
|
||||
mDeviceStorageStores.AppendElement(
|
||||
do_GetWeakReference(static_cast<DOMEventTargetHelper*>(storage)));
|
||||
return storage.forget();
|
||||
}
|
||||
|
||||
Geolocation*
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "nsInterfaceHashtable.h"
|
||||
#include "nsString.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsWeakPtr.h"
|
||||
#ifdef MOZ_EME
|
||||
#include "mozilla/dom/MediaKeySystemAccessManager.h"
|
||||
#endif
|
||||
@ -220,14 +221,18 @@ public:
|
||||
already_AddRefed<WakeLock> RequestWakeLock(const nsAString &aTopic,
|
||||
ErrorResult& aRv);
|
||||
DeviceStorageAreaListener* GetDeviceStorageAreaListener(ErrorResult& aRv);
|
||||
nsDOMDeviceStorage* GetDeviceStorage(const nsAString& aType,
|
||||
ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<nsDOMDeviceStorage> GetDeviceStorage(const nsAString& aType,
|
||||
ErrorResult& aRv);
|
||||
|
||||
void GetDeviceStorages(const nsAString& aType,
|
||||
nsTArray<nsRefPtr<nsDOMDeviceStorage> >& aStores,
|
||||
ErrorResult& aRv);
|
||||
nsDOMDeviceStorage* GetDeviceStorageByNameAndType(const nsAString& aName,
|
||||
const nsAString& aType,
|
||||
ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<nsDOMDeviceStorage>
|
||||
GetDeviceStorageByNameAndType(const nsAString& aName, const nsAString& aType,
|
||||
ErrorResult& aRv);
|
||||
|
||||
DesktopNotificationCenter* GetMozNotification(ErrorResult& aRv);
|
||||
CellBroadcast* GetMozCellBroadcast(ErrorResult& aRv);
|
||||
IccManager* GetMozIccManager(ErrorResult& aRv);
|
||||
@ -357,6 +362,9 @@ private:
|
||||
bool CheckPermission(const char* type);
|
||||
static bool CheckPermission(nsPIDOMWindow* aWindow, const char* aType);
|
||||
|
||||
already_AddRefed<nsDOMDeviceStorage> FindDeviceStorage(const nsAString& aName,
|
||||
const nsAString& aType);
|
||||
|
||||
nsRefPtr<nsMimeTypeArray> mMimeTypes;
|
||||
nsRefPtr<nsPluginArray> mPlugins;
|
||||
nsRefPtr<Permissions> mPermissions;
|
||||
@ -387,7 +395,7 @@ private:
|
||||
nsRefPtr<nsDOMCameraManager> mCameraManager;
|
||||
nsRefPtr<MediaDevices> mMediaDevices;
|
||||
nsCOMPtr<nsIDOMNavigatorSystemMessages> mMessagesManager;
|
||||
nsTArray<nsRefPtr<nsDOMDeviceStorage> > mDeviceStorageStores;
|
||||
nsTArray<nsWeakPtr> mDeviceStorageStores;
|
||||
nsRefPtr<time::TimeManager> mTimeManager;
|
||||
nsRefPtr<ServiceWorkerContainer> mServiceWorkerContainer;
|
||||
nsCOMPtr<nsPIDOMWindow> mWindow;
|
||||
|
@ -6,7 +6,6 @@
|
||||
#include "base/basictypes.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/unused.h"
|
||||
#include "nsPrintfCString.h"
|
||||
#include "nsIWeakReferenceUtils.h"
|
||||
#include "CameraCommon.h"
|
||||
#include "nsGlobalWindow.h"
|
||||
@ -18,7 +17,7 @@ using namespace mozilla;
|
||||
/* static */ StaticRefPtr<nsIThread> CameraControlImpl::sCameraThread;
|
||||
|
||||
CameraControlImpl::CameraControlImpl()
|
||||
: mListenerLock(PR_NewRWLock(PR_RWLOCK_RANK_NONE, "CameraControlImpl.Listeners.Lock"))
|
||||
: mListenerLock("mozilla::camera::CameraControlImpl.Listeners")
|
||||
, mPreviewState(CameraControlListener::kPreviewStopped)
|
||||
, mHardwareState(CameraControlListener::kHardwareUninitialized)
|
||||
, mHardwareStateChangeReason(NS_OK)
|
||||
@ -50,32 +49,11 @@ CameraControlImpl::CameraControlImpl()
|
||||
mCameraThread->Dispatch(new Delegate(), NS_DISPATCH_NORMAL);
|
||||
sCameraThread = mCameraThread;
|
||||
}
|
||||
|
||||
// Care must be taken with the mListenerLock read-write lock to prevent
|
||||
// deadlocks. Currently this is handled by ensuring that any attempts to
|
||||
// acquire the lock for writing (as in Add/RemoveListener()) happen in a
|
||||
// runnable dispatched to the Camera Thread--even if the method is being
|
||||
// called from that thread. This ensures that if a registered listener
|
||||
// (which is invoked with a read-lock) tries to call Add/RemoveListener(),
|
||||
// the lock-for-writing attempt won't happen until the listener has
|
||||
// completed.
|
||||
//
|
||||
// Multiple parallel listeners being invoked are not a problem because
|
||||
// the read-write lock allows multiple simultaneous read-locks.
|
||||
if (!mListenerLock) {
|
||||
MOZ_CRASH("Out of memory getting new PRRWLock");
|
||||
}
|
||||
}
|
||||
|
||||
CameraControlImpl::~CameraControlImpl()
|
||||
{
|
||||
DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
|
||||
|
||||
MOZ_ASSERT(mListenerLock, "mListenerLock missing in ~CameraControlImpl()");
|
||||
if (mListenerLock) {
|
||||
PR_DestroyRWLock(mListenerLock);
|
||||
mListenerLock = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -85,7 +63,7 @@ CameraControlImpl::OnHardwareStateChange(CameraControlListener::HardwareState aN
|
||||
// This callback can run on threads other than the Main Thread and
|
||||
// the Camera Thread. On Gonk, it may be called from the camera's
|
||||
// local binder thread, should the mediaserver process die.
|
||||
RwLockAutoEnterRead lock(mListenerLock);
|
||||
MutexAutoLock lock(mListenerLock);
|
||||
|
||||
if (aNewState == mHardwareState) {
|
||||
DOM_CAMERA_LOGI("OnHardwareStateChange: state did not change from %d\n", mHardwareState);
|
||||
@ -114,7 +92,7 @@ void
|
||||
CameraControlImpl::OnConfigurationChange()
|
||||
{
|
||||
MOZ_ASSERT(NS_GetCurrentThread() == mCameraThread);
|
||||
RwLockAutoEnterRead lock(mListenerLock);
|
||||
MutexAutoLock lock(mListenerLock);
|
||||
|
||||
DOM_CAMERA_LOGI("OnConfigurationChange : %zu listeners\n", mListeners.Length());
|
||||
|
||||
@ -130,7 +108,7 @@ CameraControlImpl::OnAutoFocusComplete(bool aAutoFocusSucceeded)
|
||||
// This callback can run on threads other than the Main Thread and
|
||||
// the Camera Thread. On Gonk, it is called from the camera
|
||||
// library's auto focus thread.
|
||||
RwLockAutoEnterRead lock(mListenerLock);
|
||||
MutexAutoLock lock(mListenerLock);
|
||||
|
||||
for (uint32_t i = 0; i < mListeners.Length(); ++i) {
|
||||
CameraControlListener* l = mListeners[i];
|
||||
@ -141,7 +119,7 @@ CameraControlImpl::OnAutoFocusComplete(bool aAutoFocusSucceeded)
|
||||
void
|
||||
CameraControlImpl::OnAutoFocusMoving(bool aIsMoving)
|
||||
{
|
||||
RwLockAutoEnterRead lock(mListenerLock);
|
||||
MutexAutoLock lock(mListenerLock);
|
||||
|
||||
for (uint32_t i = 0; i < mListeners.Length(); ++i) {
|
||||
CameraControlListener* l = mListeners[i];
|
||||
@ -155,7 +133,7 @@ CameraControlImpl::OnFacesDetected(const nsTArray<Face>& aFaces)
|
||||
// This callback can run on threads other than the Main Thread and
|
||||
// the Camera Thread. On Gonk, it is called from the camera
|
||||
// library's face detection thread.
|
||||
RwLockAutoEnterRead lock(mListenerLock);
|
||||
MutexAutoLock lock(mListenerLock);
|
||||
|
||||
for (uint32_t i = 0; i < mListeners.Length(); ++i) {
|
||||
CameraControlListener* l = mListeners[i];
|
||||
@ -169,7 +147,7 @@ CameraControlImpl::OnTakePictureComplete(const uint8_t* aData, uint32_t aLength,
|
||||
// This callback can run on threads other than the Main Thread and
|
||||
// the Camera Thread. On Gonk, it is called from the camera
|
||||
// library's snapshot thread.
|
||||
RwLockAutoEnterRead lock(mListenerLock);
|
||||
MutexAutoLock lock(mListenerLock);
|
||||
|
||||
for (uint32_t i = 0; i < mListeners.Length(); ++i) {
|
||||
CameraControlListener* l = mListeners[i];
|
||||
@ -182,7 +160,7 @@ CameraControlImpl::OnPoster(dom::BlobImpl* aBlobImpl)
|
||||
{
|
||||
// This callback can run on threads other than the Main Thread and
|
||||
// the Camera Thread.
|
||||
RwLockAutoEnterRead lock(mListenerLock);
|
||||
MutexAutoLock lock(mListenerLock);
|
||||
|
||||
for (uint32_t i = 0; i < mListeners.Length(); ++i) {
|
||||
CameraControlListener* l = mListeners[i];
|
||||
@ -196,7 +174,7 @@ CameraControlImpl::OnShutter()
|
||||
// This callback can run on threads other than the Main Thread and
|
||||
// the Camera Thread. On Gonk, it is called from the camera driver's
|
||||
// preview thread.
|
||||
RwLockAutoEnterRead lock(mListenerLock);
|
||||
MutexAutoLock lock(mListenerLock);
|
||||
|
||||
for (uint32_t i = 0; i < mListeners.Length(); ++i) {
|
||||
CameraControlListener* l = mListeners[i];
|
||||
@ -211,7 +189,7 @@ CameraControlImpl::OnRecorderStateChange(CameraControlListener::RecorderState aS
|
||||
// This callback can run on threads other than the Main Thread and
|
||||
// the Camera Thread. On Gonk, it is called from the media encoder
|
||||
// thread.
|
||||
RwLockAutoEnterRead lock(mListenerLock);
|
||||
MutexAutoLock lock(mListenerLock);
|
||||
|
||||
for (uint32_t i = 0; i < mListeners.Length(); ++i) {
|
||||
CameraControlListener* l = mListeners[i];
|
||||
@ -225,7 +203,7 @@ CameraControlImpl::OnPreviewStateChange(CameraControlListener::PreviewState aNew
|
||||
// This callback runs on the Main Thread and the Camera Thread, and
|
||||
// may run on the local binder thread, should the mediaserver
|
||||
// process die.
|
||||
RwLockAutoEnterRead lock(mListenerLock);
|
||||
MutexAutoLock lock(mListenerLock);
|
||||
|
||||
if (aNewState == mPreviewState) {
|
||||
DOM_CAMERA_LOGI("OnPreviewStateChange: state did not change from %d\n", mPreviewState);
|
||||
@ -252,7 +230,7 @@ void
|
||||
CameraControlImpl::OnRateLimitPreview(bool aLimit)
|
||||
{
|
||||
// This function runs on neither the Main Thread nor the Camera Thread.
|
||||
RwLockAutoEnterRead lock(mListenerLock);
|
||||
MutexAutoLock lock(mListenerLock);
|
||||
|
||||
DOM_CAMERA_LOGI("OnRateLimitPreview: %d\n", aLimit);
|
||||
|
||||
@ -267,7 +245,7 @@ CameraControlImpl::OnNewPreviewFrame(layers::Image* aImage, uint32_t aWidth, uin
|
||||
{
|
||||
// This function runs on neither the Main Thread nor the Camera Thread.
|
||||
// On Gonk, it is called from the camera driver's preview thread.
|
||||
RwLockAutoEnterRead lock(mListenerLock);
|
||||
MutexAutoLock lock(mListenerLock);
|
||||
|
||||
DOM_CAMERA_LOGI("OnNewPreviewFrame: we have %zu preview frame listener(s)\n",
|
||||
mListeners.Length());
|
||||
@ -287,7 +265,7 @@ CameraControlImpl::OnUserError(CameraControlListener::UserContext aContext,
|
||||
{
|
||||
// This callback can run on threads other than the Main Thread and
|
||||
// the Camera Thread.
|
||||
RwLockAutoEnterRead lock(mListenerLock);
|
||||
MutexAutoLock lock(mListenerLock);
|
||||
|
||||
const char* context[] = {
|
||||
"StartCamera",
|
||||
@ -328,7 +306,7 @@ CameraControlImpl::OnSystemError(CameraControlListener::SystemContext aContext,
|
||||
{
|
||||
// This callback can run on threads other than the Main Thread and
|
||||
// the Camera Thread.
|
||||
RwLockAutoEnterRead lock(mListenerLock);
|
||||
MutexAutoLock lock(mListenerLock);
|
||||
|
||||
const char* context[] = {
|
||||
"Camera Service"
|
||||
@ -746,7 +724,7 @@ protected:
|
||||
void
|
||||
CameraControlImpl::AddListenerImpl(already_AddRefed<CameraControlListener> aListener)
|
||||
{
|
||||
RwLockAutoEnterWrite lock(mListenerLock);
|
||||
MutexAutoLock lock(mListenerLock);
|
||||
|
||||
CameraControlListener* l = *mListeners.AppendElement() = aListener;
|
||||
DOM_CAMERA_LOGI("Added camera control listener %p\n", l);
|
||||
@ -784,7 +762,7 @@ CameraControlImpl::AddListener(CameraControlListener* aListener)
|
||||
void
|
||||
CameraControlImpl::RemoveListenerImpl(CameraControlListener* aListener)
|
||||
{
|
||||
RwLockAutoEnterWrite lock(mListenerLock);
|
||||
MutexAutoLock lock(mListenerLock);
|
||||
|
||||
nsRefPtr<CameraControlListener> l(aListener);
|
||||
mListeners.RemoveElement(l);
|
||||
|
@ -9,9 +9,9 @@
|
||||
#include "nsWeakPtr.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/ReentrantMonitor.h"
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsProxyRelease.h"
|
||||
#include "AutoRwLock.h"
|
||||
#include "ICameraControl.h"
|
||||
#include "CameraCommon.h"
|
||||
#include "DeviceStorage.h"
|
||||
@ -91,7 +91,7 @@ protected:
|
||||
void AddListenerImpl(already_AddRefed<CameraControlListener> aListener);
|
||||
void RemoveListenerImpl(CameraControlListener* aListener);
|
||||
nsTArray<nsRefPtr<CameraControlListener> > mListeners;
|
||||
PRRWLock* mListenerLock;
|
||||
mutable Mutex mListenerLock;
|
||||
|
||||
class ControlMessage;
|
||||
class ListenerMessage;
|
||||
|
@ -9,11 +9,11 @@
|
||||
|
||||
#include "nsIFile.h"
|
||||
#include "nsIPrincipal.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "mozilla/DOMEventTargetHelper.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/StaticPtr.h"
|
||||
#include "mozilla/dom/DOMRequest.h"
|
||||
#include "nsWeakReference.h"
|
||||
|
||||
#define DEVICESTORAGE_PICTURES "pictures"
|
||||
#define DEVICESTORAGE_VIDEOS "videos"
|
||||
@ -25,6 +25,9 @@
|
||||
class nsIInputStream;
|
||||
class nsIOutputStream;
|
||||
struct DeviceStorageFileDescriptor;
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
class nsIVolume;
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
class EventListenerManager;
|
||||
@ -130,36 +133,13 @@ private:
|
||||
uint64_t* aTotalSoFar);
|
||||
};
|
||||
|
||||
/*
|
||||
The FileUpdateDispatcher converts file-watcher-notify
|
||||
observer events to file-watcher-update events. This is
|
||||
used to be able to broadcast events from one child to
|
||||
another child in B2G. (f.e., if one child decides to add
|
||||
a file, we want to be able to able to send a onchange
|
||||
notifications to every other child watching that device
|
||||
storage object).
|
||||
|
||||
We create this object (via GetSingleton) in two places:
|
||||
* ContentParent::Init (for IPC)
|
||||
* nsDOMDeviceStorage::Init (for non-ipc)
|
||||
*/
|
||||
class FileUpdateDispatcher final
|
||||
: public nsIObserver
|
||||
{
|
||||
~FileUpdateDispatcher() {}
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
static FileUpdateDispatcher* GetSingleton();
|
||||
private:
|
||||
static mozilla::StaticRefPtr<FileUpdateDispatcher> sSingleton;
|
||||
};
|
||||
#define NS_DOM_DEVICE_STORAGE_CID \
|
||||
{ 0xe4a9b969, 0x81fe, 0x44f1, \
|
||||
{ 0xaa, 0x0c, 0x9e, 0x16, 0x64, 0x86, 0x2a, 0xd5 } }
|
||||
|
||||
class nsDOMDeviceStorage final
|
||||
: public mozilla::DOMEventTargetHelper
|
||||
, public nsIObserver
|
||||
, public nsSupportsWeakReference
|
||||
{
|
||||
typedef mozilla::ErrorResult ErrorResult;
|
||||
typedef mozilla::dom::DeviceStorageEnumerationParameters
|
||||
@ -171,8 +151,8 @@ class nsDOMDeviceStorage final
|
||||
public:
|
||||
typedef nsTArray<nsString> VolumeNameArray;
|
||||
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_DOM_DEVICE_STORAGE_CID)
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSIOBSERVER
|
||||
NS_REALLY_FORWARD_NSIDOMEVENTTARGET(DOMEventTargetHelper)
|
||||
|
||||
void EventListenerWasAdded(const nsAString& aType,
|
||||
@ -278,27 +258,38 @@ public:
|
||||
const nsAString& aType,
|
||||
nsDOMDeviceStorage** aStore);
|
||||
|
||||
static void
|
||||
CreateDeviceStoragesFor(nsPIDOMWindow* aWin,
|
||||
const nsAString& aType,
|
||||
nsTArray<nsRefPtr<nsDOMDeviceStorage> >& aStores);
|
||||
|
||||
static void
|
||||
CreateDeviceStorageByNameAndType(nsPIDOMWindow* aWin,
|
||||
const nsAString& aName,
|
||||
const nsAString& aType,
|
||||
nsDOMDeviceStorage** aStore);
|
||||
|
||||
bool Equals(nsPIDOMWindow* aWin,
|
||||
const nsAString& aName,
|
||||
const nsAString& aType);
|
||||
|
||||
void Shutdown();
|
||||
|
||||
static void GetOrderedVolumeNames(const nsAString& aType,
|
||||
nsTArray<nsString>& aVolumeNames);
|
||||
|
||||
static void GetOrderedVolumeNames(nsTArray<nsString>& aVolumeNames);
|
||||
|
||||
static void GetDefaultStorageName(const nsAString& aStorageType,
|
||||
nsAString &aStorageName);
|
||||
nsAString& aStorageName);
|
||||
|
||||
static bool ParseFullPath(const nsAString& aFullPath,
|
||||
nsAString& aOutStorageName,
|
||||
nsAString& aOutStoragePath);
|
||||
|
||||
// DeviceStorageStatics callbacks
|
||||
void OnFileWatcherUpdate(const nsCString& aData, DeviceStorageFile* aFile);
|
||||
void OnDiskSpaceWatcher(bool aLowDiskSpace);
|
||||
void OnWritableNameChanged();
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
void OnVolumeStateChanged(nsIVolume* aVolume);
|
||||
#endif
|
||||
|
||||
private:
|
||||
~nsDOMDeviceStorage();
|
||||
|
||||
@ -341,7 +332,6 @@ private:
|
||||
bool mIsWatchingFile;
|
||||
bool mAllowedToWatchFile;
|
||||
bool mIsDefaultLocation;
|
||||
void DispatchDefaultChangeEvent();
|
||||
|
||||
nsresult Notify(const char* aReason, class DeviceStorageFile* aFile);
|
||||
|
||||
@ -360,4 +350,6 @@ private:
|
||||
nsRefPtr<DeviceStorageFileSystem> mFileSystem;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsDOMDeviceStorage, NS_DOM_DEVICE_STORAGE_CID)
|
||||
|
||||
#endif
|
||||
|
833
dom/devicestorage/DeviceStorageStatics.cpp
Normal file
833
dom/devicestorage/DeviceStorageStatics.cpp
Normal file
@ -0,0 +1,833 @@
|
||||
/* -*- 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 "DeviceStorageStatics.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "nsDeviceStorage.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsAppDirectoryServiceDefs.h"
|
||||
#include "nsDirectoryServiceDefs.h"
|
||||
#include "nsISupportsPrimitives.h"
|
||||
#include "nsPrintfCString.h"
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
#include "nsIVolume.h"
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
#include "AndroidBridge.h"
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace devicestorage {
|
||||
|
||||
static const char* kPrefOverrideRootDir = "device.storage.overrideRootDir";
|
||||
static const char* kPrefTesting = "device.storage.testing";
|
||||
static const char* kPrefPromptTesting = "device.storage.prompt.testing";
|
||||
static const char* kPrefWritableName = "device.storage.writable.name";
|
||||
|
||||
static const char* kFileWatcherUpdate = "file-watcher-update";
|
||||
static const char* kDiskSpaceWatcher = "disk-space-watcher";
|
||||
static const char* kFileWatcherNotify = "file-watcher-notify";
|
||||
static const char* kDownloadWatcherNotify = "download-watcher-notify";
|
||||
|
||||
StaticRefPtr<DeviceStorageStatics> DeviceStorageStatics::sInstance;
|
||||
StaticMutex DeviceStorageStatics::sMutex;
|
||||
|
||||
NS_IMPL_ISUPPORTS(DeviceStorageStatics,
|
||||
nsIObserver)
|
||||
|
||||
/* static */ void
|
||||
DeviceStorageStatics::Initialize()
|
||||
{
|
||||
MOZ_ASSERT(!sInstance);
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
sInstance = new DeviceStorageStatics();
|
||||
sInstance->Init();
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
DeviceStorageStatics::InitializeDirs()
|
||||
{
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
if (NS_WARN_IF(!sInstance)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* The actual initialization can only happen on the main thread. This will
|
||||
either happen when device storage is first used on the main thread, or
|
||||
(in the future) when a worker is created. */
|
||||
if (!sInstance->mInitialized && NS_IsMainThread()) {
|
||||
sInstance->InitDirs();
|
||||
sInstance->mInitialized = true;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(sInstance->mInitialized);
|
||||
}
|
||||
|
||||
DeviceStorageStatics::DeviceStorageStatics()
|
||||
: mInitialized(false)
|
||||
, mPromptTesting(false)
|
||||
{
|
||||
DS_LOG_INFO("");
|
||||
}
|
||||
|
||||
DeviceStorageStatics::~DeviceStorageStatics()
|
||||
{
|
||||
DS_LOG_INFO("");
|
||||
}
|
||||
|
||||
void
|
||||
DeviceStorageStatics::Init()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
sMutex.AssertCurrentThreadOwns();
|
||||
DS_LOG_INFO("");
|
||||
|
||||
Preferences::AddStrongObserver(this, kPrefTesting);
|
||||
Preferences::AddStrongObserver(this, kPrefPromptTesting);
|
||||
Preferences::AddStrongObserver(this, kPrefWritableName);
|
||||
|
||||
mWritableName = Preferences::GetString(kPrefWritableName);
|
||||
mPromptTesting = Preferences::GetBool(kPrefPromptTesting, false);
|
||||
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
if (obs) {
|
||||
obs->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
|
||||
obs->AddObserver(this, kFileWatcherNotify, false);
|
||||
obs->AddObserver(this, kDownloadWatcherNotify, false);
|
||||
}
|
||||
DS_LOG_INFO("");
|
||||
}
|
||||
|
||||
void
|
||||
DeviceStorageStatics::InitDirs()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
sMutex.AssertCurrentThreadOwns();
|
||||
DS_LOG_INFO("");
|
||||
|
||||
nsCOMPtr<nsIProperties> dirService
|
||||
= do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID);
|
||||
MOZ_ASSERT(dirService);
|
||||
|
||||
#if !defined(MOZ_WIDGET_GONK)
|
||||
|
||||
// Keep MOZ_WIDGET_COCOA above XP_UNIX,
|
||||
// because both are defined in Darwin builds.
|
||||
#if defined (MOZ_WIDGET_COCOA)
|
||||
dirService->Get(NS_OSX_PICTURE_DOCUMENTS_DIR,
|
||||
NS_GET_IID(nsIFile),
|
||||
getter_AddRefs(mDirs[TYPE_PICTURES]));
|
||||
dirService->Get(NS_OSX_MOVIE_DOCUMENTS_DIR,
|
||||
NS_GET_IID(nsIFile),
|
||||
getter_AddRefs(mDirs[TYPE_VIDEOS]));
|
||||
dirService->Get(NS_OSX_MUSIC_DOCUMENTS_DIR,
|
||||
NS_GET_IID(nsIFile),
|
||||
getter_AddRefs(mDirs[TYPE_MUSIC]));
|
||||
|
||||
// Keep MOZ_WIDGET_ANDROID above XP_UNIX,
|
||||
// because both are defined in Android builds.
|
||||
#elif defined (MOZ_WIDGET_ANDROID)
|
||||
nsAutoString path;
|
||||
if (NS_SUCCEEDED(mozilla::AndroidBridge::GetExternalPublicDirectory(
|
||||
NS_LITERAL_STRING(DEVICESTORAGE_PICTURES), path))) {
|
||||
NS_NewLocalFile(path, /* aFollowLinks */ true,
|
||||
getter_AddRefs(mDirs[TYPE_PICTURES]));
|
||||
}
|
||||
if (NS_SUCCEEDED(mozilla::AndroidBridge::GetExternalPublicDirectory(
|
||||
NS_LITERAL_STRING(DEVICESTORAGE_VIDEOS), path))) {
|
||||
NS_NewLocalFile(path, /* aFollowLinks */ true,
|
||||
getter_AddRefs(mDirs[TYPE_VIDEOS]));
|
||||
}
|
||||
if (NS_SUCCEEDED(mozilla::AndroidBridge::GetExternalPublicDirectory(
|
||||
NS_LITERAL_STRING(DEVICESTORAGE_MUSIC), path))) {
|
||||
NS_NewLocalFile(path, /* aFollowLinks */ true,
|
||||
getter_AddRefs(mDirs[TYPE_MUSIC]));
|
||||
}
|
||||
if (NS_SUCCEEDED(mozilla::AndroidBridge::GetExternalPublicDirectory(
|
||||
NS_LITERAL_STRING(DEVICESTORAGE_SDCARD), path))) {
|
||||
NS_NewLocalFile(path, /* aFollowLinks */ true,
|
||||
getter_AddRefs(mDirs[TYPE_SDCARD]));
|
||||
}
|
||||
|
||||
#elif defined (XP_UNIX)
|
||||
dirService->Get(NS_UNIX_XDG_PICTURES_DIR,
|
||||
NS_GET_IID(nsIFile),
|
||||
getter_AddRefs(mDirs[TYPE_PICTURES]));
|
||||
dirService->Get(NS_UNIX_XDG_VIDEOS_DIR,
|
||||
NS_GET_IID(nsIFile),
|
||||
getter_AddRefs(mDirs[TYPE_VIDEOS]));
|
||||
dirService->Get(NS_UNIX_XDG_MUSIC_DIR,
|
||||
NS_GET_IID(nsIFile),
|
||||
getter_AddRefs(mDirs[TYPE_MUSIC]));
|
||||
|
||||
#elif defined (XP_WIN)
|
||||
dirService->Get(NS_WIN_PICTURES_DIR,
|
||||
NS_GET_IID(nsIFile),
|
||||
getter_AddRefs(mDirs[TYPE_PICTURES]));
|
||||
dirService->Get(NS_WIN_VIDEOS_DIR,
|
||||
NS_GET_IID(nsIFile),
|
||||
getter_AddRefs(mDirs[TYPE_VIDEOS]));
|
||||
dirService->Get(NS_WIN_MUSIC_DIR,
|
||||
NS_GET_IID(nsIFile),
|
||||
getter_AddRefs(mDirs[TYPE_MUSIC]));
|
||||
#endif
|
||||
|
||||
#ifndef MOZ_WIDGET_ANDROID
|
||||
// Eventually, on desktop, we want to do something smarter -- for example,
|
||||
// detect when an sdcard is inserted, and use that instead of this.
|
||||
dirService->Get(NS_APP_USER_PROFILE_50_DIR, NS_GET_IID(nsIFile),
|
||||
getter_AddRefs(mDirs[TYPE_SDCARD]));
|
||||
if (mDirs[TYPE_SDCARD]) {
|
||||
mDirs[TYPE_SDCARD]->AppendRelativeNativePath(NS_LITERAL_CSTRING("fake-sdcard"));
|
||||
}
|
||||
#endif // !MOZ_WIDGET_ANDROID
|
||||
|
||||
dirService->Get(NS_APP_USER_PROFILE_50_DIR, NS_GET_IID(nsIFile),
|
||||
getter_AddRefs(mDirs[TYPE_APPS]));
|
||||
if (mDirs[TYPE_APPS]) {
|
||||
mDirs[TYPE_APPS]->AppendRelativeNativePath(NS_LITERAL_CSTRING("webapps"));
|
||||
}
|
||||
#endif // !MOZ_WIDGET_GONK
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
NS_NewLocalFile(NS_LITERAL_STRING("/data"),
|
||||
false,
|
||||
getter_AddRefs(mDirs[TYPE_APPS]));
|
||||
#endif
|
||||
|
||||
if (XRE_IsParentProcess()) {
|
||||
NS_GetSpecialDirectory("UAppData", getter_AddRefs(mDirs[TYPE_CRASHES]));
|
||||
if (mDirs[TYPE_CRASHES]) {
|
||||
mDirs[TYPE_CRASHES]->Append(NS_LITERAL_STRING("Crash Reports"));
|
||||
}
|
||||
}
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
// NS_GetSpecialDirectory("UAppData") fails in content processes because
|
||||
// gAppData from toolkit/xre/nsAppRunner.cpp is not initialized.
|
||||
else {
|
||||
NS_NewLocalFile(NS_LITERAL_STRING("/data/b2g/mozilla/Crash Reports"),
|
||||
false,
|
||||
getter_AddRefs(mDirs[TYPE_CRASHES]));
|
||||
}
|
||||
#endif
|
||||
|
||||
// Directories which don't depend on a volume should be calculated once
|
||||
// here. Directories which depend on the root directory of a volume
|
||||
// should be calculated in DeviceStorageFile::GetRootDirectoryForType.
|
||||
Preferences::AddStrongObserver(this, kPrefOverrideRootDir);
|
||||
ResetOverrideRootDir();
|
||||
}
|
||||
|
||||
void
|
||||
DeviceStorageStatics::DumpDirs()
|
||||
{
|
||||
#ifdef DS_LOGGING
|
||||
sMutex.AssertCurrentThreadOwns();
|
||||
|
||||
static const char* storageTypes[] = {
|
||||
"app",
|
||||
"crashes",
|
||||
"pictures",
|
||||
"videos",
|
||||
"music",
|
||||
"sdcard",
|
||||
"override",
|
||||
nullptr
|
||||
};
|
||||
|
||||
for (uint32_t i = 0; i < TYPE_COUNT; ++i) {
|
||||
MOZ_ASSERT(storageTypes[i]);
|
||||
|
||||
nsString path;
|
||||
if (mDirs[i]) {
|
||||
mDirs[i]->GetPath(path);
|
||||
}
|
||||
DS_LOG_INFO("%s: '%s'",
|
||||
storageTypes[i], NS_LossyConvertUTF16toASCII(path).get());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
DeviceStorageStatics::Shutdown()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
sMutex.AssertCurrentThreadOwns();
|
||||
DS_LOG_INFO("");
|
||||
|
||||
Preferences::RemoveObserver(this, kPrefOverrideRootDir);
|
||||
Preferences::RemoveObserver(this, kPrefTesting);
|
||||
Preferences::RemoveObserver(this, kPrefPromptTesting);
|
||||
Preferences::RemoveObserver(this, kPrefWritableName);
|
||||
}
|
||||
|
||||
/* static */ already_AddRefed<nsIFile>
|
||||
DeviceStorageStatics::GetDir(DeviceStorageType aType)
|
||||
{
|
||||
MOZ_ASSERT(aType < TYPE_COUNT);
|
||||
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
if (NS_WARN_IF(!sInstance)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIFile> file;
|
||||
switch (aType) {
|
||||
case TYPE_APPS:
|
||||
case TYPE_CRASHES:
|
||||
case TYPE_OVERRIDE:
|
||||
file = sInstance->mDirs[aType];
|
||||
return file.forget();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// In testing, we default all device storage types to a temp directory.
|
||||
// This is only initialized if the preference device.storage.testing
|
||||
// was set to true, or if device.storage.overrideRootDir is set.
|
||||
file = sInstance->mDirs[TYPE_OVERRIDE];
|
||||
if (!file) {
|
||||
file = sInstance->mDirs[aType];
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
/* We should use volume mount points on B2G. */
|
||||
MOZ_ASSERT(!file);
|
||||
#endif
|
||||
}
|
||||
return file.forget();
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
DeviceStorageStatics::HasOverrideRootDir()
|
||||
{
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
if (NS_WARN_IF(!sInstance)) {
|
||||
return false;
|
||||
}
|
||||
return sInstance->mDirs[TYPE_OVERRIDE];
|
||||
}
|
||||
|
||||
/* static */ already_AddRefed<nsIFile>
|
||||
DeviceStorageStatics::GetAppsDir()
|
||||
{
|
||||
return GetDir(TYPE_APPS);
|
||||
}
|
||||
|
||||
/* static */ already_AddRefed<nsIFile>
|
||||
DeviceStorageStatics::GetCrashesDir()
|
||||
{
|
||||
return GetDir(TYPE_CRASHES);
|
||||
}
|
||||
|
||||
/* static */ already_AddRefed<nsIFile>
|
||||
DeviceStorageStatics::GetPicturesDir()
|
||||
{
|
||||
return GetDir(TYPE_PICTURES);
|
||||
}
|
||||
|
||||
/* static */ already_AddRefed<nsIFile>
|
||||
DeviceStorageStatics::GetVideosDir()
|
||||
{
|
||||
return GetDir(TYPE_VIDEOS);
|
||||
}
|
||||
|
||||
/* static */ already_AddRefed<nsIFile>
|
||||
DeviceStorageStatics::GetMusicDir()
|
||||
{
|
||||
return GetDir(TYPE_MUSIC);
|
||||
}
|
||||
|
||||
/* static */ already_AddRefed<nsIFile>
|
||||
DeviceStorageStatics::GetSdcardDir()
|
||||
{
|
||||
return GetDir(TYPE_SDCARD);
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
DeviceStorageStatics::IsPromptTesting()
|
||||
{
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
if (NS_WARN_IF(!sInstance)) {
|
||||
return false;
|
||||
}
|
||||
return sInstance->mPromptTesting;
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
DeviceStorageStatics::GetWritableName(nsString& aName)
|
||||
{
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
if (NS_WARN_IF(!sInstance)) {
|
||||
aName.Truncate();
|
||||
return;
|
||||
}
|
||||
aName = sInstance->mWritableName;
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
DeviceStorageStatics::SetWritableName(const nsAString& aName)
|
||||
{
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
if (!NS_WARN_IF(!sInstance)) {
|
||||
// Update inline although it will be updated again in case
|
||||
// another thread comes in checking it before the update takes
|
||||
sInstance->mWritableName = aName;
|
||||
}
|
||||
|
||||
nsString name;
|
||||
name.Assign(aName);
|
||||
NS_DispatchToMainThread(NS_NewRunnableFunction([name] () -> void {
|
||||
Preferences::SetString(kPrefWritableName, name);
|
||||
}));
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
DeviceStorageStatics::AddListener(nsDOMDeviceStorage* aListener)
|
||||
{
|
||||
DS_LOG_DEBUG("%p", aListener);
|
||||
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
if (NS_WARN_IF(!sInstance)) {
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(sInstance->mInitialized);
|
||||
if (sInstance->mListeners.IsEmpty()) {
|
||||
NS_DispatchToMainThread(
|
||||
NS_NewRunnableMethod(sInstance.get(), &DeviceStorageStatics::Register));
|
||||
}
|
||||
|
||||
nsRefPtr<ListenerWrapper> wrapper =
|
||||
new ListenerWrapper(aListener);
|
||||
sInstance->mListeners.AppendElement(wrapper.forget());
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
DeviceStorageStatics::RemoveListener(nsDOMDeviceStorage* aListener)
|
||||
{
|
||||
DS_LOG_DEBUG("%p", aListener);
|
||||
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
if (!sInstance) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool removed = false;
|
||||
uint32_t i = sInstance->mListeners.Length();
|
||||
while (i > 0) {
|
||||
--i;
|
||||
if (sInstance->mListeners[i]->Equals(aListener)) {
|
||||
sInstance->mListeners.RemoveElementAt(i);
|
||||
removed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (removed && sInstance->mListeners.IsEmpty()) {
|
||||
NS_DispatchToMainThread(
|
||||
NS_NewRunnableMethod(sInstance.get(), &DeviceStorageStatics::Deregister));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DeviceStorageStatics::Register()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
DS_LOG_INFO("");
|
||||
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
if (NS_WARN_IF(!sInstance)) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
if (obs) {
|
||||
obs->AddObserver(this, kFileWatcherUpdate, false);
|
||||
obs->AddObserver(this, kDiskSpaceWatcher, false);
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
obs->AddObserver(this, NS_VOLUME_STATE_CHANGED, false);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DeviceStorageStatics::Deregister()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
DS_LOG_INFO("");
|
||||
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
if (!sInstance) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
if (obs) {
|
||||
obs->RemoveObserver(this, kFileWatcherUpdate);
|
||||
obs->RemoveObserver(this, kDiskSpaceWatcher);
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
obs->RemoveObserver(this, NS_VOLUME_STATE_CHANGED);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DeviceStorageStatics::ResetOverrideRootDir()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
sMutex.AssertCurrentThreadOwns();
|
||||
nsCOMPtr<nsIFile> f;
|
||||
DS_LOG_INFO("");
|
||||
|
||||
if (Preferences::GetBool(kPrefTesting, false)) {
|
||||
DS_LOG_INFO("temp");
|
||||
nsCOMPtr<nsIProperties> dirService
|
||||
= do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID);
|
||||
MOZ_ASSERT(dirService);
|
||||
dirService->Get(NS_OS_TEMP_DIR, NS_GET_IID(nsIFile), getter_AddRefs(f));
|
||||
if (f) {
|
||||
f->AppendRelativeNativePath(
|
||||
NS_LITERAL_CSTRING("device-storage-testing"));
|
||||
}
|
||||
} else {
|
||||
// For users running on desktop, it's convenient to be able to override
|
||||
// all of the directories to point to a single tree, much like what happens
|
||||
// on a real device.
|
||||
const nsAdoptingString& overrideRootDir =
|
||||
mozilla::Preferences::GetString(kPrefOverrideRootDir);
|
||||
if (overrideRootDir && !overrideRootDir.IsEmpty()) {
|
||||
NS_NewLocalFile(overrideRootDir, false, getter_AddRefs(f));
|
||||
}
|
||||
}
|
||||
|
||||
if (f) {
|
||||
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
|
||||
// prior to the parent.
|
||||
nsresult rv = f->Create(nsIFile::DIRECTORY_TYPE, 0777);
|
||||
if (NS_FAILED(rv) && rv != NS_ERROR_FILE_ALREADY_EXISTS) {
|
||||
nsString path;
|
||||
f->GetPath(path);
|
||||
nsPrintfCString msg("DeviceStorage: Unable to create directory '%s'",
|
||||
NS_LossyConvertUTF16toASCII(path).get());
|
||||
NS_WARNING(msg.get());
|
||||
}
|
||||
}
|
||||
f->Normalize();
|
||||
}
|
||||
|
||||
mDirs[TYPE_OVERRIDE] = f.forget();
|
||||
DumpDirs();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DeviceStorageStatics::Observe(nsISupports* aSubject,
|
||||
const char* aTopic,
|
||||
const char16_t* aData)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (!strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID)) {
|
||||
MOZ_ASSERT(aData);
|
||||
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
if (NS_WARN_IF(!sInstance)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsDependentString name(aData);
|
||||
if (name.EqualsASCII(kPrefTesting) ||
|
||||
name.EqualsASCII(kPrefOverrideRootDir)) {
|
||||
ResetOverrideRootDir();
|
||||
} else if(name.EqualsASCII(kPrefPromptTesting)) {
|
||||
mPromptTesting = Preferences::GetBool(kPrefPromptTesting, false);
|
||||
DS_LOG_INFO("prompt testing %d", mPromptTesting);
|
||||
} else if(name.EqualsASCII(kPrefWritableName)) {
|
||||
mWritableName = Preferences::GetString(kPrefWritableName);
|
||||
uint32_t i = mListeners.Length();
|
||||
DS_LOG_INFO("writable name '%s' (%u)",
|
||||
NS_LossyConvertUTF16toASCII(mWritableName).get(), i);
|
||||
while (i > 0) {
|
||||
--i;
|
||||
mListeners[i]->OnWritableNameChanged();
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
if (!strcmp(aTopic, NS_VOLUME_STATE_CHANGED)) {
|
||||
nsCOMPtr<nsIVolume> volume = do_QueryInterface(aSubject);
|
||||
if (NS_WARN_IF(!volume)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
if (NS_WARN_IF(!sInstance)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
uint32_t i = mListeners.Length();
|
||||
DS_LOG_INFO("volume updated (%u)", i);
|
||||
while (i > 0) {
|
||||
--i;
|
||||
mListeners[i]->OnVolumeStateChanged(volume);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!strcmp(aTopic, kFileWatcherUpdate)) {
|
||||
DeviceStorageFile* file = static_cast<DeviceStorageFile*>(aSubject);
|
||||
if (NS_WARN_IF(!file)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
if (NS_WARN_IF(!sInstance)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
auto data = NS_ConvertUTF16toUTF8(aData);
|
||||
uint32_t i = mListeners.Length();
|
||||
DS_LOG_INFO("file updated (%u)", i);
|
||||
while (i > 0) {
|
||||
--i;
|
||||
mListeners[i]->OnFileWatcherUpdate(data, file);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
uint32_t i = mListeners.Length();
|
||||
DS_LOG_INFO("disk space %d (%u)", lowDiskSpace, i);
|
||||
while (i > 0) {
|
||||
--i;
|
||||
mListeners[i]->OnDiskSpaceWatcher(lowDiskSpace);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) {
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
if (NS_WARN_IF(!sInstance)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
Shutdown();
|
||||
sInstance = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* Here we convert file-watcher-notify and download-watcher-notify observer
|
||||
events to file-watcher-update events. This is used to be able to
|
||||
broadcast events from one child to another child in B2G. (f.e., if one
|
||||
child decides to add a file, we want to be able to able to send a onchange
|
||||
notifications to every other child watching that device storage object).*/
|
||||
nsRefPtr<DeviceStorageFile> dsf;
|
||||
if (!strcmp(aTopic, kDownloadWatcherNotify)) {
|
||||
// aSubject will be an nsISupportsString with the native path to the file
|
||||
// in question.
|
||||
|
||||
nsCOMPtr<nsISupportsString> supportsString = do_QueryInterface(aSubject);
|
||||
if (!supportsString) {
|
||||
return NS_OK;
|
||||
}
|
||||
nsString path;
|
||||
nsresult rv = supportsString->GetData(path);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// The downloader uses the sdcard storage type.
|
||||
nsString volName;
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
if (DeviceStorageTypeChecker::IsVolumeBased(NS_LITERAL_STRING(DEVICESTORAGE_SDCARD))) {
|
||||
nsCOMPtr<nsIVolumeService> vs = do_GetService(NS_VOLUMESERVICE_CONTRACTID);
|
||||
if (NS_WARN_IF(!vs)) {
|
||||
return NS_OK;
|
||||
}
|
||||
nsCOMPtr<nsIVolume> vol;
|
||||
rv = vs->GetVolumeByPath(path, getter_AddRefs(vol));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return NS_OK;
|
||||
}
|
||||
rv = vol->GetName(volName);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return NS_OK;
|
||||
}
|
||||
nsString mountPoint;
|
||||
rv = vol->GetMountPoint(mountPoint);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return NS_OK;
|
||||
}
|
||||
if (!Substring(path, 0, mountPoint.Length()).Equals(mountPoint)) {
|
||||
return NS_OK;
|
||||
}
|
||||
path = Substring(path, mountPoint.Length() + 1);
|
||||
}
|
||||
#endif
|
||||
dsf = new DeviceStorageFile(NS_LITERAL_STRING(DEVICESTORAGE_SDCARD), volName, path);
|
||||
|
||||
} else if (!strcmp(aTopic, kFileWatcherNotify)) {
|
||||
dsf = static_cast<DeviceStorageFile*>(aSubject);
|
||||
} else {
|
||||
DS_LOG_WARN("unhandled topic '%s'", aTopic);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(!dsf || !dsf->mFile)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!XRE_IsParentProcess()) {
|
||||
// Child process. Forward the notification to the parent.
|
||||
ContentChild::GetSingleton()
|
||||
->SendFilePathUpdateNotify(dsf->mStorageType,
|
||||
dsf->mStorageName,
|
||||
dsf->mPath,
|
||||
NS_ConvertUTF16toUTF8(aData));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Multiple storage types may match the same files. So walk through each of
|
||||
// the storage types, and if the extension matches, tell them about it.
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
if (DeviceStorageTypeChecker::IsSharedMediaRoot(dsf->mStorageType)) {
|
||||
DeviceStorageTypeChecker* typeChecker
|
||||
= DeviceStorageTypeChecker::CreateOrGet();
|
||||
MOZ_ASSERT(typeChecker);
|
||||
|
||||
static const nsLiteralString kMediaTypes[] = {
|
||||
NS_LITERAL_STRING(DEVICESTORAGE_SDCARD),
|
||||
NS_LITERAL_STRING(DEVICESTORAGE_PICTURES),
|
||||
NS_LITERAL_STRING(DEVICESTORAGE_VIDEOS),
|
||||
NS_LITERAL_STRING(DEVICESTORAGE_MUSIC),
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < MOZ_ARRAY_LENGTH(kMediaTypes); i++) {
|
||||
nsRefPtr<DeviceStorageFile> dsf2;
|
||||
if (typeChecker->Check(kMediaTypes[i], dsf->mPath)) {
|
||||
if (dsf->mStorageType.Equals(kMediaTypes[i])) {
|
||||
dsf2 = dsf;
|
||||
} else {
|
||||
dsf2 = new DeviceStorageFile(kMediaTypes[i],
|
||||
dsf->mStorageName, dsf->mPath);
|
||||
}
|
||||
obs->NotifyObservers(dsf2, kFileWatcherUpdate, aData);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
obs->NotifyObservers(dsf, kFileWatcherUpdate, aData);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
DeviceStorageStatics::ListenerWrapper::ListenerWrapper(nsDOMDeviceStorage* aListener)
|
||||
: mListener(do_GetWeakReference(static_cast<DOMEventTargetHelper*>(aListener)))
|
||||
, mOwningThread(NS_GetCurrentThread())
|
||||
{
|
||||
}
|
||||
|
||||
DeviceStorageStatics::ListenerWrapper::~ListenerWrapper()
|
||||
{
|
||||
// Even weak pointers are not thread safe
|
||||
NS_ProxyRelease(mOwningThread, mListener);
|
||||
}
|
||||
|
||||
bool
|
||||
DeviceStorageStatics::ListenerWrapper::Equals(nsDOMDeviceStorage* aListener)
|
||||
{
|
||||
bool current = false;
|
||||
mOwningThread->IsOnCurrentThread(¤t);
|
||||
if (current) {
|
||||
// It is only safe to acquire the reference on the owning thread
|
||||
nsRefPtr<nsDOMDeviceStorage> listener = do_QueryReferent(mListener);
|
||||
return listener.get() == aListener;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
DeviceStorageStatics::ListenerWrapper::OnFileWatcherUpdate(const nsCString& aData,
|
||||
DeviceStorageFile* aFile)
|
||||
{
|
||||
nsRefPtr<ListenerWrapper> self = this;
|
||||
nsCString data = aData;
|
||||
nsRefPtr<DeviceStorageFile> file = aFile;
|
||||
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([self, data, file] () -> void {
|
||||
nsRefPtr<nsDOMDeviceStorage> listener = do_QueryReferent(self->mListener);
|
||||
if (listener) {
|
||||
listener->OnFileWatcherUpdate(data, file);
|
||||
}
|
||||
});
|
||||
mOwningThread->Dispatch(r, NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
void
|
||||
DeviceStorageStatics::ListenerWrapper::OnDiskSpaceWatcher(bool aLowDiskSpace)
|
||||
{
|
||||
nsRefPtr<ListenerWrapper> self = this;
|
||||
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([self, aLowDiskSpace] () -> void {
|
||||
nsRefPtr<nsDOMDeviceStorage> listener = do_QueryReferent(self->mListener);
|
||||
if (listener) {
|
||||
listener->OnDiskSpaceWatcher(aLowDiskSpace);
|
||||
}
|
||||
});
|
||||
mOwningThread->Dispatch(r, NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
void
|
||||
DeviceStorageStatics::ListenerWrapper::OnWritableNameChanged()
|
||||
{
|
||||
nsRefPtr<ListenerWrapper> self = this;
|
||||
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([self] () -> void {
|
||||
nsRefPtr<nsDOMDeviceStorage> listener = do_QueryReferent(self->mListener);
|
||||
if (listener) {
|
||||
listener->OnWritableNameChanged();
|
||||
}
|
||||
});
|
||||
mOwningThread->Dispatch(r, NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
void
|
||||
DeviceStorageStatics::ListenerWrapper::OnVolumeStateChanged(nsIVolume* aVolume)
|
||||
{
|
||||
nsRefPtr<ListenerWrapper> self = this;
|
||||
nsCOMPtr<nsIVolume> volume = aVolume;
|
||||
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([self, volume] () -> void {
|
||||
nsRefPtr<nsDOMDeviceStorage> listener = do_QueryReferent(self->mListener);
|
||||
if (listener) {
|
||||
listener->OnVolumeStateChanged(volume);
|
||||
}
|
||||
});
|
||||
mOwningThread->Dispatch(r, NS_DISPATCH_NORMAL);
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace devicestorage
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
105
dom/devicestorage/DeviceStorageStatics.h
Normal file
105
dom/devicestorage/DeviceStorageStatics.h
Normal file
@ -0,0 +1,105 @@
|
||||
/* -*- 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_devicestorage_DeviceStorageStatics_h
|
||||
#define mozilla_dom_devicestorage_DeviceStorageStatics_h
|
||||
|
||||
#include "mozilla/Mutex.h"
|
||||
|
||||
class nsDOMDeviceStorage;
|
||||
class DeviceStorageFile;
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
class nsIVolume;
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace devicestorage {
|
||||
|
||||
class DeviceStorageStatics final : public nsIObserver
|
||||
{
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
static void Initialize();
|
||||
static void InitializeDirs();
|
||||
static void AddListener(nsDOMDeviceStorage* aListener);
|
||||
static void RemoveListener(nsDOMDeviceStorage* aListener);
|
||||
|
||||
static bool IsPromptTesting();
|
||||
static void GetWritableName(nsString& aName);
|
||||
static void SetWritableName(const nsAString& aName);
|
||||
|
||||
static bool HasOverrideRootDir();
|
||||
static already_AddRefed<nsIFile> GetAppsDir();
|
||||
static already_AddRefed<nsIFile> GetCrashesDir();
|
||||
static already_AddRefed<nsIFile> GetPicturesDir();
|
||||
static already_AddRefed<nsIFile> GetVideosDir();
|
||||
static already_AddRefed<nsIFile> GetMusicDir();
|
||||
static already_AddRefed<nsIFile> GetSdcardDir();
|
||||
|
||||
private:
|
||||
enum DeviceStorageType {
|
||||
TYPE_APPS,
|
||||
TYPE_CRASHES,
|
||||
TYPE_PICTURES,
|
||||
TYPE_VIDEOS,
|
||||
TYPE_MUSIC,
|
||||
TYPE_SDCARD,
|
||||
TYPE_OVERRIDE,
|
||||
TYPE_COUNT
|
||||
};
|
||||
|
||||
static already_AddRefed<nsIFile> GetDir(DeviceStorageType aType);
|
||||
|
||||
DeviceStorageStatics();
|
||||
virtual ~DeviceStorageStatics();
|
||||
|
||||
void Init();
|
||||
void InitDirs();
|
||||
void DumpDirs();
|
||||
void Shutdown();
|
||||
void Register();
|
||||
void Deregister();
|
||||
void ResetOverrideRootDir();
|
||||
|
||||
class ListenerWrapper final {
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ListenerWrapper)
|
||||
|
||||
explicit ListenerWrapper(nsDOMDeviceStorage* aListener);
|
||||
bool Equals(nsDOMDeviceStorage* aListener);
|
||||
void OnFileWatcherUpdate(const nsCString& aData, DeviceStorageFile* aFile);
|
||||
void OnDiskSpaceWatcher(bool aLowDiskSpace);
|
||||
void OnWritableNameChanged();
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
void OnVolumeStateChanged(nsIVolume* aVolume);
|
||||
#endif
|
||||
|
||||
private:
|
||||
virtual ~ListenerWrapper();
|
||||
|
||||
nsWeakPtr mListener;
|
||||
nsCOMPtr<nsIThread> mOwningThread;
|
||||
};
|
||||
|
||||
nsTArray<nsRefPtr<ListenerWrapper> > mListeners;
|
||||
nsCOMPtr<nsIFile> mDirs[TYPE_COUNT];
|
||||
|
||||
bool mInitialized;
|
||||
bool mPromptTesting;
|
||||
nsString mWritableName;
|
||||
|
||||
static StaticRefPtr<DeviceStorageStatics> sInstance;
|
||||
static StaticMutex sMutex;
|
||||
};
|
||||
|
||||
} // namespace devicestorage
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
@ -17,12 +17,14 @@ EXPORTS.mozilla.dom += [
|
||||
EXPORTS.mozilla.dom.devicestorage += [
|
||||
'DeviceStorageRequestChild.h',
|
||||
'DeviceStorageRequestParent.h',
|
||||
'DeviceStorageStatics.h',
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'DeviceStorageAreaListener.cpp',
|
||||
'DeviceStorageRequestChild.cpp',
|
||||
'DeviceStorageRequestParent.cpp',
|
||||
'DeviceStorageStatics.cpp',
|
||||
'nsDeviceStorage.cpp',
|
||||
]
|
||||
|
||||
|
@ -24,7 +24,6 @@
|
||||
#include "mozilla/EventDispatcher.h"
|
||||
#include "mozilla/EventListenerManager.h"
|
||||
#include "mozilla/LazyIdleThread.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/Scoped.h"
|
||||
#include "mozilla/Services.h"
|
||||
|
||||
@ -34,8 +33,6 @@
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsIDirectoryEnumerator.h"
|
||||
#include "nsAppDirectoryServiceDefs.h"
|
||||
#include "nsDirectoryServiceDefs.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsIOutputStream.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
@ -45,6 +42,7 @@
|
||||
#include "nsXULAppAPI.h"
|
||||
#include "DeviceStorageFileDescriptor.h"
|
||||
#include "DeviceStorageRequestChild.h"
|
||||
#include "DeviceStorageStatics.h"
|
||||
#include "nsCRT.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsIMIMEService.h"
|
||||
@ -53,7 +51,6 @@
|
||||
#include "nsIStringBundle.h"
|
||||
#include "nsISupportsPrimitives.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsPrintfCString.h"
|
||||
#include <algorithm>
|
||||
#include "private/pprio.h"
|
||||
#include "nsContentPermissionHelper.h"
|
||||
@ -63,10 +60,6 @@
|
||||
// Microsoft's API Name hackery sucks
|
||||
#undef CreateEvent
|
||||
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
#include "AndroidBridge.h"
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
#include "nsIVolume.h"
|
||||
#include "nsIVolumeService.h"
|
||||
@ -75,8 +68,6 @@
|
||||
#define DEVICESTORAGE_PROPERTIES \
|
||||
"chrome://global/content/devicestorage.properties"
|
||||
#define DEFAULT_THREAD_TIMEOUT_MS 30000
|
||||
#define PREF_STORAGE_WRITABLE_NAME \
|
||||
"device.storage.writable.name"
|
||||
#define STORAGE_CHANGE_EVENT "change"
|
||||
|
||||
using namespace mozilla;
|
||||
@ -84,12 +75,6 @@ using namespace mozilla::dom;
|
||||
using namespace mozilla::dom::devicestorage;
|
||||
using namespace mozilla::ipc;
|
||||
|
||||
#include "nsDirectoryServiceDefs.h"
|
||||
|
||||
const char* kFileWatcherUpdate = "file-watcher-update";
|
||||
const char* kFileWatcherNotify = "file-watcher-notify";
|
||||
const char *kDownloadWatcherNotify = "download-watcher-notify";
|
||||
|
||||
namespace mozilla {
|
||||
MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLATE(ScopedPRFileDesc, PRFileDesc, PR_Close);
|
||||
} // namespace mozilla
|
||||
@ -200,25 +185,6 @@ DeviceStorageUsedSpaceCache::SetUsedSizes(const nsAString& aStorageName,
|
||||
cacheEntry->mDirty = false;
|
||||
}
|
||||
|
||||
class GlobalDirs
|
||||
{
|
||||
private:
|
||||
~GlobalDirs() {}
|
||||
public:
|
||||
NS_INLINE_DECL_REFCOUNTING(GlobalDirs)
|
||||
#if !defined(MOZ_WIDGET_GONK)
|
||||
nsCOMPtr<nsIFile> pictures;
|
||||
nsCOMPtr<nsIFile> videos;
|
||||
nsCOMPtr<nsIFile> music;
|
||||
nsCOMPtr<nsIFile> sdcard;
|
||||
#endif
|
||||
nsCOMPtr<nsIFile> apps;
|
||||
nsCOMPtr<nsIFile> crashes;
|
||||
nsCOMPtr<nsIFile> overrideRootDir;
|
||||
};
|
||||
|
||||
static StaticRefPtr<GlobalDirs> sDirs;
|
||||
|
||||
StaticAutoPtr<DeviceStorageTypeChecker>
|
||||
DeviceStorageTypeChecker::sDeviceStorageTypeChecker;
|
||||
|
||||
@ -475,136 +441,10 @@ DeviceStorageTypeChecker::IsSharedMediaRoot(const nsAString& aType)
|
||||
#else
|
||||
// For desktop, if the directories have been overridden, then they share
|
||||
// a common root.
|
||||
return IsMediaType(aType) && sDirs->overrideRootDir;
|
||||
return IsMediaType(aType) && DeviceStorageStatics::HasOverrideRootDir();
|
||||
#endif
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(FileUpdateDispatcher, nsIObserver)
|
||||
|
||||
mozilla::StaticRefPtr<FileUpdateDispatcher> FileUpdateDispatcher::sSingleton;
|
||||
|
||||
FileUpdateDispatcher*
|
||||
FileUpdateDispatcher::GetSingleton()
|
||||
{
|
||||
if (sSingleton) {
|
||||
return sSingleton;
|
||||
}
|
||||
|
||||
sSingleton = new FileUpdateDispatcher();
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
obs->AddObserver(sSingleton, kFileWatcherNotify, false);
|
||||
obs->AddObserver(sSingleton, kDownloadWatcherNotify, false);
|
||||
ClearOnShutdown(&sSingleton);
|
||||
|
||||
return sSingleton;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
FileUpdateDispatcher::Observe(nsISupports* aSubject,
|
||||
const char* aTopic,
|
||||
const char16_t* aData)
|
||||
{
|
||||
nsRefPtr<DeviceStorageFile> dsf;
|
||||
|
||||
if (!strcmp(aTopic, kDownloadWatcherNotify)) {
|
||||
// aSubject will be an nsISupportsString with the native path to the file
|
||||
// in question.
|
||||
|
||||
nsCOMPtr<nsISupportsString> supportsString = do_QueryInterface(aSubject);
|
||||
if (!supportsString) {
|
||||
return NS_OK;
|
||||
}
|
||||
nsString path;
|
||||
nsresult rv = supportsString->GetData(path);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// The downloader uses the sdcard storage type.
|
||||
nsString volName;
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
if (DeviceStorageTypeChecker::IsVolumeBased(NS_LITERAL_STRING(DEVICESTORAGE_SDCARD))) {
|
||||
nsCOMPtr<nsIVolumeService> vs = do_GetService(NS_VOLUMESERVICE_CONTRACTID);
|
||||
if (NS_WARN_IF(!vs)) {
|
||||
return NS_OK;
|
||||
}
|
||||
nsCOMPtr<nsIVolume> vol;
|
||||
rv = vs->GetVolumeByPath(path, getter_AddRefs(vol));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return NS_OK;
|
||||
}
|
||||
rv = vol->GetName(volName);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return NS_OK;
|
||||
}
|
||||
nsString mountPoint;
|
||||
rv = vol->GetMountPoint(mountPoint);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return NS_OK;
|
||||
}
|
||||
if (!Substring(path, 0, mountPoint.Length()).Equals(mountPoint)) {
|
||||
return NS_OK;
|
||||
}
|
||||
path = Substring(path, mountPoint.Length() + 1);
|
||||
}
|
||||
#endif
|
||||
dsf = new DeviceStorageFile(NS_LITERAL_STRING(DEVICESTORAGE_SDCARD), volName, path);
|
||||
|
||||
} else if (!strcmp(aTopic, kFileWatcherNotify)) {
|
||||
dsf = static_cast<DeviceStorageFile*>(aSubject);
|
||||
} else {
|
||||
NS_WARNING("FileUpdateDispatcher: Unrecognized topic");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!dsf || !dsf->mFile) {
|
||||
NS_WARNING("FileUpdateDispatcher: Device storage file looks invalid!");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!XRE_IsParentProcess()) {
|
||||
// Child process. Forward the notification to the parent.
|
||||
ContentChild::GetSingleton()
|
||||
->SendFilePathUpdateNotify(dsf->mStorageType,
|
||||
dsf->mStorageName,
|
||||
dsf->mPath,
|
||||
NS_ConvertUTF16toUTF8(aData));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Multiple storage types may match the same files. So walk through each of
|
||||
// the storage types, and if the extension matches, tell them about it.
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
if (DeviceStorageTypeChecker::IsSharedMediaRoot(dsf->mStorageType)) {
|
||||
DeviceStorageTypeChecker* typeChecker
|
||||
= DeviceStorageTypeChecker::CreateOrGet();
|
||||
MOZ_ASSERT(typeChecker);
|
||||
|
||||
static const nsLiteralString kMediaTypes[] = {
|
||||
NS_LITERAL_STRING(DEVICESTORAGE_SDCARD),
|
||||
NS_LITERAL_STRING(DEVICESTORAGE_PICTURES),
|
||||
NS_LITERAL_STRING(DEVICESTORAGE_VIDEOS),
|
||||
NS_LITERAL_STRING(DEVICESTORAGE_MUSIC),
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < MOZ_ARRAY_LENGTH(kMediaTypes); i++) {
|
||||
nsRefPtr<DeviceStorageFile> dsf2;
|
||||
if (typeChecker->Check(kMediaTypes[i], dsf->mPath)) {
|
||||
if (dsf->mStorageType.Equals(kMediaTypes[i])) {
|
||||
dsf2 = dsf;
|
||||
} else {
|
||||
dsf2 = new DeviceStorageFile(kMediaTypes[i],
|
||||
dsf->mStorageName, dsf->mPath);
|
||||
}
|
||||
obs->NotifyObservers(dsf2, kFileWatcherUpdate, aData);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
obs->NotifyObservers(dsf, kFileWatcherUpdate, aData);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
class IOEventComplete : public nsRunnable
|
||||
{
|
||||
public:
|
||||
@ -623,7 +463,7 @@ public:
|
||||
CopyASCIItoUTF16(mType, data);
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
|
||||
obs->NotifyObservers(mFile, kFileWatcherNotify, data.get());
|
||||
obs->NotifyObservers(mFile, "file-watcher-notify", data.get());
|
||||
|
||||
DeviceStorageUsedSpaceCache* usedSpaceCache
|
||||
= DeviceStorageUsedSpaceCache::CreateOrGet();
|
||||
@ -721,240 +561,6 @@ DeviceStorageFile::Init()
|
||||
MOZ_ASSERT(typeChecker);
|
||||
}
|
||||
|
||||
// The OverrideRootDir is needed to facilitate testing of the
|
||||
// device.storage.overrideRootDir preference. The preference is normally
|
||||
// only read once during initialization, but since the test environment has
|
||||
// no convenient way to restart, we use a pref watcher instead.
|
||||
class OverrideRootDir final : public nsIObserver
|
||||
{
|
||||
~OverrideRootDir();
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
static OverrideRootDir* GetSingleton();
|
||||
void Init();
|
||||
private:
|
||||
static mozilla::StaticRefPtr<OverrideRootDir> sSingleton;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(OverrideRootDir, nsIObserver)
|
||||
|
||||
mozilla::StaticRefPtr<OverrideRootDir>
|
||||
OverrideRootDir::sSingleton;
|
||||
|
||||
OverrideRootDir*
|
||||
OverrideRootDir::GetSingleton()
|
||||
{
|
||||
if (sSingleton) {
|
||||
return sSingleton;
|
||||
}
|
||||
// Preference changes are automatically forwarded from parent to child
|
||||
// in ContentParent::Observe, so we'll see the change in both the parent
|
||||
// and the child process.
|
||||
|
||||
sSingleton = new OverrideRootDir();
|
||||
Preferences::AddStrongObserver(sSingleton, "device.storage.overrideRootDir");
|
||||
Preferences::AddStrongObserver(sSingleton, "device.storage.testing");
|
||||
ClearOnShutdown(&sSingleton);
|
||||
|
||||
return sSingleton;
|
||||
}
|
||||
|
||||
OverrideRootDir::~OverrideRootDir()
|
||||
{
|
||||
Preferences::RemoveObserver(this, "device.storage.overrideRootDir");
|
||||
Preferences::RemoveObserver(this, "device.storage.testing");
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
OverrideRootDir::Observe(nsISupports *aSubject,
|
||||
const char *aTopic,
|
||||
const char16_t *aData)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (sSingleton) {
|
||||
sSingleton->Init();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
OverrideRootDir::Init()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (!sDirs) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mozilla::Preferences::GetBool("device.storage.testing", false)) {
|
||||
nsCOMPtr<nsIProperties> dirService
|
||||
= do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID);
|
||||
MOZ_ASSERT(dirService);
|
||||
dirService->Get(NS_OS_TEMP_DIR, NS_GET_IID(nsIFile),
|
||||
getter_AddRefs(sDirs->overrideRootDir));
|
||||
if (sDirs->overrideRootDir) {
|
||||
sDirs->overrideRootDir->AppendRelativeNativePath(
|
||||
NS_LITERAL_CSTRING("device-storage-testing"));
|
||||
}
|
||||
} else {
|
||||
// For users running on desktop, it's convenient to be able to override
|
||||
// all of the directories to point to a single tree, much like what happens
|
||||
// on a real device.
|
||||
const nsAdoptingString& overrideRootDir =
|
||||
mozilla::Preferences::GetString("device.storage.overrideRootDir");
|
||||
if (overrideRootDir && overrideRootDir.Length() > 0) {
|
||||
NS_NewLocalFile(overrideRootDir, false,
|
||||
getter_AddRefs(sDirs->overrideRootDir));
|
||||
} else {
|
||||
sDirs->overrideRootDir = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (sDirs->overrideRootDir) {
|
||||
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
|
||||
// prior to the parent.
|
||||
nsresult rv
|
||||
= sDirs->overrideRootDir->Create(nsIFile::DIRECTORY_TYPE, 0777);
|
||||
nsString path;
|
||||
sDirs->overrideRootDir->GetPath(path);
|
||||
if (NS_FAILED(rv) && rv != NS_ERROR_FILE_ALREADY_EXISTS) {
|
||||
nsPrintfCString msg("DeviceStorage: Unable to create directory '%s'",
|
||||
NS_LossyConvertUTF16toASCII(path).get());
|
||||
NS_WARNING(msg.get());
|
||||
}
|
||||
}
|
||||
sDirs->overrideRootDir->Normalize();
|
||||
}
|
||||
}
|
||||
|
||||
// Directories which don't depend on a volume should be calculated once
|
||||
// here. Directories which depend on the root directory of a volume
|
||||
// should be calculated in DeviceStorageFile::GetRootDirectoryForType.
|
||||
static void
|
||||
InitDirs()
|
||||
{
|
||||
if (sDirs) {
|
||||
return;
|
||||
}
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
sDirs = new GlobalDirs;
|
||||
ClearOnShutdown(&sDirs);
|
||||
|
||||
nsCOMPtr<nsIProperties> dirService
|
||||
= do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID);
|
||||
MOZ_ASSERT(dirService);
|
||||
|
||||
#if !defined(MOZ_WIDGET_GONK)
|
||||
|
||||
// Keep MOZ_WIDGET_COCOA above XP_UNIX,
|
||||
// because both are defined in Darwin builds.
|
||||
#if defined (MOZ_WIDGET_COCOA)
|
||||
dirService->Get(NS_OSX_PICTURE_DOCUMENTS_DIR,
|
||||
NS_GET_IID(nsIFile),
|
||||
getter_AddRefs(sDirs->pictures));
|
||||
dirService->Get(NS_OSX_MOVIE_DOCUMENTS_DIR,
|
||||
NS_GET_IID(nsIFile),
|
||||
getter_AddRefs(sDirs->videos));
|
||||
dirService->Get(NS_OSX_MUSIC_DOCUMENTS_DIR,
|
||||
NS_GET_IID(nsIFile),
|
||||
getter_AddRefs(sDirs->music));
|
||||
|
||||
// Keep MOZ_WIDGET_ANDROID above XP_UNIX,
|
||||
// because both are defined in Android builds.
|
||||
#elif defined (MOZ_WIDGET_ANDROID)
|
||||
nsAutoString path;
|
||||
if (NS_SUCCEEDED(mozilla::AndroidBridge::GetExternalPublicDirectory(
|
||||
NS_LITERAL_STRING(DEVICESTORAGE_PICTURES), path))) {
|
||||
NS_NewLocalFile(path, /* aFollowLinks */ true,
|
||||
getter_AddRefs(sDirs->pictures));
|
||||
}
|
||||
if (NS_SUCCEEDED(mozilla::AndroidBridge::GetExternalPublicDirectory(
|
||||
NS_LITERAL_STRING(DEVICESTORAGE_VIDEOS), path))) {
|
||||
NS_NewLocalFile(path, /* aFollowLinks */ true,
|
||||
getter_AddRefs(sDirs->videos));
|
||||
}
|
||||
if (NS_SUCCEEDED(mozilla::AndroidBridge::GetExternalPublicDirectory(
|
||||
NS_LITERAL_STRING(DEVICESTORAGE_MUSIC), path))) {
|
||||
NS_NewLocalFile(path, /* aFollowLinks */ true,
|
||||
getter_AddRefs(sDirs->music));
|
||||
}
|
||||
if (NS_SUCCEEDED(mozilla::AndroidBridge::GetExternalPublicDirectory(
|
||||
NS_LITERAL_STRING(DEVICESTORAGE_SDCARD), path))) {
|
||||
NS_NewLocalFile(path, /* aFollowLinks */ true,
|
||||
getter_AddRefs(sDirs->sdcard));
|
||||
}
|
||||
|
||||
#elif defined (XP_UNIX)
|
||||
dirService->Get(NS_UNIX_XDG_PICTURES_DIR,
|
||||
NS_GET_IID(nsIFile),
|
||||
getter_AddRefs(sDirs->pictures));
|
||||
dirService->Get(NS_UNIX_XDG_VIDEOS_DIR,
|
||||
NS_GET_IID(nsIFile),
|
||||
getter_AddRefs(sDirs->videos));
|
||||
dirService->Get(NS_UNIX_XDG_MUSIC_DIR,
|
||||
NS_GET_IID(nsIFile),
|
||||
getter_AddRefs(sDirs->music));
|
||||
|
||||
#elif defined (XP_WIN)
|
||||
dirService->Get(NS_WIN_PICTURES_DIR,
|
||||
NS_GET_IID(nsIFile),
|
||||
getter_AddRefs(sDirs->pictures));
|
||||
dirService->Get(NS_WIN_VIDEOS_DIR,
|
||||
NS_GET_IID(nsIFile),
|
||||
getter_AddRefs(sDirs->videos));
|
||||
dirService->Get(NS_WIN_MUSIC_DIR,
|
||||
NS_GET_IID(nsIFile),
|
||||
getter_AddRefs(sDirs->music));
|
||||
#endif
|
||||
|
||||
#ifndef MOZ_WIDGET_ANDROID
|
||||
// Eventually, on desktop, we want to do something smarter -- for example,
|
||||
// detect when an sdcard is inserted, and use that instead of this.
|
||||
dirService->Get(NS_APP_USER_PROFILE_50_DIR, NS_GET_IID(nsIFile),
|
||||
getter_AddRefs(sDirs->sdcard));
|
||||
if (sDirs->sdcard) {
|
||||
sDirs->sdcard->AppendRelativeNativePath(NS_LITERAL_CSTRING("fake-sdcard"));
|
||||
}
|
||||
#endif // !MOZ_WIDGET_ANDROID
|
||||
#endif // !MOZ_WIDGET_GONK
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
NS_NewLocalFile(NS_LITERAL_STRING("/data"),
|
||||
false,
|
||||
getter_AddRefs(sDirs->apps));
|
||||
#else
|
||||
dirService->Get(NS_APP_USER_PROFILE_50_DIR, NS_GET_IID(nsIFile),
|
||||
getter_AddRefs(sDirs->apps));
|
||||
if (sDirs->apps) {
|
||||
sDirs->apps->AppendRelativeNativePath(NS_LITERAL_CSTRING("webapps"));
|
||||
}
|
||||
#endif
|
||||
|
||||
if (XRE_IsParentProcess()) {
|
||||
NS_GetSpecialDirectory("UAppData", getter_AddRefs(sDirs->crashes));
|
||||
if (sDirs->crashes) {
|
||||
sDirs->crashes->Append(NS_LITERAL_STRING("Crash Reports"));
|
||||
}
|
||||
} else {
|
||||
// NS_GetSpecialDirectory("UAppData") fails in content processes because
|
||||
// gAppData from toolkit/xre/nsAppRunner.cpp is not initialized.
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
NS_NewLocalFile(NS_LITERAL_STRING("/data/b2g/mozilla/Crash Reports"),
|
||||
false,
|
||||
getter_AddRefs(sDirs->crashes));
|
||||
#endif
|
||||
}
|
||||
|
||||
OverrideRootDir::GetSingleton()->Init();
|
||||
}
|
||||
|
||||
void
|
||||
DeviceStorageFile::GetFullPath(nsAString &aFullPath)
|
||||
{
|
||||
@ -973,8 +579,8 @@ DeviceStorageFile::GetFullPath(nsAString &aFullPath)
|
||||
|
||||
|
||||
// Directories which don't depend on a volume should be calculated once
|
||||
// in InitDirs. Directories which depend on the root directory of a volume
|
||||
// should be calculated in this method.
|
||||
// in DeviceStorageStatics::Initialize. Directories which depend on the
|
||||
// root directory of a volume should be calculated in this method.
|
||||
void
|
||||
DeviceStorageFile::GetRootDirectoryForType(const nsAString& aStorageType,
|
||||
const nsAString& aStorageName,
|
||||
@ -982,9 +588,8 @@ DeviceStorageFile::GetRootDirectoryForType(const nsAString& aStorageType,
|
||||
{
|
||||
nsCOMPtr<nsIFile> f;
|
||||
*aFile = nullptr;
|
||||
bool allowOverride = true;
|
||||
|
||||
InitDirs();
|
||||
DeviceStorageStatics::InitializeDirs();
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
nsresult rv;
|
||||
@ -994,7 +599,7 @@ DeviceStorageFile::GetRootDirectoryForType(const nsAString& aStorageType,
|
||||
NS_ENSURE_TRUE_VOID(vs);
|
||||
nsCOMPtr<nsIVolume> vol;
|
||||
rv = vs->GetVolumeByName(aStorageName, getter_AddRefs(vol));
|
||||
if(NS_FAILED(rv)) {
|
||||
if (NS_FAILED(rv)) {
|
||||
printf_stderr("##### DeviceStorage: GetVolumeByName('%s') failed\n",
|
||||
NS_LossyConvertUTF16toASCII(aStorageName).get());
|
||||
}
|
||||
@ -1003,85 +608,36 @@ DeviceStorageFile::GetRootDirectoryForType(const nsAString& aStorageType,
|
||||
}
|
||||
#endif
|
||||
|
||||
// Picture directory
|
||||
if (aStorageType.EqualsLiteral(DEVICESTORAGE_PICTURES)) {
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
rv = NS_NewLocalFile(volMountPoint, false, getter_AddRefs(f));
|
||||
if(NS_FAILED(rv)) {
|
||||
printf_stderr("##### DeviceStorage: NS_NewLocalFile failed StorageType: '%s' path '%s'\n",
|
||||
NS_LossyConvertUTF16toASCII(volMountPoint).get(),
|
||||
NS_LossyConvertUTF16toASCII(aStorageType).get());
|
||||
}
|
||||
#else
|
||||
f = sDirs->pictures;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Video directory
|
||||
else if (aStorageType.EqualsLiteral(DEVICESTORAGE_VIDEOS)) {
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
rv = NS_NewLocalFile(volMountPoint, false, getter_AddRefs(f));
|
||||
if(NS_FAILED(rv)) {
|
||||
printf_stderr("##### DeviceStorage: NS_NewLocalFile failed StorageType: '%s' path '%s'\n",
|
||||
NS_LossyConvertUTF16toASCII(volMountPoint).get(),
|
||||
NS_LossyConvertUTF16toASCII(aStorageType).get());
|
||||
}
|
||||
#else
|
||||
f = sDirs->videos;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Music directory
|
||||
else if (aStorageType.EqualsLiteral(DEVICESTORAGE_MUSIC)) {
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
rv = NS_NewLocalFile(volMountPoint, false, getter_AddRefs(f));
|
||||
if(NS_FAILED(rv)) {
|
||||
printf_stderr("##### DeviceStorage: NS_NewLocalFile failed StorageType: '%s' path '%s'\n",
|
||||
NS_LossyConvertUTF16toASCII(volMountPoint).get(),
|
||||
NS_LossyConvertUTF16toASCII(aStorageType).get());
|
||||
}
|
||||
#else
|
||||
f = sDirs->music;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Apps directory
|
||||
else if (aStorageType.EqualsLiteral(DEVICESTORAGE_APPS)) {
|
||||
f = sDirs->apps;
|
||||
allowOverride = false;
|
||||
}
|
||||
|
||||
// default SDCard
|
||||
else if (aStorageType.EqualsLiteral(DEVICESTORAGE_SDCARD)) {
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
rv = NS_NewLocalFile(volMountPoint, false, getter_AddRefs(f));
|
||||
if(NS_FAILED(rv)) {
|
||||
printf_stderr("##### DeviceStorage: NS_NewLocalFile failed StorageType: '%s' path '%s'\n",
|
||||
NS_LossyConvertUTF16toASCII(volMountPoint).get(),
|
||||
NS_LossyConvertUTF16toASCII(aStorageType).get());
|
||||
}
|
||||
#else
|
||||
f = sDirs->sdcard;
|
||||
#endif
|
||||
}
|
||||
|
||||
// crash reports directory.
|
||||
else if (aStorageType.EqualsLiteral(DEVICESTORAGE_CRASHES)) {
|
||||
f = sDirs->crashes;
|
||||
allowOverride = false;
|
||||
f = DeviceStorageStatics::GetPicturesDir();
|
||||
} else if (aStorageType.EqualsLiteral(DEVICESTORAGE_VIDEOS)) {
|
||||
f = DeviceStorageStatics::GetVideosDir();
|
||||
} else if (aStorageType.EqualsLiteral(DEVICESTORAGE_MUSIC)) {
|
||||
f = DeviceStorageStatics::GetMusicDir();
|
||||
} else if (aStorageType.EqualsLiteral(DEVICESTORAGE_APPS)) {
|
||||
f = DeviceStorageStatics::GetAppsDir();
|
||||
} else if (aStorageType.EqualsLiteral(DEVICESTORAGE_CRASHES)) {
|
||||
f = DeviceStorageStatics::GetCrashesDir();
|
||||
} else if (aStorageType.EqualsLiteral(DEVICESTORAGE_SDCARD)) {
|
||||
f = DeviceStorageStatics::GetSdcardDir();
|
||||
} else {
|
||||
// Not a storage type that we recognize. Return null
|
||||
printf_stderr("##### DeviceStorage: Unrecognized StorageType: '%s'\n",
|
||||
NS_LossyConvertUTF16toASCII(aStorageType).get());
|
||||
return;
|
||||
}
|
||||
|
||||
// In testing, we default all device storage types to a temp directory.
|
||||
// sDirs->overrideRootDir will only have been initialized (in InitDirs)
|
||||
// if the preference device.storage.testing was set to true, or if
|
||||
// device.storage.overrideRootDir is set. We can't test the preferences
|
||||
// directly here, since we may not be on the main thread.
|
||||
if (allowOverride && sDirs->overrideRootDir) {
|
||||
f = sDirs->overrideRootDir;
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
/* For volume based storage types, we will only have a file already
|
||||
if the override root directory option is in effect. */
|
||||
if (!f && !volMountPoint.IsEmpty()) {
|
||||
rv = NS_NewLocalFile(volMountPoint, false, getter_AddRefs(f));
|
||||
if (NS_FAILED(rv)) {
|
||||
printf_stderr("##### DeviceStorage: NS_NewLocalFile failed StorageType: '%s' path '%s'\n",
|
||||
NS_LossyConvertUTF16toASCII(volMountPoint).get(),
|
||||
NS_LossyConvertUTF16toASCII(aStorageType).get());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (f) {
|
||||
f->Clone(aFile);
|
||||
@ -1841,24 +1397,6 @@ DeviceStorageFile::GetStorageStatus(nsAString& aStatus)
|
||||
|
||||
NS_IMPL_ISUPPORTS0(DeviceStorageFile)
|
||||
|
||||
static void
|
||||
RegisterForSDCardChanges(nsIObserver* aObserver)
|
||||
{
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
obs->AddObserver(aObserver, NS_VOLUME_STATE_CHANGED, false);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
UnregisterForSDCardChanges(nsIObserver* aObserver)
|
||||
{
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
obs->RemoveObserver(aObserver, NS_VOLUME_STATE_CHANGED);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMDeviceStorage::SetRootDirectoryForType(const nsAString& aStorageType,
|
||||
const nsAString& aStorageName)
|
||||
@ -1869,9 +1407,6 @@ nsDOMDeviceStorage::SetRootDirectoryForType(const nsAString& aStorageType,
|
||||
DeviceStorageFile::GetRootDirectoryForType(aStorageType,
|
||||
aStorageName,
|
||||
getter_AddRefs(f));
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
obs->AddObserver(this, kFileWatcherUpdate, false);
|
||||
obs->AddObserver(this, "disk-space-watcher", false);
|
||||
mRootDirectory = f;
|
||||
mStorageType = aStorageType;
|
||||
mStorageName = aStorageName;
|
||||
@ -2930,7 +2465,7 @@ public:
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (mozilla::Preferences::GetBool("device.storage.prompt.testing", false)) {
|
||||
if (DeviceStorageStatics::IsPromptTesting()) {
|
||||
Allow(JS::UndefinedHandleValue);
|
||||
return NS_OK;
|
||||
}
|
||||
@ -3363,7 +2898,12 @@ NS_IMPL_CYCLE_COLLECTION(DeviceStorageRequest,
|
||||
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsDOMDeviceStorage)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIObserver)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
|
||||
/* nsISupports is an ambiguous base of nsDOMDeviceStorage
|
||||
so we have to work around that. */
|
||||
if ( aIID.Equals(NS_GET_IID(nsDOMDeviceStorage)) )
|
||||
foundInterface = static_cast<nsISupports*>(static_cast<void*>(this));
|
||||
else
|
||||
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(nsDOMDeviceStorage, DOMEventTargetHelper)
|
||||
@ -3392,20 +2932,16 @@ nsresult
|
||||
nsDOMDeviceStorage::Init(nsPIDOMWindow* aWindow, const nsAString &aType,
|
||||
const nsAString &aVolName)
|
||||
{
|
||||
DebugOnly<FileUpdateDispatcher*> observer
|
||||
= FileUpdateDispatcher::GetSingleton();
|
||||
MOZ_ASSERT(observer);
|
||||
|
||||
MOZ_ASSERT(aWindow);
|
||||
|
||||
SetRootDirectoryForType(aType, aVolName);
|
||||
if (!mRootDirectory) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
DeviceStorageStatics::AddListener(this);
|
||||
if (!mStorageName.IsEmpty()) {
|
||||
Preferences::AddStrongObserver(this, PREF_STORAGE_WRITABLE_NAME);
|
||||
mIsDefaultLocation = Default();
|
||||
RegisterForSDCardChanges(this);
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
if (DeviceStorageTypeChecker::IsVolumeBased(mStorageType)) {
|
||||
@ -3467,6 +3003,7 @@ nsDOMDeviceStorage::~nsDOMDeviceStorage()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
sInstanceCount--;
|
||||
DeviceStorageStatics::RemoveListener(this);
|
||||
}
|
||||
|
||||
void
|
||||
@ -3479,14 +3016,7 @@ nsDOMDeviceStorage::Shutdown()
|
||||
mFileSystem = nullptr;
|
||||
}
|
||||
|
||||
if (!mStorageName.IsEmpty()) {
|
||||
Preferences::RemoveObserver(this, PREF_STORAGE_WRITABLE_NAME);
|
||||
UnregisterForSDCardChanges(this);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
obs->RemoveObserver(this, kFileWatcherUpdate);
|
||||
obs->RemoveObserver(this, "disk-space-watcher");
|
||||
DeviceStorageStatics::RemoveListener(this);
|
||||
}
|
||||
|
||||
StaticAutoPtr<nsTArray<nsString>> nsDOMDeviceStorage::sVolumeNameCache;
|
||||
@ -3505,7 +3035,20 @@ void nsDOMDeviceStorage::InvalidateVolumeCaches()
|
||||
// static
|
||||
void
|
||||
nsDOMDeviceStorage::GetOrderedVolumeNames(
|
||||
nsDOMDeviceStorage::VolumeNameArray &aVolumeNames)
|
||||
const nsAString& aType,
|
||||
nsDOMDeviceStorage::VolumeNameArray& aVolumeNames)
|
||||
{
|
||||
if (!DeviceStorageTypeChecker::IsVolumeBased(aType)) {
|
||||
aVolumeNames.Clear();
|
||||
return;
|
||||
}
|
||||
GetOrderedVolumeNames(aVolumeNames);
|
||||
}
|
||||
|
||||
// static
|
||||
void
|
||||
nsDOMDeviceStorage::GetOrderedVolumeNames(
|
||||
nsDOMDeviceStorage::VolumeNameArray& aVolumeNames)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
@ -3554,12 +3097,7 @@ nsDOMDeviceStorage::CreateDeviceStorageFor(nsPIDOMWindow* aWin,
|
||||
nsDOMDeviceStorage** aStore)
|
||||
{
|
||||
nsString storageName;
|
||||
if (!DeviceStorageTypeChecker::IsVolumeBased(aType)) {
|
||||
// The storage name will be the empty string
|
||||
storageName.Truncate();
|
||||
} else {
|
||||
GetDefaultStorageName(aType, storageName);
|
||||
}
|
||||
GetDefaultStorageName(aType, storageName);
|
||||
|
||||
nsRefPtr<nsDOMDeviceStorage> ds = new nsDOMDeviceStorage(aWin);
|
||||
if (NS_FAILED(ds->Init(aWin, aType, storageName))) {
|
||||
@ -3569,37 +3107,6 @@ nsDOMDeviceStorage::CreateDeviceStorageFor(nsPIDOMWindow* aWin,
|
||||
ds.forget(aStore);
|
||||
}
|
||||
|
||||
// static
|
||||
void
|
||||
nsDOMDeviceStorage::CreateDeviceStoragesFor(
|
||||
nsPIDOMWindow* aWin,
|
||||
const nsAString &aType,
|
||||
nsTArray<nsRefPtr<nsDOMDeviceStorage> > &aStores)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
if (!DeviceStorageTypeChecker::IsVolumeBased(aType)) {
|
||||
nsRefPtr<nsDOMDeviceStorage> storage = new nsDOMDeviceStorage(aWin);
|
||||
rv = storage->Init(aWin, aType, EmptyString());
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
aStores.AppendElement(storage);
|
||||
}
|
||||
return;
|
||||
}
|
||||
VolumeNameArray volNames;
|
||||
GetOrderedVolumeNames(volNames);
|
||||
|
||||
VolumeNameArray::size_type numVolumeNames = volNames.Length();
|
||||
for (VolumeNameArray::index_type i = 0; i < numVolumeNames; i++) {
|
||||
nsRefPtr<nsDOMDeviceStorage> storage = new nsDOMDeviceStorage(aWin);
|
||||
rv = storage->Init(aWin, aType, volNames[i]);
|
||||
if (NS_FAILED(rv)) {
|
||||
break;
|
||||
}
|
||||
aStores.AppendElement(storage);
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
void
|
||||
nsDOMDeviceStorage::CreateDeviceStorageByNameAndType(
|
||||
@ -3628,6 +3135,19 @@ nsDOMDeviceStorage::CreateDeviceStorageByNameAndType(
|
||||
NS_ADDREF(*aStore = storage.get());
|
||||
}
|
||||
|
||||
bool
|
||||
nsDOMDeviceStorage::Equals(nsPIDOMWindow* aWin,
|
||||
const nsAString& aName,
|
||||
const nsAString& aType)
|
||||
{
|
||||
MOZ_ASSERT(aWin);
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> window = GetOwner();
|
||||
return aWin && aWin == window &&
|
||||
mStorageName.Equals(aName) &&
|
||||
mStorageType.Equals(aType);
|
||||
}
|
||||
|
||||
// static
|
||||
bool
|
||||
nsDOMDeviceStorage::ParseFullPath(const nsAString& aFullPath,
|
||||
@ -3723,11 +3243,17 @@ void
|
||||
nsDOMDeviceStorage::GetDefaultStorageName(const nsAString& aStorageType,
|
||||
nsAString& aStorageName)
|
||||
{
|
||||
// See if the preferred volume is available.
|
||||
nsAdoptingString prefStorageName =
|
||||
mozilla::Preferences::GetString(PREF_STORAGE_WRITABLE_NAME);
|
||||
if (!DeviceStorageTypeChecker::IsVolumeBased(aStorageType)) {
|
||||
// The storage name will be the empty string
|
||||
aStorageName.Truncate();
|
||||
return;
|
||||
}
|
||||
|
||||
if (prefStorageName) {
|
||||
// See if the preferred volume is available.
|
||||
nsString prefStorageName;
|
||||
DeviceStorageStatics::GetWritableName(prefStorageName);
|
||||
|
||||
if (!prefStorageName.IsEmpty()) {
|
||||
nsString status;
|
||||
nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(aStorageType,
|
||||
prefStorageName);
|
||||
@ -3746,7 +3272,7 @@ nsDOMDeviceStorage::GetDefaultStorageName(const nsAString& aStorageType,
|
||||
if (volNames.Length() > 0) {
|
||||
aStorageName = volNames[0];
|
||||
// overwrite the value of "device.storage.writable.name"
|
||||
mozilla::Preferences::SetString(PREF_STORAGE_WRITABLE_NAME, aStorageName);
|
||||
DeviceStorageStatics::SetWritableName(aStorageName);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -4333,7 +3859,7 @@ nsDOMDeviceStorage::EnumerateInternal(const nsAString& aPath,
|
||||
nsRefPtr<DeviceStorageCursorRequest> r
|
||||
= new DeviceStorageCursorRequest(cursor);
|
||||
|
||||
if (mozilla::Preferences::GetBool("device.storage.prompt.testing", false)) {
|
||||
if (DeviceStorageStatics::IsPromptTesting()) {
|
||||
r->Allow(JS::UndefinedHandleValue);
|
||||
return cursor.forget();
|
||||
}
|
||||
@ -4344,7 +3870,7 @@ nsDOMDeviceStorage::EnumerateInternal(const nsAString& aPath,
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMDeviceStorage::DispatchDefaultChangeEvent()
|
||||
nsDOMDeviceStorage::OnWritableNameChanged()
|
||||
{
|
||||
nsAdoptingString DefaultLocation;
|
||||
GetDefaultStorageName(mStorageType, DefaultLocation);
|
||||
@ -4422,78 +3948,58 @@ nsDOMDeviceStorage::DispatchStorageStatusChangeEvent(nsAString& aStorageStatus)
|
||||
}
|
||||
#endif
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMDeviceStorage::Observe(nsISupports *aSubject,
|
||||
const char *aTopic,
|
||||
const char16_t *aData)
|
||||
void
|
||||
nsDOMDeviceStorage::OnFileWatcherUpdate(const nsCString& aData, DeviceStorageFile* aFile)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
Notify(aData.get(), aFile);
|
||||
}
|
||||
|
||||
if (!strcmp(aTopic, kFileWatcherUpdate)) {
|
||||
|
||||
DeviceStorageFile* file = static_cast<DeviceStorageFile*>(aSubject);
|
||||
Notify(NS_ConvertUTF16toUTF8(aData).get(), file);
|
||||
return NS_OK;
|
||||
}
|
||||
if (!strcmp(aTopic, "disk-space-watcher")) {
|
||||
// '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.
|
||||
nsRefPtr<DeviceStorageFile> file =
|
||||
new DeviceStorageFile(mStorageType, mStorageName);
|
||||
if (!NS_strcmp(aData, MOZ_UTF16("full"))) {
|
||||
Notify("low-disk-space", file);
|
||||
} else if (!NS_strcmp(aData, MOZ_UTF16("free"))) {
|
||||
Notify("available-disk-space", file);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID) &&
|
||||
aData &&
|
||||
nsDependentString(aData).Equals(NS_LITERAL_STRING(PREF_STORAGE_WRITABLE_NAME)))
|
||||
{
|
||||
DispatchDefaultChangeEvent();
|
||||
return NS_OK;
|
||||
void
|
||||
nsDOMDeviceStorage::OnDiskSpaceWatcher(bool aLowDiskSpace)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
nsRefPtr<DeviceStorageFile> file =
|
||||
new DeviceStorageFile(mStorageType, mStorageName);
|
||||
if (aLowDiskSpace) {
|
||||
Notify("low-disk-space", file);
|
||||
} else {
|
||||
Notify("available-disk-space", file);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
else if (!strcmp(aTopic, NS_VOLUME_STATE_CHANGED)) {
|
||||
// We invalidate the used space cache for the volume that actually changed
|
||||
// state.
|
||||
nsCOMPtr<nsIVolume> vol = do_QueryInterface(aSubject);
|
||||
if (!vol) {
|
||||
return NS_OK;
|
||||
}
|
||||
nsString volName;
|
||||
vol->GetName(volName);
|
||||
void
|
||||
nsDOMDeviceStorage::OnVolumeStateChanged(nsIVolume* aVolume) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
DeviceStorageUsedSpaceCache* usedSpaceCache
|
||||
= DeviceStorageUsedSpaceCache::CreateOrGet();
|
||||
MOZ_ASSERT(usedSpaceCache);
|
||||
usedSpaceCache->Invalidate(volName);
|
||||
// We invalidate the used space cache for the volume that actually changed
|
||||
// state.
|
||||
nsString volName;
|
||||
aVolume->GetName(volName);
|
||||
|
||||
if (!volName.Equals(mStorageName)) {
|
||||
// Not our volume - we can ignore.
|
||||
return NS_OK;
|
||||
}
|
||||
DeviceStorageUsedSpaceCache* usedSpaceCache
|
||||
= DeviceStorageUsedSpaceCache::CreateOrGet();
|
||||
MOZ_ASSERT(usedSpaceCache);
|
||||
usedSpaceCache->Invalidate(volName);
|
||||
|
||||
nsRefPtr<DeviceStorageFile> dsf(new DeviceStorageFile(mStorageType, mStorageName));
|
||||
nsString status, storageStatus;
|
||||
|
||||
// Get Status (one of "available, unavailable, shared")
|
||||
dsf->GetStatus(status);
|
||||
DispatchStatusChangeEvent(status);
|
||||
|
||||
// Get real volume status (defined in dom/system/gonk/nsIVolume.idl)
|
||||
dsf->GetStorageStatus(storageStatus);
|
||||
DispatchStorageStatusChangeEvent(storageStatus);
|
||||
return NS_OK;
|
||||
if (!volName.Equals(mStorageName)) {
|
||||
// Not our volume - we can ignore.
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
return NS_OK;
|
||||
|
||||
nsRefPtr<DeviceStorageFile> dsf(new DeviceStorageFile(mStorageType, mStorageName));
|
||||
nsString status, storageStatus;
|
||||
|
||||
// Get Status (one of "available, unavailable, shared")
|
||||
dsf->GetStatus(status);
|
||||
DispatchStatusChangeEvent(status);
|
||||
|
||||
// Get real volume status (defined in dom/system/gonk/nsIVolume.idl)
|
||||
dsf->GetStorageStatus(storageStatus);
|
||||
DispatchStorageStatusChangeEvent(storageStatus);
|
||||
}
|
||||
#endif
|
||||
|
||||
nsresult
|
||||
nsDOMDeviceStorage::Notify(const char* aReason, DeviceStorageFile* aFile)
|
||||
|
@ -39,6 +39,25 @@ class Blob;
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
//#define DS_LOGGING 1
|
||||
|
||||
#ifdef DS_LOGGING
|
||||
/* Polyfill __func__ on MSVC to pass to the log. */
|
||||
#ifdef _MSC_VER
|
||||
#define __func__ __FUNCTION__
|
||||
#endif
|
||||
|
||||
#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
|
||||
#define DS_LOG_ERROR DS_LOG_DEBUG
|
||||
#else
|
||||
#define DS_LOG_DEBUG(msg, ...)
|
||||
#define DS_LOG_INFO(msg, ...)
|
||||
#define DS_LOG_WARN(msg, ...)
|
||||
#define DS_LOG_ERROR(msg, ...)
|
||||
#endif
|
||||
|
||||
#define POST_ERROR_EVENT_FILE_EXISTS "NoModificationAllowedError"
|
||||
#define POST_ERROR_EVENT_FILE_DOES_NOT_EXIST "NotFoundError"
|
||||
#define POST_ERROR_EVENT_FILE_NOT_ENUMERABLE "TypeMismatchError"
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "nsDeviceStorage.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "nsGlobalWindow.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
@ -23,7 +24,7 @@ namespace dom {
|
||||
DeviceStorageFileSystem::DeviceStorageFileSystem(
|
||||
const nsAString& aStorageType,
|
||||
const nsAString& aStorageName)
|
||||
: mDeviceStorage(nullptr)
|
||||
: mWindowId(0)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
|
||||
|
||||
@ -76,14 +77,15 @@ DeviceStorageFileSystem::Init(nsDOMDeviceStorage* aDeviceStorage)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
|
||||
MOZ_ASSERT(aDeviceStorage);
|
||||
mDeviceStorage = aDeviceStorage;
|
||||
nsCOMPtr<nsPIDOMWindow> window = aDeviceStorage->GetOwner();
|
||||
MOZ_ASSERT(window->IsInnerWindow());
|
||||
mWindowId = window->WindowID();
|
||||
}
|
||||
|
||||
void
|
||||
DeviceStorageFileSystem::Shutdown()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
|
||||
mDeviceStorage = nullptr;
|
||||
mShutdown = true;
|
||||
}
|
||||
|
||||
@ -91,10 +93,9 @@ nsPIDOMWindow*
|
||||
DeviceStorageFileSystem::GetWindow() const
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
|
||||
if (!mDeviceStorage) {
|
||||
return nullptr;
|
||||
}
|
||||
return mDeviceStorage->GetOwner();
|
||||
nsGlobalWindow* window = nsGlobalWindow::GetInnerWindowWithId(mWindowId);
|
||||
MOZ_ASSERT_IF(!mShutdown, window);
|
||||
return window;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -48,7 +48,7 @@ private:
|
||||
nsString mStorageType;
|
||||
nsString mStorageName;
|
||||
|
||||
nsDOMDeviceStorage* mDeviceStorage;
|
||||
uint64_t mWindowId;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
@ -842,9 +842,6 @@ ContentChild::InitXPCOM()
|
||||
global->SetInitialProcessData(data);
|
||||
}
|
||||
|
||||
DebugOnly<FileUpdateDispatcher*> observer = FileUpdateDispatcher::GetSingleton();
|
||||
NS_ASSERTION(observer, "FileUpdateDispatcher is null");
|
||||
|
||||
// This object is held alive by the observer service.
|
||||
nsRefPtr<SystemMessageHandledObserver> sysMsgObserver =
|
||||
new SystemMessageHandledObserver();
|
||||
|
@ -1459,9 +1459,6 @@ ContentParent::Init()
|
||||
unused << SendActivateA11y();
|
||||
}
|
||||
#endif
|
||||
|
||||
DebugOnly<FileUpdateDispatcher*> observer = FileUpdateDispatcher::GetSingleton();
|
||||
NS_ASSERTION(observer, "FileUpdateDispatcher is null");
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -71,7 +71,8 @@ DataCall.prototype = {
|
||||
ifname: null,
|
||||
addreses: null,
|
||||
dnses: null,
|
||||
gateways: null
|
||||
gateways: null,
|
||||
pcscf: null
|
||||
};
|
||||
|
||||
function DataCallInterfaceService() {
|
||||
|
@ -960,7 +960,8 @@ function DataCall(aClientId, aApnSetting, aDataCallHandler) {
|
||||
ifname: null,
|
||||
addresses: [],
|
||||
dnses: [],
|
||||
gateways: []
|
||||
gateways: [],
|
||||
pcscf: []
|
||||
};
|
||||
this.state = NETWORK_STATE_UNKNOWN;
|
||||
this.requestedNetworkIfaces = [];
|
||||
@ -1091,6 +1092,7 @@ DataCall.prototype = {
|
||||
this.linkInfo.addresses = aDataCall.addresses ? aDataCall.addresses.split(" ") : [];
|
||||
this.linkInfo.gateways = aDataCall.gateways ? aDataCall.gateways.split(" ") : [];
|
||||
this.linkInfo.dnses = aDataCall.dnses ? aDataCall.dnses.split(" ") : [];
|
||||
this.linkInfo.pcscf = aDataCall.pcscf ? aDataCall.pcscf.split(" ") : [];
|
||||
this.state = this._getGeckoDataCallState(aDataCall);
|
||||
|
||||
// Notify DataCallHandler about data call connected.
|
||||
@ -1143,7 +1145,8 @@ DataCall.prototype = {
|
||||
ifname: aUpdatedDataCall.ifname,
|
||||
addresses: aUpdatedDataCall.addresses ? aUpdatedDataCall.addresses.split(" ") : [],
|
||||
dnses: aUpdatedDataCall.dnses ? aUpdatedDataCall.dnses.split(" ") : [],
|
||||
gateways: aUpdatedDataCall.gateways ? aUpdatedDataCall.gateways.split(" ") : []
|
||||
gateways: aUpdatedDataCall.gateways ? aUpdatedDataCall.gateways.split(" ") : [],
|
||||
pcscf: aUpdatedDataCall.pcscf ? aUpdatedDataCall.pcscf.split(" ") : []
|
||||
};
|
||||
|
||||
switch (dataCallState) {
|
||||
@ -1169,6 +1172,7 @@ DataCall.prototype = {
|
||||
this.linkInfo.addresses = newLinkInfo.addresses.slice();
|
||||
this.linkInfo.gateways = newLinkInfo.gateways.slice();
|
||||
this.linkInfo.dnses = newLinkInfo.dnses.slice();
|
||||
this.linkInfo.pcscf = newLinkInfo.pcscf.slice();
|
||||
}
|
||||
break;
|
||||
case NETWORK_STATE_DISCONNECTED:
|
||||
@ -1267,6 +1271,7 @@ DataCall.prototype = {
|
||||
this.linkInfo.addresses = [];
|
||||
this.linkInfo.dnses = [];
|
||||
this.linkInfo.gateways = [];
|
||||
this.linkInfo.pcscf = [];
|
||||
},
|
||||
|
||||
reset: function() {
|
||||
@ -1604,6 +1609,20 @@ RILNetworkInfo.prototype = {
|
||||
// See http://www.iana.org/assignments/port-numbers
|
||||
return this.getApnSetting().mmsport || -1;
|
||||
},
|
||||
|
||||
getPcscf: function(aCount) {
|
||||
if (this.type != NETWORK_TYPE_MOBILE_IMS) {
|
||||
if (DEBUG) this.debug("Error! Only IMS network can get pcscf.");
|
||||
throw Cr.NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
let linkInfo = this.getDataCall().linkInfo;
|
||||
|
||||
if (aCount) {
|
||||
aCount.value = linkInfo.pcscf.length;
|
||||
}
|
||||
return linkInfo.pcscf.slice();
|
||||
},
|
||||
};
|
||||
|
||||
function RILNetworkInterface(aDataCallHandler, aType, aApnSetting, aDataCall) {
|
||||
|
@ -392,7 +392,8 @@ DataCall.prototype = {
|
||||
ifname: null,
|
||||
addreses: null,
|
||||
dnses: null,
|
||||
gateways: null
|
||||
gateways: null,
|
||||
pcscf: null
|
||||
};
|
||||
|
||||
function RadioInterfaceLayer() {
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
[scriptable, uuid(d27ce247-9c7c-4582-826b-125e8275e9c2)]
|
||||
[scriptable, uuid(88f18811-8f19-4902-a9b8-2a6430c71c94)]
|
||||
interface nsIDataCall : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -55,6 +55,12 @@ interface nsIDataCall : nsISupports
|
||||
* A space-delimited list of default gateway addresses.
|
||||
*/
|
||||
readonly attribute DOMString gateways;
|
||||
|
||||
/**
|
||||
* A space-delimited list of Proxy Call State Control Function addresses for
|
||||
* IMS client.
|
||||
*/
|
||||
readonly attribute DOMString pcscf;
|
||||
};
|
||||
|
||||
[scriptable, uuid(e119c54b-9354-4ad6-a1ee-18608bde9320)]
|
||||
|
@ -5,7 +5,7 @@
|
||||
#include "nsISupports.idl"
|
||||
#include "nsINetworkInterface.idl"
|
||||
|
||||
[scriptable, uuid(501b7041-0754-4ddb-9174-946e2c2ebd83)]
|
||||
[scriptable, uuid(b8bcd6aa-5b06-4362-a68c-317878429e51)]
|
||||
interface nsIRilNetworkInfo : nsINetworkInfo
|
||||
{
|
||||
readonly attribute unsigned long serviceId;
|
||||
@ -15,6 +15,17 @@ interface nsIRilNetworkInfo : nsINetworkInfo
|
||||
readonly attribute DOMString mmsc; // Empty string if not set.
|
||||
readonly attribute DOMString mmsProxy; // Empty string if not set.
|
||||
readonly attribute long mmsPort; // -1 if not set.
|
||||
|
||||
/**
|
||||
* Get the list of pcscf addresses, could be IPv4 or IPv6.
|
||||
*
|
||||
* @param count
|
||||
* The length of the list of pcscf addresses.
|
||||
*
|
||||
* @returns the list of pcscf addresses.
|
||||
*/
|
||||
void getPcscf([optional] out unsigned long count,
|
||||
[array, size_is(count), retval] out wstring pcscf);
|
||||
};
|
||||
|
||||
[scriptable, function, uuid(cb2f0f5b-67f4-4c14-93e8-01e66b630464)]
|
||||
|
@ -4236,12 +4236,11 @@ RilObject.prototype[REQUEST_SETUP_DATA_CALL] = function REQUEST_SETUP_DATA_CALL(
|
||||
}
|
||||
|
||||
let Buf = this.context.Buf;
|
||||
// Skip version of data call.
|
||||
Buf.readInt32();
|
||||
let version = Buf.readInt32();
|
||||
// Skip number of data calls.
|
||||
Buf.readInt32();
|
||||
|
||||
this.readDataCall_v6(options);
|
||||
this.readDataCall(options, version);
|
||||
this.sendChromeMessage(options);
|
||||
};
|
||||
RilObject.prototype[REQUEST_SIM_IO] = function REQUEST_SIM_IO(length, options) {
|
||||
@ -4512,9 +4511,13 @@ RilObject.prototype[REQUEST_LAST_DATA_CALL_FAIL_CAUSE] = null;
|
||||
* length.
|
||||
* # dnses - A space-delimited list of DNS server addresses.
|
||||
* # gateways - A space-delimited list of default gateway addresses.
|
||||
*
|
||||
* V10:
|
||||
* # pcscf - A space-delimited list of Proxy Call State Control Function
|
||||
* addresses.
|
||||
*/
|
||||
|
||||
RilObject.prototype.readDataCall_v6 = function(options) {
|
||||
RilObject.prototype.readDataCall = function(options, version) {
|
||||
if (!options) {
|
||||
options = {};
|
||||
}
|
||||
@ -4529,6 +4532,10 @@ RilObject.prototype.readDataCall_v6 = function(options) {
|
||||
options.dnses = Buf.readString();
|
||||
options.gateways = Buf.readString();
|
||||
|
||||
if (version >= 10) {
|
||||
options.pcscf = Buf.readString();
|
||||
}
|
||||
|
||||
return options;
|
||||
};
|
||||
|
||||
@ -4557,7 +4564,7 @@ RilObject.prototype[REQUEST_DATA_CALL_LIST] = function REQUEST_DATA_CALL_LIST(le
|
||||
let datacalls = [];
|
||||
for (let i = 0; i < num; i++) {
|
||||
let datacall;
|
||||
datacall = this.readDataCall_v6();
|
||||
datacall = this.readDataCall({}, version);
|
||||
datacalls.push(datacall);
|
||||
}
|
||||
|
||||
|
@ -136,6 +136,7 @@ using namespace mozilla::system;
|
||||
#include "TouchManager.h"
|
||||
#include "MediaDecoder.h"
|
||||
#include "mozilla/layers/CompositorLRU.h"
|
||||
#include "mozilla/dom/devicestorage/DeviceStorageStatics.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::net;
|
||||
@ -319,6 +320,8 @@ nsLayoutStatics::Initialize()
|
||||
|
||||
layers::CompositorLRU::Init();
|
||||
|
||||
mozilla::dom::devicestorage::DeviceStorageStatics::Initialize();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user