| Index: chrome/browser/devtools/devtools_file_helper.cc
|
| diff --git a/chrome/browser/devtools/devtools_file_helper.cc b/chrome/browser/devtools/devtools_file_helper.cc
|
| index 945de5f72935184ffbba30a2f2229a6a759b00f6..5605008364a509fa5fc0f396f2a1f7decab7761d 100644
|
| --- a/chrome/browser/devtools/devtools_file_helper.cc
|
| +++ b/chrome/browser/devtools/devtools_file_helper.cc
|
| @@ -11,6 +11,7 @@
|
| #include "base/file_util.h"
|
| #include "base/lazy_instance.h"
|
| #include "base/md5.h"
|
| +#include "base/utf_string_conversions.h"
|
| #include "base/value_conversions.h"
|
| #include "chrome/browser/browser_process.h"
|
| #include "chrome/browser/download/download_prefs.h"
|
| @@ -21,14 +22,25 @@
|
| #include "chrome/common/pref_names.h"
|
| #include "content/public/browser/browser_context.h"
|
| #include "content/public/browser/browser_thread.h"
|
| +#include "content/public/browser/child_process_security_policy.h"
|
| #include "content/public/browser/download_manager.h"
|
| +#include "content/public/browser/render_process_host.h"
|
| +#include "content/public/browser/render_view_host.h"
|
| +#include "content/public/browser/web_contents.h"
|
| +#include "content/public/common/content_client.h"
|
| +#include "grit/generated_resources.h"
|
| #include "ui/base/dialogs/select_file_dialog.h"
|
| +#include "ui/base/l10n/l10n_util.h"
|
| +#include "webkit/fileapi/file_system_util.h"
|
| +#include "webkit/fileapi/isolated_context.h"
|
|
|
| using base::Bind;
|
| using base::Callback;
|
| using content::BrowserContext;
|
| using content::BrowserThread;
|
| using content::DownloadManager;
|
| +using content::RenderViewHost;
|
| +using content::WebContents;
|
|
|
| namespace {
|
|
|
| @@ -42,6 +54,9 @@ namespace {
|
| typedef Callback<void(const FilePath&)> SelectedCallback;
|
| typedef Callback<void(void)> CanceledCallback;
|
|
|
| +const FilePath::CharType kMagicFileName[] =
|
| + FILE_PATH_LITERAL(".allow-devtools-edit");
|
| +
|
| class SelectFileDialog : public ui::SelectFileDialog::Listener,
|
| public base::RefCounted<SelectFileDialog> {
|
| public:
|
| @@ -106,10 +121,89 @@ void AppendToFile(const FilePath& path, const std::string& content) {
|
| file_util::AppendToFile(path, content.c_str(), content.length());
|
| }
|
|
|
| +fileapi::IsolatedContext* isolated_context() {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| + fileapi::IsolatedContext* isolated_context =
|
| + fileapi::IsolatedContext::GetInstance();
|
| + DCHECK(isolated_context);
|
| + return isolated_context;
|
| +}
|
| +
|
| +std::string RegisterFileSystem(WebContents* web_contents,
|
| + const FilePath& path,
|
| + std::string* registered_name) {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| + CHECK(content::GetContentClient()->HasWebUIScheme(web_contents->GetURL()));
|
| + std::string file_system_id = isolated_context()->RegisterFileSystemForPath(
|
| + fileapi::kFileSystemTypeNativeLocal, path, registered_name);
|
| +
|
| + content::ChildProcessSecurityPolicy* policy =
|
| + content::ChildProcessSecurityPolicy::GetInstance();
|
| + RenderViewHost* render_view_host = web_contents->GetRenderViewHost();
|
| + int renderer_id = render_view_host->GetProcess()->GetID();
|
| + policy->GrantReadWriteFileSystem(renderer_id, file_system_id);
|
| +
|
| + // We only need file level access for reading FileEntries. Saving FileEntries
|
| + // just needs the file system to have read/write access, which is granted
|
| + // above if required.
|
| + if (!policy->CanReadFile(renderer_id, path))
|
| + policy->GrantReadFile(renderer_id, path);
|
| +
|
| + return file_system_id;
|
| +}
|
| +
|
| +typedef Callback<void(const std::vector<FilePath>&)> ValidateFoldersCallback;
|
| +
|
| +void ValidateFoldersOnFileThread(const std::vector<FilePath>& file_paths,
|
| + const ValidateFoldersCallback& callback) {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
|
| + std::vector<FilePath> permitted_paths;
|
| + std::vector<FilePath>::const_iterator it;
|
| + for (it = file_paths.begin(); it != file_paths.end(); ++it) {
|
| + FilePath security_file_path = it->Append(kMagicFileName);
|
| + if (file_util::PathExists(security_file_path))
|
| + permitted_paths.push_back(*it);
|
| + }
|
| + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
|
| + Bind(callback, permitted_paths));
|
| +}
|
| +
|
| +DevToolsFileHelper::FileSystem CreateFileSystemStruct(
|
| + WebContents* web_contents,
|
| + const std::string& file_system_id,
|
| + const std::string& registered_name,
|
| + const std::string& file_system_path) {
|
| + const GURL origin = web_contents->GetURL().GetOrigin();
|
| + std::string file_system_name = fileapi::GetIsolatedFileSystemName(
|
| + origin,
|
| + file_system_id);
|
| + std::string root_url = fileapi::GetIsolatedFileSystemRootURIString(
|
| + origin,
|
| + file_system_id,
|
| + registered_name);
|
| + return DevToolsFileHelper::FileSystem(file_system_name,
|
| + root_url,
|
| + file_system_path);
|
| +}
|
| +
|
| } // namespace
|
|
|
| -DevToolsFileHelper::DevToolsFileHelper(Profile* profile) : profile_(profile),
|
| - weak_factory_(this) {
|
| +DevToolsFileHelper::FileSystem::FileSystem() {
|
| +}
|
| +
|
| +DevToolsFileHelper::FileSystem::FileSystem(const std::string& file_system_name,
|
| + const std::string& root_url,
|
| + const std::string& file_system_path)
|
| + : file_system_name(file_system_name),
|
| + root_url(root_url),
|
| + file_system_path(file_system_path) {
|
| +}
|
| +
|
| +DevToolsFileHelper::DevToolsFileHelper(WebContents* web_contents,
|
| + Profile* profile)
|
| + : web_contents_(web_contents),
|
| + profile_(profile),
|
| + ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) {
|
| }
|
|
|
| DevToolsFileHelper::~DevToolsFileHelper() {
|
| @@ -171,7 +265,7 @@ void DevToolsFileHelper::Append(const std::string& url,
|
| return;
|
| callback.Run();
|
| BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
|
| - base::Bind(&AppendToFile, it->second, content));
|
| + Bind(&AppendToFile, it->second, content));
|
| }
|
|
|
| void DevToolsFileHelper::SaveAsFileSelected(const std::string& url,
|
| @@ -188,8 +282,116 @@ void DevToolsFileHelper::SaveAsFileSelected(const std::string& url,
|
| base::CreateFilePathValue(path));
|
| callback.Run();
|
| BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
|
| - base::Bind(&WriteToFile, path, content));
|
| + Bind(&WriteToFile, path, content));
|
| }
|
|
|
| void DevToolsFileHelper::SaveAsFileSelectionCanceled() {
|
| }
|
| +
|
| +void DevToolsFileHelper::AddFileSystem(const AddFileSystemCallback& callback) {
|
| + scoped_refptr<SelectFileDialog> select_file_dialog = new SelectFileDialog(
|
| + Bind(&DevToolsFileHelper::InnerAddFileSystem,
|
| + weak_factory_.GetWeakPtr(),
|
| + callback),
|
| + Bind(callback, "", FileSystem()));
|
| + select_file_dialog->Show(ui::SelectFileDialog::SELECT_FOLDER, FilePath());
|
| +}
|
| +
|
| +void DevToolsFileHelper::InnerAddFileSystem(
|
| + const AddFileSystemCallback& callback,
|
| + const FilePath& path) {
|
| + std::vector<FilePath> file_paths(1, path);
|
| + ValidateFoldersCallback validate_folders_callback = Bind(
|
| + &DevToolsFileHelper::AddValidatedFileSystem,
|
| + weak_factory_.GetWeakPtr(),
|
| + callback);
|
| + BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
|
| + Bind(&ValidateFoldersOnFileThread,
|
| + file_paths,
|
| + validate_folders_callback));
|
| +}
|
| +
|
| +void DevToolsFileHelper::AddValidatedFileSystem(
|
| + const AddFileSystemCallback& callback,
|
| + const std::vector<FilePath>& permitted_paths) {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| + if (permitted_paths.empty()) {
|
| + std::string magic_file_name = FilePath(kMagicFileName).AsUTF8Unsafe();
|
| + std::string error_string = l10n_util::GetStringFUTF8(
|
| + IDS_DEV_TOOLS_MAGIC_FILE_NOT_EXISTS_MESSAGE,
|
| + UTF8ToUTF16(magic_file_name));
|
| + callback.Run(error_string, FileSystem());
|
| + return;
|
| + }
|
| + FilePath path = permitted_paths.at(0);
|
| + std::string registered_name;
|
| + std::string file_system_id = RegisterFileSystem(web_contents_,
|
| + path,
|
| + ®istered_name);
|
| + std::string file_system_path = path.AsUTF8Unsafe();
|
| +
|
| + DictionaryPrefUpdate update(profile_->GetPrefs(),
|
| + prefs::kDevToolsFileSystemPaths);
|
| + DictionaryValue* file_systems_paths_value = update.Get();
|
| + file_systems_paths_value->Set(file_system_path, Value::CreateNullValue());
|
| +
|
| + FileSystem filesystem = CreateFileSystemStruct(web_contents_,
|
| + file_system_id,
|
| + registered_name,
|
| + file_system_path);
|
| + callback.Run("", filesystem);
|
| +}
|
| +
|
| +void DevToolsFileHelper::RequestFileSystems(
|
| + const RequestFileSystemsCallback& callback) {
|
| + const DictionaryValue* file_systems_paths_value =
|
| + profile_->GetPrefs()->GetDictionary(prefs::kDevToolsFileSystemPaths);
|
| + std::vector<FilePath> saved_paths;
|
| + DictionaryValue::key_iterator it = file_systems_paths_value->begin_keys();
|
| + for (; it != file_systems_paths_value->end_keys(); ++it) {
|
| + std::string file_system_path = *it;
|
| + FilePath path = FilePath::FromUTF8Unsafe(file_system_path);
|
| + saved_paths.push_back(path);
|
| + }
|
| +
|
| + ValidateFoldersCallback validate_folders_callback = Bind(
|
| + &DevToolsFileHelper::RestoreValidatedFileSystems,
|
| + weak_factory_.GetWeakPtr(),
|
| + callback);
|
| + BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
|
| + Bind(&ValidateFoldersOnFileThread,
|
| + saved_paths,
|
| + validate_folders_callback));
|
| +}
|
| +
|
| +void DevToolsFileHelper::RestoreValidatedFileSystems(
|
| + const RequestFileSystemsCallback& callback,
|
| + const std::vector<FilePath>& permitted_paths) {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| + std::vector<FileSystem> file_systems;
|
| + std::vector<FilePath>::const_iterator it;
|
| + for (it = permitted_paths.begin(); it != permitted_paths.end(); ++it) {
|
| + std::string registered_name;
|
| + std::string file_system_id = RegisterFileSystem(web_contents_,
|
| + *it,
|
| + ®istered_name);
|
| + std::string file_system_path = it->AsUTF8Unsafe();
|
| + FileSystem filesystem = CreateFileSystemStruct(web_contents_,
|
| + file_system_id,
|
| + registered_name,
|
| + file_system_path);
|
| + file_systems.push_back(filesystem);
|
| + }
|
| + callback.Run(file_systems);
|
| +}
|
| +
|
| +void DevToolsFileHelper::RemoveFileSystem(const std::string& file_system_path) {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| + FilePath path = FilePath::FromUTF8Unsafe(file_system_path);
|
| + isolated_context()->RevokeFileSystemByPath(path);
|
| +
|
| + DictionaryPrefUpdate update(profile_->GetPrefs(),
|
| + prefs::kDevToolsFileSystemPaths);
|
| + DictionaryValue* file_systems_paths_value = update.Get();
|
| + file_systems_paths_value->RemoveWithoutPathExpansion(file_system_path, NULL);
|
| +}
|
|
|