| OLD | NEW |
| (Empty) |
| 1 // 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 | |
| 5 #include "chrome/browser/debugger/devtools_file_helper.h" | |
| 6 | |
| 7 #include <vector> | |
| 8 | |
| 9 #include "base/bind.h" | |
| 10 #include "base/callback.h" | |
| 11 #include "base/file_util.h" | |
| 12 #include "base/lazy_instance.h" | |
| 13 #include "base/md5.h" | |
| 14 #include "base/value_conversions.h" | |
| 15 #include "chrome/browser/browser_process.h" | |
| 16 #include "chrome/browser/download/download_prefs.h" | |
| 17 #include "chrome/browser/prefs/pref_service.h" | |
| 18 #include "chrome/browser/prefs/scoped_user_pref_update.h" | |
| 19 #include "chrome/browser/profiles/profile.h" | |
| 20 #include "chrome/browser/ui/chrome_select_file_policy.h" | |
| 21 #include "chrome/common/pref_names.h" | |
| 22 #include "content/public/browser/browser_context.h" | |
| 23 #include "content/public/browser/download_manager.h" | |
| 24 #include "ui/base/dialogs/select_file_dialog.h" | |
| 25 | |
| 26 using content::BrowserContext; | |
| 27 using content::BrowserThread; | |
| 28 using content::DownloadManager; | |
| 29 | |
| 30 namespace { | |
| 31 | |
| 32 base::LazyInstance<FilePath>::Leaky | |
| 33 g_last_save_path = LAZY_INSTANCE_INITIALIZER; | |
| 34 | |
| 35 } // namespace | |
| 36 | |
| 37 class DevToolsFileHelper::SaveAsDialog : public ui::SelectFileDialog::Listener, | |
| 38 public base::RefCounted<SaveAsDialog> { | |
| 39 public: | |
| 40 explicit SaveAsDialog(DevToolsFileHelper* helper) | |
| 41 : helper_(helper) { | |
| 42 select_file_dialog_ = ui::SelectFileDialog::Create( | |
| 43 this, new ChromeSelectFilePolicy(NULL)); | |
| 44 } | |
| 45 | |
| 46 void ResetHelper() { | |
| 47 helper_ = NULL; | |
| 48 } | |
| 49 | |
| 50 void Show(const std::string& url, | |
| 51 const FilePath& initial_path, | |
| 52 const std::string& content) { | |
| 53 AddRef(); // Balanced in the three listener outcomes. | |
| 54 | |
| 55 url_ = url; | |
| 56 content_ = content; | |
| 57 | |
| 58 select_file_dialog_->SelectFile(ui::SelectFileDialog::SELECT_SAVEAS_FILE, | |
| 59 string16(), | |
| 60 initial_path, | |
| 61 NULL, | |
| 62 0, | |
| 63 FILE_PATH_LITERAL(""), | |
| 64 NULL, | |
| 65 NULL); | |
| 66 } | |
| 67 | |
| 68 // ui::SelectFileDialog::Listener implementation. | |
| 69 virtual void FileSelected(const FilePath& path, | |
| 70 int index, void* params) { | |
| 71 if (helper_) | |
| 72 helper_->FileSelected(url_, path, content_); | |
| 73 Release(); // Balanced in ::Show. | |
| 74 } | |
| 75 | |
| 76 virtual void MultiFilesSelected( | |
| 77 const std::vector<FilePath>& files, void* params) { | |
| 78 Release(); // Balanced in ::Show. | |
| 79 NOTREACHED() << "Should not be able to select multiple files"; | |
| 80 } | |
| 81 | |
| 82 virtual void FileSelectionCanceled(void* params) { | |
| 83 Release(); // Balanced in ::Show. | |
| 84 } | |
| 85 | |
| 86 private: | |
| 87 friend class base::RefCounted<SaveAsDialog>; | |
| 88 virtual ~SaveAsDialog() {} | |
| 89 | |
| 90 scoped_refptr<ui::SelectFileDialog> select_file_dialog_; | |
| 91 std::string url_; | |
| 92 std::string content_; | |
| 93 DevToolsFileHelper* helper_; | |
| 94 }; | |
| 95 | |
| 96 // static | |
| 97 void DevToolsFileHelper::WriteFile(const FilePath& path, | |
| 98 const std::string& content) { | |
| 99 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | |
| 100 DCHECK(!path.empty()); | |
| 101 | |
| 102 file_util::WriteFile(path, content.c_str(), content.length()); | |
| 103 } | |
| 104 | |
| 105 // static | |
| 106 void DevToolsFileHelper::AppendToFile(const FilePath& path, | |
| 107 const std::string& content) { | |
| 108 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | |
| 109 DCHECK(!path.empty()); | |
| 110 | |
| 111 file_util::AppendToFile(path, content.c_str(), content.length()); | |
| 112 } | |
| 113 | |
| 114 DevToolsFileHelper::DevToolsFileHelper(Profile* profile, Delegate* delegate) | |
| 115 : profile_(profile), | |
| 116 delegate_(delegate) { | |
| 117 } | |
| 118 | |
| 119 DevToolsFileHelper::~DevToolsFileHelper() { | |
| 120 if (save_as_dialog_) | |
| 121 save_as_dialog_->ResetHelper(); | |
| 122 } | |
| 123 | |
| 124 void DevToolsFileHelper::Save(const std::string& url, | |
| 125 const std::string& content, | |
| 126 bool save_as) { | |
| 127 PathsMap::iterator it = saved_files_.find(url); | |
| 128 if (it != saved_files_.end() && !save_as) { | |
| 129 FileSelected(url, it->second, content); | |
| 130 return; | |
| 131 } | |
| 132 | |
| 133 if (save_as_dialog_) | |
| 134 save_as_dialog_->ResetHelper(); | |
| 135 | |
| 136 const DictionaryValue* file_map = | |
| 137 profile_->GetPrefs()->GetDictionary(prefs::kDevToolsEditedFiles); | |
| 138 FilePath initial_path; | |
| 139 | |
| 140 const Value* path_value; | |
| 141 if (file_map->Get(base::MD5String(url), &path_value)) | |
| 142 base::GetValueAsFilePath(*path_value, &initial_path); | |
| 143 | |
| 144 if (initial_path.empty()) { | |
| 145 GURL gurl(url); | |
| 146 std::string suggested_file_name = gurl.is_valid() ? | |
| 147 gurl.ExtractFileName() : url; | |
| 148 | |
| 149 if (suggested_file_name.length() > 64) | |
| 150 suggested_file_name = suggested_file_name.substr(0, 64); | |
| 151 | |
| 152 if (!g_last_save_path.Pointer()->empty()) { | |
| 153 initial_path = g_last_save_path.Pointer()->DirName().AppendASCII( | |
| 154 suggested_file_name); | |
| 155 } else { | |
| 156 FilePath download_path = DownloadPrefs::FromDownloadManager( | |
| 157 BrowserContext::GetDownloadManager(profile_))->DownloadPath(); | |
| 158 initial_path = download_path.AppendASCII(suggested_file_name); | |
| 159 } | |
| 160 } | |
| 161 | |
| 162 save_as_dialog_ = new SaveAsDialog(this); | |
| 163 save_as_dialog_->Show(url, initial_path, content); | |
| 164 } | |
| 165 | |
| 166 void DevToolsFileHelper::Append(const std::string& url, | |
| 167 const std::string& content) { | |
| 168 PathsMap::iterator it = saved_files_.find(url); | |
| 169 if (it == saved_files_.end()) | |
| 170 return; | |
| 171 | |
| 172 delegate_->AppendedTo(url); | |
| 173 | |
| 174 BrowserThread::PostTask( | |
| 175 BrowserThread::FILE, FROM_HERE, | |
| 176 base::Bind(&DevToolsFileHelper::AppendToFile, | |
| 177 it->second, | |
| 178 content)); | |
| 179 } | |
| 180 | |
| 181 void DevToolsFileHelper::FileSelected(const std::string& url, | |
| 182 const FilePath& path, | |
| 183 const std::string& content) { | |
| 184 *g_last_save_path.Pointer() = path; | |
| 185 saved_files_[url] = path; | |
| 186 | |
| 187 DictionaryPrefUpdate update(profile_->GetPrefs(), | |
| 188 prefs::kDevToolsEditedFiles); | |
| 189 DictionaryValue* files_map = update.Get(); | |
| 190 files_map->SetWithoutPathExpansion(base::MD5String(url), | |
| 191 base::CreateFilePathValue(path)); | |
| 192 delegate_->FileSavedAs(url); | |
| 193 | |
| 194 BrowserThread::PostTask( | |
| 195 BrowserThread::FILE, FROM_HERE, | |
| 196 base::Bind(&DevToolsFileHelper::WriteFile, | |
| 197 path, | |
| 198 content)); | |
| 199 } | |
| OLD | NEW |