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 |