diff --git a/dom/devicestorage/DeviceStorage.h b/dom/devicestorage/DeviceStorage.h index f5c01e7eda2..89d238dca7f 100644 --- a/dom/devicestorage/DeviceStorage.h +++ b/dom/devicestorage/DeviceStorage.h @@ -50,6 +50,9 @@ private: bool aEditable, nsIDOMDeviceStorageCursor** aRetval); + static bool IsMimeTypeCorrectForStorageType(nsAString& aType, + nsIDOMBlob* aBlob); + nsString mStorageType; nsCOMPtr mRootDirectory; diff --git a/dom/devicestorage/nsDeviceStorage.cpp b/dom/devicestorage/nsDeviceStorage.cpp index 2db2d135dd2..a2e4838caca 100644 --- a/dom/devicestorage/nsDeviceStorage.cpp +++ b/dom/devicestorage/nsDeviceStorage.cpp @@ -39,6 +39,8 @@ #include "nsIMIMEService.h" #include "nsCExternalHandlerService.h" +#include "nsIStringBundle.h" + // Microsoft's API Name hackery sucks #undef CreateEvent @@ -47,11 +49,7 @@ #include "nsIVolumeService.h" #endif -#define DEBUG_ISTYPE 1 - -#ifdef DEBUG_ISTYPE -#include "nsIConsoleService.h" -#endif +#define DEVICESTORAGE_PROPERTIES "chrome://global/content/devicestorage.properties" using namespace mozilla::dom; using namespace mozilla::dom::devicestorage; @@ -84,7 +82,9 @@ private: 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) @@ -155,61 +155,38 @@ DeviceStorageFile::IsType(nsAString& aType) { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); -#ifdef DEBUG_ISTYPE - nsCOMPtr svc = do_GetService(NS_CONSOLESERVICE_CONTRACTID); - char buffer[1024]; - nsCString path; - mFile->GetNativePath(path); - - PRIntervalTime iStart = PR_IntervalNow(); -#endif - - nsAutoCString mimeType; - nsCOMPtr mimeService = do_GetService(NS_MIMESERVICE_CONTRACTID); - if (!mimeService) { + // String bundles are cached by the bundle service. + nsCOMPtr stringService = mozilla::services::GetStringBundleService(); + if (!stringService) { return false; } - 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)); - - nsString data; - CopyASCIItoUTF16(buffer, data); - svc->LogStringMessage(data.get()); - printf("%s\n", buffer); -#endif + nsCOMPtr filterBundle; + if (NS_FAILED(stringService->CreateBundle(DEVICESTORAGE_PROPERTIES, + getter_AddRefs(filterBundle)))) { return false; } -#ifdef DEBUG_ISTYPE - sprintf(buffer, "IsType of %s is %s (took: %dms)\n", - path.get(), - mimeType.get(), - PR_IntervalToMilliseconds(PR_IntervalNow() - iStart)); + nsString path; + mFile->GetPath(path); - 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/")); + int32_t dotIdx = path.RFindChar(PRUnichar('.')); + if (dotIdx == kNotFound) { + return false; } - if (aType.Equals(NS_LITERAL_STRING("videos"))) { - return StringBeginsWith(mimeType, NS_LITERAL_CSTRING("video/")); + nsAutoString extensionMatch; + extensionMatch.AssignASCII("*"); + extensionMatch.Append(Substring(path, dotIdx)); + extensionMatch.AppendASCII(";"); + + nsString extensionListStr; + if (NS_FAILED(filterBundle->GetStringFromName(aType.BeginReading(), + getter_Copies(extensionListStr)))) { + return false; } - if (aType.Equals(NS_LITERAL_STRING("music"))) { - return StringBeginsWith(mimeType, NS_LITERAL_CSTRING("audio/")); - } - - return false; + return FindInReadable(extensionMatch, extensionListStr); } void @@ -343,7 +320,7 @@ DeviceStorageFile::Remove() if (NS_FAILED(rv)) { return rv; } - + if (!check) { return NS_OK; } @@ -1565,17 +1542,65 @@ 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 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, 128); + NS_MakeRandomString(buffer, ArrayLength(buffer)); - nsString path; - path.AssignWithConversion(nsDependentCString(buffer)); + nsAutoCString path; + path.Assign(nsDependentCString(buffer)); + path.Append("."); + path.Append(extension); - return AddNamed(aBlob, path, _retval); + return AddNamed(aBlob, NS_ConvertASCIItoUTF16(path), _retval); } NS_IMETHODIMP @@ -1598,14 +1623,17 @@ nsDOMDeviceStorage::AddNamed(nsIDOMBlob *aBlob, nsCOMPtr r; nsRefPtr dsf = new DeviceStorageFile(mStorageType, mRootDirectory, aPath); - - if (!dsf->IsSafePath()) { + if (!dsf->IsType(mStorageType) || !IsMimeTypeCorrectForStorageType(mStorageType, aBlob)) { + r = new PostErrorEvent(request, POST_ERROR_EVENT_ILLEGAL_TYPE, dsf); + } + else 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; } @@ -1655,7 +1683,6 @@ nsDOMDeviceStorage::GetInternal(const JS::Value & aPath, nsRefPtr dsf = new DeviceStorageFile(mStorageType, mRootDirectory, path); dsf->SetEditable(aEditable); - if (!dsf->IsSafePath()) { r = new PostErrorEvent(request, POST_ERROR_EVENT_ILLEGAL_FILE_NAME, dsf); } else { diff --git a/dom/devicestorage/nsDeviceStorage.h b/dom/devicestorage/nsDeviceStorage.h index b5c1f5e5797..260faec8063 100644 --- a/dom/devicestorage/nsDeviceStorage.h +++ b/dom/devicestorage/nsDeviceStorage.h @@ -33,6 +33,7 @@ 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" diff --git a/dom/devicestorage/test/Makefile.in b/dom/devicestorage/test/Makefile.in index f029a097d8b..e26cffb59eb 100644 --- a/dom/devicestorage/test/Makefile.in +++ b/dom/devicestorage/test/Makefile.in @@ -10,8 +10,12 @@ relativesrcdir = @relativesrcdir@ include $(DEPTH)/config/autoconf.mk +# man, our mime database sucks hard. followup bug # 788273 +# test_add.html \ + MOCHITEST_FILES = \ test_sanity.html \ + test_addCorrectType.html \ test_basic.html \ test_enumerate.html \ test_enumerateMultipleContinue.html \ diff --git a/dom/devicestorage/test/test_add.html b/dom/devicestorage/test/test_add.html new file mode 100644 index 00000000000..2e1bd6edb21 --- /dev/null +++ b/dom/devicestorage/test/test_add.html @@ -0,0 +1,68 @@ + + + + + + Test for basic sanity of the device storage API + + + + + + +Mozilla Bug 786922 +

+ +
+
+
+ + + diff --git a/dom/devicestorage/test/test_addCorrectType.html b/dom/devicestorage/test/test_addCorrectType.html new file mode 100644 index 00000000000..2920840f91e --- /dev/null +++ b/dom/devicestorage/test/test_addCorrectType.html @@ -0,0 +1,72 @@ + + + + + + Test for basic sanity of the device storage API + + + + + + +Mozilla Bug 786922 +

+ +
+
+
+ + +