12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/devtools/devtools_file_helper.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include <set>
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <vector>
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/callback.h"
121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/lazy_instance.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/md5.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_service.h"
161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "base/prefs/scoped_user_pref_update.h"
17868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/value_conversions.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/browser_process.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/download/download_prefs.h"
217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/platform_util.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/profiles/profile.h"
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/chrome_select_file_policy.h"
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/pref_names.h"
2503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "chrome/grit/generated_resources.h"
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/browser_context.h"
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/browser_thread.h"
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/child_process_security_policy.h"
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/download_manager.h"
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/render_process_host.h"
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/render_view_host.h"
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/web_contents.h"
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/common/content_client.h"
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/common/url_constants.h"
351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/browser/fileapi/file_system_url.h"
361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/browser/fileapi/isolated_context.h"
371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "storage/common/fileapi/file_system_util.h"
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/base/l10n/l10n_util.h"
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/shell_dialogs/select_file_dialog.h"
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using base::Bind;
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using base::Callback;
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using content::BrowserContext;
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using content::BrowserThread;
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using content::DownloadManager;
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using content::RenderViewHost;
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using content::WebContents;
482385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochusing std::set;
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::LazyInstance<base::FilePath>::Leaky
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    g_last_save_path = LAZY_INSTANCE_INITIALIZER;
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)typedef Callback<void(const base::FilePath&)> SelectedCallback;
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)typedef Callback<void(void)> CanceledCallback;
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class SelectFileDialog : public ui::SelectFileDialog::Listener,
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         public base::RefCounted<SelectFileDialog> {
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SelectFileDialog(const SelectedCallback& selected_callback,
667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                   const CanceledCallback& canceled_callback,
677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                   WebContents* web_contents)
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      : selected_callback_(selected_callback),
697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        canceled_callback_(canceled_callback),
707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        web_contents_(web_contents) {
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    select_file_dialog_ = ui::SelectFileDialog::Create(
72f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        this, new ChromeSelectFilePolicy(web_contents));
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void Show(ui::SelectFileDialog::Type type,
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            const base::FilePath& default_path) {
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    AddRef();  // Balanced in the three listener outcomes.
787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    select_file_dialog_->SelectFile(
797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      type,
80f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      base::string16(),
817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      default_path,
827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      NULL,
837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      0,
847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      base::FilePath::StringType(),
85010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      platform_util::GetTopLevel(web_contents_->GetNativeView()),
867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      NULL);
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // ui::SelectFileDialog::Listener implementation.
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void FileSelected(const base::FilePath& path,
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            int index,
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            void* params) OVERRIDE {
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    selected_callback_.Run(path);
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Release();  // Balanced in ::Show.
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void MultiFilesSelected(const std::vector<base::FilePath>& files,
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  void* params) OVERRIDE {
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Release();  // Balanced in ::Show.
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    NOTREACHED() << "Should not be able to select multiple files";
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void FileSelectionCanceled(void* params) OVERRIDE {
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    canceled_callback_.Run();
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Release();  // Balanced in ::Show.
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  friend class base::RefCounted<SelectFileDialog>;
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~SelectFileDialog() {}
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<ui::SelectFileDialog> select_file_dialog_;
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SelectedCallback selected_callback_;
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CanceledCallback canceled_callback_;
1157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  WebContents* web_contents_;
116f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
117f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(SelectFileDialog);
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void WriteToFile(const base::FilePath& path, const std::string& content) {
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!path.empty());
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
124a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  base::WriteFile(path, content.c_str(), content.length());
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AppendToFile(const base::FilePath& path, const std::string& content) {
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!path.empty());
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
131a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  base::AppendToFile(path, content.c_str(), content.length());
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)storage::IsolatedContext* isolated_context() {
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
13603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  storage::IsolatedContext* isolated_context =
13703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      storage::IsolatedContext::GetInstance();
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(isolated_context);
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return isolated_context;
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)std::string RegisterFileSystem(WebContents* web_contents,
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               const base::FilePath& path,
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               std::string* registered_name) {
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  CHECK(web_contents->GetURL().SchemeIs(content::kChromeDevToolsScheme));
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string file_system_id = isolated_context()->RegisterFileSystemForPath(
14803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      storage::kFileSystemTypeNativeLocal,
14903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      std::string(),
15003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      path,
1516d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      registered_name);
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  content::ChildProcessSecurityPolicy* policy =
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      content::ChildProcessSecurityPolicy::GetInstance();
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  RenderViewHost* render_view_host = web_contents->GetRenderViewHost();
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int renderer_id = render_view_host->GetProcess()->GetID();
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  policy->GrantReadFileSystem(renderer_id, file_system_id);
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  policy->GrantWriteFileSystem(renderer_id, file_system_id);
159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  policy->GrantCreateFileForFileSystem(renderer_id, file_system_id);
1608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  policy->GrantDeleteFromFileSystem(renderer_id, file_system_id);
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // We only need file level access for reading FileEntries. Saving FileEntries
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // just needs the file system to have read/write access, which is granted
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // above if required.
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!policy->CanReadFile(renderer_id, path))
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    policy->GrantReadFile(renderer_id, path);
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return file_system_id;
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DevToolsFileHelper::FileSystem CreateFileSystemStruct(
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    WebContents* web_contents,
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& file_system_id,
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& registered_name,
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& file_system_path) {
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const GURL origin = web_contents->GetURL().GetOrigin();
17703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  std::string file_system_name =
17803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      storage::GetIsolatedFileSystemName(origin, file_system_id);
17903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  std::string root_url = storage::GetIsolatedFileSystemRootURIString(
18003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      origin, file_system_id, registered_name);
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return DevToolsFileHelper::FileSystem(file_system_name,
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                        root_url,
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                        file_system_path);
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1862385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochset<std::string> GetAddedFileSystemPaths(Profile* profile) {
1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const base::DictionaryValue* file_systems_paths_value =
1882385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch      profile->GetPrefs()->GetDictionary(prefs::kDevToolsFileSystemPaths);
1892385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  set<std::string> result;
1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (base::DictionaryValue::Iterator it(*file_systems_paths_value);
1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       !it.IsAtEnd(); it.Advance()) {
1922385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    result.insert(it.key());
1932385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  }
1942385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  return result;
1952385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch}
1962385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DevToolsFileHelper::FileSystem::FileSystem() {
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DevToolsFileHelper::FileSystem::FileSystem(const std::string& file_system_name,
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                           const std::string& root_url,
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                           const std::string& file_system_path)
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : file_system_name(file_system_name),
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      root_url(root_url),
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      file_system_path(file_system_path) {
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DevToolsFileHelper::DevToolsFileHelper(WebContents* web_contents,
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       Profile* profile)
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : web_contents_(web_contents),
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      profile_(profile),
214c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      weak_factory_(this) {
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DevToolsFileHelper::~DevToolsFileHelper() {
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DevToolsFileHelper::Save(const std::string& url,
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              const std::string& content,
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              bool save_as,
223a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                              const SaveCallback& saveCallback,
224a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                              const SaveCallback& cancelCallback) {
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PathsMap::iterator it = saved_files_.find(url);
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (it != saved_files_.end() && !save_as) {
227a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    SaveAsFileSelected(url, content, saveCallback, it->second);
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const base::DictionaryValue* file_map =
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      profile_->GetPrefs()->GetDictionary(prefs::kDevToolsEditedFiles);
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath initial_path;
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const base::Value* path_value;
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (file_map->Get(base::MD5String(url), &path_value))
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::GetValueAsFilePath(*path_value, &initial_path);
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (initial_path.empty()) {
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GURL gurl(url);
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string suggested_file_name = gurl.is_valid() ?
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        gurl.ExtractFileName() : url;
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (suggested_file_name.length() > 64)
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      suggested_file_name = suggested_file_name.substr(0, 64);
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!g_last_save_path.Pointer()->empty()) {
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      initial_path = g_last_save_path.Pointer()->DirName().AppendASCII(
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          suggested_file_name);
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::FilePath download_path = DownloadPrefs::FromDownloadManager(
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          BrowserContext::GetDownloadManager(profile_))->DownloadPath();
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      initial_path = download_path.AppendASCII(suggested_file_name);
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<SelectFileDialog> select_file_dialog = new SelectFileDialog(
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      Bind(&DevToolsFileHelper::SaveAsFileSelected,
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           weak_factory_.GetWeakPtr(),
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           url,
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           content,
262a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)           saveCallback),
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      Bind(&DevToolsFileHelper::SaveAsFileSelectionCanceled,
264a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)           weak_factory_.GetWeakPtr(),
265a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)           cancelCallback),
2667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      web_contents_);
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  select_file_dialog->Show(ui::SelectFileDialog::SELECT_SAVEAS_FILE,
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           initial_path);
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DevToolsFileHelper::Append(const std::string& url,
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                const std::string& content,
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                const AppendCallback& callback) {
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PathsMap::iterator it = saved_files_.find(url);
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (it == saved_files_.end())
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  callback.Run();
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          Bind(&AppendToFile, it->second, content));
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DevToolsFileHelper::SaveAsFileSelected(const std::string& url,
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                            const std::string& content,
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                            const SaveCallback& callback,
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                            const base::FilePath& path) {
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *g_last_save_path.Pointer() = path;
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  saved_files_[url] = path;
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DictionaryPrefUpdate update(profile_->GetPrefs(),
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              prefs::kDevToolsEditedFiles);
2915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::DictionaryValue* files_map = update.Get();
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  files_map->SetWithoutPathExpansion(base::MD5String(url),
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                     base::CreateFilePathValue(path));
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  callback.Run();
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          Bind(&WriteToFile, path, content));
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
299a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void DevToolsFileHelper::SaveAsFileSelectionCanceled(
300a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const SaveCallback& callback) {
301a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  callback.Run();
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
304c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void DevToolsFileHelper::AddFileSystem(
305c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const AddFileSystemCallback& callback,
306c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const ShowInfoBarCallback& show_info_bar_callback) {
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<SelectFileDialog> select_file_dialog = new SelectFileDialog(
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      Bind(&DevToolsFileHelper::InnerAddFileSystem,
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           weak_factory_.GetWeakPtr(),
310c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)           callback,
311c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)           show_info_bar_callback),
3127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      Bind(callback, FileSystem()),
3137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      web_contents_);
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  select_file_dialog->Show(ui::SelectFileDialog::SELECT_FOLDER,
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           base::FilePath());
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
318f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void DevToolsFileHelper::UpgradeDraggedFileSystemPermissions(
319f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const std::string& file_system_url,
320f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const AddFileSystemCallback& callback,
321f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const ShowInfoBarCallback& show_info_bar_callback) {
32203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  storage::FileSystemURL root_url =
323f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      isolated_context()->CrackURL(GURL(file_system_url));
324f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!root_url.is_valid() || !root_url.path().empty()) {
325f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    callback.Run(FileSystem());
326f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return;
327f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
328f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
32903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  std::vector<storage::MountPoints::MountPointInfo> mount_points;
330f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  isolated_context()->GetDraggedFileInfo(root_url.filesystem_id(),
331f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                         &mount_points);
332f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
33303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  std::vector<storage::MountPoints::MountPointInfo>::const_iterator it =
334f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      mount_points.begin();
335f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  for (; it != mount_points.end(); ++it)
336f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    InnerAddFileSystem(callback, show_info_bar_callback, it->path);
337f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
338f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DevToolsFileHelper::InnerAddFileSystem(
3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const AddFileSystemCallback& callback,
341c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const ShowInfoBarCallback& show_info_bar_callback,
3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::FilePath& path) {
343ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  std::string file_system_path = path.AsUTF8Unsafe();
344ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
3455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const base::DictionaryValue* file_systems_paths_value =
346ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      profile_->GetPrefs()->GetDictionary(prefs::kDevToolsFileSystemPaths);
347ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (file_systems_paths_value->HasKey(file_system_path)) {
348ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    callback.Run(FileSystem());
349ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    return;
350ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  }
351ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
352c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch  std::string path_display_name = path.AsEndingWithSeparator().AsUTF8Unsafe();
353f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  base::string16 message = l10n_util::GetStringFUTF16(
354c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      IDS_DEV_TOOLS_CONFIRM_ADD_FILE_SYSTEM_MESSAGE,
3555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::UTF8ToUTF16(path_display_name));
356c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  show_info_bar_callback.Run(
357c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      message,
358c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      Bind(&DevToolsFileHelper::AddUserConfirmedFileSystem,
359c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)           weak_factory_.GetWeakPtr(),
360c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)           callback, path));
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
363c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void DevToolsFileHelper::AddUserConfirmedFileSystem(
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const AddFileSystemCallback& callback,
365c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::FilePath& path,
366c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bool allowed) {
367c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!allowed) {
368c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    callback.Run(FileSystem());
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string registered_name;
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string file_system_id = RegisterFileSystem(web_contents_,
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                  path,
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                  &registered_name);
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string file_system_path = path.AsUTF8Unsafe();
3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DictionaryPrefUpdate update(profile_->GetPrefs(),
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              prefs::kDevToolsFileSystemPaths);
3795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::DictionaryValue* file_systems_paths_value = update.Get();
3805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  file_systems_paths_value->SetWithoutPathExpansion(
3815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      file_system_path, base::Value::CreateNullValue());
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FileSystem filesystem = CreateFileSystemStruct(web_contents_,
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                 file_system_id,
3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                 registered_name,
3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                 file_system_path);
387c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback.Run(filesystem);
3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DevToolsFileHelper::RequestFileSystems(
3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const RequestFileSystemsCallback& callback) {
3922385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  set<std::string> file_system_paths = GetAddedFileSystemPaths(profile_);
3932385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  set<std::string>::const_iterator it = file_system_paths.begin();
394c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::vector<FileSystem> file_systems;
3952385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  for (; it != file_system_paths.end(); ++it) {
3962385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    std::string file_system_path = *it;
3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::FilePath path = base::FilePath::FromUTF8Unsafe(file_system_path);
3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string registered_name;
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string file_system_id = RegisterFileSystem(web_contents_,
401c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                                    path,
4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                    &registered_name);
4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    FileSystem filesystem = CreateFileSystemStruct(web_contents_,
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                   file_system_id,
4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                   registered_name,
4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                   file_system_path);
4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    file_systems.push_back(filesystem);
4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  callback.Run(file_systems);
4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DevToolsFileHelper::RemoveFileSystem(const std::string& file_system_path) {
4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath path = base::FilePath::FromUTF8Unsafe(file_system_path);
4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  isolated_context()->RevokeFileSystemByPath(path);
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DictionaryPrefUpdate update(profile_->GetPrefs(),
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              prefs::kDevToolsFileSystemPaths);
4195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::DictionaryValue* file_systems_paths_value = update.Get();
4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  file_systems_paths_value->RemoveWithoutPathExpansion(file_system_path, NULL);
4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4222385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
4232385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochbool DevToolsFileHelper::IsFileSystemAdded(
4242385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch    const std::string& file_system_path) {
4252385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
4262385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  set<std::string> file_system_paths = GetAddedFileSystemPaths(profile_);
4272385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  return file_system_paths.find(file_system_path) != file_system_paths.end();
4282385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch}
429