Bug 1257180 - patch 2 - Directory can be sent via postMessage(), r=smaug

This commit is contained in:
Andrea Marchesini
2016-04-12 08:51:04 -04:00
parent 65cc374a11
commit 31f9661a43
6 changed files with 119 additions and 14 deletions

View File

@@ -11,6 +11,7 @@
#include "mozilla/dom/BlobBinding.h"
#include "mozilla/dom/CryptoKey.h"
#include "mozilla/dom/Directory.h"
#include "mozilla/dom/DirectoryBinding.h"
#include "mozilla/dom/File.h"
#include "mozilla/dom/FileList.h"
#include "mozilla/dom/FileListBinding.h"
@@ -658,7 +659,7 @@ ReadBlob(JSContext* aCx,
MOZ_ASSERT(blobImpl);
// RefPtr<File> needs to go out of scope before toObjectOrNull() is
// RefPtr<File> needs to go out of scope before toObject() is
// called because the static analysis thinks dereferencing XPCOM objects
// can GC (because in some cases it can!), and a return statement with a
// JSObject* type means that JSObject* is on the stack as a raw pointer
@@ -705,6 +706,80 @@ WriteBlob(JSStructuredCloneWriter* aWriter,
return false;
}
// A directory is serialized as:
// - pair of ints: SCTAG_DOM_DIRECTORY, 0
// - pair of ints: type (eDOMRootDirectory/eDOMNotRootDirectory) - path length
// - path as string
bool
WriteDirectory(JSStructuredCloneWriter* aWriter,
Directory* aDirectory)
{
MOZ_ASSERT(aWriter);
MOZ_ASSERT(aDirectory);
nsAutoString path;
aDirectory->GetFullRealPath(path);
size_t charSize = sizeof(nsString::char_type);
return JS_WriteUint32Pair(aWriter, SCTAG_DOM_DIRECTORY, 0) &&
JS_WriteUint32Pair(aWriter, (uint32_t)aDirectory->Type(),
path.Length()) &&
JS_WriteBytes(aWriter, path.get(), path.Length() * charSize);
}
JSObject*
ReadDirectory(JSContext* aCx,
JSStructuredCloneReader* aReader,
uint32_t aZero,
StructuredCloneHolder* aHolder)
{
MOZ_ASSERT(aCx);
MOZ_ASSERT(aReader);
MOZ_ASSERT(aHolder);
MOZ_ASSERT(aZero == 0);
uint32_t directoryType, lengthOfString;
if (!JS_ReadUint32Pair(aReader, &directoryType, &lengthOfString)) {
return nullptr;
}
MOZ_ASSERT(directoryType == Directory::eDOMRootDirectory ||
directoryType == Directory::eNotDOMRootDirectory);
nsAutoString path;
path.SetLength(lengthOfString);
size_t charSize = sizeof(nsString::char_type);
if (!JS_ReadBytes(aReader, (void*) path.BeginWriting(),
lengthOfString * charSize)) {
return nullptr;
}
nsCOMPtr<nsIFile> file;
nsresult rv = NS_NewNativeLocalFile(NS_ConvertUTF16toUTF8(path), true,
getter_AddRefs(file));
if (NS_WARN_IF(NS_FAILED(rv))) {
return nullptr;
}
// RefPtr<Directory> needs to go out of scope before toObject() is
// called because the static analysis thinks dereferencing XPCOM objects
// can GC (because in some cases it can!), and a return statement with a
// JSObject* type means that JSObject* is on the stack as a raw pointer
// while destructors are running.
JS::Rooted<JS::Value> val(aCx);
{
RefPtr<Directory> directory =
Directory::Create(aHolder->ParentDuringRead(), file,
(Directory::DirectoryType) directoryType);
if (!ToJSValue(aCx, directory, &val)) {
return nullptr;
}
}
return &val.toObject();
}
// Read the WriteFileList for the format.
JSObject*
ReadFileList(JSContext* aCx,
@@ -1002,6 +1077,10 @@ StructuredCloneHolder::CustomReadHandler(JSContext* aCx,
return ReadBlob(aCx, aIndex, this);
}
if (aTag == SCTAG_DOM_DIRECTORY) {
return ReadDirectory(aCx, aReader, aIndex, this);
}
if (aTag == SCTAG_DOM_FILELIST) {
return ReadFileList(aCx, aReader, aIndex, this);
}
@@ -1042,6 +1121,14 @@ StructuredCloneHolder::CustomWriteHandler(JSContext* aCx,
}
}
// See if this is a Directory object.
{
Directory* directory = nullptr;
if (NS_SUCCEEDED(UNWRAP_OBJECT(Directory, aObj, directory))) {
return WriteDirectory(aWriter, directory);
}
}
// See if this is a FileList object.
{
FileList* fileList = nullptr;

View File

@@ -17,7 +17,6 @@ namespace dom {
enum StructuredCloneTags {
SCTAG_BASE = JS_SCTAG_USER_MIN,
// These tags are used only for main thread structured clone.
SCTAG_DOM_BLOB,
// This tag is obsolete and exists only for backwards compatibility with
@@ -53,6 +52,8 @@ enum StructuredCloneTags {
SCTAG_DOM_EXPANDED_PRINCIPAL,
SCTAG_DOM_DIRECTORY,
SCTAG_DOM_MAX
};

View File

@@ -114,6 +114,34 @@ function create_fileList_forDir() {
script.sendAsyncMessage("dir.open");
}
function create_directory() {
if (navigator.userAgent.toLowerCase().indexOf('Android') != -1) {
next();
return;
}
var url = SimpleTest.getTestFileURL("script_postmessages_fileList.js");
var script = SpecialPowers.loadChromeScript(url);
function onOpened(message) {
var fileList = document.getElementById('fileList');
SpecialPowers.wrap(fileList).mozSetDirectory(message.dir);
fileList.getFilesAndDirectories().then(function(list) {
// Just a simple test
is(list.length, 1, "This list has 1 element");
ok(list[0] instanceof Directory, "We have a directory.");
clonableObjects.push(list[0]);
script.destroy();
next();
});
}
script.addMessageListener("dir.opened", onOpened);
script.sendAsyncMessage("dir.open");
}
function runTests(obj) {
ok(('clonableObjects' in obj) &&
('transferableObjects' in obj) &&
@@ -522,6 +550,7 @@ function test_messagePort_inWorkers() {
var tests = [
create_fileList_forFile,
create_fileList_forDir,
create_directory,
test_windowToWindow,
test_windowToIframe,

View File

@@ -72,7 +72,6 @@ GetDirectoryListingTaskChild::GetDirectoryListingTaskChild(FileSystemBase* aFile
GetDirectoryListingTaskChild::~GetDirectoryListingTaskChild()
{
MOZ_ASSERT(NS_IsMainThread());
mFileSystem->AssertIsOnOwningThread();
}

View File

@@ -59,7 +59,6 @@ nsISupports*
OSFileSystem::GetParentObject() const
{
AssertIsOnOwningThread();
MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
return mParent;
}
@@ -94,8 +93,6 @@ void
OSFileSystem::Unlink()
{
AssertIsOnOwningThread();
MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
mParent = nullptr;
}
@@ -103,7 +100,6 @@ void
OSFileSystem::Traverse(nsCycleCollectionTraversalCallback &cb)
{
AssertIsOnOwningThread();
MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
OSFileSystem* tmp = this;
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParent);

View File

@@ -5042,13 +5042,6 @@ HTMLInputElement::GetFilesAndDirectories(ErrorResult& aRv)
for (uint32_t i = 0; i < filesAndDirs.Length(); ++i) {
if (filesAndDirs[i].IsDirectory()) {
#if defined(ANDROID) || defined(MOZ_B2G)
MOZ_ASSERT(false,
"Directory picking should have been redirected to normal "
"file picking for platforms that don't have a directory "
"picker");
#endif
RefPtr<Directory> directory = filesAndDirs[i].GetAsDirectory();
// In future we could refactor SetFilePickerFiltersFromAccept to return a