blob: 5c062c3b8a3f98148f5cdd7f39655cd35a298656 [file] [log] [blame]
[email protected]29975022012-04-04 15:23:501// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]70019152012-12-19 11:44:195#include "chrome/browser/devtools/devtools_file_helper.h"
[email protected]29975022012-04-04 15:23:506
[email protected]200bd332013-08-05 16:19:117#include <set>
[email protected]d5b21972012-07-20 02:06:018#include <vector>
9
[email protected]29975022012-04-04 15:23:5010#include "base/bind.h"
[email protected]6e1fcd12012-07-02 17:14:2011#include "base/callback.h"
thestig18dfb7a52014-08-26 10:44:0412#include "base/files/file_util.h"
Daniel Chengd07ef712019-03-28 23:13:4113#include "base/hash/md5.h"
[email protected]29975022012-04-04 15:23:5014#include "base/lazy_instance.h"
avie4d7b6f2015-12-26 00:59:1815#include "base/macros.h"
[email protected]135cb802013-06-09 16:44:2016#include "base/strings/utf_string_conversions.h"
Gabriel Charette44db1422018-08-06 11:19:3317#include "base/task/post_task.h"
Andrey Kosyakov7dabf712017-06-20 23:50:3018#include "base/threading/sequenced_task_runner_handle.h"
[email protected]29975022012-04-04 15:23:5019#include "base/value_conversions.h"
20#include "chrome/browser/browser_process.h"
pfeldman7d01b872015-11-05 08:24:3521#include "chrome/browser/devtools/devtools_file_watcher.h"
[email protected]29975022012-04-04 15:23:5022#include "chrome/browser/download/download_prefs.h"
[email protected]29975022012-04-04 15:23:5023#include "chrome/browser/profiles/profile.h"
[email protected]6e1fcd12012-07-02 17:14:2024#include "chrome/browser/ui/chrome_select_file_policy.h"
[email protected]29975022012-04-04 15:23:5025#include "chrome/common/pref_names.h"
[email protected]af39f002014-08-22 10:18:1826#include "chrome/grit/generated_resources.h"
brettwb1fc1b82016-02-02 00:19:0827#include "components/prefs/pref_service.h"
28#include "components/prefs/scoped_user_pref_update.h"
[email protected]d5b21972012-07-20 02:06:0129#include "content/public/browser/browser_context.h"
[email protected]b7b63872013-01-03 02:41:1930#include "content/public/browser/browser_thread.h"
[email protected]e492a802013-01-16 11:12:1131#include "content/public/browser/child_process_security_policy.h"
[email protected]d5b21972012-07-20 02:06:0132#include "content/public/browser/download_manager.h"
[email protected]e492a802013-01-16 11:12:1133#include "content/public/browser/render_process_host.h"
34#include "content/public/browser/render_view_host.h"
35#include "content/public/browser/web_contents.h"
36#include "content/public/common/content_client.h"
[email protected]86a0a6e2013-01-28 06:33:0337#include "content/public/common/url_constants.h"
pilgrime92c5fcd2014-09-10 23:31:2338#include "storage/browser/fileapi/file_system_url.h"
39#include "storage/browser/fileapi/isolated_context.h"
pilgrim16330552014-09-10 01:32:2240#include "storage/common/fileapi/file_system_util.h"
[email protected]e492a802013-01-16 11:12:1141#include "ui/base/l10n/l10n_util.h"
[email protected]4344a3c2013-01-17 23:49:2042#include "ui/shell_dialogs/select_file_dialog.h"
[email protected]29975022012-04-04 15:23:5043
[email protected]d879ed32012-12-27 15:35:3644using base::Bind;
45using base::Callback;
[email protected]d5b21972012-07-20 02:06:0146using content::BrowserContext;
[email protected]29975022012-04-04 15:23:5047using content::BrowserThread;
[email protected]d5b21972012-07-20 02:06:0148using content::DownloadManager;
[email protected]e492a802013-01-16 11:12:1149using content::RenderViewHost;
50using content::WebContents;
[email protected]200bd332013-08-05 16:19:1151using std::set;
[email protected]29975022012-04-04 15:23:5052
53namespace {
54
pfeldman31834e22015-10-10 00:47:0555static const char kRootName[] = "<root>";
Pavel Feldman44bd99172017-10-20 16:37:1956static const char kPermissionDenied[] = "<permission denied>";
pfeldman31834e22015-10-10 00:47:0557
[email protected]650b2d52013-02-10 03:41:4558base::LazyInstance<base::FilePath>::Leaky
[email protected]29975022012-04-04 15:23:5059 g_last_save_path = LAZY_INSTANCE_INITIALIZER;
60
[email protected]650b2d52013-02-10 03:41:4561typedef Callback<void(const base::FilePath&)> SelectedCallback;
[email protected]d879ed32012-12-27 15:35:3662typedef Callback<void(void)> CanceledCallback;
63
64class SelectFileDialog : public ui::SelectFileDialog::Listener,
65 public base::RefCounted<SelectFileDialog> {
[email protected]29975022012-04-04 15:23:5066 public:
[email protected]d879ed32012-12-27 15:35:3667 SelectFileDialog(const SelectedCallback& selected_callback,
[email protected]7ad5be62013-07-11 00:02:5968 const CanceledCallback& canceled_callback,
69 WebContents* web_contents)
[email protected]d879ed32012-12-27 15:35:3670 : selected_callback_(selected_callback),
[email protected]7ad5be62013-07-11 00:02:5971 canceled_callback_(canceled_callback),
72 web_contents_(web_contents) {
[email protected]92f54082012-07-31 01:43:1473 select_file_dialog_ = ui::SelectFileDialog::Create(
Brett Wilson804e83c2017-08-18 22:57:3374 this, std::make_unique<ChromeSelectFilePolicy>(web_contents));
[email protected]29975022012-04-04 15:23:5075 }
76
[email protected]d879ed32012-12-27 15:35:3677 void Show(ui::SelectFileDialog::Type type,
[email protected]650b2d52013-02-10 03:41:4578 const base::FilePath& default_path) {
[email protected]29975022012-04-04 15:23:5079 AddRef(); // Balanced in the three listener outcomes.
[email protected]7ad5be62013-07-11 00:02:5980 select_file_dialog_->SelectFile(
81 type,
[email protected]4317aee2013-11-28 07:20:1182 base::string16(),
[email protected]7ad5be62013-07-11 00:02:5983 default_path,
84 NULL,
85 0,
86 base::FilePath::StringType(),
[email protected]fc2b46b2014-05-03 16:33:4587 platform_util::GetTopLevel(web_contents_->GetNativeView()),
[email protected]7ad5be62013-07-11 00:02:5988 NULL);
[email protected]29975022012-04-04 15:23:5089 }
90
[email protected]92f54082012-07-31 01:43:1491 // ui::SelectFileDialog::Listener implementation.
dcheng03748a42014-10-21 10:19:1392 void FileSelected(const base::FilePath& path,
93 int index,
94 void* params) override {
[email protected]d879ed32012-12-27 15:35:3695 selected_callback_.Run(path);
[email protected]29975022012-04-04 15:23:5096 Release(); // Balanced in ::Show.
97 }
98
dcheng03748a42014-10-21 10:19:1399 void MultiFilesSelected(const std::vector<base::FilePath>& files,
100 void* params) override {
[email protected]29975022012-04-04 15:23:50101 Release(); // Balanced in ::Show.
102 NOTREACHED() << "Should not be able to select multiple files";
103 }
104
dcheng03748a42014-10-21 10:19:13105 void FileSelectionCanceled(void* params) override {
pfeldman7b96f89c2015-10-13 00:49:47106 if (!canceled_callback_.is_null())
107 canceled_callback_.Run();
[email protected]29975022012-04-04 15:23:50108 Release(); // Balanced in ::Show.
109 }
110
111 private:
[email protected]d879ed32012-12-27 15:35:36112 friend class base::RefCounted<SelectFileDialog>;
dcheng03748a42014-10-21 10:19:13113 ~SelectFileDialog() override {}
[email protected]29975022012-04-04 15:23:50114
[email protected]92f54082012-07-31 01:43:14115 scoped_refptr<ui::SelectFileDialog> select_file_dialog_;
[email protected]d879ed32012-12-27 15:35:36116 SelectedCallback selected_callback_;
117 CanceledCallback canceled_callback_;
[email protected]7ad5be62013-07-11 00:02:59118 WebContents* web_contents_;
[email protected]4317aee2013-11-28 07:20:11119
120 DISALLOW_COPY_AND_ASSIGN(SelectFileDialog);
[email protected]29975022012-04-04 15:23:50121};
122
[email protected]650b2d52013-02-10 03:41:45123void WriteToFile(const base::FilePath& path, const std::string& content) {
[email protected]29975022012-04-04 15:23:50124 DCHECK(!path.empty());
125
[email protected]e5c2a22e2014-03-06 20:42:30126 base::WriteFile(path, content.c_str(), content.length());
[email protected]29975022012-04-04 15:23:50127}
128
[email protected]650b2d52013-02-10 03:41:45129void AppendToFile(const base::FilePath& path, const std::string& content) {
[email protected]e2641d82012-05-02 07:48:42130 DCHECK(!path.empty());
131
chirantan75ea2fd2014-10-07 23:15:30132 base::AppendToFile(path, content.c_str(), content.size());
[email protected]e2641d82012-05-02 07:48:42133}
134
[email protected]cd501a72014-08-22 19:58:31135storage::IsolatedContext* isolated_context() {
mostynb13260d52015-03-26 09:12:09136 DCHECK_CURRENTLY_ON(BrowserThread::UI);
[email protected]cd501a72014-08-22 19:58:31137 storage::IsolatedContext* isolated_context =
138 storage::IsolatedContext::GetInstance();
[email protected]e492a802013-01-16 11:12:11139 DCHECK(isolated_context);
140 return isolated_context;
141}
142
143std::string RegisterFileSystem(WebContents* web_contents,
pfeldman31834e22015-10-10 00:47:05144 const base::FilePath& path) {
mostynb13260d52015-03-26 09:12:09145 DCHECK_CURRENTLY_ON(BrowserThread::UI);
[email protected]b3690f72014-02-17 00:32:48146 CHECK(web_contents->GetURL().SchemeIs(content::kChromeDevToolsScheme));
pfeldman31834e22015-10-10 00:47:05147 std::string root_name(kRootName);
Marijn Kruisselbrinkd0134ef2019-05-21 01:24:52148 storage::IsolatedContext::ScopedFSHandle file_system =
149 isolated_context()->RegisterFileSystemForPath(
150 storage::kFileSystemTypeNativeLocal, std::string(), path, &root_name);
[email protected]e492a802013-01-16 11:12:11151
152 content::ChildProcessSecurityPolicy* policy =
153 content::ChildProcessSecurityPolicy::GetInstance();
154 RenderViewHost* render_view_host = web_contents->GetRenderViewHost();
155 int renderer_id = render_view_host->GetProcess()->GetID();
Marijn Kruisselbrinkd0134ef2019-05-21 01:24:52156 policy->GrantReadFileSystem(renderer_id, file_system.id());
157 policy->GrantWriteFileSystem(renderer_id, file_system.id());
158 policy->GrantCreateFileForFileSystem(renderer_id, file_system.id());
159 policy->GrantDeleteFromFileSystem(renderer_id, file_system.id());
[email protected]e492a802013-01-16 11:12:11160
161 // We only need file level access for reading FileEntries. Saving FileEntries
162 // just needs the file system to have read/write access, which is granted
163 // above if required.
164 if (!policy->CanReadFile(renderer_id, path))
165 policy->GrantReadFile(renderer_id, path);
Marijn Kruisselbrinkd0134ef2019-05-21 01:24:52166 return file_system.id();
[email protected]e492a802013-01-16 11:12:11167}
168
[email protected]e492a802013-01-16 11:12:11169DevToolsFileHelper::FileSystem CreateFileSystemStruct(
170 WebContents* web_contents,
Pavel Feldman44bd99172017-10-20 16:37:19171 const std::string& type,
[email protected]e492a802013-01-16 11:12:11172 const std::string& file_system_id,
[email protected]e492a802013-01-16 11:12:11173 const std::string& file_system_path) {
174 const GURL origin = web_contents->GetURL().GetOrigin();
[email protected]cd501a72014-08-22 19:58:31175 std::string file_system_name =
176 storage::GetIsolatedFileSystemName(origin, file_system_id);
177 std::string root_url = storage::GetIsolatedFileSystemRootURIString(
pfeldman31834e22015-10-10 00:47:05178 origin, file_system_id, kRootName);
Pavel Feldman44bd99172017-10-20 16:37:19179 return DevToolsFileHelper::FileSystem(type, file_system_name, root_url,
[email protected]e492a802013-01-16 11:12:11180 file_system_path);
181}
182
Pavel Feldman44bd99172017-10-20 16:37:19183using PathToType = std::map<std::string, std::string>;
184PathToType GetAddedFileSystemPaths(Profile* profile) {
[email protected]5bcdd99d2013-12-23 18:28:30185 const base::DictionaryValue* file_systems_paths_value =
[email protected]200bd332013-08-05 16:19:11186 profile->GetPrefs()->GetDictionary(prefs::kDevToolsFileSystemPaths);
Pavel Feldman44bd99172017-10-20 16:37:19187 PathToType result;
[email protected]5bcdd99d2013-12-23 18:28:30188 for (base::DictionaryValue::Iterator it(*file_systems_paths_value);
189 !it.IsAtEnd(); it.Advance()) {
Pavel Feldman44bd99172017-10-20 16:37:19190 std::string type =
191 it.value().is_string() ? it.value().GetString() : std::string();
192 result[it.key()] = type;
[email protected]200bd332013-08-05 16:19:11193 }
194 return result;
195}
196
[email protected]d879ed32012-12-27 15:35:36197} // namespace
198
Pavel Feldman44bd99172017-10-20 16:37:19199DevToolsFileHelper::FileSystem::FileSystem() = default;
[email protected]e492a802013-01-16 11:12:11200
Pavel Feldman44bd99172017-10-20 16:37:19201DevToolsFileHelper::FileSystem::~FileSystem() = default;
202
203DevToolsFileHelper::FileSystem::FileSystem(const FileSystem& other) = default;
204
205DevToolsFileHelper::FileSystem::FileSystem(const std::string& type,
206 const std::string& file_system_name,
[email protected]e492a802013-01-16 11:12:11207 const std::string& root_url,
208 const std::string& file_system_path)
Pavel Feldman44bd99172017-10-20 16:37:19209 : type(type),
210 file_system_name(file_system_name),
[email protected]e492a802013-01-16 11:12:11211 root_url(root_url),
Pavel Feldman44bd99172017-10-20 16:37:19212 file_system_path(file_system_path) {}
[email protected]e492a802013-01-16 11:12:11213
214DevToolsFileHelper::DevToolsFileHelper(WebContents* web_contents,
pfeldman31834e22015-10-10 00:47:05215 Profile* profile,
216 Delegate* delegate)
[email protected]e492a802013-01-16 11:12:11217 : web_contents_(web_contents),
218 profile_(profile),
pfeldman31834e22015-10-10 00:47:05219 delegate_(delegate),
Sami Kyostila4ba007d2019-08-14 12:03:14220 file_task_runner_(base::CreateSequencedTaskRunner(
221 {base::ThreadPool(), base::MayBlock()})) {
Sam McNally71714a7ab2017-06-09 02:44:23222 pref_change_registrar_.Init(profile_->GetPrefs());
[email protected]29975022012-04-04 15:23:50223}
224
Andrey Kosyakov7dabf712017-06-20 23:50:30225DevToolsFileHelper::~DevToolsFileHelper() = default;
[email protected]29975022012-04-04 15:23:50226
227void DevToolsFileHelper::Save(const std::string& url,
228 const std::string& content,
[email protected]d879ed32012-12-27 15:35:36229 bool save_as,
[email protected]9a3b90ad2013-11-28 12:59:49230 const SaveCallback& saveCallback,
Nathan Bruer4dfb9b152017-10-02 22:42:41231 const CancelCallback& cancelCallback) {
jdoerriec6fe63e2018-10-03 20:53:40232 auto it = saved_files_.find(url);
[email protected]29975022012-04-04 15:23:50233 if (it != saved_files_.end() && !save_as) {
[email protected]9a3b90ad2013-11-28 12:59:49234 SaveAsFileSelected(url, content, saveCallback, it->second);
[email protected]29975022012-04-04 15:23:50235 return;
236 }
237
[email protected]5bcdd99d2013-12-23 18:28:30238 const base::DictionaryValue* file_map =
[email protected]29975022012-04-04 15:23:50239 profile_->GetPrefs()->GetDictionary(prefs::kDevToolsEditedFiles);
[email protected]650b2d52013-02-10 03:41:45240 base::FilePath initial_path;
[email protected]29975022012-04-04 15:23:50241
[email protected]5bcdd99d2013-12-23 18:28:30242 const base::Value* path_value;
Xiaohan Wangec1c552a2019-02-07 18:29:08243 if (file_map->Get(base::MD5String(url), &path_value)) {
244 // Ignore base::GetValueAsFilePath() failure since we handle empty
245 // |initial_path| below.
246 ignore_result(base::GetValueAsFilePath(*path_value, &initial_path));
247 }
[email protected]29975022012-04-04 15:23:50248
249 if (initial_path.empty()) {
250 GURL gurl(url);
251 std::string suggested_file_name = gurl.is_valid() ?
252 gurl.ExtractFileName() : url;
253
[email protected]0cfb4302012-12-12 13:45:06254 if (suggested_file_name.length() > 64)
255 suggested_file_name = suggested_file_name.substr(0, 64);
[email protected]29975022012-04-04 15:23:50256
257 if (!g_last_save_path.Pointer()->empty()) {
258 initial_path = g_last_save_path.Pointer()->DirName().AppendASCII(
259 suggested_file_name);
260 } else {
[email protected]650b2d52013-02-10 03:41:45261 base::FilePath download_path = DownloadPrefs::FromDownloadManager(
[email protected]d5b21972012-07-20 02:06:01262 BrowserContext::GetDownloadManager(profile_))->DownloadPath();
263 initial_path = download_path.AppendASCII(suggested_file_name);
[email protected]29975022012-04-04 15:23:50264 }
265 }
266
[email protected]d879ed32012-12-27 15:35:36267 scoped_refptr<SelectFileDialog> select_file_dialog = new SelectFileDialog(
268 Bind(&DevToolsFileHelper::SaveAsFileSelected,
269 weak_factory_.GetWeakPtr(),
270 url,
271 content,
[email protected]9a3b90ad2013-11-28 12:59:49272 saveCallback),
pfeldman86b26df2015-10-05 20:12:23273 cancelCallback,
[email protected]7ad5be62013-07-11 00:02:59274 web_contents_);
[email protected]d879ed32012-12-27 15:35:36275 select_file_dialog->Show(ui::SelectFileDialog::SELECT_SAVEAS_FILE,
276 initial_path);
[email protected]29975022012-04-04 15:23:50277}
278
[email protected]e2641d82012-05-02 07:48:42279void DevToolsFileHelper::Append(const std::string& url,
[email protected]d879ed32012-12-27 15:35:36280 const std::string& content,
281 const AppendCallback& callback) {
jdoerriec6fe63e2018-10-03 20:53:40282 auto it = saved_files_.find(url);
[email protected]e2641d82012-05-02 07:48:42283 if (it == saved_files_.end())
284 return;
[email protected]d879ed32012-12-27 15:35:36285 callback.Run();
Andrey Kosyakov7dabf712017-06-20 23:50:30286 file_task_runner_->PostTask(FROM_HERE,
287 BindOnce(&AppendToFile, it->second, content));
[email protected]e2641d82012-05-02 07:48:42288}
289
[email protected]d879ed32012-12-27 15:35:36290void DevToolsFileHelper::SaveAsFileSelected(const std::string& url,
291 const std::string& content,
292 const SaveCallback& callback,
[email protected]650b2d52013-02-10 03:41:45293 const base::FilePath& path) {
[email protected]29975022012-04-04 15:23:50294 *g_last_save_path.Pointer() = path;
295 saved_files_[url] = path;
296
297 DictionaryPrefUpdate update(profile_->GetPrefs(),
298 prefs::kDevToolsEditedFiles);
[email protected]5bcdd99d2013-12-23 18:28:30299 base::DictionaryValue* files_map = update.Get();
Christian Dullweber13740082018-07-26 13:09:09300 files_map->SetKey(base::MD5String(url), base::CreateFilePathValue(path));
Nathan Bruer4dfb9b152017-10-02 22:42:41301 std::string file_system_path = path.AsUTF8Unsafe();
302 callback.Run(file_system_path);
Andrey Kosyakov7dabf712017-06-20 23:50:30303 file_task_runner_->PostTask(FROM_HERE, BindOnce(&WriteToFile, path, content));
[email protected]d879ed32012-12-27 15:35:36304}
[email protected]29975022012-04-04 15:23:50305
[email protected]942521852013-04-26 12:29:23306void DevToolsFileHelper::AddFileSystem(
Pavel Feldman44bd99172017-10-20 16:37:19307 const std::string& type,
[email protected]942521852013-04-26 12:29:23308 const ShowInfoBarCallback& show_info_bar_callback) {
Pavel Feldman44bd99172017-10-20 16:37:19309 scoped_refptr<SelectFileDialog> select_file_dialog = new SelectFileDialog(
310 Bind(&DevToolsFileHelper::InnerAddFileSystem, weak_factory_.GetWeakPtr(),
311 show_info_bar_callback, type),
312 Bind(&DevToolsFileHelper::FailedToAddFileSystem,
313 weak_factory_.GetWeakPtr(), kPermissionDenied),
314 web_contents_);
315 select_file_dialog->Show(ui::SelectFileDialog::SELECT_FOLDER,
316 base::FilePath());
[email protected]e492a802013-01-16 11:12:11317}
318
[email protected]d3d9b45b2013-11-05 20:21:44319void DevToolsFileHelper::UpgradeDraggedFileSystemPermissions(
320 const std::string& file_system_url,
[email protected]d3d9b45b2013-11-05 20:21:44321 const ShowInfoBarCallback& show_info_bar_callback) {
[email protected]cd501a72014-08-22 19:58:31322 storage::FileSystemURL root_url =
[email protected]d3d9b45b2013-11-05 20:21:44323 isolated_context()->CrackURL(GURL(file_system_url));
pfeldman31834e22015-10-10 00:47:05324 if (!root_url.is_valid() || !root_url.path().empty())
[email protected]d3d9b45b2013-11-05 20:21:44325 return;
[email protected]d3d9b45b2013-11-05 20:21:44326
[email protected]cd501a72014-08-22 19:58:31327 std::vector<storage::MountPoints::MountPointInfo> mount_points;
[email protected]d3d9b45b2013-11-05 20:21:44328 isolated_context()->GetDraggedFileInfo(root_url.filesystem_id(),
329 &mount_points);
330
[email protected]cd501a72014-08-22 19:58:31331 std::vector<storage::MountPoints::MountPointInfo>::const_iterator it =
[email protected]d3d9b45b2013-11-05 20:21:44332 mount_points.begin();
333 for (; it != mount_points.end(); ++it)
Pavel Feldman44bd99172017-10-20 16:37:19334 InnerAddFileSystem(show_info_bar_callback, std::string(), it->path);
[email protected]d3d9b45b2013-11-05 20:21:44335}
336
[email protected]e492a802013-01-16 11:12:11337void DevToolsFileHelper::InnerAddFileSystem(
[email protected]942521852013-04-26 12:29:23338 const ShowInfoBarCallback& show_info_bar_callback,
Pavel Feldman44bd99172017-10-20 16:37:19339 const std::string& type,
[email protected]650b2d52013-02-10 03:41:45340 const base::FilePath& path) {
[email protected]2c7136e2013-07-19 19:42:40341 std::string file_system_path = path.AsUTF8Unsafe();
342
Joel Einbinder92f494e2017-12-12 01:45:25343 if (IsFileSystemAdded(file_system_path))
344 RemoveFileSystem(file_system_path);
[email protected]2c7136e2013-07-19 19:42:40345
[email protected]ad1eec62013-08-12 15:21:05346 std::string path_display_name = path.AsEndingWithSeparator().AsUTF8Unsafe();
[email protected]4317aee2013-11-28 07:20:11347 base::string16 message = l10n_util::GetStringFUTF16(
[email protected]942521852013-04-26 12:29:23348 IDS_DEV_TOOLS_CONFIRM_ADD_FILE_SYSTEM_MESSAGE,
[email protected]04338722013-12-24 23:18:05349 base::UTF8ToUTF16(path_display_name));
[email protected]942521852013-04-26 12:29:23350 show_info_bar_callback.Run(
Pavel Feldman44bd99172017-10-20 16:37:19351 message, Bind(&DevToolsFileHelper::AddUserConfirmedFileSystem,
352 weak_factory_.GetWeakPtr(), type, path));
[email protected]e492a802013-01-16 11:12:11353}
354
Pavel Feldman44bd99172017-10-20 16:37:19355void DevToolsFileHelper::AddUserConfirmedFileSystem(const std::string& type,
356 const base::FilePath& path,
357 bool allowed) {
Dmitry Gozmanffa4fa22017-10-20 04:00:49358 if (!allowed) {
Pavel Feldman44bd99172017-10-20 16:37:19359 FailedToAddFileSystem(kPermissionDenied);
[email protected]e492a802013-01-16 11:12:11360 return;
Dmitry Gozmanffa4fa22017-10-20 04:00:49361 }
pfeldman31834e22015-10-10 00:47:05362
363 std::string file_system_id = RegisterFileSystem(web_contents_, path);
[email protected]e492a802013-01-16 11:12:11364 std::string file_system_path = path.AsUTF8Unsafe();
365
366 DictionaryPrefUpdate update(profile_->GetPrefs(),
367 prefs::kDevToolsFileSystemPaths);
[email protected]5bcdd99d2013-12-23 18:28:30368 base::DictionaryValue* file_systems_paths_value = update.Get();
369 file_systems_paths_value->SetWithoutPathExpansion(
Jeremy Romanec48d7a2018-03-01 17:35:09370 file_system_path, std::make_unique<base::Value>(type));
[email protected]e492a802013-01-16 11:12:11371}
372
Pavel Feldman44bd99172017-10-20 16:37:19373void DevToolsFileHelper::FailedToAddFileSystem(const std::string& error) {
374 delegate_->FileSystemAdded(error, nullptr);
Dmitry Gozmanffa4fa22017-10-20 04:00:49375}
376
pfeldman31834e22015-10-10 00:47:05377std::vector<DevToolsFileHelper::FileSystem>
378DevToolsFileHelper::GetFileSystems() {
379 file_system_paths_ = GetAddedFileSystemPaths(profile_);
[email protected]942521852013-04-26 12:29:23380 std::vector<FileSystem> file_systems;
Pavel Feldmanb353680e2017-06-09 19:29:39381 if (!file_watcher_) {
Andrey Kosyakov7dabf712017-06-20 23:50:30382 file_watcher_.reset(new DevToolsFileWatcher(
383 base::Bind(&DevToolsFileHelper::FilePathsChanged,
384 weak_factory_.GetWeakPtr()),
385 base::SequencedTaskRunnerHandle::Get()));
Pavel Feldmanb353680e2017-06-09 19:29:39386 pref_change_registrar_.Add(
387 prefs::kDevToolsFileSystemPaths,
388 base::Bind(&DevToolsFileHelper::FileSystemPathsSettingChanged,
389 base::Unretained(this)));
390 }
pfeldman31834e22015-10-10 00:47:05391 for (auto file_system_path : file_system_paths_) {
Pavel Feldman44bd99172017-10-20 16:37:19392 base::FilePath path =
393 base::FilePath::FromUTF8Unsafe(file_system_path.first);
pfeldman31834e22015-10-10 00:47:05394 std::string file_system_id = RegisterFileSystem(web_contents_, path);
Pavel Feldman44bd99172017-10-20 16:37:19395 FileSystem filesystem =
396 CreateFileSystemStruct(web_contents_, file_system_path.second,
397 file_system_id, file_system_path.first);
[email protected]e492a802013-01-16 11:12:11398 file_systems.push_back(filesystem);
Andrey Kosyakov7dabf712017-06-20 23:50:30399 file_watcher_->AddWatch(std::move(path));
[email protected]e492a802013-01-16 11:12:11400 }
pfeldman31834e22015-10-10 00:47:05401 return file_systems;
[email protected]e492a802013-01-16 11:12:11402}
403
404void DevToolsFileHelper::RemoveFileSystem(const std::string& file_system_path) {
mostynb13260d52015-03-26 09:12:09405 DCHECK_CURRENTLY_ON(BrowserThread::UI);
[email protected]650b2d52013-02-10 03:41:45406 base::FilePath path = base::FilePath::FromUTF8Unsafe(file_system_path);
[email protected]e492a802013-01-16 11:12:11407 isolated_context()->RevokeFileSystemByPath(path);
408
409 DictionaryPrefUpdate update(profile_->GetPrefs(),
410 prefs::kDevToolsFileSystemPaths);
[email protected]5bcdd99d2013-12-23 18:28:30411 base::DictionaryValue* file_systems_paths_value = update.Get();
[email protected]e492a802013-01-16 11:12:11412 file_systems_paths_value->RemoveWithoutPathExpansion(file_system_path, NULL);
413}
[email protected]200bd332013-08-05 16:19:11414
415bool DevToolsFileHelper::IsFileSystemAdded(
416 const std::string& file_system_path) {
mostynb13260d52015-03-26 09:12:09417 DCHECK_CURRENTLY_ON(BrowserThread::UI);
Pavel Feldman44bd99172017-10-20 16:37:19418
419 const base::DictionaryValue* file_systems_paths_value =
420 profile_->GetPrefs()->GetDictionary(prefs::kDevToolsFileSystemPaths);
421 return file_systems_paths_value->HasKey(file_system_path);
[email protected]200bd332013-08-05 16:19:11422}
pfeldman31834e22015-10-10 00:47:05423
Joel Einbinder488905f2018-01-09 20:53:10424void DevToolsFileHelper::OnOpenItemComplete(
425 const base::FilePath& path,
426 platform_util::OpenOperationResult result) {
427 DCHECK_CURRENTLY_ON(BrowserThread::UI);
428 if (result == platform_util::OPEN_FAILED_INVALID_TYPE)
429 platform_util::ShowItemInFolder(profile_, path);
430}
431
432void DevToolsFileHelper::ShowItemInFolder(const std::string& file_system_path) {
433 DCHECK_CURRENTLY_ON(BrowserThread::UI);
434 if (file_system_path.empty())
435 return;
436 base::FilePath path = base::FilePath::FromUTF8Unsafe(file_system_path);
437 platform_util::OpenItem(profile_, path, platform_util::OPEN_FOLDER,
438 base::Bind(&DevToolsFileHelper::OnOpenItemComplete,
439 weak_factory_.GetWeakPtr(), path));
440}
441
pfeldman31834e22015-10-10 00:47:05442void DevToolsFileHelper::FileSystemPathsSettingChanged() {
Pavel Feldman44bd99172017-10-20 16:37:19443 PathToType remaining;
pfeldman31834e22015-10-10 00:47:05444 remaining.swap(file_system_paths_);
Pavel Feldmanb353680e2017-06-09 19:29:39445 DCHECK(file_watcher_.get());
pfeldman31834e22015-10-10 00:47:05446
Pavel Feldman44bd99172017-10-20 16:37:19447 for (auto file_system : GetAddedFileSystemPaths(profile_)) {
448 if (remaining.find(file_system.first) == remaining.end()) {
449 base::FilePath path = base::FilePath::FromUTF8Unsafe(file_system.first);
pfeldman31834e22015-10-10 00:47:05450 std::string file_system_id = RegisterFileSystem(web_contents_, path);
Pavel Feldman44bd99172017-10-20 16:37:19451 FileSystem filesystem = CreateFileSystemStruct(
452 web_contents_, file_system.second, file_system_id, file_system.first);
453 delegate_->FileSystemAdded(std::string(), &filesystem);
Andrey Kosyakov7dabf712017-06-20 23:50:30454 file_watcher_->AddWatch(std::move(path));
pfeldman31834e22015-10-10 00:47:05455 } else {
Pavel Feldman44bd99172017-10-20 16:37:19456 remaining.erase(file_system.first);
pfeldman31834e22015-10-10 00:47:05457 }
Pavel Feldman44bd99172017-10-20 16:37:19458 file_system_paths_[file_system.first] = file_system.second;
pfeldman31834e22015-10-10 00:47:05459 }
460
Pavel Feldman44bd99172017-10-20 16:37:19461 for (auto file_system : remaining) {
462 delegate_->FileSystemRemoved(file_system.first);
463 base::FilePath path = base::FilePath::FromUTF8Unsafe(file_system.first);
Andrey Kosyakov7dabf712017-06-20 23:50:30464 file_watcher_->RemoveWatch(std::move(path));
pfeldman7d01b872015-11-05 08:24:35465 }
466}
467
468void DevToolsFileHelper::FilePathsChanged(
lushnikov2eaab0b32016-10-04 17:17:17469 const std::vector<std::string>& changed_paths,
470 const std::vector<std::string>& added_paths,
471 const std::vector<std::string>& removed_paths) {
472 delegate_->FilePathsChanged(changed_paths, added_paths, removed_paths);
pfeldman31834e22015-10-10 00:47:05473}