Bug 872800 - Fix volume availability notifications for composite storage areas. r=mchen

This commit is contained in:
Dave Hylands 2013-05-16 11:11:58 -07:00
parent 4e6b1ff1bd
commit 22d3b834a6
3 changed files with 46 additions and 37 deletions

View File

@ -987,7 +987,7 @@ NS_IMETHODIMP Navigator::GetDeviceStorages(const nsAString &aType, nsIVariant**
}
nsTArray<nsRefPtr<nsDOMDeviceStorage> > stores;
nsDOMDeviceStorage::CreateDeviceStoragesFor(win, aType, stores);
nsDOMDeviceStorage::CreateDeviceStoragesFor(win, aType, stores, false);
nsCOMPtr<nsIWritableVariant> result = do_CreateInstance("@mozilla.org/variant;1");
NS_ENSURE_TRUE(result, NS_ERROR_FAILURE);

View File

@ -160,7 +160,8 @@ public:
static void CreateDeviceStoragesFor(nsPIDOMWindow* aWin,
const nsAString& aType,
nsTArray<nsRefPtr<nsDOMDeviceStorage> >& aStores);
nsTArray<nsRefPtr<nsDOMDeviceStorage> >& aStores,
bool aCompositeComponent);
void Shutdown();
static void GetOrderedVolumeNames(nsTArray<nsString>& aVolumeNames);
@ -198,8 +199,21 @@ private:
nsString mStorageType;
nsCOMPtr<nsIFile> mRootDirectory;
nsString mStorageName;
bool mCompositeComponent;
// A composite device storage object is one which front-ends for multiple
// real storage objects. The real storage objects will each be stored in
// mStores and will each have a unique mStorageName. The composite storage
// object will have mStorageName == "", and mRootDirectory will be null.
//
// Note that on desktop (or other non-gonk), composite storage areas
// don't exist, and mStorageName will also be "".
//
// A device storage object which is stored in mStores is considered to be
// a composite component.
bool IsComposite() { return mStores.Length() > 0; }
bool IsCompositeComponent() { return mCompositeComponent; }
nsTArray<nsRefPtr<nsDOMDeviceStorage> > mStores;
already_AddRefed<nsDOMDeviceStorage> GetStorage(const nsAString& aCompositePath,
nsAString& aOutStoragePath);

View File

@ -1266,21 +1266,23 @@ DeviceStorageFile::GetStatusInternal(nsAString& aStorageName, nsAString& aStatus
NS_IMPL_THREADSAFE_ISUPPORTS0(DeviceStorageFile)
#ifdef MOZ_WIDGET_GONK
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,
@ -1290,11 +1292,6 @@ nsDOMDeviceStorage::SetRootDirectoryForType(const nsAString& aStorageType,
DeviceStorageFile::GetRootDirectoryForType(aStorageType,
aStorageName,
getter_AddRefs(f));
#ifdef MOZ_WIDGET_GONK
RegisterForSDCardChanges(this);
#endif
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
obs->AddObserver(this, "file-watcher-update", false);
obs->AddObserver(this, "disk-space-watcher", false);
@ -2354,7 +2351,8 @@ NS_IMPL_ADDREF_INHERITED(nsDOMDeviceStorage, nsDOMEventTargetHelper)
NS_IMPL_RELEASE_INHERITED(nsDOMDeviceStorage, nsDOMEventTargetHelper)
nsDOMDeviceStorage::nsDOMDeviceStorage()
: mIsWatchingFile(false)
: mCompositeComponent(false),
mIsWatchingFile(false)
, mAllowedToWatchFile(false)
{ }
@ -2385,6 +2383,9 @@ nsDOMDeviceStorage::Init(nsPIDOMWindow* aWindow, const nsAString &aType, const n
return NS_ERROR_NOT_AVAILABLE;
}
}
if (!IsCompositeComponent()) {
RegisterForSDCardChanges(this);
}
BindToOwner(aWindow);
@ -2425,9 +2426,9 @@ nsDOMDeviceStorage::Shutdown()
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
#ifdef MOZ_WIDGET_GONK
UnregisterForSDCardChanges(this);
#endif
if (!IsCompositeComponent()) {
UnregisterForSDCardChanges(this);
}
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
obs->RemoveObserver(this, "file-watcher-update");
@ -2475,7 +2476,7 @@ nsDOMDeviceStorage::CreateDeviceStorageFor(nsPIDOMWindow* aWin,
{
// Create the underlying non-composite device storage objects
nsTArray<nsRefPtr<nsDOMDeviceStorage> > stores;
CreateDeviceStoragesFor(aWin, aType, stores);
CreateDeviceStoragesFor(aWin, aType, stores, true);
if (stores.Length() == 0) {
*aStore = nullptr;
return;
@ -2502,7 +2503,8 @@ nsDOMDeviceStorage::CreateDeviceStorageFor(nsPIDOMWindow* aWin,
void
nsDOMDeviceStorage::CreateDeviceStoragesFor(nsPIDOMWindow* aWin,
const nsAString &aType,
nsTArray<nsRefPtr<nsDOMDeviceStorage> > &aStores)
nsTArray<nsRefPtr<nsDOMDeviceStorage> > &aStores,
bool aCompositeComponent)
{
nsresult rv;
@ -2520,6 +2522,7 @@ nsDOMDeviceStorage::CreateDeviceStoragesFor(nsPIDOMWindow* aWin,
VolumeNameArray::size_type numVolumeNames = volNames.Length();
for (VolumeNameArray::index_type i = 0; i < numVolumeNames; i++) {
nsRefPtr<nsDOMDeviceStorage> storage = new nsDOMDeviceStorage();
storage->mCompositeComponent = aCompositeComponent;
rv = storage->Init(aWin, aType, volNames[i]);
if (NS_FAILED(rv)) {
break;
@ -3116,27 +3119,11 @@ nsDOMDeviceStorage::Observe(nsISupports *aSubject, const char *aTopic, const PRU
#ifdef MOZ_WIDGET_GONK
else if (!strcmp(aTopic, NS_VOLUME_STATE_CHANGED)) {
// We only invalidate the used space cache for the volume that actually changed state.
nsCOMPtr<nsIVolume> vol = do_QueryInterface(aSubject);
if (!vol) {
return NS_OK;
}
int32_t state;
nsresult rv = vol->GetState(&state);
if (NS_FAILED(rv)) {
return NS_OK;
}
nsString type;
if (state == nsIVolume::STATE_MOUNTED) {
type.Assign(NS_LITERAL_STRING("available"));
} else if (state == nsIVolume::STATE_SHARED || state == nsIVolume::STATE_SHAREDMNT) {
type.Assign(NS_LITERAL_STRING("shared"));
} else if (state == nsIVolume::STATE_NOMEDIA || state == nsIVolume::STATE_UNMOUNTING) {
type.Assign(NS_LITERAL_STRING("unavailable"));
} else {
// ignore anything else.
return NS_OK;
}
nsString volName;
vol->GetName(volName);
@ -3144,7 +3131,13 @@ nsDOMDeviceStorage::Observe(nsISupports *aSubject, const char *aTopic, const PRU
NS_ASSERTION(usedSpaceCache, "DeviceStorageUsedSpaceCache is null");
usedSpaceCache->Invalidate(volName);
DispatchMountChangeEvent(volName, type);
// But if we're a composite storage area, we want to report a composite availability,
// so we use mStorageName here instead of volName. (Note: for composite devices,
// mStorageName will be the empty string).
DeviceStorageFile dsf(mStorageType, mStorageName);
nsString status;
dsf.GetStatus(status);
DispatchMountChangeEvent(mStorageName, status);
return NS_OK;
}
#endif
@ -3203,7 +3196,7 @@ nsDOMDeviceStorage::AddEventListener(const nsAString & aType,
nsresult rv = mStores[i]->AddEventListener(aType, aListener, aUseCapture, aWantsUntrusted, aArgc);
NS_ENSURE_SUCCESS(rv, rv);
}
return NS_OK;
// Fall through, so that we add an event listener for the composite object as well.
}
nsRefPtr<DOMRequest> request = new DOMRequest(win);
@ -3233,7 +3226,7 @@ nsDOMDeviceStorage::AddEventListener(const nsAString & aType,
for (i = 0; i < n; i++) {
mStores[i]->AddEventListener(aType, aListener, aUseCapture, aWantsUntrusted, aRv);
}
return;
// Fall through, so that we add an event listener for the composite object as well.
}
nsRefPtr<DOMRequest> request = new DOMRequest(win);
@ -3282,7 +3275,8 @@ nsDOMDeviceStorage::RemoveEventListener(const nsAString & aType,
nsresult rv = mStores[i]->RemoveEventListener(aType, aListener, aUseCapture);
NS_ENSURE_SUCCESS(rv, rv);
}
return NS_OK;
// Fall through, so that we remove the event listener for the composite
// object as well.
}
nsDOMEventTargetHelper::RemoveEventListener(aType, aListener, false);
@ -3306,7 +3300,8 @@ nsDOMDeviceStorage::RemoveEventListener(const nsAString& aType,
for (i = 0; i < n; i++) {
mStores[i]->RemoveEventListener(aType, aListener, aCapture, aRv);
}
return;
// Fall through, so that we remove the event listener for the composite
// object as well.
}
nsDOMEventTargetHelper::RemoveEventListener(aType, aListener, aCapture, aRv);