summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgrv@chromium.org <grv@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-01-17 10:02:15 +0000
committergrv@chromium.org <grv@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-01-17 10:02:15 +0000
commit27b63409118ffb337df1f75a0f8d89d27f389ec0 (patch)
treeb51c218f39c8d1a0bd0ff7244901639b79abac5e
parentdfbaa1f0797cf602c8da17834ed8e7fe0764946c (diff)
downloadchromium_src-27b63409118ffb337df1f75a0f8d89d27f389ec0.zip
chromium_src-27b63409118ffb337df1f75a0f8d89d27f389ec0.tar.gz
chromium_src-27b63409118ffb337df1f75a0f8d89d27f389ec0.tar.bz2
New API to copy syncfs folder to localfs.
Changed the API to take a HTML5 DirectoryEntry. loadDirectory(DirectoryEntry entry). BUG=335299 TBR=thakis@chromiun.org Review URL: https://codereview.chromium.org/132313009 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@245474 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/extensions/api/developer_private/developer_private_api.cc223
-rw-r--r--chrome/browser/extensions/api/developer_private/developer_private_api.h40
-rw-r--r--chrome/common/extensions/api/developer_private.idl11
-rw-r--r--chrome/renderer/extensions/dispatcher.cc2
-rw-r--r--chrome/renderer/resources/extensions/developer_private_custom_bindings.js27
-rw-r--r--chrome/renderer/resources/renderer_resources.grd1
6 files changed, 153 insertions, 151 deletions
diff --git a/chrome/browser/extensions/api/developer_private/developer_private_api.cc b/chrome/browser/extensions/api/developer_private/developer_private_api.cc
index 3720958..c10bf03 100644
--- a/chrome/browser/extensions/api/developer_private/developer_private_api.cc
+++ b/chrome/browser/extensions/api/developer_private/developer_private_api.cc
@@ -22,6 +22,7 @@
#include "chrome/browser/extensions/api/developer_private/developer_private_api_factory.h"
#include "chrome/browser/extensions/api/developer_private/entry_picker.h"
#include "chrome/browser/extensions/api/extension_action/extension_action_api.h"
+#include "chrome/browser/extensions/api/file_handlers/app_file_handler_util.h"
#include "chrome/browser/extensions/devtools_util.h"
#include "chrome/browser/extensions/extension_disabled_ui.h"
#include "chrome/browser/extensions/extension_error_reporter.h"
@@ -66,6 +67,7 @@
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/base/webui/web_ui_util.h"
+#include "webkit/browser/fileapi/external_mount_points.h"
#include "webkit/browser/fileapi/file_system_context.h"
#include "webkit/browser/fileapi/file_system_operation.h"
#include "webkit/browser/fileapi/file_system_operation_runner.h"
@@ -126,23 +128,6 @@ GURL ToDataURL(const base::FilePath& path, developer_private::ItemType type) {
return GetImageURLFromData(contents);
}
-bool ValidateFolderName(const base::FilePath::StringType& name) {
- base::FilePath::StringType name_sanitized(name);
- file_util::ReplaceIllegalCharactersInPath(&name_sanitized, '_');
- return name == name_sanitized;
-}
-
-const Extension* GetExtensionByPath(const extensions::ExtensionSet* extensions,
- const base::FilePath& path) {
- base::FilePath extension_path = base::MakeAbsoluteFilePath(path);
- for (extensions::ExtensionSet::const_iterator iter = extensions->begin();
- iter != extensions->end(); ++iter) {
- if ((*iter)->path() == extension_path)
- return iter->get();
- }
- return NULL;
-}
-
std::string GetExtensionID(const RenderViewHost* render_view_host) {
if (!render_view_host->GetSiteInstance())
return std::string();
@@ -961,63 +946,114 @@ DeveloperPrivatePackDirectoryFunction::~DeveloperPrivatePackDirectoryFunction()
DeveloperPrivateLoadUnpackedFunction::~DeveloperPrivateLoadUnpackedFunction() {}
-bool DeveloperPrivateExportSyncfsFolderToLocalfsFunction::RunImpl() {
+bool DeveloperPrivateLoadDirectoryFunction::RunImpl() {
// TODO(grv) : add unittests.
- base::FilePath::StringType project_name;
- EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &project_name));
- if (!ValidateFolderName(project_name)) {
- DVLOG(0) << "Invalid project_name : [" << project_name << "]";
+ std::string directory_url_str;
+ std::string filesystem_name;
+ std::string filesystem_path;
+
+ EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &filesystem_name));
+ EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &filesystem_path));
+ EXTENSION_FUNCTION_VALIDATE(args_->GetString(2, &directory_url_str));
+
+ // Directory url is non empty only for syncfilesystem.
+ if (directory_url_str != "") {
+
+ context_ = content::BrowserContext::GetStoragePartition(
+ GetProfile(), render_view_host()->GetSiteInstance())
+ ->GetFileSystemContext();
+
+ fileapi::FileSystemURL directory_url =
+ context_->CrackURL(GURL(directory_url_str));
+
+ if (!directory_url.is_valid() && directory_url.type() ==
+ fileapi::kFileSystemTypeSyncable) {
+ SetError("DirectoryEntry of unsupported filesystem.");
+ return false;
+ }
+
+ size_t pos = 0;
+ // Parse the project directory name from the project url. The project url is
+ // expected to have project name as the suffix.
+ if ((pos = directory_url_str.rfind("/")) == std::string::npos) {
+ SetError("Invalid Directory entry.");
+ return false;
+ }
+
+ std::string project_name;
+ project_name = directory_url_str.substr(pos + 1);
+ project_base_url_ = directory_url_str.substr(0, pos + 1);
+
+ base::FilePath project_path(GetProfile()->GetPath());
+ project_path = project_path.Append(kUnpackedAppsFolder);
+ project_path = project_path.Append(
+ base::FilePath::FromUTF8Unsafe(project_name));
+
+ project_base_path_ = project_path;
+
+ content::BrowserThread::PostTask(content::BrowserThread::FILE, FROM_HERE,
+ base::Bind(&DeveloperPrivateLoadDirectoryFunction::
+ ClearExistingDirectoryContent,
+ this,
+ project_base_path_));
+ } else {
+
+ // Check if the DirecotryEntry is the instace of chrome filesystem..
+ if (!app_file_handler_util::ValidateFileEntryAndGetPath(filesystem_name,
+ filesystem_path,
+ render_view_host_,
+ &project_base_path_,
+ &error_))
return false;
+
+ Load();
}
- context_ = content::BrowserContext::GetStoragePartition(
- GetProfile(), render_view_host()->GetSiteInstance())
- ->GetFileSystemContext();
+ return true;
+}
- base::FilePath project_path(GetProfile()->GetPath());
- project_path = project_path.Append(kUnpackedAppsFolder);
- project_path = project_path.Append(project_name);
+void DeveloperPrivateLoadDirectoryFunction::Load() {
- content::BrowserThread::PostTask(content::BrowserThread::FILE, FROM_HERE,
- base::Bind(&DeveloperPrivateExportSyncfsFolderToLocalfsFunction::
- ClearPrexistingDirectoryContent,
- this,
- project_path));
+ ExtensionService* service = GetProfile()->GetExtensionService();
+ UnpackedInstaller::Create(service)->Load(project_base_path_);
- return true;
+ // TODO(grv) : The unpacked installer should fire an event when complete
+ // and return the extension_id.
+ SetResult(new base::StringValue("-1"));
+ SendResponse(true);
}
-void DeveloperPrivateExportSyncfsFolderToLocalfsFunction::
- ClearPrexistingDirectoryContent(const base::FilePath& project_path) {
+void DeveloperPrivateLoadDirectoryFunction::ClearExistingDirectoryContent(
+ const base::FilePath& project_path) {
// Clear the project directory before copying new files.
base::DeleteFile(project_path, true/*recursive*/);
- pendingCopyOperationsCount_ = 1;
+ pending_copy_operations_count_ = 1;
content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
- base::Bind(&DeveloperPrivateExportSyncfsFolderToLocalfsFunction::
+ base::Bind(&DeveloperPrivateLoadDirectoryFunction::
ReadSyncFileSystemDirectory,
this, project_path, project_path.BaseName()));
}
-void DeveloperPrivateExportSyncfsFolderToLocalfsFunction::
- ReadSyncFileSystemDirectory(const base::FilePath& project_path,
- const base::FilePath& destination_path) {
- std::string origin_url(
- Extension::GetBaseURLFromExtensionId(extension_id()).spec());
- fileapi::FileSystemURL url(sync_file_system::CreateSyncableFileSystemURL(
- GURL(origin_url),
- destination_path));
+void DeveloperPrivateLoadDirectoryFunction::ReadSyncFileSystemDirectory(
+ const base::FilePath& project_path,
+ const base::FilePath& destination_path) {
+
+ current_path_ = context_->CrackURL(GURL(project_base_url_)).path();
+
+ GURL project_url = GURL(project_base_url_ + destination_path.MaybeAsASCII());
+
+ fileapi::FileSystemURL url = context_->CrackURL(project_url);
context_->operation_runner()->ReadDirectory(
- url, base::Bind(&DeveloperPrivateExportSyncfsFolderToLocalfsFunction::
+ url, base::Bind(&DeveloperPrivateLoadDirectoryFunction::
ReadSyncFileSystemDirectoryCb,
this, project_path, destination_path));
}
-void DeveloperPrivateExportSyncfsFolderToLocalfsFunction::
- ReadSyncFileSystemDirectoryCb(
+void DeveloperPrivateLoadDirectoryFunction::ReadSyncFileSystemDirectoryCb(
const base::FilePath& project_path,
const base::FilePath& destination_path,
base::PlatformFileError status,
@@ -1036,7 +1072,7 @@ void DeveloperPrivateExportSyncfsFolderToLocalfsFunction::
// In case the directory happens to be executing the last copy operation it
// will call SendResponse to send the response to the API. The pending copy
// operations of files are released by the CopyFile function.
- pendingCopyOperationsCount_ += file_list.size();
+ pending_copy_operations_count_ += file_list.size();
for (size_t i = 0; i < file_list.size(); ++i) {
if (file_list[i].is_directory) {
@@ -1049,33 +1085,30 @@ void DeveloperPrivateExportSyncfsFolderToLocalfsFunction::
Extension::GetBaseURLFromExtensionId(extension_id()).spec());
fileapi::FileSystemURL url(sync_file_system::CreateSyncableFileSystemURL(
GURL(origin_url),
- destination_path.Append(file_list[i].name)));
+ current_path_.Append(destination_path.Append(file_list[i].name))));
base::FilePath target_path = project_path;
target_path = target_path.Append(file_list[i].name);
context_->operation_runner()->CreateSnapshotFile(
url,
- base::Bind(
- &DeveloperPrivateExportSyncfsFolderToLocalfsFunction::
- SnapshotFileCallback,
+ base::Bind(&DeveloperPrivateLoadDirectoryFunction::SnapshotFileCallback,
this,
target_path));
}
// Directory copy operation released here.
- pendingCopyOperationsCount_--;
+ pending_copy_operations_count_--;
- if (!pendingCopyOperationsCount_) {
+ if (!pending_copy_operations_count_) {
content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
- base::Bind(&DeveloperPrivateExportSyncfsFolderToLocalfsFunction::
- SendResponse,
+ base::Bind(&DeveloperPrivateLoadDirectoryFunction::SendResponse,
this,
success_));
}
}
-void DeveloperPrivateExportSyncfsFolderToLocalfsFunction::SnapshotFileCallback(
+void DeveloperPrivateLoadDirectoryFunction::SnapshotFileCallback(
const base::FilePath& target_path,
base::PlatformFileError result,
const base::PlatformFileInfo& file_info,
@@ -1088,13 +1121,13 @@ void DeveloperPrivateExportSyncfsFolderToLocalfsFunction::SnapshotFileCallback(
}
content::BrowserThread::PostTask(content::BrowserThread::FILE, FROM_HERE,
- base::Bind(&DeveloperPrivateExportSyncfsFolderToLocalfsFunction::CopyFile,
+ base::Bind(&DeveloperPrivateLoadDirectoryFunction::CopyFile,
this,
src_path,
target_path));
}
-void DeveloperPrivateExportSyncfsFolderToLocalfsFunction::CopyFile(
+void DeveloperPrivateLoadDirectoryFunction::CopyFile(
const base::FilePath& src_path,
const base::FilePath& target_path) {
if (!base::CreateDirectory(target_path.DirName())) {
@@ -1105,71 +1138,21 @@ void DeveloperPrivateExportSyncfsFolderToLocalfsFunction::CopyFile(
if (success_)
base::CopyFile(src_path, target_path);
- CHECK(pendingCopyOperationsCount_ > 0);
- pendingCopyOperationsCount_--;
+ CHECK(pending_copy_operations_count_ > 0);
+ pending_copy_operations_count_--;
- if (!pendingCopyOperationsCount_) {
+ if (!pending_copy_operations_count_) {
content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
- base::Bind(&DeveloperPrivateExportSyncfsFolderToLocalfsFunction::
- SendResponse,
- this,
- success_));
+ base::Bind(&DeveloperPrivateLoadDirectoryFunction::Load,
+ this));
}
}
-DeveloperPrivateExportSyncfsFolderToLocalfsFunction::
- DeveloperPrivateExportSyncfsFolderToLocalfsFunction()
- : pendingCopyOperationsCount_(0), success_(true) {}
-
-DeveloperPrivateExportSyncfsFolderToLocalfsFunction::
- ~DeveloperPrivateExportSyncfsFolderToLocalfsFunction() {}
-
-bool DeveloperPrivateLoadProjectFunction::RunImpl() {
- // TODO(grv) : add unit tests.
- base::FilePath::StringType project_name;
- EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &project_name));
- if (!ValidateFolderName(project_name)) {
- DVLOG(0) << "Invalid project_name : [" << project_name << "]";
- return false;
- }
-
- base::FilePath path(GetProfile()->GetPath());
- path = path.Append(kUnpackedAppsFolder);
- // TODO(grv) : Sanitize / check project_name.
- path = path.Append(project_name);
- ExtensionService* service = GetProfile()->GetExtensionService();
- UnpackedInstaller::Create(service)->Load(path);
-
- const extensions::ExtensionSet* extensions = service->extensions();
- // Released by GetUnpackedExtension.
- AddRef();
- content::BrowserThread::PostTask(content::BrowserThread::FILE, FROM_HERE,
- base::Bind(&DeveloperPrivateLoadProjectFunction::GetUnpackedExtension,
- this, path, extensions));
- return true;
-}
-
-void DeveloperPrivateLoadProjectFunction::GetUnpackedExtension(
- const base::FilePath& path,
- const extensions::ExtensionSet* extensions) {
- const Extension* extension = GetExtensionByPath(extensions, path);
- bool success = true;
- if (extension) {
- SetResult(new base::StringValue(extension->id()));
- } else {
- SetError("unable to load the project");
- success = false;
- }
- content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
- base::Bind(&DeveloperPrivateLoadProjectFunction::SendResponse,
- this,
- success));
- Release();
-}
-
-DeveloperPrivateLoadProjectFunction::DeveloperPrivateLoadProjectFunction() {}
+DeveloperPrivateLoadDirectoryFunction::DeveloperPrivateLoadDirectoryFunction()
+ : pending_copy_operations_count_(0), success_(true) {}
-DeveloperPrivateLoadProjectFunction::~DeveloperPrivateLoadProjectFunction() {}
+DeveloperPrivateLoadDirectoryFunction::~DeveloperPrivateLoadDirectoryFunction()
+ {}
bool DeveloperPrivateChoosePathFunction::RunImpl() {
diff --git a/chrome/browser/extensions/api/developer_private/developer_private_api.h b/chrome/browser/extensions/api/developer_private/developer_private_api.h
index d747fd1..366c98f 100644
--- a/chrome/browser/extensions/api/developer_private/developer_private_api.h
+++ b/chrome/browser/extensions/api/developer_private/developer_private_api.h
@@ -366,21 +366,21 @@ class DeveloperPrivateIsProfileManagedFunction
virtual bool RunImpl() OVERRIDE;
};
-class DeveloperPrivateExportSyncfsFolderToLocalfsFunction
+class DeveloperPrivateLoadDirectoryFunction
: public ChromeAsyncExtensionFunction {
public:
- DECLARE_EXTENSION_FUNCTION("developerPrivate.exportSyncfsFolderToLocalfs",
+ DECLARE_EXTENSION_FUNCTION("developerPrivate.loadDirectory",
DEVELOPERPRIVATE_LOADUNPACKEDCROS);
- DeveloperPrivateExportSyncfsFolderToLocalfsFunction();
+ DeveloperPrivateLoadDirectoryFunction();
protected:
- virtual ~DeveloperPrivateExportSyncfsFolderToLocalfsFunction();
+ virtual ~DeveloperPrivateLoadDirectoryFunction();
// ExtensionFunction
virtual bool RunImpl() OVERRIDE;
- void ClearPrexistingDirectoryContent(const base::FilePath& project_path);
+ void ClearExistingDirectoryContent(const base::FilePath& project_path);
void ReadSyncFileSystemDirectory(const base::FilePath& project_path,
const base::FilePath& destination_path);
@@ -402,32 +402,26 @@ class DeveloperPrivateExportSyncfsFolderToLocalfsFunction
void CopyFile(const base::FilePath& src_path,
const base::FilePath& dest_path);
+ void Load();
+
scoped_refptr<fileapi::FileSystemContext> context_;
+ // syncfs url representing the root of the folder to be copied.
+ std::string project_base_url_;
+
+ // physical path on disc of the folder to be copied.
+ base::FilePath project_base_path_;
+
+ // Path of the current folder to be copied.
+ base::FilePath current_path_;
+
private:
- int pendingCopyOperationsCount_;
+ int pending_copy_operations_count_;
// This is set to false if any of the copyFile operations fail on
// call of the API. It is returned as a response of the API call.
bool success_;
-};
-
-class DeveloperPrivateLoadProjectFunction
- : public ChromeAsyncExtensionFunction {
- public:
- DECLARE_EXTENSION_FUNCTION("developerPrivate.loadProject",
- DEVELOPERPRIVATE_LOADPROJECT);
-
- DeveloperPrivateLoadProjectFunction();
-
- protected:
- virtual ~DeveloperPrivateLoadProjectFunction();
-
- // ExtensionFunction
- virtual bool RunImpl() OVERRIDE;
- void GetUnpackedExtension(const base::FilePath& path,
- const ExtensionSet* extensions);
};
} // namespace api
diff --git a/chrome/common/extensions/api/developer_private.idl b/chrome/common/extensions/api/developer_private.idl
index 57307e3..c16f22c 100644
--- a/chrome/common/extensions/api/developer_private.idl
+++ b/chrome/common/extensions/api/developer_private.idl
@@ -175,14 +175,9 @@ namespace developerPrivate {
// Load a user selected unpacked item
static void loadUnpacked(optional VoidCallback callback);
- // Copies the syncfs folder for the extension to local disk.
- static void exportSyncfsFolderToLocalfs(DOMString folder_name,
- optional VoidCallback callback);
-
- // Loads the unpacked app / extension.
- // |callback| called with itemId of the loaded item.
- static void loadProject(DOMString project_name,
- PathCallback callback);
+ // Loads an extension / app from a given |directory|
+ static void loadDirectory([instanceOf=DirectoryEntry] object directory,
+ PathCallback callback);
// Open Dialog to browse to an entry.
// |select_type| : Select a file or a folder.
diff --git a/chrome/renderer/extensions/dispatcher.cc b/chrome/renderer/extensions/dispatcher.cc
index 6b55b5a..277b094 100644
--- a/chrome/renderer/extensions/dispatcher.cc
+++ b/chrome/renderer/extensions/dispatcher.cc
@@ -981,6 +981,8 @@ void Dispatcher::PopulateSourceMap() {
IDR_DECLARATIVE_WEBREQUEST_CUSTOM_BINDINGS_JS);
source_map_.RegisterSource("desktopCapture",
IDR_DESKTOP_CAPTURE_CUSTOM_BINDINGS_JS);
+ source_map_.RegisterSource("developerPrivate",
+ IDR_DEVELOPER_PRIVATE_CUSTOM_BINDINGS_JS);
source_map_.RegisterSource("downloads",
IDR_DOWNLOADS_CUSTOM_BINDINGS_JS);
source_map_.RegisterSource("experimental.offscreen",
diff --git a/chrome/renderer/resources/extensions/developer_private_custom_bindings.js b/chrome/renderer/resources/extensions/developer_private_custom_bindings.js
new file mode 100644
index 0000000..bb818a82
--- /dev/null
+++ b/chrome/renderer/resources/extensions/developer_private_custom_bindings.js
@@ -0,0 +1,27 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Custom binding for the developerPrivate API.
+
+var binding = require('binding').Binding.create('developerPrivate');
+
+binding.registerCustomHook(function(bindingsAPI) {
+ var apiFunctions = bindingsAPI.apiFunctions;
+
+ // Converts the argument of |functionName| from DirectoryEntry to URL.
+ function bindFileSystemFunction(functionName) {
+ apiFunctions.setUpdateArgumentsPostValidate(
+ functionName, function(directoryEntry, callback) {
+ var fileSystemName = directoryEntry.filesystem.name;
+ var relativePath = $String.slice(directoryEntry.fullPath, 1);
+ var url = directoryEntry.toURL();
+ return [fileSystemName, relativePath, url, callback];
+ });
+ }
+
+ bindFileSystemFunction('loadDirectory');
+
+});
+
+exports.binding = binding.generate();
diff --git a/chrome/renderer/resources/renderer_resources.grd b/chrome/renderer/resources/renderer_resources.grd
index cf79c70..c34ec03 100644
--- a/chrome/renderer/resources/renderer_resources.grd
+++ b/chrome/renderer/resources/renderer_resources.grd
@@ -60,6 +60,7 @@ without changes to the corresponding grd file. fb9 -->
<include name="IDR_DECLARATIVE_CONTENT_CUSTOM_BINDINGS_JS" file="extensions\declarative_content_custom_bindings.js" type="BINDATA" />
<include name="IDR_DECLARATIVE_WEBREQUEST_CUSTOM_BINDINGS_JS" file="extensions\declarative_webrequest_custom_bindings.js" type="BINDATA" />
<include name="IDR_DESKTOP_CAPTURE_CUSTOM_BINDINGS_JS" file="extensions\desktop_capture_custom_bindings.js" type="BINDATA" />
+ <include name="IDR_DEVELOPER_PRIVATE_CUSTOM_BINDINGS_JS" file="extensions\developer_private_custom_bindings.js" type="BINDATA" />
<include name="IDR_DOWNLOADS_CUSTOM_BINDINGS_JS" file="extensions\downloads_custom_bindings.js" type="BINDATA" />
<include name="IDR_BLUETOOTH_CUSTOM_BINDINGS_JS" file="extensions\bluetooth_custom_bindings.js" type="BINDATA" />
<include name="IDR_PERMISSIONS_CUSTOM_BINDINGS_JS" file="extensions\permissions_custom_bindings.js" type="BINDATA" />