diff options
author | grv@chromium.org <grv@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-01-17 10:02:15 +0000 |
---|---|---|
committer | grv@chromium.org <grv@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-01-17 10:02:15 +0000 |
commit | 27b63409118ffb337df1f75a0f8d89d27f389ec0 (patch) | |
tree | b51c218f39c8d1a0bd0ff7244901639b79abac5e | |
parent | dfbaa1f0797cf602c8da17834ed8e7fe0764946c (diff) | |
download | chromium_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
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" /> |