diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml
index 6463543043c3..6a65b020ff9c 100644
--- a/b2g/config/dolphin/sources.xml
+++ b/b2g/config/dolphin/sources.xml
@@ -15,7 +15,7 @@
-
+
diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml
index 9c8b243948d5..8689b52509eb 100644
--- a/b2g/config/emulator-ics/sources.xml
+++ b/b2g/config/emulator-ics/sources.xml
@@ -19,7 +19,7 @@
-
+
diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml
index 082a69b37cd9..e3e5ad363fd5 100644
--- a/b2g/config/emulator-jb/sources.xml
+++ b/b2g/config/emulator-jb/sources.xml
@@ -17,7 +17,7 @@
-
+
diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml
index 205f8844f305..d91bfa9b69d6 100644
--- a/b2g/config/emulator-kk/sources.xml
+++ b/b2g/config/emulator-kk/sources.xml
@@ -15,7 +15,7 @@
-
+
diff --git a/b2g/config/emulator-l/sources.xml b/b2g/config/emulator-l/sources.xml
index 059239643330..d6ed7845464c 100644
--- a/b2g/config/emulator-l/sources.xml
+++ b/b2g/config/emulator-l/sources.xml
@@ -15,7 +15,7 @@
-
+
diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml
index 9c8b243948d5..8689b52509eb 100644
--- a/b2g/config/emulator/sources.xml
+++ b/b2g/config/emulator/sources.xml
@@ -19,7 +19,7 @@
-
+
diff --git a/b2g/config/flame-kk/sources.xml b/b2g/config/flame-kk/sources.xml
index f6c2445cf48e..c6370b364ef7 100644
--- a/b2g/config/flame-kk/sources.xml
+++ b/b2g/config/flame-kk/sources.xml
@@ -15,7 +15,7 @@
-
+
diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml
index bd6addaa0201..ee864d9288a2 100644
--- a/b2g/config/flame/sources.xml
+++ b/b2g/config/flame/sources.xml
@@ -17,7 +17,7 @@
-
+
diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json
index a4cd19f85a0e..9784892bcce1 100644
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,9 +1,9 @@
{
"git": {
- "git_revision": "e1773d6d1014c997be4b5c4233bba3ee073b8d7b",
+ "git_revision": "42dc5f02a9df006b129824cd9bffa93cab937ab2",
"remote": "https://git.mozilla.org/releases/gaia.git",
"branch": ""
},
- "revision": "172680469094791e563268fa7d074fee9e0105ab",
+ "revision": "1ada14e78334ed61c226ba43be1f3ac286c66a95",
"repo_path": "integration/gaia-central"
}
diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml
index 6bf6665b613b..e1059f090f4d 100644
--- a/b2g/config/nexus-4/sources.xml
+++ b/b2g/config/nexus-4/sources.xml
@@ -17,7 +17,7 @@
-
+
diff --git a/b2g/config/nexus-5-l/sources.xml b/b2g/config/nexus-5-l/sources.xml
index f1d18c78b54b..811029dc989b 100644
--- a/b2g/config/nexus-5-l/sources.xml
+++ b/b2g/config/nexus-5-l/sources.xml
@@ -15,7 +15,7 @@
-
+
diff --git a/browser/themes/shared/aboutNetError.css b/browser/themes/shared/aboutNetError.css
index f507d3a858dc..460efd5d2eeb 100644
--- a/browser/themes/shared/aboutNetError.css
+++ b/browser/themes/shared/aboutNetError.css
@@ -136,13 +136,3 @@ span#hostname {
#automaticallyReportInFuture {
cursor: pointer;
}
-
-#reportSendingMessage {
- /* adjust the line-height to match the link */
- line-height: 22px;
-}
-
-#reportSentMessage {
- /* adjust the line-height to match the link */
- line-height: 22px;
-}
diff --git a/dom/base/Navigator.cpp b/dom/base/Navigator.cpp
index a28f528ee32f..bfecce47afd4 100644
--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -32,6 +32,7 @@
#include "mozilla/Preferences.h"
#include "mozilla/Telemetry.h"
#include "BatteryManager.h"
+#include "mozilla/dom/DeviceStorageAreaListener.h"
#include "mozilla/dom/PowerManager.h"
#include "mozilla/dom/WakeLock.h"
#include "mozilla/dom/power/PowerManagerService.h"
@@ -210,6 +211,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Navigator)
#ifdef MOZ_EME
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMediaKeySystemAccessManager)
#endif
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDeviceStorageAreaListener)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
@@ -334,6 +336,10 @@ Navigator::Invalidate()
mMediaKeySystemAccessManager = nullptr;
}
#endif
+
+ if (mDeviceStorageAreaListener) {
+ mDeviceStorageAreaListener = nullptr;
+ }
}
//*****************************************************************************
@@ -914,6 +920,20 @@ Navigator::RegisterProtocolHandler(const nsAString& aProtocol,
mWindow->GetOuterWindow());
}
+DeviceStorageAreaListener*
+Navigator::GetDeviceStorageAreaListener(ErrorResult& aRv)
+{
+ if (!mDeviceStorageAreaListener) {
+ if (!mWindow || !mWindow->GetOuterWindow() || !mWindow->GetDocShell()) {
+ aRv.Throw(NS_ERROR_FAILURE);
+ return nullptr;
+ }
+ mDeviceStorageAreaListener = new DeviceStorageAreaListener(mWindow);
+ }
+
+ return mDeviceStorageAreaListener;
+}
+
nsDOMDeviceStorage*
Navigator::GetDeviceStorage(const nsAString& aType, ErrorResult& aRv)
{
@@ -949,6 +969,28 @@ Navigator::GetDeviceStorages(const nsAString& aType,
mDeviceStorageStores.AppendElements(aStores);
}
+nsDOMDeviceStorage*
+Navigator::GetDeviceStorageByNameAndType(const nsAString& aName,
+ const nsAString& aType,
+ ErrorResult& aRv)
+{
+ if (!mWindow || !mWindow->GetOuterWindow() || !mWindow->GetDocShell()) {
+ aRv.Throw(NS_ERROR_FAILURE);
+ return nullptr;
+ }
+
+ nsRefPtr storage;
+ nsDOMDeviceStorage::CreateDeviceStorageByNameAndType(mWindow, aName, aType,
+ getter_AddRefs(storage));
+
+ if (!storage) {
+ return nullptr;
+ }
+
+ mDeviceStorageStores.AppendElement(storage);
+ return storage;
+}
+
Geolocation*
Navigator::GetGeolocation(ErrorResult& aRv)
{
diff --git a/dom/base/Navigator.h b/dom/base/Navigator.h
index c059708d5cd5..2cf82718db2e 100644
--- a/dom/base/Navigator.h
+++ b/dom/base/Navigator.h
@@ -94,6 +94,7 @@ class Telephony;
class Voicemail;
class TVManager;
class InputPortManager;
+class DeviceStorageAreaListener;
namespace time {
class TimeManager;
@@ -214,11 +215,15 @@ public:
void RemoveIdleObserver(MozIdleObserver& aObserver, ErrorResult& aRv);
already_AddRefed RequestWakeLock(const nsAString &aTopic,
ErrorResult& aRv);
+ DeviceStorageAreaListener* GetDeviceStorageAreaListener(ErrorResult& aRv);
nsDOMDeviceStorage* GetDeviceStorage(const nsAString& aType,
ErrorResult& aRv);
void GetDeviceStorages(const nsAString& aType,
nsTArray >& aStores,
ErrorResult& aRv);
+ nsDOMDeviceStorage* GetDeviceStorageByNameAndType(const nsAString& aName,
+ const nsAString& aType,
+ ErrorResult& aRv);
DesktopNotificationCenter* GetMozNotification(ErrorResult& aRv);
CellBroadcast* GetMozCellBroadcast(ErrorResult& aRv);
IccManager* GetMozIccManager(ErrorResult& aRv);
@@ -379,6 +384,7 @@ private:
nsRefPtr mTimeManager;
nsRefPtr mServiceWorkerContainer;
nsCOMPtr mWindow;
+ nsRefPtr mDeviceStorageAreaListener;
// Hashtable for saving cached objects DoResolve created, so we don't create
// the object twice if asked for it twice, whether due to use of "delete" or
diff --git a/dom/cache/Cache.cpp b/dom/cache/Cache.cpp
index 64c3d2c8b133..140b38fb317e 100644
--- a/dom/cache/Cache.cpp
+++ b/dom/cache/Cache.cpp
@@ -512,7 +512,7 @@ Cache::CreatePushStream(nsIAsyncInputStream* aStream)
NS_ASSERT_OWNINGTHREAD(Cache);
MOZ_ASSERT(mActor);
MOZ_ASSERT(aStream);
- return mActor->CreatePushStream(aStream);
+ return mActor->CreatePushStream(this, aStream);
}
Cache::~Cache()
diff --git a/dom/cache/CacheChild.cpp b/dom/cache/CacheChild.cpp
index 4c2fe7abcf71..bb39d44e281d 100644
--- a/dom/cache/CacheChild.cpp
+++ b/dom/cache/CacheChild.cpp
@@ -73,11 +73,11 @@ CacheChild::ExecuteOp(nsIGlobalObject* aGlobal, Promise* aPromise,
}
CachePushStreamChild*
-CacheChild::CreatePushStream(nsIAsyncInputStream* aStream)
+CacheChild::CreatePushStream(nsISupports* aParent, nsIAsyncInputStream* aStream)
{
mNumChildActors += 1;
auto actor = SendPCachePushStreamConstructor(
- new CachePushStreamChild(GetFeature(), aStream));
+ new CachePushStreamChild(GetFeature(), aParent, aStream));
MOZ_ASSERT(actor);
return static_cast(actor);
}
diff --git a/dom/cache/CacheChild.h b/dom/cache/CacheChild.h
index 647df82cc69f..4d43535cc52a 100644
--- a/dom/cache/CacheChild.h
+++ b/dom/cache/CacheChild.h
@@ -43,7 +43,7 @@ public:
nsISupports* aParent, const CacheOpArgs& aArgs);
CachePushStreamChild*
- CreatePushStream(nsIAsyncInputStream* aStream);
+ CreatePushStream(nsISupports* aParent, nsIAsyncInputStream* aStream);
// Our parent Listener object has gone out of scope and is being destroyed.
void StartDestroyFromListener();
diff --git a/dom/cache/CachePushStreamChild.cpp b/dom/cache/CachePushStreamChild.cpp
index 57eca994ef73..0c5d90974762 100644
--- a/dom/cache/CachePushStreamChild.cpp
+++ b/dom/cache/CachePushStreamChild.cpp
@@ -93,10 +93,13 @@ NS_IMPL_ISUPPORTS(CachePushStreamChild::Callback, nsIInputStreamCallback,
nsICancelableRunnable);
CachePushStreamChild::CachePushStreamChild(Feature* aFeature,
+ nsISupports* aParent,
nsIAsyncInputStream* aStream)
- : mStream(aStream)
+ : mParent(aParent)
+ , mStream(aStream)
, mClosed(false)
{
+ MOZ_ASSERT(mParent);
MOZ_ASSERT(mStream);
MOZ_ASSERT_IF(!NS_IsMainThread(), aFeature);
SetFeature(aFeature);
diff --git a/dom/cache/CachePushStreamChild.h b/dom/cache/CachePushStreamChild.h
index 03b1d3ed4f1d..9517aabba03f 100644
--- a/dom/cache/CachePushStreamChild.h
+++ b/dom/cache/CachePushStreamChild.h
@@ -31,7 +31,8 @@ private:
class Callback;
// This class must be constructed using CacheChild::CreatePushStream()
- CachePushStreamChild(Feature* aFeature, nsIAsyncInputStream* aStream);
+ CachePushStreamChild(Feature* aFeature, nsISupports* aParent,
+ nsIAsyncInputStream* aStream);
~CachePushStreamChild();
// PCachePushStreamChild methods
@@ -46,6 +47,7 @@ private:
void OnEnd(nsresult aRv);
+ nsCOMPtr mParent;
nsCOMPtr mStream;
nsRefPtr mCallback;
bool mClosed;
diff --git a/dom/devicestorage/DeviceStorage.h b/dom/devicestorage/DeviceStorage.h
index 3a982feba228..43d308e42b27 100644
--- a/dom/devicestorage/DeviceStorage.h
+++ b/dom/devicestorage/DeviceStorage.h
@@ -292,6 +292,12 @@ public:
const nsAString& aType,
nsTArray >& aStores);
+ static void
+ CreateDeviceStorageByNameAndType(nsPIDOMWindow* aWin,
+ const nsAString& aName,
+ const nsAString& aType,
+ nsDOMDeviceStorage** aStore);
+
void Shutdown();
static void GetOrderedVolumeNames(nsTArray& aVolumeNames);
@@ -334,6 +340,11 @@ private:
already_AddRefed
GetStorageByName(const nsAString &aStorageName);
+ static already_AddRefed
+ GetStorageByNameAndType(nsPIDOMWindow* aWin,
+ const nsAString& aStorageName,
+ const nsAString& aType);
+
nsCOMPtr mPrincipal;
bool mIsWatchingFile;
diff --git a/dom/devicestorage/DeviceStorageAreaListener.cpp b/dom/devicestorage/DeviceStorageAreaListener.cpp
new file mode 100755
index 000000000000..22eeaae0e62d
--- /dev/null
+++ b/dom/devicestorage/DeviceStorageAreaListener.cpp
@@ -0,0 +1,149 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/dom/DeviceStorageAreaListener.h"
+#include "mozilla/dom/DeviceStorageAreaListenerBinding.h"
+#include "mozilla/Attributes.h"
+#include "mozilla/Services.h"
+#include "nsIObserverService.h"
+#ifdef MOZ_WIDGET_GONK
+#include "nsIVolume.h"
+#include "nsIVolumeService.h"
+#endif
+
+namespace mozilla {
+namespace dom {
+
+class VolumeStateObserver final : public nsIObserver
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIOBSERVER
+
+ explicit VolumeStateObserver(DeviceStorageAreaListener* aListener)
+ : mDeviceStorageAreaListener(aListener) {}
+ void ForgetListener() { mDeviceStorageAreaListener = nullptr; }
+
+private:
+ ~VolumeStateObserver() {};
+
+ // This reference is non-owning and it's cleared by
+ // DeviceStorageAreaListener's destructor.
+ DeviceStorageAreaListener* MOZ_NON_OWNING_REF mDeviceStorageAreaListener;
+};
+
+NS_IMPL_ISUPPORTS(VolumeStateObserver, nsIObserver)
+
+NS_IMETHODIMP
+VolumeStateObserver::Observe(nsISupports *aSubject,
+ const char *aTopic,
+ const char16_t *aData)
+{
+ if (!mDeviceStorageAreaListener) {
+ return NS_OK;
+ }
+
+#ifdef MOZ_WIDGET_GONK
+ if (!strcmp(aTopic, NS_VOLUME_STATE_CHANGED)) {
+ nsCOMPtr vol = do_QueryInterface(aSubject);
+ MOZ_ASSERT(vol);
+
+ int32_t state;
+ nsresult rv = vol->GetState(&state);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsString volName;
+ vol->GetName(volName);
+
+ switch (state) {
+ case nsIVolume::STATE_MOUNTED:
+ mDeviceStorageAreaListener->DispatchStorageAreaChangedEvent(
+ volName,
+ DeviceStorageAreaChangedEventOperation::Added);
+ break;
+ default:
+ mDeviceStorageAreaListener->DispatchStorageAreaChangedEvent(
+ volName,
+ DeviceStorageAreaChangedEventOperation::Removed);
+ break;
+ }
+ }
+#endif
+ return NS_OK;
+}
+
+NS_IMPL_ADDREF_INHERITED(DeviceStorageAreaListener, DOMEventTargetHelper)
+NS_IMPL_RELEASE_INHERITED(DeviceStorageAreaListener, DOMEventTargetHelper)
+
+NS_INTERFACE_MAP_BEGIN(DeviceStorageAreaListener)
+NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
+
+DeviceStorageAreaListener::DeviceStorageAreaListener(nsPIDOMWindow* aWindow)
+ : DOMEventTargetHelper(aWindow)
+{
+ MOZ_ASSERT(aWindow);
+
+ mVolumeStateObserver = new VolumeStateObserver(this);
+#ifdef MOZ_WIDGET_GONK
+ nsCOMPtr obs = mozilla::services::GetObserverService();
+ if (obs) {
+ obs->AddObserver(mVolumeStateObserver, NS_VOLUME_STATE_CHANGED, false);
+ }
+#endif
+}
+
+DeviceStorageAreaListener::~DeviceStorageAreaListener()
+{
+#ifdef MOZ_WIDGET_GONK
+ nsCOMPtr obs = mozilla::services::GetObserverService();
+ if (obs) {
+ obs->RemoveObserver(mVolumeStateObserver, NS_VOLUME_STATE_CHANGED);
+ }
+#endif
+ mVolumeStateObserver->ForgetListener();
+}
+
+JSObject*
+DeviceStorageAreaListener::WrapObject(JSContext* aCx, JS::Handle aGivenProto)
+{
+ return DeviceStorageAreaListenerBinding::Wrap(aCx, this, aGivenProto);
+}
+
+void
+DeviceStorageAreaListener::DispatchStorageAreaChangedEvent(
+ const nsString& aStorageName,
+ DeviceStorageAreaChangedEventOperation aOperation)
+{
+ StateMapType::const_iterator iter = mStorageAreaStateMap.find(aStorageName);
+ if (iter == mStorageAreaStateMap.end() &&
+ aOperation != DeviceStorageAreaChangedEventOperation::Added) {
+ // The operation of the first event to dispatch should be "Added".
+ return;
+ }
+ if (iter != mStorageAreaStateMap.end() &&
+ iter->second == aOperation) {
+ // No need to disptach the event if the state is unchanged.
+ return;
+ }
+
+ DeviceStorageAreaChangedEventInit init;
+ init.mOperation = aOperation;
+ init.mStorageName = aStorageName;
+
+ nsRefPtr event =
+ DeviceStorageAreaChangedEvent::Constructor(this,
+ NS_LITERAL_STRING("storageareachanged"),
+ init);
+ event->SetTrusted(true);
+
+ bool ignore;
+ DOMEventTargetHelper::DispatchEvent(event, &ignore);
+
+ mStorageAreaStateMap[aStorageName] = aOperation;
+}
+
+} // namespace dom
+} // namespace mozilla
diff --git a/dom/devicestorage/DeviceStorageAreaListener.h b/dom/devicestorage/DeviceStorageAreaListener.h
new file mode 100755
index 000000000000..59c2854d7958
--- /dev/null
+++ b/dom/devicestorage/DeviceStorageAreaListener.h
@@ -0,0 +1,47 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* 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_DeviceStorageAreaListener_h
+#define mozilla_dom_DeviceStorageAreaListener_h
+
+#include