Chromium Code Reviews| Index: chrome/browser/devtools/devtools_file_system_helper.cc |
| diff --git a/chrome/browser/devtools/devtools_file_system_helper.cc b/chrome/browser/devtools/devtools_file_system_helper.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..1d6214c27c0e3109fed0f2d684f820ca29bfcf5f |
| --- /dev/null |
| +++ b/chrome/browser/devtools/devtools_file_system_helper.cc |
| @@ -0,0 +1,273 @@ |
| +// Copyright (c) 2012 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. |
| + |
| +#include "chrome/browser/devtools/devtools_file_system_helper.h" |
| + |
| +#include <vector> |
| + |
| +#include "base/bind.h" |
| +#include "base/file_util.h" |
| +#include "base/utf_string_conversions.h" |
| +#include "chrome/browser/prefs/pref_service.h" |
| +#include "chrome/browser/prefs/scoped_user_pref_update.h" |
| +#include "chrome/browser/profiles/profile.h" |
| +#include "chrome/browser/ui/chrome_select_file_policy.h" |
| +#include "chrome/common/pref_names.h" |
| +#include "content/public/browser/browser_thread.h" |
| +#include "content/public/browser/child_process_security_policy.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 "grit/generated_resources.h" |
| +#include "ui/base/dialogs/select_file_dialog.h" |
| +#include "ui/base/l10n/l10n_util.h" |
| +#include "webkit/fileapi/isolated_context.h" |
| + |
| +using content::BrowserThread; |
| +using content::RenderViewHost; |
| +using content::WebContents; |
| + |
| +namespace { |
| + const char kSecurityFileName[] = ".allow-devtools-edit"; |
| +} |
| + |
| +class DevToolsFileSystemHelper::SelectFolderDialog |
|
pfeldman
2012/12/24 19:01:03
This class is almost exactly the same as the one i
|
| + : public ui::SelectFileDialog::Listener, |
| + public base::RefCounted<SelectFolderDialog> { |
| + public: |
| + explicit SelectFolderDialog(DevToolsFileSystemHelper* helper) |
| + : helper_(helper) { |
| + select_file_dialog_ = ui::SelectFileDialog::Create( |
| + this, new ChromeSelectFilePolicy(NULL)); |
| + } |
| + |
| + void ResetHelper() { |
| + helper_ = NULL; |
| + } |
| + |
| + void Show() { |
| + AddRef(); // Balanced in the three listener outcomes. |
| + select_file_dialog_->SelectFile(ui::SelectFileDialog::SELECT_FOLDER, |
| + string16(), |
| + FilePath(), |
| + NULL, |
| + 0, |
| + FILE_PATH_LITERAL(""), |
| + NULL, |
| + NULL); |
| + } |
| + |
| + // ui::SelectFileDialog::Listener implementation. |
| + virtual void FileSelected(const FilePath& path, |
| + int index, void* params) { |
| + if (helper_) |
| + helper_->FolderSelected(path); |
| + Release(); // Balanced in ::Show. |
| + } |
| + |
| + virtual void MultiFilesSelected( |
| + const std::vector<FilePath>& files, void* params) { |
| + Release(); // Balanced in ::Show. |
| + NOTREACHED() << "Should not be able to select multiple files"; |
| + } |
| + |
| + virtual void FileSelectionCanceled(void* params) { |
| + if (helper_) |
| + helper_->FolderSelectionCanceled(); |
| + Release(); // Balanced in ::Show. |
| + } |
| + |
| + private: |
| + friend class base::RefCounted<SelectFolderDialog>; |
| + virtual ~SelectFolderDialog() {} |
| + |
| + scoped_refptr<ui::SelectFileDialog> select_file_dialog_; |
| + DevToolsFileSystemHelper* helper_; |
| +}; |
| + |
| +DevToolsFileSystemHelper::FileSystem::FileSystem( |
| + const std::string& filesystem_id, |
| + const std::string& registered_name, |
| + const std::string& file_system_path) |
| + : filesystem_id(filesystem_id), |
| + registered_name(registered_name), |
| + file_system_path(file_system_path) { |
| +} |
| + |
| +DevToolsFileSystemHelper::DevToolsFileSystemHelper( |
| + WebContents* web_contents, |
| + Profile* profile, |
| + Delegate* delegate) |
| + : web_contents_(web_contents), |
| + profile_(profile), |
| + delegate_(delegate) { |
| +} |
| + |
| +DevToolsFileSystemHelper::~DevToolsFileSystemHelper() { |
| + if (select_folder_dialog_) |
| + select_folder_dialog_->ResetHelper(); |
| +} |
| + |
| +namespace { |
| + |
| +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)); |
| + 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; |
| +} |
| + |
| +bool CheckSecurityFileExistsInFolder(const FilePath& path) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| + FilePath security_file_path = path.Append( |
| + FILE_PATH_LITERAL(kSecurityFileName)); |
| + return file_util::PathExists(security_file_path); |
| +} |
| + |
| +} // namespace |
| + |
| +void DevToolsFileSystemHelper::SelectFolderAndGrantPermission() { |
| + if (select_folder_dialog_) |
| + select_folder_dialog_->ResetHelper(); |
| + select_folder_dialog_ = new SelectFolderDialog(this); |
| + select_folder_dialog_->Show(); |
| +} |
| + |
| +void DevToolsFileSystemHelper::FolderSelected(const FilePath& path) { |
| + BrowserThread::PostTask( |
| + BrowserThread::FILE, FROM_HERE, |
| + base::Bind(&DevToolsFileSystemHelper::CheckSelectedPath, this, path)); |
| +} |
| + |
| +void DevToolsFileSystemHelper::FolderSelectionCanceled() { |
| + delegate_->FileSystemFolderSelectionCanceled(); |
| +} |
| + |
| +void DevToolsFileSystemHelper::CheckSelectedPath(const FilePath& path) { |
| + if (!CheckSecurityFileExistsInFolder(path)) { |
| + BrowserThread::PostTask( |
| + BrowserThread::UI, FROM_HERE, |
| + base::Bind(&DevToolsFileSystemHelper::SelectedFileSystemForbidden, |
| + this)); |
| + return; |
| + } |
| + |
| + BrowserThread::PostTask( |
| + BrowserThread::UI, FROM_HERE, |
| + base::Bind(&DevToolsFileSystemHelper::SelectedFileSystemPermitted, |
| + this, |
| + path)); |
| +} |
| + |
| +void DevToolsFileSystemHelper::SelectedFileSystemPermitted( |
| + const FilePath& path) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| + 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::kDevToolsSavedFileSystemPathes); |
| + DictionaryValue* file_systems_pathes_value = update.Get(); |
| + file_systems_pathes_value->Set(file_system_path, Value::CreateNullValue()); |
| + |
| + FileSystem file_system(file_system_id, registered_name, file_system_path); |
| + delegate_->FileSystemFolderSelected(file_system); |
| +} |
| + |
| +void DevToolsFileSystemHelper::SelectedFileSystemForbidden() { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| + std::string error_string = l10n_util::GetStringFUTF8( |
| + IDS_DEV_TOOLS_FILE_SYSTEM_SECURITY_FILE_NOT_EXISTS_MESSAGE, |
| + UTF8ToUTF16(kSecurityFileName)); |
| + delegate_->FileSystemFolderSelectionError(error_string); |
| +} |
| + |
| +void DevToolsFileSystemHelper::RequestPermissions() { |
| + const DictionaryValue* file_systems_pathes_value = |
| + profile_->GetPrefs()->GetDictionary( |
| + prefs::kDevToolsSavedFileSystemPathes); |
| + std::vector<FilePath> saved_pathes; |
| + DictionaryValue::key_iterator it = file_systems_pathes_value->begin_keys(); |
| + for (; it != file_systems_pathes_value->end_keys(); ++it) { |
| + std::string file_system_path = *it; |
| + FilePath path = FilePath::FromUTF8Unsafe(file_system_path); |
| + saved_pathes.push_back(path); |
| + } |
| + |
| + BrowserThread::PostTask( |
| + BrowserThread::FILE, FROM_HERE, |
| + base::Bind(&DevToolsFileSystemHelper::CheckSavedPathes, |
| + this, |
| + saved_pathes)); |
| +} |
| + |
| +void DevToolsFileSystemHelper::CheckSavedPathes( |
| + const std::vector<FilePath>& file_pathes) { |
| + std::vector<FilePath> permitted_pathes; |
| + std::vector<FilePath>::const_iterator it; |
| + for (it = file_pathes.begin(); it != file_pathes.end(); ++it) { |
| + if (CheckSecurityFileExistsInFolder(*it)) |
| + permitted_pathes.push_back(*it); |
| + } |
| + |
| + BrowserThread::PostTask( |
| + BrowserThread::UI, FROM_HERE, |
| + base::Bind(&DevToolsFileSystemHelper::RegisterSavedFileSystems, |
| + this, |
| + permitted_pathes)); |
| +} |
| + |
| +void DevToolsFileSystemHelper::RegisterSavedFileSystems( |
| + const std::vector<FilePath>& file_pathes) { |
| + std::vector<FileSystem> file_systems; |
| + std::vector<FilePath>::const_iterator it; |
| + for (it = file_pathes.begin(); it != file_pathes.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 file_system(file_system_id, registered_name, file_system_path); |
| + file_systems.push_back(file_system); |
| + } |
| + delegate_->FileSystemPermissionsLoaded(file_systems); |
| +} |
| + |
| +void DevToolsFileSystemHelper::RevokePermission( |
| + 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::kDevToolsSavedFileSystemPathes); |
| + DictionaryValue* file_systems_pathes_value = update.Get(); |
| + file_systems_pathes_value->RemoveWithoutPathExpansion(file_system_path, NULL); |
| +} |