summaryrefslogtreecommitdiffstats
path: root/chrome/browser/devtools/devtools_file_helper.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/devtools/devtools_file_helper.cc')
-rw-r--r--chrome/browser/devtools/devtools_file_helper.cc199
1 files changed, 199 insertions, 0 deletions
diff --git a/chrome/browser/devtools/devtools_file_helper.cc b/chrome/browser/devtools/devtools_file_helper.cc
new file mode 100644
index 0000000..6eab113
--- /dev/null
+++ b/chrome/browser/devtools/devtools_file_helper.cc
@@ -0,0 +1,199 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/devtools/devtools_file_helper.h"
+
+#include <vector>
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/file_util.h"
+#include "base/lazy_instance.h"
+#include "base/md5.h"
+#include "base/value_conversions.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/download/download_prefs.h"
+#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/browser/prefs/scoped_user_pref_update.h"
+#include "chrome/browser/profiles/profile.h"
+#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/download_manager.h"
+#include "ui/base/dialogs/select_file_dialog.h"
+
+using content::BrowserContext;
+using content::BrowserThread;
+using content::DownloadManager;
+
+namespace {
+
+base::LazyInstance<FilePath>::Leaky
+ g_last_save_path = LAZY_INSTANCE_INITIALIZER;
+
+} // namespace
+
+class DevToolsFileHelper::SaveAsDialog : public ui::SelectFileDialog::Listener,
+ public base::RefCounted<SaveAsDialog> {
+ public:
+ explicit SaveAsDialog(DevToolsFileHelper* helper)
+ : helper_(helper) {
+ select_file_dialog_ = ui::SelectFileDialog::Create(
+ this, new ChromeSelectFilePolicy(NULL));
+ }
+
+ void ResetHelper() {
+ helper_ = NULL;
+ }
+
+ void Show(const std::string& url,
+ const FilePath& initial_path,
+ const std::string& content) {
+ AddRef(); // Balanced in the three listener outcomes.
+
+ url_ = url;
+ content_ = content;
+
+ select_file_dialog_->SelectFile(ui::SelectFileDialog::SELECT_SAVEAS_FILE,
+ string16(),
+ initial_path,
+ NULL,
+ 0,
+ FILE_PATH_LITERAL(""),
+ NULL,
+ NULL);
+ }
+
+ // ui::SelectFileDialog::Listener implementation.
+ virtual void FileSelected(const FilePath& path,
+ int index, void* params) {
+ if (helper_)
+ helper_->FileSelected(url_, path, content_);
+ Release(); // Balanced in ::Show.
+ }
+
+ virtual void MultiFilesSelected(
+ const std::vector<FilePath>& files, void* params) {
+ Release(); // Balanced in ::Show.
+ NOTREACHED() << "Should not be able to select multiple files";
+ }
+
+ virtual void FileSelectionCanceled(void* params) {
+ Release(); // Balanced in ::Show.
+ }
+
+ private:
+ friend class base::RefCounted<SaveAsDialog>;
+ virtual ~SaveAsDialog() {}
+
+ scoped_refptr<ui::SelectFileDialog> select_file_dialog_;
+ std::string url_;
+ std::string content_;
+ DevToolsFileHelper* helper_;
+};
+
+// static
+void DevToolsFileHelper::WriteFile(const FilePath& path,
+ const std::string& content) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ DCHECK(!path.empty());
+
+ file_util::WriteFile(path, content.c_str(), content.length());
+}
+
+// static
+void DevToolsFileHelper::AppendToFile(const FilePath& path,
+ const std::string& content) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ DCHECK(!path.empty());
+
+ file_util::AppendToFile(path, content.c_str(), content.length());
+}
+
+DevToolsFileHelper::DevToolsFileHelper(Profile* profile, Delegate* delegate)
+ : profile_(profile),
+ delegate_(delegate) {
+}
+
+DevToolsFileHelper::~DevToolsFileHelper() {
+ if (save_as_dialog_)
+ save_as_dialog_->ResetHelper();
+}
+
+void DevToolsFileHelper::Save(const std::string& url,
+ const std::string& content,
+ bool save_as) {
+ PathsMap::iterator it = saved_files_.find(url);
+ if (it != saved_files_.end() && !save_as) {
+ FileSelected(url, it->second, content);
+ return;
+ }
+
+ if (save_as_dialog_)
+ save_as_dialog_->ResetHelper();
+
+ const DictionaryValue* file_map =
+ profile_->GetPrefs()->GetDictionary(prefs::kDevToolsEditedFiles);
+ FilePath initial_path;
+
+ const Value* path_value;
+ if (file_map->Get(base::MD5String(url), &path_value))
+ base::GetValueAsFilePath(*path_value, &initial_path);
+
+ if (initial_path.empty()) {
+ GURL gurl(url);
+ std::string suggested_file_name = gurl.is_valid() ?
+ gurl.ExtractFileName() : url;
+
+ if (suggested_file_name.length() > 64)
+ suggested_file_name = suggested_file_name.substr(0, 64);
+
+ if (!g_last_save_path.Pointer()->empty()) {
+ initial_path = g_last_save_path.Pointer()->DirName().AppendASCII(
+ suggested_file_name);
+ } else {
+ FilePath download_path = DownloadPrefs::FromDownloadManager(
+ BrowserContext::GetDownloadManager(profile_))->DownloadPath();
+ initial_path = download_path.AppendASCII(suggested_file_name);
+ }
+ }
+
+ save_as_dialog_ = new SaveAsDialog(this);
+ save_as_dialog_->Show(url, initial_path, content);
+}
+
+void DevToolsFileHelper::Append(const std::string& url,
+ const std::string& content) {
+ PathsMap::iterator it = saved_files_.find(url);
+ if (it == saved_files_.end())
+ return;
+
+ delegate_->AppendedTo(url);
+
+ BrowserThread::PostTask(
+ BrowserThread::FILE, FROM_HERE,
+ base::Bind(&DevToolsFileHelper::AppendToFile,
+ it->second,
+ content));
+}
+
+void DevToolsFileHelper::FileSelected(const std::string& url,
+ const FilePath& path,
+ const std::string& content) {
+ *g_last_save_path.Pointer() = path;
+ saved_files_[url] = path;
+
+ DictionaryPrefUpdate update(profile_->GetPrefs(),
+ prefs::kDevToolsEditedFiles);
+ DictionaryValue* files_map = update.Get();
+ files_map->SetWithoutPathExpansion(base::MD5String(url),
+ base::CreateFilePathValue(path));
+ delegate_->FileSavedAs(url);
+
+ BrowserThread::PostTask(
+ BrowserThread::FILE, FROM_HERE,
+ base::Bind(&DevToolsFileHelper::WriteFile,
+ path,
+ content));
+}