Bug 786922 - Device Storage - use a properties file instead of the mime service. r=bent

--HG--
extra : rebase_source : 17cd95eadccd4155dd00620586a1d655892f59f9
This commit is contained in:
Doug Turner 2012-09-05 14:30:36 -07:00
parent 8fb45eafd4
commit 1acfa52de1
6 changed files with 234 additions and 59 deletions

View File

@ -50,6 +50,9 @@ private:
bool aEditable,
nsIDOMDeviceStorageCursor** aRetval);
static bool IsMimeTypeCorrectForStorageType(nsAString& aType,
nsIDOMBlob* aBlob);
nsString mStorageType;
nsCOMPtr<nsIFile> mRootDirectory;

View File

@ -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<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) {
// String bundles are cached by the bundle service.
nsCOMPtr<nsIStringBundleService> 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<nsIStringBundle> 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<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, 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<nsIRunnable> r;
nsRefPtr<DeviceStorageFile> 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<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 {

View File

@ -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"

View File

@ -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 \

View File

@ -0,0 +1,68 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=786922
-->
<head>
<title>Test for basic sanity of the device storage API </title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="devicestorage_common.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=786922">Mozilla Bug 786922</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
devicestorage_setup();
function add(storage, mime) {
dump("adding: " + mime + "\n");
return navigator.getDeviceStorage(storage).add(createRandomBlob(mime));
}
var tests = [
function () { return add("pictures", "image/png")},
function () { return add("videos", "video/webm")},
function () { return add("music", "audio/wav")},
];
function fail(e) {
ok(false, "onerror was called");
devicestorage_cleanup();
}
function next(e) {
if (e != undefined)
ok(true, "addError was called");
var f = tests.pop();
if (f == undefined) {
devicestorage_cleanup();
return;
}
request = f();
request.onsuccess = next;
request.onerror = fail;
}
next();
</script>
</pre>
</body>
</html>

View File

@ -0,0 +1,72 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=786922
-->
<head>
<title>Test for basic sanity of the device storage API </title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="devicestorage_common.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=786922">Mozilla Bug 786922</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
devicestorage_setup();
function addNamed(storage, mime, fileExtension) {
dump("adding: " + mime + " " + fileExtension + "\n");
return navigator.getDeviceStorage(storage).addNamed(createRandomBlob(mime), randomFilename(40) + "." + fileExtension);
}
// These tests must all fail
var tests = [
function () { return addNamed("pictures", "kyle/smash", ".png")},
function () { return addNamed("pictures", "image/png", ".poo")},
function () { return addNamed("music", "kyle/smash", ".mp3")},
function () { return addNamed("music", "music/mp3", ".poo")},
function () { return addNamed("videos", "kyle/smash", ".ogv")},
function () { return addNamed("videos", "video/ogv", ".poo")},
];
function fail(e) {
ok(false, "addSuccess was called");
devicestorage_cleanup();
}
function next(e) {
if (e != undefined)
ok(true, "addError was called");
var f = tests.pop();
if (f == undefined) {
devicestorage_cleanup();
return;
}
request = f();
request.onsuccess = fail;
request.onerror = next;
}
next();
</script>
</pre>
</body>
</html>