Bug 1257180 - patch 2 - Directory can be sent via postMessage(), r=smaug
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -72,7 +72,6 @@ GetDirectoryListingTaskChild::GetDirectoryListingTaskChild(FileSystemBase* aFile
|
||||
|
||||
GetDirectoryListingTaskChild::~GetDirectoryListingTaskChild()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mFileSystem->AssertIsOnOwningThread();
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user