Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1658)

Unified Diff: chrome/browser/devtools/devtools_file_helper.cc

Issue 11570081: Support file system access in DevTools with isolated file system. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Renamed methods and added CHECK() Created 8 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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 e7657a52a8643310b9d6549d96de411b92a3b6fd..5145dc18ef2a589aa701f71c004bf7ac36e949bd 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"
@@ -20,14 +21,25 @@
#include "chrome/browser/ui/chrome_select_file_policy.h"
#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/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 {
@@ -41,6 +53,8 @@ namespace {
typedef Callback<void(const FilePath&)> SelectedCallback;
typedef Callback<void(void)> CanceledCallback;
+const char kMagicFileName[] = ".allow-devtools-edit";
kinuko 2013/01/04 14:20:55 const FilePath::CharType kMagicFileName[]
vsevik 2013/01/09 11:54:40 Done.
+
class SelectFileDialog : public ui::SelectFileDialog::Listener,
public base::RefCounted<SelectFileDialog> {
public:
@@ -105,10 +119,79 @@ 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 filesystem_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, filesystem_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 filesystem_id;
+}
+
+typedef Callback<void(const std::vector<FilePath>&)> ValidateFoldersCallback;
+
+void RunFoldersValidationCallback(
+ const ValidateFoldersCallback& callback,
+ const std::vector<FilePath>& permitted_paths) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ callback.Run(permitted_paths);
+}
+
+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(FILE_PATH_LITERAL(kMagicFileName));
kinuko 2013/01/04 14:20:55 This wouldn't work on windows (the macro works onl
vsevik 2013/01/09 11:54:40 Done, moved FILE_PATH_LITERAL to line 56.
+ if (file_util::PathExists(security_file_path))
+ permitted_paths.push_back(*it);
+ }
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ Bind(&RunFoldersValidationCallback, callback, permitted_paths));
kinuko 2013/01/04 14:20:55 Unless you really want to check the callback runs
vsevik 2013/01/09 11:54:40 Done.
+}
+
} // namespace
-DevToolsFileHelper::DevToolsFileHelper(Profile* profile) : profile_(profile),
- weak_factory_(this) {
+DevToolsFileHelper::Filesystem::Filesystem() {
+}
+
+DevToolsFileHelper::Filesystem::Filesystem(const std::string& filesystem_id,
+ const std::string& registered_name,
+ const std::string& filesystem_path)
+ : filesystem_id(filesystem_id),
+ registered_name(registered_name),
+ filesystem_path(filesystem_path) {
+}
+
+DevToolsFileHelper::DevToolsFileHelper(WebContents* web_contents,
+ Profile* profile)
+ : web_contents_(web_contents),
+ profile_(profile),
+ weak_factory_(this) {
}
DevToolsFileHelper::~DevToolsFileHelper() {
@@ -170,7 +253,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,
@@ -187,8 +270,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) {
kinuko 2013/01/04 14:20:55 nit: In most other places we use 'FileSystem' (cap
vsevik 2013/01/09 11:54:40 Done.
+ scoped_refptr<SelectFileDialog> select_file_dialog = new SelectFileDialog(
+ Bind(&DevToolsFileHelper::InnerAddFilesystem,
+ weak_factory_.GetWeakPtr(),
+ callback),
+ Bind(&DevToolsFileHelper::CancelFilesystemAdding,
+ weak_factory_.GetWeakPtr(),
+ callback));
kinuko 2013/01/04 14:20:55 Bind(callback, "", Filesystem()) might be simpler?
vsevik 2013/01/09 11:54:40 Done.
+ 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 error_string = l10n_util::GetStringFUTF8(
+ IDS_DEV_TOOLS_MAGIC_FILE_NOT_EXISTS_MESSAGE,
+ UTF8ToUTF16(kMagicFileName));
kinuko 2013/01/04 14:20:55 FilePathStringToWebString(kMagicFileName)
vsevik 2013/01/09 11:54:40 I don't need WebString at this point as GetStringF
+ callback.Run(error_string, Filesystem());
+ return;
+ }
+ FilePath path = permitted_paths.at(0);
+ std::string registered_name;
+ std::string filesystem_id = RegisterFilesystem(web_contents_,
+ path,
+ &registered_name);
+ std::string filesystem_path = path.AsUTF8Unsafe();
+
+ DictionaryPrefUpdate update(profile_->GetPrefs(),
+ prefs::kDevToolsFilesystemPaths);
+ DictionaryValue* filesystems_paths_value = update.Get();
+ filesystems_paths_value->Set(filesystem_path, Value::CreateNullValue());
+
+ Filesystem filesystem(filesystem_id, registered_name, filesystem_path);
+ callback.Run("", filesystem);
+}
+
+void DevToolsFileHelper::CancelFilesystemAdding(
+ const AddFilesystemCallback& callback) {
+ callback.Run("", Filesystem());
+}
+
+void DevToolsFileHelper::RequestFilesystems(
+ const RequestFilesystemsCallback& callback) {
+ const DictionaryValue* filesystems_paths_value =
+ profile_->GetPrefs()->GetDictionary(prefs::kDevToolsFilesystemPaths);
+ std::vector<FilePath> saved_paths;
+ DictionaryValue::key_iterator it = filesystems_paths_value->begin_keys();
+ for (; it != filesystems_paths_value->end_keys(); ++it) {
+ std::string filesystem_path = *it;
+ FilePath path = FilePath::FromUTF8Unsafe(filesystem_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> filesystems;
+ std::vector<FilePath>::const_iterator it;
+ for (it = permitted_paths.begin(); it != permitted_paths.end(); ++it) {
+ std::string registered_name;
+ std::string filesystem_id = RegisterFilesystem(web_contents_,
+ *it,
+ &registered_name);
kinuko 2013/01/04 14:20:55 nit: indent
vsevik 2013/01/09 11:54:40 Done.
vsevik 2013/01/09 11:54:40 Done.
+ std::string filesystem_path = it->AsUTF8Unsafe();
+ Filesystem filesystem(filesystem_id, registered_name, filesystem_path);
+ filesystems.push_back(filesystem);
+ }
+ callback.Run(filesystems);
+}
+
+void DevToolsFileHelper::RemoveFilesystem(const std::string& filesystem_path) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ FilePath path = FilePath::FromUTF8Unsafe(filesystem_path);
+ isolated_context()->RevokeFileSystemByPath(path);
+
+ DictionaryPrefUpdate update(profile_->GetPrefs(),
+ prefs::kDevToolsFilesystemPaths);
+ DictionaryValue* filesystems_paths_value = update.Get();
+ filesystems_paths_value->RemoveWithoutPathExpansion(filesystem_path, NULL);
kinuko 2013/01/04 14:20:55 These file paths look to be saved/removed per prof
vsevik 2013/01/09 11:54:40 This is correct and intended behavior.
+}

Powered by Google App Engine
This is Rietveld 408576698