Bug 838038 - Pt 1 - Make volumes available to child processes. r=dougt

This commit is contained in:
Dave Hylands 2013-04-02 12:52:17 -07:00
Родитель 5477d459ee
Коммит b5994c6fe9
6 изменённых файлов: 144 добавлений и 35 удалений

Просмотреть файл

@ -45,6 +45,9 @@ interface nsIVolume : nsISupports
// the wakelock every time the volume becomes mounted. // the wakelock every time the volume becomes mounted.
readonly attribute DOMString mountLockName; readonly attribute DOMString mountLockName;
// Determines if a mountlock is currently being held against this volume.
readonly attribute boolean isMountLocked;
nsIVolumeStat getStats(); nsIVolumeStat getStats();
}; };

Просмотреть файл

@ -6,7 +6,13 @@
#include "nsIVolume.idl" #include "nsIVolume.idl"
#include "nsIVolumeMountLock.idl" #include "nsIVolumeMountLock.idl"
[scriptable, uuid(597403c6-5ba4-4e7b-b3f4-ed3f05f775d8)] %{C++
#include "nsTArray.h"
#include "nsString.h"
%}
[ref] native nsStringTArrayRef(nsTArray<nsString>);
[scriptable, uuid(fc4e6449-922e-463d-880b-bfbab4909114)]
interface nsIVolumeService : nsISupports interface nsIVolumeService : nsISupports
{ {
nsIVolume getVolumeByName(in DOMString volName); nsIVolume getVolumeByName(in DOMString volName);
@ -15,6 +21,8 @@ interface nsIVolumeService : nsISupports
void BroadcastVolume(in DOMString volName); void BroadcastVolume(in DOMString volName);
nsIVolumeMountLock createMountLock(in DOMString volName); nsIVolumeMountLock createMountLock(in DOMString volName);
[noscript] void getVolumeNames(in nsStringTArrayRef aVolNames);
}; };
%{C++ %{C++

Просмотреть файл

@ -54,6 +54,46 @@ nsVolume::nsVolume(const Volume* aVolume)
{ {
} }
bool nsVolume::Equals(nsIVolume* aVolume)
{
nsString volName;
aVolume->GetName(volName);
if (!mName.Equals(volName)) {
return false;
}
nsString volMountPoint;
aVolume->GetMountPoint(volMountPoint);
if (!mMountPoint.Equals(volMountPoint)) {
return false;
}
int32_t volState;
aVolume->GetState(&volState);
if (mState != volState){
return false;
}
int32_t volMountGeneration;
aVolume->GetMountGeneration(&volMountGeneration);
if (mMountGeneration != volMountGeneration) {
return false;
}
bool volIsMountLocked;
aVolume->GetIsMountLocked(&volIsMountLocked);
if (mMountLocked != volIsMountLocked) {
return false;
}
return true;
}
NS_IMETHODIMP nsVolume::GetIsMountLocked(bool *aIsMountLocked)
{
*aIsMountLocked = mMountLocked;
return NS_OK;
}
NS_IMETHODIMP nsVolume::GetName(nsAString& aName) NS_IMETHODIMP nsVolume::GetName(nsAString& aName)
{ {
aName = mName; aName = mName;
@ -109,13 +149,16 @@ nsVolume::LogState() const
LOG("nsVolume: %s state %s", NameStr().get(), StateStr()); LOG("nsVolume: %s state %s", NameStr().get(), StateStr());
} }
void nsVolume::Set(const nsVolume* aVolume) void nsVolume::Set(nsIVolume* aVolume)
{ {
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
mName = aVolume->mName; aVolume->GetName(mName);
mMountPoint = aVolume->mMountPoint; aVolume->GetMountPoint(mMountPoint);
mState = aVolume->mState; aVolume->GetState(&mState);
int32_t volMountGeneration;
aVolume->GetMountGeneration(&volMountGeneration);
if (mState != nsIVolume::STATE_MOUNTED) { if (mState != nsIVolume::STATE_MOUNTED) {
// Since we're not in the mounted state, we need to // Since we're not in the mounted state, we need to
@ -123,12 +166,18 @@ void nsVolume::Set(const nsVolume* aVolume)
mMountGeneration = -1; mMountGeneration = -1;
return; return;
} }
if (mMountGeneration == aVolume->mMountGeneration) { if (mMountGeneration == volMountGeneration) {
// No change in mount generation, nothing else to do // No change in mount generation, nothing else to do
return; return;
} }
mMountGeneration = aVolume->mMountGeneration; mMountGeneration = volMountGeneration;
if (XRE_GetProcessType() != GeckoProcessType_Default) {
// Child processes just track the state, not maintain it.
aVolume->GetIsMountLocked(&mMountLocked);
return;
}
// Notify the Volume on IOThread whether the volume is locked or not. // Notify the Volume on IOThread whether the volume is locked or not.
nsCOMPtr<nsIPowerManagerService> pmService = nsCOMPtr<nsIPowerManagerService> pmService =
@ -146,6 +195,7 @@ void nsVolume::Set(const nsVolume* aVolume)
void void
nsVolume::UpdateMountLock(const nsAString& aMountLockState) nsVolume::UpdateMountLock(const nsAString& aMountLockState)
{ {
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
// There are 3 states, unlocked, locked-background, and locked-foreground // There are 3 states, unlocked, locked-background, and locked-foreground
@ -156,6 +206,7 @@ nsVolume::UpdateMountLock(const nsAString& aMountLockState)
void void
nsVolume::UpdateMountLock(bool aMountLocked) nsVolume::UpdateMountLock(bool aMountLocked)
{ {
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
if (aMountLocked == mMountLocked) { if (aMountLocked == mMountLocked) {

Просмотреть файл

@ -46,16 +46,8 @@ public:
{ {
} }
bool Equals(const nsVolume* aVolume) bool Equals(nsIVolume* aVolume);
{ void Set(nsIVolume* aVolume);
return mName.Equals(aVolume->mName)
&& mMountPoint.Equals(aVolume->mMountPoint)
&& (mState == aVolume->mState)
&& (mMountGeneration == aVolume->mMountGeneration)
&& (mMountLocked == aVolume->mMountLocked);
}
void Set(const nsVolume* aVolume);
void LogState() const; void LogState() const;

Просмотреть файл

@ -62,7 +62,13 @@ nsVolumeService::GetSingleton()
void void
nsVolumeService::Shutdown() nsVolumeService::Shutdown()
{ {
if (!sSingleton || (XRE_GetProcessType() != GeckoProcessType_Default)) { if (!sSingleton) {
return;
}
if (XRE_GetProcessType() != GeckoProcessType_Default) {
nsCOMPtr<nsIObserverService> obs = GetObserverService();
obs->RemoveObserver(sSingleton.get(), NS_VOLUME_STATE_CHANGED);
sSingleton = nullptr;
return; return;
} }
@ -84,10 +90,12 @@ nsVolumeService::nsVolumeService()
sSingleton = this; sSingleton = this;
if (XRE_GetProcessType() != GeckoProcessType_Default) { if (XRE_GetProcessType() != GeckoProcessType_Default) {
// We don't support the nsIVolumeService in the child processes, // For child processes, we keep a cache of the volume state.
// but we get constructed due to the way we're registered with nsCOMPtr<nsIObserverService> obs = GetObserverService();
// nsLayoutModule.cpp. So we exit early to reduce our memory obs->AddObserver(this, NS_VOLUME_STATE_CHANGED, false /*weak*/);
// impact, and so that we don't start unnecessary IOThread stuff.
// Request the initial state for all volumes.
ContentChild::GetSingleton()->SendBroadcastVolume(NS_LITERAL_STRING(""));
return; return;
} }
@ -119,6 +127,25 @@ NS_IMETHODIMP nsVolumeService::Callback(const nsAString& aTopic, const nsAString
NS_IMETHODIMP nsVolumeService::BroadcastVolume(const nsAString& aVolName) NS_IMETHODIMP nsVolumeService::BroadcastVolume(const nsAString& aVolName)
{ {
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default); MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
if (aVolName.EqualsLiteral("")) {
// We treat being passed the empty string as "broadcast all volumes"
nsVolume::Array::size_type numVolumes = mVolumeArray.Length();
nsVolume::Array::index_type volIndex;
for (volIndex = 0; volIndex < numVolumes; volIndex++) {
const nsString &volName(mVolumeArray[volIndex]->Name());
if (!volName.EqualsLiteral("")) {
// Note: The volume service is the only entity that should be able to
// modify the array of volumes. So we shouldn't have any issues with
// the array being modified under our feet (Since we're the volume
// service the array can't change until after we finish iterating the
// the loop).
nsresult rv = BroadcastVolume(volName);
NS_ENSURE_SUCCESS(rv, rv);
}
}
return NS_OK;
}
nsRefPtr<nsVolume> vol = FindVolumeByName(aVolName); nsRefPtr<nsVolume> vol = FindVolumeByName(aVolName);
if (!vol) { if (!vol) {
ERR("BroadcastVolume: Unable to locate volume '%s'", ERR("BroadcastVolume: Unable to locate volume '%s'",
@ -137,11 +164,8 @@ NS_IMETHODIMP nsVolumeService::BroadcastVolume(const nsAString& aVolName)
NS_IMETHODIMP nsVolumeService::GetVolumeByName(const nsAString& aVolName, nsIVolume **aResult) NS_IMETHODIMP nsVolumeService::GetVolumeByName(const nsAString& aVolName, nsIVolume **aResult)
{ {
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
nsRefPtr<nsVolume> vol = FindVolumeByName(aVolName); nsRefPtr<nsVolume> vol = FindVolumeByName(aVolName);
if (!vol) { if (!vol) {
ERR("GetVolumeByName: Unable to locate volume '%s'",
NS_LossyConvertUTF16toASCII(aVolName).get());
return NS_ERROR_NOT_AVAILABLE; return NS_ERROR_NOT_AVAILABLE;
} }
@ -151,7 +175,6 @@ NS_IMETHODIMP nsVolumeService::GetVolumeByName(const nsAString& aVolName, nsIVol
NS_IMETHODIMP nsVolumeService::GetVolumeByPath(const nsAString& aPath, nsIVolume **aResult) NS_IMETHODIMP nsVolumeService::GetVolumeByPath(const nsAString& aPath, nsIVolume **aResult)
{ {
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
nsCString utf8Path = NS_ConvertUTF16toUTF8(aPath); nsCString utf8Path = NS_ConvertUTF16toUTF8(aPath);
char realPathBuf[PATH_MAX]; char realPathBuf[PATH_MAX];
@ -170,7 +193,7 @@ NS_IMETHODIMP nsVolumeService::GetVolumeByPath(const nsAString& aPath, nsIVolume
strlcat(realPathBuf, "/", sizeof(realPathBuf)); strlcat(realPathBuf, "/", sizeof(realPathBuf));
nsVolume::Array::size_type numVolumes = mVolumeArray.Length(); nsVolume::Array::size_type numVolumes = mVolumeArray.Length();
nsVolume::Array::index_type volIndex; nsVolume::Array::index_type volIndex;
for (volIndex = 0; volIndex < numVolumes; volIndex++) { for (volIndex = 0; volIndex < numVolumes; volIndex++) {
nsRefPtr<nsVolume> vol = mVolumeArray[volIndex]; nsRefPtr<nsVolume> vol = mVolumeArray[volIndex];
@ -192,6 +215,18 @@ NS_IMETHODIMP nsVolumeService::GetVolumeByPath(const nsAString& aPath, nsIVolume
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP nsVolumeService::GetVolumeNames(nsTArray<nsString>& aVolNames)
{
nsVolume::Array::size_type numVolumes = mVolumeArray.Length();
nsVolume::Array::index_type volIndex;
for (volIndex = 0; volIndex < numVolumes; volIndex++) {
nsRefPtr<nsVolume> vol = mVolumeArray[volIndex];
aVolNames.AppendElement(vol->Name());
}
return NS_OK;
}
NS_IMETHODIMP nsVolumeService::CreateMountLock(const nsAString& aVolumeName, nsIVolumeMountLock **aResult) NS_IMETHODIMP nsVolumeService::CreateMountLock(const nsAString& aVolumeName, nsIVolumeMountLock **aResult)
{ {
nsRefPtr<nsVolumeMountLock> mountLock = nsVolumeMountLock::Create(aVolumeName); nsRefPtr<nsVolumeMountLock> mountLock = nsVolumeMountLock::Create(aVolumeName);
@ -208,7 +243,7 @@ void nsVolumeService::CheckMountLock(const nsAString& aMountLockName,
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default); MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
nsVolume::Array::size_type numVolumes = mVolumeArray.Length(); nsVolume::Array::size_type numVolumes = mVolumeArray.Length();
nsVolume::Array::index_type volIndex; nsVolume::Array::index_type volIndex;
for (volIndex = 0; volIndex < numVolumes; volIndex++) { for (volIndex = 0; volIndex < numVolumes; volIndex++) {
nsRefPtr<nsVolume> vol = mVolumeArray[volIndex]; nsRefPtr<nsVolume> vol = mVolumeArray[volIndex];
@ -223,10 +258,9 @@ void nsVolumeService::CheckMountLock(const nsAString& aMountLockName,
already_AddRefed<nsVolume> nsVolumeService::FindVolumeByName(const nsAString& aName) already_AddRefed<nsVolume> nsVolumeService::FindVolumeByName(const nsAString& aName)
{ {
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
nsVolume::Array::size_type numVolumes = mVolumeArray.Length(); nsVolume::Array::size_type numVolumes = mVolumeArray.Length();
nsVolume::Array::index_type volIndex; nsVolume::Array::index_type volIndex;
for (volIndex = 0; volIndex < numVolumes; volIndex++) { for (volIndex = 0; volIndex < numVolumes; volIndex++) {
nsRefPtr<nsVolume> vol = mVolumeArray[volIndex]; nsRefPtr<nsVolume> vol = mVolumeArray[volIndex];
@ -240,7 +274,6 @@ already_AddRefed<nsVolume> nsVolumeService::FindVolumeByName(const nsAString& aN
//static //static
already_AddRefed<nsVolume> nsVolumeService::FindAddVolumeByName(const nsAString& aName) already_AddRefed<nsVolume> nsVolumeService::FindAddVolumeByName(const nsAString& aName)
{ {
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
nsRefPtr<nsVolume> vol; nsRefPtr<nsVolume> vol;
@ -254,17 +287,36 @@ already_AddRefed<nsVolume> nsVolumeService::FindAddVolumeByName(const nsAString&
return vol.forget(); return vol.forget();
} }
void nsVolumeService::UpdateVolume(const nsVolume* aVolume) NS_IMETHODIMP nsVolumeService::Observe(nsISupports* aSubject, const char* aTopic, const PRUnichar* aData)
{
if (strcmp(aTopic, NS_VOLUME_STATE_CHANGED) != 0) {
return NS_OK;
}
MOZ_ASSERT(XRE_GetProcessType() != GeckoProcessType_Default);
nsCOMPtr<nsIVolume> vol = do_QueryInterface(aSubject);
if (!vol) {
return NS_OK;
}
UpdateVolume(vol);
return NS_OK;
}
void nsVolumeService::UpdateVolume(nsIVolume* aVolume)
{ {
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
nsRefPtr<nsVolume> vol = FindAddVolumeByName(aVolume->Name()); nsString volName;
aVolume->GetName(volName);
nsRefPtr<nsVolume> vol = FindAddVolumeByName(volName);
if (vol->Equals(aVolume)) { if (vol->Equals(aVolume)) {
// Nothing has really changed. Don't bother telling anybody. // Nothing has really changed. Don't bother telling anybody.
return; return;
} }
vol->Set(aVolume); vol->Set(aVolume);
if (XRE_GetProcessType() != GeckoProcessType_Default) {
// Only the parent broadcasts the state changes
return;
}
nsCOMPtr<nsIObserverService> obs = GetObserverService(); nsCOMPtr<nsIObserverService> obs = GetObserverService();
if (!obs) { if (!obs) {
return; return;

Просмотреть файл

@ -9,6 +9,7 @@
#include "mozilla/StaticPtr.h" #include "mozilla/StaticPtr.h"
#include "nsCOMPtr.h" #include "nsCOMPtr.h"
#include "nsIDOMWakeLockListener.h" #include "nsIDOMWakeLockListener.h"
#include "nsIObserver.h"
#include "nsIVolume.h" #include "nsIVolume.h"
#include "nsIVolumeService.h" #include "nsIVolumeService.h"
#include "nsVolume.h" #include "nsVolume.h"
@ -26,10 +27,12 @@ class WakeLockCallback;
*/ */
class nsVolumeService MOZ_FINAL : public nsIVolumeService, class nsVolumeService MOZ_FINAL : public nsIVolumeService,
public nsIObserver,
public nsIDOMMozWakeLockListener public nsIDOMMozWakeLockListener
{ {
public: public:
NS_DECL_ISUPPORTS NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
NS_DECL_NSIVOLUMESERVICE NS_DECL_NSIVOLUMESERVICE
NS_DECL_NSIDOMMOZWAKELOCKLISTENER NS_DECL_NSIDOMMOZWAKELOCKLISTENER
@ -43,7 +46,7 @@ public:
const nsAString& aMountLockState); const nsAString& aMountLockState);
already_AddRefed<nsVolume> FindVolumeByName(const nsAString& aName); already_AddRefed<nsVolume> FindVolumeByName(const nsAString& aName);
already_AddRefed<nsVolume> FindAddVolumeByName(const nsAString& aName); already_AddRefed<nsVolume> FindAddVolumeByName(const nsAString& aName);
void UpdateVolume(const nsVolume* aVolume); void UpdateVolume(nsIVolume* aVolume);
void UpdateVolumeIOThread(const Volume* aVolume); void UpdateVolumeIOThread(const Volume* aVolume);
private: private: