Skip to content

Commit

Permalink
Back out dougt (bug 788588 et al.) for burning the tree (and some nos…
Browse files Browse the repository at this point in the history
…talgia).
  • Loading branch information
khuey committed Sep 5, 2012
1 parent 247ae26 commit 19dc351
Show file tree
Hide file tree
Showing 23 changed files with 131 additions and 416 deletions.
3 changes: 0 additions & 3 deletions dom/devicestorage/DeviceStorage.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,6 @@ class nsDOMDeviceStorage MOZ_FINAL
bool aEditable,
nsIDOMDeviceStorageCursor** aRetval);

static bool IsMimeTypeCorrectForStorageType(nsAString& aType,
nsIDOMBlob* aBlob);

nsString mStorageType;
nsCOMPtr<nsIFile> mRootDirectory;

Expand Down
2 changes: 1 addition & 1 deletion dom/devicestorage/DeviceStorageRequestParent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ DeviceStorageRequestParent::StatFileEvent::CancelableRun()

nsCOMPtr<nsIRunnable> r;
uint64_t diskUsage = 0;
DeviceStorageFile::DirectoryDiskUsage(mFile->mFile, &diskUsage, mFile->mStorageType);
DeviceStorageFile::DirectoryDiskUsage(mFile->mFile, &diskUsage);
int64_t freeSpace = 0;
nsresult rv = mFile->mFile->GetDiskSpaceAvailable(&freeSpace);
if (NS_FAILED(rv)) {
Expand Down
195 changes: 85 additions & 110 deletions dom/devicestorage/nsDeviceStorage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,6 @@
#include "nsIMIMEService.h"
#include "nsCExternalHandlerService.h"

#include "nsIStringBundle.h"

// Microsoft's API Name hackery sucks
#undef CreateEvent

Expand All @@ -49,7 +47,11 @@
#include "nsIVolumeService.h"
#endif

#define DEVICESTORAGE_PROPERTIES "chrome://global/content/devicestorage.properties"
#define DEBUG_ISTYPE 1

#ifdef DEBUG_ISTYPE
#include "nsIConsoleService.h"
#endif

using namespace mozilla::dom;
using namespace mozilla::dom::devicestorage;
Expand Down Expand Up @@ -82,9 +84,7 @@ class IOEventComplete : public nsRunnable
nsCString mType;
};

DeviceStorageFile::DeviceStorageFile(const nsAString& aStorageType,
nsIFile* aFile,
const nsAString& aPath)
DeviceStorageFile::DeviceStorageFile(const nsAString& aStorageType, nsIFile* aFile, const nsAString& aPath)
: mPath(aPath)
, mStorageType(aStorageType)
, mEditable(false)
Expand Down Expand Up @@ -151,40 +151,72 @@ DeviceStorageFile::IsSafePath()
}

bool
DeviceStorageFile::IsType(nsIFile* aFile, const nsAString& aStorageType)
DeviceStorageFile::IsType(nsAString& aType)
{
// String bundles are cached by the bundle service.
nsCOMPtr<nsIStringBundleService> stringService = mozilla::services::GetStringBundleService();
if (!stringService) {
return false;
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");

// in testing, we ignore filtering for the testing types
if (mozilla::Preferences::GetBool("device.storage.testing", false) &&
(aType.Equals(NS_LITERAL_STRING("testing")) ||
aType.Equals(NS_LITERAL_STRING("testing-other")))) {
return true;
}

nsCOMPtr<nsIStringBundle> filterBundle;
if (NS_FAILED(stringService->CreateBundle(DEVICESTORAGE_PROPERTIES,
getter_AddRefs(filterBundle)))) {
#ifdef DEBUG_ISTYPE
nsCOMPtr<nsIConsoleService> svc = do_GetService(NS_CONSOLESERVICE_CONTRACTID);
char buffer[1024];
nsCString path;
mFile->GetNativePath(path);

PRIntervalTime iStart = PR_IntervalNow();
#endif

nsAutoCString mimeType;
nsCOMPtr<nsIMIMEService> mimeService = do_GetService(NS_MIMESERVICE_CONTRACTID);
if (!mimeService) {
return false;
}

nsString path;
aFile->GetPath(path);
nsresult rv = mimeService->GetTypeFromFile(mFile, mimeType);
if (NS_FAILED(rv)) {
#ifdef DEBUG_ISTYPE
sprintf(buffer, "GetTypeFromFile failed for %s (took: %dms)\n",
path.get(),
PR_IntervalToMilliseconds(PR_IntervalNow() - iStart));

int32_t dotIdx = path.RFindChar(PRUnichar('.'));
if (dotIdx == kNotFound) {
nsString data;
CopyASCIItoUTF16(buffer, data);
svc->LogStringMessage(data.get());
printf("%s\n", buffer);
#endif
return false;
}

nsAutoString extensionMatch;
extensionMatch.AssignASCII("*");
extensionMatch.Append(Substring(path, dotIdx));
extensionMatch.AppendASCII(";");
#ifdef DEBUG_ISTYPE
sprintf(buffer, "IsType of %s is %s (took: %dms)\n",
path.get(),
mimeType.get(),
PR_IntervalToMilliseconds(PR_IntervalNow() - iStart));

nsString extensionListStr;
if (NS_FAILED(filterBundle->GetStringFromName(aStorageType.BeginReading(),
getter_Copies(extensionListStr)))) {
return false;
nsString data;
CopyASCIItoUTF16(buffer, data);
svc->LogStringMessage(data.get());
printf("%s\n", buffer);
#endif

if (aType.Equals(NS_LITERAL_STRING("pictures"))) {
return StringBeginsWith(mimeType, NS_LITERAL_CSTRING("image/"));
}

if (aType.Equals(NS_LITERAL_STRING("videos"))) {
return StringBeginsWith(mimeType, NS_LITERAL_CSTRING("video/"));
}

if (aType.Equals(NS_LITERAL_STRING("music"))) {
return StringBeginsWith(mimeType, NS_LITERAL_CSTRING("audio/"));
}

return FindInReadable(extensionMatch, extensionListStr);
return false;
}

void
Expand Down Expand Up @@ -318,7 +350,7 @@ DeviceStorageFile::Remove()
if (NS_FAILED(rv)) {
return rv;
}

if (!check) {
return NS_OK;
}
Expand Down Expand Up @@ -403,7 +435,7 @@ DeviceStorageFile::collectFilesInternal(nsTArray<nsRefPtr<DeviceStorageFile> > &
}

void
DeviceStorageFile::DirectoryDiskUsage(nsIFile* aFile, uint64_t* aSoFar, const nsAString& aStorageType)
DeviceStorageFile::DirectoryDiskUsage(nsIFile* aFile, uint64_t* aSoFar)
{
if (!aFile) {
return;
Expand Down Expand Up @@ -439,18 +471,12 @@ DeviceStorageFile::DirectoryDiskUsage(nsIFile* aFile, uint64_t* aSoFar, const ns
if (NS_FAILED(rv)) {
continue;
}

if (isLink) {
// for now, lets just totally ignore symlinks.
NS_WARNING("DirectoryDiskUsage ignores symlinks");
} else if (isDir) {
DirectoryDiskUsage(f, aSoFar, aStorageType);
DirectoryDiskUsage(f, aSoFar);
} else if (isFile) {

if (!DeviceStorageFile::IsType(f, aStorageType)) {
continue;
}

int64_t size;
rv = f->GetFileSize(&size);
if (NS_SUCCEEDED(rv)) {
Expand Down Expand Up @@ -521,8 +547,6 @@ nsDOMDeviceStorage::SetRootDirectoryForType(const nsAString& aType)
dirService->Get(NS_OSX_PICTURE_DOCUMENTS_DIR, NS_GET_IID(nsIFile), getter_AddRefs(f));
#elif defined (XP_UNIX)
dirService->Get(NS_UNIX_XDG_PICTURES_DIR, NS_GET_IID(nsIFile), getter_AddRefs(f));
#elif defined (XP_WIN)
dirService->Get(NS_WIN_PERSONAL_DIR, NS_GET_IID(nsIFile), getter_AddRefs(f));
#endif
}

Expand All @@ -534,8 +558,6 @@ nsDOMDeviceStorage::SetRootDirectoryForType(const nsAString& aType)
dirService->Get(NS_OSX_MOVIE_DOCUMENTS_DIR, NS_GET_IID(nsIFile), getter_AddRefs(f));
#elif defined (XP_UNIX)
dirService->Get(NS_UNIX_XDG_VIDEOS_DIR, NS_GET_IID(nsIFile), getter_AddRefs(f));
#elif defined (XP_WIN)
dirService->Get(NS_WIN_PERSONAL_DIR, NS_GET_IID(nsIFile), getter_AddRefs(f));
#endif
}

Expand All @@ -547,18 +569,21 @@ nsDOMDeviceStorage::SetRootDirectoryForType(const nsAString& aType)
dirService->Get(NS_OSX_MUSIC_DOCUMENTS_DIR, NS_GET_IID(nsIFile), getter_AddRefs(f));
#elif defined (XP_UNIX)
dirService->Get(NS_UNIX_XDG_MUSIC_DIR, NS_GET_IID(nsIFile), getter_AddRefs(f));
#elif defined (XP_WIN)
dirService->Get(NS_WIN_PERSONAL_DIR, NS_GET_IID(nsIFile), getter_AddRefs(f));
#endif
}

// in testing, we default all device storage types to a temp directory
if (f && mozilla::Preferences::GetBool("device.storage.testing", false)) {
dirService->Get(NS_OS_TEMP_DIR, NS_GET_IID(nsIFile), getter_AddRefs(f));
if (f) {
f->AppendRelativeNativePath(NS_LITERAL_CSTRING("device-storage-testing"));
f->Create(nsIFile::DIRECTORY_TYPE, 0777);
f->Normalize();
// in testing, we have access to a few more directory locations
if (mozilla::Preferences::GetBool("device.storage.testing", false)) {

// testing directory
if (aType.Equals(NS_LITERAL_STRING("testing")) ||
aType.Equals(NS_LITERAL_STRING("testing-other"))) {
dirService->Get(NS_OS_TEMP_DIR, NS_GET_IID(nsIFile), getter_AddRefs(f));
if (f) {
f->AppendRelativeNativePath(NS_LITERAL_CSTRING("device-storage-testing"));
f->Create(nsIFile::DIRECTORY_TYPE, 0777);
f->Normalize();
}
}
}

Expand Down Expand Up @@ -783,7 +808,7 @@ ContinueCursorEvent::Run() {
while (cursor->mFiles.Length() > 0) {
nsRefPtr<DeviceStorageFile> file = cursor->mFiles[0];
cursor->mFiles.RemoveElementAt(0);
if (!DeviceStorageFile::IsType(file->mFile, cursorStorageType)) {
if (!file->IsType(cursorStorageType)) {
continue;
}
val = nsIFileToJsval(cursor->GetOwner(), file);
Expand Down Expand Up @@ -1197,7 +1222,7 @@ class StatFileEvent : public nsRunnable
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
nsCOMPtr<nsIRunnable> r;
uint64_t diskUsage = 0;
DeviceStorageFile::DirectoryDiskUsage(mFile->mFile, &diskUsage, mFile->mStorageType);
DeviceStorageFile::DirectoryDiskUsage(mFile->mFile, &diskUsage);
int64_t freeSpace = 0;
nsresult rv = mFile->mFile->GetDiskSpaceAvailable(&freeSpace);
if (NS_FAILED(rv)) {
Expand Down Expand Up @@ -1552,65 +1577,17 @@ nsDOMDeviceStorage::CreateDeviceStoragesFor(nsPIDOMWindow* aWin,
}
}

bool
nsDOMDeviceStorage::IsMimeTypeCorrectForStorageType(nsAString& aType, nsIDOMBlob* aBlob)
{
NS_ASSERTION(aBlob, "Calling IsMimeTypeCorrectForStorageType without a blob");

nsString mimeType;
if (NS_FAILED(aBlob->GetType(mimeType))) {
return false;
}

if (aType.Equals(NS_LITERAL_STRING("pictures"))) {
return StringBeginsWith(mimeType, NS_LITERAL_STRING("image/"));
}

if (aType.Equals(NS_LITERAL_STRING("videos"))) {
return StringBeginsWith(mimeType, NS_LITERAL_STRING("video/"));
}

if (aType.Equals(NS_LITERAL_STRING("music"))) {
return StringBeginsWith(mimeType, NS_LITERAL_STRING("audio/"));
}

return false;
}

NS_IMETHODIMP
nsDOMDeviceStorage::Add(nsIDOMBlob *aBlob, nsIDOMDOMRequest * *_retval)
{
if (!aBlob) {
return NS_OK;
}

nsCOMPtr<nsIMIMEService> mimeSvc = do_GetService(NS_MIMESERVICE_CONTRACTID);
if (!mimeSvc) {
return NS_ERROR_FAILURE;
}

// if mimeType isn't set, we will not get a correct
// extension, and AddNamed() will fail. This will post an
// onerror to the requestee.
nsString mimeType;
aBlob->GetType(mimeType);

nsCString extension;
mimeSvc->GetPrimaryExtension(NS_LossyConvertUTF16toASCII(mimeType), EmptyCString(), extension);
// if extension is null here, we will ignore it for now.
// AddNamed() will check the file path and fail. This
// will post an onerror to the requestee.

// possible race here w/ unique filename
char buffer[128];
NS_MakeRandomString(buffer, ArrayLength(buffer));
NS_MakeRandomString(buffer, 128);

nsAutoCString path;
path.Assign(nsDependentCString(buffer));
path.Append(".");
path.Append(extension);
nsString path;
path.AssignWithConversion(nsDependentCString(buffer));

return AddNamed(aBlob, NS_ConvertASCIItoUTF16(path), _retval);
return AddNamed(aBlob, path, _retval);
}

NS_IMETHODIMP
Expand All @@ -1633,17 +1610,14 @@ nsDOMDeviceStorage::AddNamed(nsIDOMBlob *aBlob,
nsCOMPtr<nsIRunnable> r;

nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(mStorageType, mRootDirectory, aPath);
if (!DeviceStorageFile::IsType(dsf->mFile, mStorageType) || !IsMimeTypeCorrectForStorageType(mStorageType, aBlob)) {
r = new PostErrorEvent(request, POST_ERROR_EVENT_ILLEGAL_TYPE, dsf);
}
else if (!dsf->IsSafePath()) {

if (!dsf->IsSafePath()) {
r = new PostErrorEvent(request, POST_ERROR_EVENT_ILLEGAL_FILE_NAME, dsf);
}
else {
r = new DeviceStorageRequest(DeviceStorageRequest::DEVICE_STORAGE_REQUEST_WRITE,
win, mPrincipal, dsf, request, aBlob);
win, mPrincipal, dsf, request, aBlob);
}

NS_DispatchToMainThread(r);
return NS_OK;
}
Expand Down Expand Up @@ -1693,6 +1667,7 @@ nsDOMDeviceStorage::GetInternal(const JS::Value & aPath,

nsRefPtr<DeviceStorageFile> dsf = new DeviceStorageFile(mStorageType, mRootDirectory, path);
dsf->SetEditable(aEditable);

if (!dsf->IsSafePath()) {
r = new PostErrorEvent(request, POST_ERROR_EVENT_ILLEGAL_FILE_NAME, dsf);
} else {
Expand Down Expand Up @@ -2158,4 +2133,4 @@ nsDOMDeviceStorage::GetJSContextForEventHandlers()
return nsDOMEventTargetHelper::GetJSContextForEventHandlers();
}

NS_IMPL_EVENT_HANDLER(nsDOMDeviceStorage, change)
NS_IMPL_EVENT_HANDLER(nsDOMDeviceStorage, change)
5 changes: 2 additions & 3 deletions dom/devicestorage/nsDeviceStorage.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ class nsPIDOMWindow;
#define POST_ERROR_EVENT_FILE_NOT_ENUMERABLE "File location is not enumerable"
#define POST_ERROR_EVENT_PERMISSION_DENIED "Permission Denied"
#define POST_ERROR_EVENT_ILLEGAL_FILE_NAME "Illegal file name"
#define POST_ERROR_EVENT_ILLEGAL_TYPE "Illegal content type"
#define POST_ERROR_EVENT_UNKNOWN "Unknown"
#define POST_ERROR_EVENT_NON_STRING_TYPE_UNSUPPORTED "Non-string type unsupported"
#define POST_ERROR_EVENT_NOT_IMPLEMENTED "Not implemented"
Expand All @@ -58,15 +57,15 @@ class DeviceStorageFile MOZ_FINAL
// we want to make sure that the names of file can't reach
// outside of the type of storage the user asked for.
bool IsSafePath();
bool IsType(nsAString& aType);

nsresult Remove();
nsresult Write(nsIInputStream* aInputStream);
nsresult Write(InfallibleTArray<uint8_t>& bits);
void CollectFiles(nsTArray<nsRefPtr<DeviceStorageFile> > &aFiles, uint64_t aSince = 0);
void collectFilesInternal(nsTArray<nsRefPtr<DeviceStorageFile> > &aFiles, uint64_t aSince, nsAString& aRootPath);

static bool IsType(nsIFile* aFile, const nsAString& aStorageType);
static void DirectoryDiskUsage(nsIFile* aFile, uint64_t* aSoFar, const nsAString& aStorageType);
static void DirectoryDiskUsage(nsIFile* aFile, uint64_t* aSoFar);

private:
void NormalizeFilePath();
Expand Down
Loading

0 comments on commit 19dc351

Please sign in to comment.