summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorxiyuan@chromium.org <xiyuan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-01-29 22:03:57 +0000
committerxiyuan@chromium.org <xiyuan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-01-29 22:03:57 +0000
commit274e42bf367cc47931bdac85837cfc2c8259f8a1 (patch)
tree75dc09021e2b1e85d416928773b351de33b7fae3
parenta9aca52ac15959a2c71a4ee22539a2392d3ee06b (diff)
downloadchromium_src-274e42bf367cc47931bdac85837cfc2c8259f8a1.zip
chromium_src-274e42bf367cc47931bdac85837cfc2c8259f8a1.tar.gz
chromium_src-274e42bf367cc47931bdac85837cfc2c8259f8a1.tar.bz2
Replace GtkFileChooser with file browser for ChromeOS
- Remove dialogs_gtk.cc and add select_file_dialog.cc for chrome os build; - select_file_dialog.cc provides a SelectFileDialogImpl that serves file browse html via HTMLDialogUI; BUG=none TEST=none Review URL: http://codereview.chromium.org/543137 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@37547 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/dom_ui/downloads_dom_handler.cc110
-rw-r--r--chrome/browser/dom_ui/downloads_dom_handler.h8
-rw-r--r--chrome/browser/dom_ui/filebrowse_ui.cc135
-rw-r--r--chrome/browser/dom_ui/filebrowse_ui.h4
-rw-r--r--chrome/browser/download/download_util.cc105
-rw-r--r--chrome/browser/download/download_util.h10
-rw-r--r--chrome/browser/resources/filebrowse.html417
-rw-r--r--chrome/browser/views/dialog_stubs_gtk.cc6
-rw-r--r--chrome/browser/views/dom_view.cc2
-rw-r--r--chrome/browser/views/select_file_dialog.cc390
-rwxr-xr-xchrome/chrome_browser.gypi8
11 files changed, 1050 insertions, 145 deletions
diff --git a/chrome/browser/dom_ui/downloads_dom_handler.cc b/chrome/browser/dom_ui/downloads_dom_handler.cc
index 7e8d1a0..501faf0 100644
--- a/chrome/browser/dom_ui/downloads_dom_handler.cc
+++ b/chrome/browser/dom_ui/downloads_dom_handler.cc
@@ -6,7 +6,6 @@
#include "app/l10n_util.h"
#include "base/basictypes.h"
-#include "base/i18n/time_formatting.h"
#include "base/singleton.h"
#include "base/string_piece.h"
#include "base/thread.h"
@@ -20,7 +19,6 @@
#include "chrome/browser/profile.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/common/jstemplate_builder.h"
-#include "chrome/common/time_format.h"
#include "chrome/common/url_constants.h"
#include "grit/browser_resources.h"
#include "grit/generated_resources.h"
@@ -106,7 +104,7 @@ void DownloadsDOMHandler::OnDownloadUpdated(DownloadItem* download) {
const int id = static_cast<int>(it - download_items_.begin());
ListValue results_value;
- results_value.Append(CreateDownloadItemValue(download, id));
+ results_value.Append(download_util::CreateDownloadItemValue(download, id));
dom_ui_->CallJavascriptFunction(L"downloadUpdated", results_value);
}
@@ -221,63 +219,12 @@ void DownloadsDOMHandler::SendCurrentDownloads() {
int index = static_cast<int>(it - download_items_.begin());
if (index > kMaxDownloads)
break;
- results_value.Append(CreateDownloadItemValue(*it, index));
+ results_value.Append(download_util::CreateDownloadItemValue(*it, index));
}
dom_ui_->CallJavascriptFunction(L"downloadsList", results_value);
}
-DictionaryValue* DownloadsDOMHandler::CreateDownloadItemValue(
- DownloadItem* download, int id) {
- DictionaryValue* file_value = new DictionaryValue();
-
- file_value->SetInteger(L"started",
- static_cast<int>(download->start_time().ToTimeT()));
- file_value->SetString(L"since_string",
- TimeFormat::RelativeDate(download->start_time(), NULL));
- file_value->SetString(L"date_string",
- base::TimeFormatShortDate(download->start_time()));
- file_value->SetInteger(L"id", id);
- file_value->SetString(L"file_path", download->full_path().ToWStringHack());
- // Keep file names as LTR.
- std::wstring file_name = download->GetFileName().ToWStringHack();
- if (l10n_util::GetTextDirection() == l10n_util::RIGHT_TO_LEFT)
- l10n_util::WrapStringWithLTRFormatting(&file_name);
- file_value->SetString(L"file_name", file_name);
- file_value->SetString(L"url", download->url().spec());
-
- if (download->state() == DownloadItem::IN_PROGRESS) {
- if (download->safety_state() == DownloadItem::DANGEROUS) {
- file_value->SetString(L"state", L"DANGEROUS");
- } else if (download->is_paused()) {
- file_value->SetString(L"state", L"PAUSED");
- } else {
- file_value->SetString(L"state", L"IN_PROGRESS");
- }
-
- file_value->SetString(L"progress_status_text",
- GetProgressStatusText(download));
-
- file_value->SetInteger(L"percent",
- static_cast<int>(download->PercentComplete()));
- file_value->SetInteger(L"received",
- static_cast<int>(download->received_bytes()));
- } else if (download->state() == DownloadItem::CANCELLED) {
- file_value->SetString(L"state", L"CANCELLED");
- } else if (download->state() == DownloadItem::COMPLETE) {
- if (download->safety_state() == DownloadItem::DANGEROUS) {
- file_value->SetString(L"state", L"DANGEROUS");
- } else {
- file_value->SetString(L"state", L"COMPLETE");
- }
- }
-
- file_value->SetInteger(L"total",
- static_cast<int>(download->total_bytes()));
-
- return file_value;
-}
-
void DownloadsDOMHandler::ClearDownloadItems() {
// Clear out old state and remove self as observer for each download.
for (OrderedDownloads::iterator it = download_items_.begin();
@@ -305,56 +252,3 @@ DownloadItem* DownloadsDOMHandler::GetDownloadByValue(const Value* value) {
}
return NULL;
}
-
-std::wstring DownloadsDOMHandler::GetProgressStatusText(
- DownloadItem* download) {
- int64 total = download->total_bytes();
- int64 size = download->received_bytes();
- DataUnits amount_units = GetByteDisplayUnits(size);
- std::wstring received_size = FormatBytes(size, amount_units, true);
- std::wstring amount = received_size;
-
- // Adjust both strings for the locale direction since we don't yet know which
- // string we'll end up using for constructing the final progress string.
- std::wstring amount_localized;
- if (l10n_util::AdjustStringForLocaleDirection(amount, &amount_localized)) {
- amount.assign(amount_localized);
- received_size.assign(amount_localized);
- }
-
- if (total) {
- amount_units = GetByteDisplayUnits(total);
- std::wstring total_text = FormatBytes(total, amount_units, true);
- std::wstring total_text_localized;
- if (l10n_util::AdjustStringForLocaleDirection(total_text,
- &total_text_localized))
- total_text.assign(total_text_localized);
-
- amount = l10n_util::GetStringF(IDS_DOWNLOAD_TAB_PROGRESS_SIZE,
- received_size,
- total_text);
- } else {
- amount.assign(received_size);
- }
- amount_units = GetByteDisplayUnits(download->CurrentSpeed());
- std::wstring speed_text = FormatSpeed(download->CurrentSpeed(),
- amount_units, true);
- std::wstring speed_text_localized;
- if (l10n_util::AdjustStringForLocaleDirection(speed_text,
- &speed_text_localized))
- speed_text.assign(speed_text_localized);
-
- base::TimeDelta remaining;
- std::wstring time_remaining;
- if (download->is_paused())
- time_remaining = l10n_util::GetString(IDS_DOWNLOAD_PROGRESS_PAUSED);
- else if (download->TimeRemaining(&remaining))
- time_remaining = TimeFormat::TimeRemaining(remaining);
-
- if (time_remaining.empty()) {
- return l10n_util::GetStringF(IDS_DOWNLOAD_TAB_PROGRESS_STATUS_TIME_UNKNOWN,
- speed_text, amount);
- }
- return l10n_util::GetStringF(IDS_DOWNLOAD_TAB_PROGRESS_STATUS, speed_text,
- amount, time_remaining);
-}
diff --git a/chrome/browser/dom_ui/downloads_dom_handler.h b/chrome/browser/dom_ui/downloads_dom_handler.h
index ad7d459..e43882c 100644
--- a/chrome/browser/dom_ui/downloads_dom_handler.h
+++ b/chrome/browser/dom_ui/downloads_dom_handler.h
@@ -10,7 +10,6 @@
#include "chrome/browser/dom_ui/dom_ui.h"
#include "chrome/browser/download/download_manager.h"
-class DictionaryValue;
class Value;
// The handler for Javascript messages related to the "downloads" view,
@@ -73,10 +72,6 @@ class DownloadsDOMHandler : public DOMMessageHandler,
// Send the current list of downloads to the page.
void SendCurrentDownloads();
- // Creates a representation of a download in a format that the downloads
- // HTML page can understand.
- DictionaryValue* CreateDownloadItemValue(DownloadItem* download, int id);
-
// Clear all download items and their observers.
void ClearDownloadItems();
@@ -86,9 +81,6 @@ class DownloadsDOMHandler : public DOMMessageHandler,
// Return the download that is referred to in a given value.
DownloadItem* GetDownloadByValue(const Value* value);
- // Get the localized status text for an in-progress download.
- std::wstring GetProgressStatusText(DownloadItem* download);
-
// Current search text.
std::wstring search_text_;
diff --git a/chrome/browser/dom_ui/filebrowse_ui.cc b/chrome/browser/dom_ui/filebrowse_ui.cc
index 68dbd21..dfc5ed5 100644
--- a/chrome/browser/dom_ui/filebrowse_ui.cc
+++ b/chrome/browser/dom_ui/filebrowse_ui.cc
@@ -21,6 +21,8 @@
#include "chrome/browser/browser_window.h"
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/dom_ui/dom_ui_favicon_source.h"
+#include "chrome/browser/download/download_manager.h"
+#include "chrome/browser/download/download_util.h"
#include "chrome/browser/metrics/user_metrics.h"
#include "chrome/browser/net/url_fetcher.h"
#include "chrome/browser/history/history_types.h"
@@ -80,11 +82,16 @@ class FilebrowseHandler : public net::DirectoryLister::DirectoryListerDelegate,
public chromeos::MountLibrary::Observer,
#endif
public base::SupportsWeakPtr<FilebrowseHandler>,
- public URLFetcher::Delegate {
+ public URLFetcher::Delegate,
+ public DownloadManager::Observer,
+ public DownloadItem::Observer {
public:
FilebrowseHandler();
virtual ~FilebrowseHandler();
+ // Init work after Attach.
+ void Init();
+
// DirectoryLister::DirectoryListerDelegate methods:
virtual void OnListFile(const file_util::FileEnumerator::FindInfo& data);
virtual void OnListDone(int error);
@@ -99,6 +106,15 @@ class FilebrowseHandler : public net::DirectoryLister::DirectoryListerDelegate,
const std::string& path);
#endif
+ // DownloadItem::Observer interface
+ virtual void OnDownloadUpdated(DownloadItem* download);
+ virtual void OnDownloadFileCompleted(DownloadItem* download) { }
+ virtual void OnDownloadOpened(DownloadItem* download) { }
+
+ // DownloadManager::Observer interface
+ virtual void ModelChanged();
+ virtual void SetDownloads(std::vector<DownloadItem*>& downloads);
+
// Callback for the "getRoots" message.
void HandleGetRoots(const Value* value);
@@ -122,6 +138,11 @@ class FilebrowseHandler : public net::DirectoryLister::DirectoryListerDelegate,
// Callback for the "uploadToPicasaweb" message.
void UploadToPicasaweb(const Value* value);
+ // Callback for the "getDownloads" message.
+ void HandleGetDownloads(const Value* value);
+
+ void HandleCreateNewFolder(const Value* value);
+
void ReadInFile();
void FireUploadComplete();
@@ -129,6 +150,12 @@ class FilebrowseHandler : public net::DirectoryLister::DirectoryListerDelegate,
void OpenNewWindow(const Value* value, bool popup);
+ // Clear all download items and their observers.
+ void ClearDownloadItems();
+
+ // Send the current list of downloads to the page.
+ void SendCurrentDownloads();
+
scoped_ptr<ListValue> filelist_value_;
FilePath currentpath_;
Profile* profile_;
@@ -138,6 +165,10 @@ class FilebrowseHandler : public net::DirectoryLister::DirectoryListerDelegate,
TaskProxy* CurrentTask_;
scoped_refptr<net::DirectoryLister> lister_;
+ DownloadManager* download_manager_;
+ typedef std::vector<DownloadItem*> DownloadList;
+ DownloadList download_items_;
+
DISALLOW_COPY_AND_ASSIGN(FilebrowseHandler);
};
@@ -200,7 +231,8 @@ void FileBrowseUIHTMLSource::StartDataRequest(const std::string& path,
//
////////////////////////////////////////////////////////////////////////////////
FilebrowseHandler::FilebrowseHandler()
- : profile_(NULL) {
+ : profile_(NULL),
+ download_manager_(NULL) {
// TODO(dhg): Check to see if this is really necessary
#if defined(OS_CHROMEOS)
chromeos::MountLibrary* lib = chromeos::MountLibrary::Get();
@@ -218,6 +250,9 @@ FilebrowseHandler::~FilebrowseHandler() {
lister_->Cancel();
lister_->set_delegate(NULL);
}
+
+ ClearDownloadItems();
+ download_manager_->RemoveObserver(this);
}
DOMMessageHandler* FilebrowseHandler::Attach(DOMUI* dom_ui) {
@@ -229,9 +264,15 @@ DOMMessageHandler* FilebrowseHandler::Attach(DOMUI* dom_ui) {
&ChromeURLDataManager::AddDataSource,
make_scoped_refptr(new DOMUIFavIconSource(dom_ui->GetProfile()))));
profile_ = dom_ui->GetProfile();
+
return DOMMessageHandler::Attach(dom_ui);
}
+void FilebrowseHandler::Init() {
+ download_manager_ = profile_->GetOriginalProfile()->GetDownloadManager();
+ download_manager_->AddObserver(this);
+}
+
void FilebrowseHandler::RegisterMessages() {
dom_ui_->RegisterMessageCallback("getRoots",
NewCallback(this, &FilebrowseHandler::HandleGetRoots));
@@ -245,6 +286,10 @@ void FilebrowseHandler::RegisterMessages() {
NewCallback(this, &FilebrowseHandler::OpenNewFullWindow));
dom_ui_->RegisterMessageCallback("uploadToPicasaweb",
NewCallback(this, &FilebrowseHandler::UploadToPicasaweb));
+ dom_ui_->RegisterMessageCallback("getDownloads",
+ NewCallback(this, &FilebrowseHandler::HandleGetDownloads));
+ dom_ui_->RegisterMessageCallback("createNewFolder",
+ NewCallback(this, &FilebrowseHandler::HandleCreateNewFolder));
}
void FilebrowseHandler::FireUploadComplete() {
@@ -345,6 +390,29 @@ void FilebrowseHandler::HandleGetRoots(const Value* value) {
info_value, results_value);
}
+void FilebrowseHandler::HandleCreateNewFolder(const Value* value) {
+#if defined(OS_CHROMEOS)
+ if (value && value->GetType() == Value::TYPE_LIST) {
+ const ListValue* list_value = static_cast<const ListValue*>(value);
+ std::string path;
+
+ // Get path string.
+ if (list_value->GetString(0, &path)) {
+
+ FilePath currentpath;
+ currentpath = FilePath(path);
+
+ if (!file_util::CreateDirectory(currentpath)) {
+ LOG(ERROR) << "unable to create directory";
+ }
+ } else {
+ LOG(ERROR) << "Unable to get string";
+ return;
+ }
+ }
+#endif
+}
+
void FilebrowseHandler::OpenNewFullWindow(const Value* value) {
OpenNewWindow(value, false);
}
@@ -548,15 +616,76 @@ void FilebrowseHandler::OnListDone(int error) {
void FilebrowseHandler::HandleGetMetadata(const Value* value) {
}
+void FilebrowseHandler::HandleGetDownloads(const Value* value) {
+ ModelChanged();
+}
+
+void FilebrowseHandler::ModelChanged() {
+ ClearDownloadItems();
+ download_manager_->GetDownloads(this, std::wstring());
+}
+
+void FilebrowseHandler::SetDownloads(std::vector<DownloadItem*>& downloads) {
+ ClearDownloadItems();
+
+ // Scan for any in progress downloads and add ourself to them as an observer.
+ for (DownloadList::iterator it = downloads.begin();
+ it != downloads.end(); ++it) {
+ DownloadItem* download = *it;
+ // We want to know what happens as the download progresses and be notified
+ // when the user validates the dangerous download.
+ if (download->state() == DownloadItem::IN_PROGRESS ||
+ download->safety_state() == DownloadItem::DANGEROUS) {
+ download->AddObserver(this);
+ download_items_.push_back(download);
+ }
+ }
+
+ SendCurrentDownloads();
+}
+
+void FilebrowseHandler::OnDownloadUpdated(DownloadItem* download) {
+ DownloadList::iterator it = find(download_items_.begin(),
+ download_items_.end(),
+ download);
+ if (it == download_items_.end())
+ return;
+ const int id = static_cast<int>(it - download_items_.begin());
+
+ ListValue results_value;
+ results_value.Append(download_util::CreateDownloadItemValue(download, id));
+ dom_ui_->CallJavascriptFunction(L"downloadUpdated", results_value);
+}
+
+void FilebrowseHandler::ClearDownloadItems() {
+ for (DownloadList::iterator it = download_items_.begin();
+ it != download_items_.end(); ++it) {
+ (*it)->RemoveObserver(this);
+ }
+ download_items_.clear();
+}
+
+void FilebrowseHandler::SendCurrentDownloads() {
+ ListValue results_value;
+ for (DownloadList::iterator it = download_items_.begin();
+ it != download_items_.end(); ++it) {
+ int index = static_cast<int>(it - download_items_.begin());
+ results_value.Append(download_util::CreateDownloadItemValue(*it, index));
+ }
+
+ dom_ui_->CallJavascriptFunction(L"downloadsList", results_value);
+}
+
////////////////////////////////////////////////////////////////////////////////
//
// FileBrowseUIContents
//
////////////////////////////////////////////////////////////////////////////////
-FileBrowseUI::FileBrowseUI(TabContents* contents) : DOMUI(contents) {
+FileBrowseUI::FileBrowseUI(TabContents* contents) : HtmlDialogUI(contents) {
FilebrowseHandler* handler = new FilebrowseHandler();
AddMessageHandler((handler)->Attach(this));
+ handler->Init();
FileBrowseUIHTMLSource* html_source = new FileBrowseUIHTMLSource();
// Set up the chrome://filebrowse/ source.
diff --git a/chrome/browser/dom_ui/filebrowse_ui.h b/chrome/browser/dom_ui/filebrowse_ui.h
index 6da8916..5f45fe4 100644
--- a/chrome/browser/dom_ui/filebrowse_ui.h
+++ b/chrome/browser/dom_ui/filebrowse_ui.h
@@ -9,14 +9,14 @@
#include "base/scoped_ptr.h"
#include "base/values.h"
#include "chrome/browser/dom_ui/chrome_url_data_manager.h"
-#include "chrome/browser/dom_ui/dom_ui.h"
+#include "chrome/browser/dom_ui/html_dialog_ui.h"
#include "chrome/browser/history/history.h"
#include "net/base/directory_lister.h"
class GURL;
-class FileBrowseUI : public DOMUI {
+class FileBrowseUI : public HtmlDialogUI {
public:
explicit FileBrowseUI(TabContents* contents);
diff --git a/chrome/browser/download/download_util.cc b/chrome/browser/download/download_util.cc
index 7662bc7..711c24c 100644
--- a/chrome/browser/download/download_util.cc
+++ b/chrome/browser/download/download_util.cc
@@ -13,11 +13,14 @@
#include "app/resource_bundle.h"
#include "base/file_util.h"
#include "base/gfx/rect.h"
+#include "base/i18n/time_formatting.h"
#include "base/string_util.h"
+#include "base/values.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/download/download_item_model.h"
#include "chrome/browser/download/download_manager.h"
#include "chrome/common/extensions/extension.h"
+#include "chrome/common/time_format.h"
#include "grit/generated_resources.h"
#include "grit/locale_settings.h"
#include "grit/theme_resources.h"
@@ -295,4 +298,106 @@ void DragDownload(const DownloadItem* download,
}
#endif // OS_LINUX
+DictionaryValue* CreateDownloadItemValue(DownloadItem* download, int id) {
+ DictionaryValue* file_value = new DictionaryValue();
+
+ file_value->SetInteger(L"started",
+ static_cast<int>(download->start_time().ToTimeT()));
+ file_value->SetString(L"since_string",
+ TimeFormat::RelativeDate(download->start_time(), NULL));
+ file_value->SetString(L"date_string",
+ base::TimeFormatShortDate(download->start_time()));
+ file_value->SetInteger(L"id", id);
+ file_value->SetString(L"file_path", download->full_path().ToWStringHack());
+ // Keep file names as LTR.
+ std::wstring file_name = download->GetFileName().ToWStringHack();
+ if (l10n_util::GetTextDirection() == l10n_util::RIGHT_TO_LEFT)
+ l10n_util::WrapStringWithLTRFormatting(&file_name);
+ file_value->SetString(L"file_name", file_name);
+ file_value->SetString(L"url", download->url().spec());
+
+ if (download->state() == DownloadItem::IN_PROGRESS) {
+ if (download->safety_state() == DownloadItem::DANGEROUS) {
+ file_value->SetString(L"state", L"DANGEROUS");
+ } else if (download->is_paused()) {
+ file_value->SetString(L"state", L"PAUSED");
+ } else {
+ file_value->SetString(L"state", L"IN_PROGRESS");
+ }
+
+ file_value->SetString(L"progress_status_text",
+ GetProgressStatusText(download));
+
+ file_value->SetInteger(L"percent",
+ static_cast<int>(download->PercentComplete()));
+ file_value->SetInteger(L"received",
+ static_cast<int>(download->received_bytes()));
+ } else if (download->state() == DownloadItem::CANCELLED) {
+ file_value->SetString(L"state", L"CANCELLED");
+ } else if (download->state() == DownloadItem::COMPLETE) {
+ if (download->safety_state() == DownloadItem::DANGEROUS) {
+ file_value->SetString(L"state", L"DANGEROUS");
+ } else {
+ file_value->SetString(L"state", L"COMPLETE");
+ }
+ }
+
+ file_value->SetInteger(L"total",
+ static_cast<int>(download->total_bytes()));
+
+ return file_value;
+}
+
+std::wstring GetProgressStatusText(DownloadItem* download) {
+ int64 total = download->total_bytes();
+ int64 size = download->received_bytes();
+ DataUnits amount_units = GetByteDisplayUnits(size);
+ std::wstring received_size = FormatBytes(size, amount_units, true);
+ std::wstring amount = received_size;
+
+ // Adjust both strings for the locale direction since we don't yet know which
+ // string we'll end up using for constructing the final progress string.
+ std::wstring amount_localized;
+ if (l10n_util::AdjustStringForLocaleDirection(amount, &amount_localized)) {
+ amount.assign(amount_localized);
+ received_size.assign(amount_localized);
+ }
+
+ if (total) {
+ amount_units = GetByteDisplayUnits(total);
+ std::wstring total_text = FormatBytes(total, amount_units, true);
+ std::wstring total_text_localized;
+ if (l10n_util::AdjustStringForLocaleDirection(total_text,
+ &total_text_localized))
+ total_text.assign(total_text_localized);
+
+ amount = l10n_util::GetStringF(IDS_DOWNLOAD_TAB_PROGRESS_SIZE,
+ received_size,
+ total_text);
+ } else {
+ amount.assign(received_size);
+ }
+ amount_units = GetByteDisplayUnits(download->CurrentSpeed());
+ std::wstring speed_text = FormatSpeed(download->CurrentSpeed(),
+ amount_units, true);
+ std::wstring speed_text_localized;
+ if (l10n_util::AdjustStringForLocaleDirection(speed_text,
+ &speed_text_localized))
+ speed_text.assign(speed_text_localized);
+
+ base::TimeDelta remaining;
+ std::wstring time_remaining;
+ if (download->is_paused())
+ time_remaining = l10n_util::GetString(IDS_DOWNLOAD_PROGRESS_PAUSED);
+ else if (download->TimeRemaining(&remaining))
+ time_remaining = TimeFormat::TimeRemaining(remaining);
+
+ if (time_remaining.empty()) {
+ return l10n_util::GetStringF(IDS_DOWNLOAD_TAB_PROGRESS_STATUS_TIME_UNKNOWN,
+ speed_text, amount);
+ }
+ return l10n_util::GetStringF(IDS_DOWNLOAD_TAB_PROGRESS_STATUS, speed_text,
+ amount, time_remaining);
+}
+
} // namespace download_util
diff --git a/chrome/browser/download/download_util.h b/chrome/browser/download/download_util.h
index 7636b55..93114fe 100644
--- a/chrome/browser/download/download_util.h
+++ b/chrome/browser/download/download_util.h
@@ -23,6 +23,7 @@ class Canvas;
}
class BaseDownloadItemModel;
+class DictionaryValue;
class DownloadItem;
class SkBitmap;
@@ -134,6 +135,15 @@ void DragDownload(const DownloadItem* download,
// Determine if the specified extension is an executable extension.
bool IsExecutableExtension(const std::string& extension);
+// Helpers ---------------------------------------------------------------------
+
+// Creates a representation of a download in a format that the downloads
+// HTML page can understand.
+DictionaryValue* CreateDownloadItemValue(DownloadItem* download, int id);
+
+// Get the localized status text for an in-progress download.
+std::wstring GetProgressStatusText(DownloadItem* download);
+
} // namespace download_util
#endif // CHROME_BROWSER_DOWNLOAD_DOWNLOAD_UTIL_H_
diff --git a/chrome/browser/resources/filebrowse.html b/chrome/browser/resources/filebrowse.html
index 4189d68..ab1dcb3 100644
--- a/chrome/browser/resources/filebrowse.html
+++ b/chrome/browser/resources/filebrowse.html
@@ -34,11 +34,12 @@ div.header {
.rowlink {
height: 100%;
width: 90%;
+ cursor: pointer;
}
a.iconlink {
display: block;
- font-family: helvetica;
+/* font-family: helvetica; */
font-weight: bold;
font-size: 11px;
color: white;
@@ -117,7 +118,7 @@ li.filebrowserow div.icon {
width: 10px;
}
-.uploadicon {
+.uploaicon {
background: url('../../app/theme/filebrowse_upload.png');
position: absolute;
right: 0;
@@ -157,17 +158,36 @@ li.filebrowserow {
padding: 8px 5px 5px 54px;
/* overflow: hidden; */
font-size:.8em;
- font-family: helvetica;
+/* font-family: helvetica; */
position: relative;
}
+.downloadstatus {
+ width: 100%;
+ font-size:.6em;
+}
+
+li.filebrowserow:hover {
+ background: #ebeff9;
+}
+
li.filebrowserow span.name {
margin-top: 10px;
margin-left: -22px;
position: relative;
+}
+
+li.filebrowserow span.namelink {
+ margin-top: 10px;
+ margin-left: -22px;
+ position: relative;
text-decoration:underline;
}
+.selected {
+ background-color: #b1c8f2;
+}
+
div.title {
text-align: right;
position: relative;
@@ -188,6 +208,7 @@ div.controlbutton {
padding-bottom: 4px;
padding-right: 7px;
height: 15px;
+ cursor: pointer;
}
div.column {
@@ -257,6 +278,78 @@ div.scanningcontainer {
height: 100%;
}
+div.filebutton {
+ width: 70px;
+ height: 20px;
+ cursor: pointer;
+ padding-top:2px;
+ border:1px solid #abb6ce;
+ background-color: #f5f7fc;
+ -webkit-border-radius: 5px;
+ text-align: center;
+ font-size:.8em;
+}
+
+.filenameprompt {
+ top: 10px;
+ left: 13px;
+ font-size:.8em;
+ position: absolute;
+}
+
+.filename {
+ left: 80px;
+ top:5px;
+ right:10px;
+ font-size:.8em;
+ position: absolute;
+}
+
+div.openbutton {
+ bottom: 5px;
+ left: 10px;
+ position: absolute;
+}
+
+div.cancelbutton {
+ bottom: 5px;
+ left: 90px;
+ position: absolute;
+}
+
+div.newfolderbutton {
+ bottom: 5px;
+ right: 10px;
+ position: absolute;
+}
+
+div.opencontainer {
+ width: 100%;
+ bottom: 0;
+ left:0;
+ height: 30px;
+ position: absolute;
+ background-image: -webkit-gradient(linear,
+ 0% 0%,
+ 0% 90%,
+ from(rgb(239, 242, 249)),
+ to(rgba(201, 212, 245, 1)));
+}
+
+div.savecontainer {
+ width: 100%;
+ bottom: 0;
+ left:0;
+ height: 60px;
+ position: absolute;
+ background-image: -webkit-gradient(linear,
+ 0% 0%,
+ 0% 90%,
+ from(rgb(239, 242, 249)),
+ to(rgba(201, 212, 245, 1)));
+}
+
+
div.container {
top: 0;
position: absolute;
@@ -265,6 +358,22 @@ div.container {
bottom: 0;
}
+div.containerwithopenbuttons {
+ top: 0;
+ position: absolute;
+ width: 100%;
+ left: 0;
+ bottom: 30px;
+}
+
+div.containerwithsavebuttons {
+ top: 0;
+ position: absolute;
+ width: 100%;
+ left: 0;
+ bottom: 60px;
+}
+
div.fullcontainer {
top: 0px;
position: absolute;
@@ -337,7 +446,7 @@ a:hover {
}
</style>
-<script src="local_strings.js"></script>
+<script src='local_strings.js'></script>
<script>
@@ -351,11 +460,16 @@ var currentNode = -1;
var foundImages = [];
var currentImageMenu = '';
var inFullMode = false;
+var inSelectMode = false;
var videoPlaybackElement = null;
var photoPreviewElement = null;
var numColumns = 0;
var divArray = [];
var rootsDiv = null;
+var currentlySelectedItems = new Array();
+var currentlySelectedPaths = new Array();
+var multiSelect = false;
+var inSaveMode = false;
function goBackInList() {
if (currentNode > 0) {
@@ -389,7 +503,7 @@ function animateScrollRight() {
// it stops growing, so clear it out and no more timeouts.
if (lastScrollLeft != main.scrollLeft) {
lastScrollLeft = main.scrollLeft;
- setTimeout("animateScrollRight()", 15);
+ setTimeout('animateScrollRight()', 15);
} else {
lastScrollLeft = 0;
}
@@ -516,14 +630,242 @@ function setUpForScanning() {
main.textContent = 'Scanning Device...';
};
+function dialogOkClick() {
+ if (!multiSelect) {
+ chrome.send('DialogClose', [JSON.stringify({'path' : currentlySelectedPaths[0]})]);
+ } else {
+ chrome.send('DialogClose', [JSON.stringify({'path' : currentlySelectedPaths})]);
+ }
+};
+
+function dialogCancelClick() {
+ chrome.send('DialogClose', ['']);
+};
+
+function dialogSaveClick() {
+ var filenameInput = $('filename');
+ var filename = filenameInput.value;
+ var currentPath = pathArray[pathArray.length - 1];
+ currentPath += '/';
+ currentPath += filename;
+ chrome.send('DialogClose', [JSON.stringify({'path' : currentPath})]);
+};
+
+
+function createNewFormItem(initialName, isDirectory, id, blurcallback, keypresscallback) {
+ var element = document.createElement('li');
+ element.className = 'filebrowserow';
+ element.id = 'listItem' + elementIdCounter;
+ elementIdCounter++;
+
+ var link;
+ link = document.createElement('div');
+ link.className = 'rowlink';
+
+ var icon = document.createElement('div');
+ icon.className = getClassForPath('', isDirectory);
+ link.appendChild(icon);
+ var input = document.createElement('input');
+ input.className = 'name';
+ input.id = 'newfoldername';
+ input.onblur = blurcallback;
+ input.onkeypress = keypresscallback;
+ input.focus();
+
+ input.value = initialName;
+ link.appendChild(input);
+
+ element.appendChild(link);
+ if (isDirectory) {
+ var rightarrow = document.createElement('div');
+ rightarrow.align = 'right';
+ rightarrow.innerHTML = '&raquo;';
+ rightarrow.className = 'rightarrow';
+ element.appendChild(rightarrow);
+ }
+
+ return element;
+};
+
+function createFolder(elementId) {
+ var currentPath = pathArray[pathArray.length - 1];
+ var element = $('newfoldername');
+ if (element) {
+ element.id = '';
+ var filename = element.value;
+ currentPath += '/';
+ currentPath += filename;
+ var parent = element.parentNode;
+ parent.removeChild(element);
+ listitem = parent.parentNode;
+
+ parent.onclick = new Function(getFunctionForItem(currentPath, listitem.id, true));
+
+ var span = document.createElement('span');
+ if (inSelectMode) {
+ span.className = 'name';
+ } else {
+ span.className = 'namelink';
+ }
+ span.textContent = filename;
+ parent.appendChild(span);
+
+ chrome.send('createNewFolder', [currentPath]);
+ }
+ return false;
+};
+
+function createFolderTyping(elementId) {
+ if (window.event.keyCode == 13) {
+ createFolder(elementId);
+ }
+};
+
+function getDirectoryForPath(path) {
+ var index = path.lastIndexOf('/');
+ if (index == -1) {
+ return path;
+ }
+ return path.substr(path, index);
+};
+
+function downloadsList(results) {
+// alert(JSON.stringify(results));
+// We might want to do something with this... For now assume that the update will get the necessary info
+};
+
+function downloadUpdated(results) {
+ for (var x = 0; x < results.length; x++) {
+ var element = $(results[x].file_path);
+ if (element) {
+ if (results[x].percent < 100) {
+ var progressDiv = null;
+ for (var y = 0; y < element.children.length; y++) {
+ if (element.children[y].className == 'downloadstatus') {
+ progressDiv = element.children[y];
+ break;
+ }
+ }
+ if (progressDiv == null) {
+ element.className = 'filebrowserow downloading';
+ var progressDiv = document.createElement('div');
+ progressDiv.className = 'downloadstatus';
+ element.appendChild(progressDiv);
+ }
+ progressDiv.textContent = results[x].progress_status_text;
+
+ } else {
+ for (var x = 0; x < element.children.length; x++) {
+ if (element.children[x].className == 'downloadstatus') {
+ var child = element.children[x];
+ element.removeChild(child);
+ }
+ }
+ element.className = 'filebrowserow';
+ }
+ } else {
+ // TODO(dhg):Get the new file
+ }
+ }
+};
+
+function dialogNewFolderClick() {
+
+
+ var main = divArray[divArray.length - 1];
+ var list;
+ for (var x = 0; x < main.childNodes.length; x++ ) {
+ if (main.childNodes[x].className == 'columnlist') {
+ list = main.childNodes[x].firstChild;
+ break;
+ }
+ }
+ var id = 'listItem' + elementIdCounter;
+ elementIdCounter++;
+ var element = createNewFormItem('',
+ true,
+ id,
+ new Function('createFolder("' + id + '")'),
+ new Function('createFolderTyping("' + id + '")'));
+ list.appendChild(element);
+ element.scrollIntoView();
+};
+
///////////////////////////////////////////////////////////////////////////////
// Document Functions:
/**
* Window onload handler, sets up the page.
*/
function load() {
- if(document.documentElement.clientWidth <= 400) {
+ if(document.documentElement.clientWidth <= 600) {
inFullMode = false;
+ if (chrome.dialogArguments) {
+ var args = JSON.parse(chrome.dialogArguments);
+ if (args.type == 'open') {
+ multiSelect = false;
+ } else if (args.type == 'save') {
+ inSaveMode = true;
+ } else if (args.type == 'open_multiple') {
+ multiSelect = true;
+ } else {
+ alert ('got unknown type');
+ }
+ inSelectMode = true;
+ if (inSaveMode) {
+ var main = $('main');
+ main.className = 'containerwithsavebuttons';
+ var savemenu = document.createElement('div');
+ savemenu.className = 'savecontainer';
+
+ var savebutton = document.createElement('div');
+ savebutton.className = 'filebutton openbutton';
+ savebutton.onclick = dialogSaveClick;
+ savebutton.textContent = 'Save';
+ savemenu.appendChild(savebutton);
+
+ var cancelbutton = document.createElement('div');
+ cancelbutton.className = 'filebutton cancelbutton';
+ savemenu.appendChild(cancelbutton);
+ cancelbutton.textContent = 'Cancel';
+ cancelbutton.onclick = dialogCancelClick;
+
+ var filenameprompt = document.createElement('div');
+ filenameprompt.className = 'filenameprompt';
+ filenameprompt.textContent = 'File name:';
+ savemenu.appendChild(filenameprompt);
+
+ var filename = document.createElement('input');
+ filename.className = 'filename';
+ filename.id = 'filename';
+ filename.value = args.current_file;
+ savemenu.appendChild(filename);
+
+ var newfolderbutton = document.createElement('div');
+ newfolderbutton.className = 'filebutton newfolderbutton';
+ newfolderbutton.textContent = 'New Folder';
+ newfolderbutton.onclick = dialogNewFolderClick;
+ savemenu.appendChild(newfolderbutton);
+
+ document.body.appendChild(savemenu);
+
+ } else {
+ var main = $('main');
+ main.className = 'containerwithopenbuttons';
+ var openmenu = document.createElement('div');
+ openmenu.className = 'opencontainer';
+ var openbutton = document.createElement('div');
+ openbutton.className = 'filebutton openbutton';
+ var cancelbutton = document.createElement('div');
+ cancelbutton.className = 'filebutton cancelbutton';
+ openmenu.appendChild(openbutton);
+ openbutton.onclick = dialogOkClick;
+ openmenu.appendChild(cancelbutton);
+ cancelbutton.onclick = dialogCancelClick;
+ openbutton.textContent = 'Open';
+ cancelbutton.textContent = 'Cancel';
+ document.body.appendChild(openmenu);
+ }
+ }
} else {
var main = $('main');
main.className = 'fullcontainer';
@@ -553,6 +895,7 @@ function load() {
pathArray.push('roots');
getDataForPath('roots');
}
+ chrome.send("getDownloads", []);
};
function jumpToNode(nodeNumber) {
@@ -669,35 +1012,77 @@ function uploadComplete(result) {
}
};
+function findInArray(arr, element) {
+ for (var x = 0; x < arr.length; x++) {
+ if (arr[x] == element) {
+ return x;
+ }
+ }
+ return -1;
+};
+
+function selectItem(elementid, path) {
+ var element = $(elementid);
+ var index;
+ if ((index = findInArray(currentlySelectedItems, element)) != -1) {
+ // the user must want to toggle
+ currentlySelectedItems.splice(index, 1);
+ element.classname = 'filebrowserow';
+ index = findInArray(currentlySelectedPaths, path);
+ currentlySelectedPaths.splice(index, 1);
+ } else {
+ if (!multiSelect) {
+ // clear out previous selected elements
+ for (var x = 0; x < currentlySelectedItems.length; x++) {
+ currentlySelectedItems[x].className = 'filebrowserow';
+ }
+ }
+ element.className = 'selected filebrowserow';
+ currentlySelectedItems.push(element);
+ currentlySelectedPaths.push(path);
+ }
+};
+
// TODO(dhg): Do not use javascript: href, use onclick instead
-function createHrefForItem(path, isDirectory) {
+function getFunctionForItem(path, id, isDirectory) {
if (isDirectory) {
- return 'javascript:descend("' + path + '", ' + currentNode + ');';
+ return 'descend("' + path + '", ' + currentNode + ')';
+ } if(inSelectMode) {
+ return 'selectItem("' + id + '", "' + path + '")';
} if (pathIsAudioFile(path)) {
- return 'javascript:playMediaFile("' + path + '");';
+ return 'playMediaFile("' + path + '")';
} if (pathIsVideoFile(path)) {
- return 'javascript:playMediaFile("' + path + '");';
+ return 'playMediaFile("' + path + '")';
} if (pathIsImageFile(path)) {
- return 'javascript:showImage("' + path + '");';
+ return 'showImage("' + path + '")';
} else {
return '';
}
};
+var elementIdCounter = 0;
+
function createNewItem(title, path, isDirectory) {
var element = document.createElement('li');
element.className = 'filebrowserow';
-
- var link = document.createElement('a');
+ /*element.id = 'listItem' + elementIdCounter;*/
+ element.id = path;
+ elementIdCounter++;
+ var link;
+ link = document.createElement('div');
+ link.onclick = new Function(getFunctionForItem(path, element.id, isDirectory));
link.className = 'rowlink';
- link.href = createHrefForItem(path, isDirectory);
var icon = document.createElement('div');
icon.className = getClassForPath(path, isDirectory);
link.appendChild(icon);
var span = document.createElement('span');
- span.className = 'name';
+ if (inSelectMode) {
+ span.className = 'name';
+ } else {
+ span.className = 'namelink';
+ }
span.textContent = title;
link.appendChild(span);
@@ -782,7 +1167,7 @@ function createNewList(title, results, main, path) {
};
</script>
-<body onload="load();" onclick='clearImageMenus()'>
+<body onload='load();' onclick='clearImageMenus()' onselectstart='return false'>
<div id='header' class=''>
<div id='back' class='backbutton controlbutton' onclick='goBackInList();return false;'>
<img src="../../app/theme/filebrowse_back.png" width='100%' height='100%'>
diff --git a/chrome/browser/views/dialog_stubs_gtk.cc b/chrome/browser/views/dialog_stubs_gtk.cc
index d9a0f0c..9d8c7d2 100644
--- a/chrome/browser/views/dialog_stubs_gtk.cc
+++ b/chrome/browser/views/dialog_stubs_gtk.cc
@@ -45,12 +45,6 @@ void ShowBookmarkManagerView(Profile* profile) {
BookmarkManagerGtk::Show(profile);
}
-void ShowHtmlDialogView(gfx::NativeWindow parent, Browser* browser,
- HtmlDialogUIDelegate* delegate) {
- // Hasn't been implemented yet on linux.
- NOTIMPLEMENTED();
-}
-
void ShowPasswordsExceptionsWindowView(Profile* profile) {
ShowPasswordsExceptionsWindow(profile);
}
diff --git a/chrome/browser/views/dom_view.cc b/chrome/browser/views/dom_view.cc
index cd3dc8f..29aaf19 100644
--- a/chrome/browser/views/dom_view.cc
+++ b/chrome/browser/views/dom_view.cc
@@ -7,7 +7,7 @@
#include "chrome/browser/tab_contents/tab_contents.h"
#include "views/focus/focus_manager.h"
-DOMView::DOMView() : initialized_(false), tab_contents_(NULL) {
+DOMView::DOMView() : tab_contents_(NULL), initialized_(false) {
SetFocusable(true);
}
diff --git a/chrome/browser/views/select_file_dialog.cc b/chrome/browser/views/select_file_dialog.cc
new file mode 100644
index 0000000..375e224
--- /dev/null
+++ b/chrome/browser/views/select_file_dialog.cc
@@ -0,0 +1,390 @@
+// Copyright (c) 2010 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/shell_dialogs.h"
+
+#include "app/l10n_util.h"
+#include "base/file_path.h"
+#include "base/json/json_reader.h"
+#include "base/scoped_ptr.h"
+#include "base/string_util.h"
+#include "base/utf_string_conversions.h"
+#include "base/values.h"
+#include "chrome/browser/browser.h"
+#include "chrome/browser/browser_list.h"
+#include "chrome/browser/chrome_thread.h"
+#include "chrome/browser/dom_ui/html_dialog_ui.h"
+#include "chrome/browser/shell_dialogs.h"
+#include "chrome/common/url_constants.h"
+#include "grit/generated_resources.h"
+
+namespace {
+
+static const wchar_t* kKeyNamePath = L"path";
+
+}; // namespace
+
+// Implementation of SelectFileDialog that shows an UI for choosing a file
+// or folder using FileBrowseUI.
+class SelectFileDialogImpl : public SelectFileDialog {
+ public:
+ explicit SelectFileDialogImpl(Listener* listener);
+
+ // BaseShellDialog implementation.
+ virtual bool IsRunning(gfx::NativeWindow parent_window) const;
+ virtual void ListenerDestroyed();
+
+ // SelectFileDialog implementation.
+ // |params| is user data we pass back via the Listener interface.
+ virtual void SelectFile(Type type,
+ const string16& title,
+ const FilePath& default_path,
+ const FileTypeInfo* file_types,
+ int file_type_index,
+ const FilePath::StringType& default_extension,
+ gfx::NativeWindow owning_window,
+ void* params);
+
+ private:
+ virtual ~SelectFileDialogImpl();
+
+ class FileBrowseDelegate : public HtmlDialogUIDelegate {
+ public:
+ FileBrowseDelegate(SelectFileDialogImpl* owner,
+ Type type,
+ const std::wstring& title,
+ const FilePath& default_path,
+ const FileTypeInfo* file_types,
+ int file_type_index,
+ const FilePath::StringType& default_extension,
+ gfx::NativeWindow parent,
+ void* params);
+
+ // Owner of this FileBrowseDelegate.
+ SelectFileDialogImpl* owner_;
+
+ // Parent window.
+ gfx::NativeWindow parent_;
+
+ // The type of dialog we are showing the user.
+ Type type_;
+
+ // The dialog title.
+ std::wstring title_;
+
+ // Default path of the file dialog.
+ FilePath default_path_;
+
+ // The file filters.
+ FileTypeInfo file_types_;
+
+ // The index of the default selected file filter.
+ // Note: This starts from 1, not 0.
+ size_t file_type_index_;
+
+ // Default extension to be added to file if user does not type one.
+ FilePath::StringType default_extension_;
+
+ // Associated user data.
+ void* params_;
+
+ private:
+ ~FileBrowseDelegate();
+
+ // Overridden from HtmlDialogUI::Delegate:
+ virtual bool IsDialogModal() const;
+ virtual std::wstring GetDialogTitle() const;
+ virtual GURL GetDialogContentURL() const;
+ virtual void GetDOMMessageHandlers(
+ std::vector<DOMMessageHandler*>* handlers) const;
+ virtual void GetDialogSize(gfx::Size* size) const;
+ virtual std::string GetDialogArgs() const;
+ virtual void OnDialogClosed(const std::string& json_retval);
+
+ DISALLOW_COPY_AND_ASSIGN(FileBrowseDelegate);
+ };
+
+ // Notification from FileBrowseDelegate when file browse UI is dismissed.
+ void OnDialogClosed(FileBrowseDelegate* delegate, const std::string& json);
+
+ // The set of all parent windows for which we are currently running dialogs.
+ std::set<gfx::NativeWindow> parents_;
+
+ // The set of all FileBrowseDelegate that we are currently running.
+ std::set<FileBrowseDelegate*> delegates_;
+
+ // The listener to be notified of selection completion.
+ Listener* listener_;
+
+ DISALLOW_COPY_AND_ASSIGN(SelectFileDialogImpl);
+};
+
+// static
+SelectFileDialog* SelectFileDialog::Create(Listener* listener) {
+ DCHECK(!ChromeThread::CurrentlyOn(ChromeThread::IO));
+ DCHECK(!ChromeThread::CurrentlyOn(ChromeThread::FILE));
+ return new SelectFileDialogImpl(listener);
+}
+
+SelectFileDialogImpl::SelectFileDialogImpl(Listener* listener)
+ : listener_(listener) {
+}
+
+SelectFileDialogImpl::~SelectFileDialogImpl() {
+ // All dialogs should be dismissed by now.
+ DCHECK(parents_.empty() && delegates_.empty());
+}
+
+bool SelectFileDialogImpl::IsRunning(gfx::NativeWindow parent_window) const {
+ return parent_window && parents_.find(parent_window) != parents_.end();
+}
+
+void SelectFileDialogImpl::ListenerDestroyed() {
+ listener_ = NULL;
+}
+
+void SelectFileDialogImpl::SelectFile(
+ Type type,
+ const string16& title,
+ const FilePath& default_path,
+ const FileTypeInfo* file_types,
+ int file_type_index,
+ const FilePath::StringType& default_extension,
+ gfx::NativeWindow owning_window,
+ void* params) {
+ std::wstring title_string;
+ if (title.empty()) {
+ int string_id;
+ switch (type) {
+ case SELECT_FOLDER:
+ string_id = IDS_SELECT_FOLDER_DIALOG_TITLE;
+ break;
+ case SELECT_OPEN_FILE:
+ case SELECT_OPEN_MULTI_FILE:
+ string_id = IDS_OPEN_FILE_DIALOG_TITLE;
+ break;
+ case SELECT_SAVEAS_FILE:
+ string_id = IDS_SAVE_AS_DIALOG_TITLE;
+ break;
+ default:
+ NOTREACHED();
+ return;
+ }
+ title_string = l10n_util::GetString(string_id);
+ } else {
+ title_string = UTF16ToWide(title);
+ }
+
+ if (owning_window)
+ parents_.insert(owning_window);
+
+ FileBrowseDelegate* file_browse_delegate = new FileBrowseDelegate(this,
+ type, title_string, default_path, file_types, file_type_index,
+ default_extension, owning_window, params);
+ delegates_.insert(file_browse_delegate);
+
+ Browser* browser = BrowserList::GetLastActive();
+ DCHECK(browser);
+ browser->BrowserShowHtmlDialog(file_browse_delegate, owning_window);
+}
+
+void SelectFileDialogImpl::OnDialogClosed(FileBrowseDelegate* delegate,
+ const std::string& json) {
+ // Nothing to do if listener_ is gone.
+
+ if (!listener_)
+ return;
+
+ bool notification_fired = false;
+
+ if (!json.empty()) {
+ scoped_ptr<Value> value(base::JSONReader::Read(json, false));
+ if (!value.get() || !value->IsType(Value::TYPE_DICTIONARY)) {
+ // Bad json value returned.
+ NOTREACHED();
+ } else {
+ const DictionaryValue* dict = static_cast<DictionaryValue*>(value.get());
+ if (delegate->type_ == SELECT_OPEN_FILE ||
+ delegate->type_ == SELECT_SAVEAS_FILE ||
+ delegate->type_ == SELECT_FOLDER) {
+ std::wstring path_string;
+ if (dict->HasKey(kKeyNamePath) &&
+ dict->GetString(kKeyNamePath, &path_string)) {
+ FilePath path = FilePath::FromWStringHack(path_string);
+
+ listener_->FileSelected(path, 0, delegate->params_);
+ notification_fired = true;
+ }
+ } else if (delegate->type_ == SELECT_OPEN_MULTI_FILE) {
+ ListValue* paths_value = NULL;
+ if (dict->HasKey(kKeyNamePath) &&
+ dict->GetList(kKeyNamePath, &paths_value) &&
+ paths_value) {
+ std::vector<FilePath> paths;
+ paths.reserve(paths_value->GetSize());
+ for (size_t i = 0; i < paths_value->GetSize(); ++i) {
+ std::wstring path_string;
+ if (paths_value->GetString(i, &path_string) &&
+ !path_string.empty()) {
+ paths.push_back(FilePath::FromWStringHack(path_string));
+ }
+ }
+
+ listener_->MultiFilesSelected(paths, delegate->params_);
+ notification_fired = true;
+ }
+ } else {
+ NOTREACHED();
+ }
+ }
+ }
+
+ // Always notify listener when dialog is dismissed.
+ if (!notification_fired)
+ listener_->FileSelectionCanceled(delegate->params_);
+
+ parents_.erase(delegate->parent_);
+ delegates_.erase(delegate);
+}
+
+SelectFileDialogImpl::FileBrowseDelegate::FileBrowseDelegate(
+ SelectFileDialogImpl* owner,
+ Type type,
+ const std::wstring& title,
+ const FilePath& default_path,
+ const FileTypeInfo* file_types,
+ int file_type_index,
+ const FilePath::StringType& default_extension,
+ gfx::NativeWindow parent,
+ void* params)
+ : owner_(owner),
+ parent_(parent),
+ type_(type),
+ title_(title),
+ default_path_(default_path),
+ file_type_index_(file_type_index),
+ default_extension_(default_extension),
+ params_(params) {
+ if (file_types)
+ file_types_ = *file_types;
+ else
+ file_types_.include_all_files = true;
+}
+
+SelectFileDialogImpl::FileBrowseDelegate::~FileBrowseDelegate() {
+}
+
+bool SelectFileDialogImpl::FileBrowseDelegate::IsDialogModal() const {
+ return true;
+}
+
+std::wstring SelectFileDialogImpl::FileBrowseDelegate::GetDialogTitle() const {
+ return title_;
+}
+
+GURL SelectFileDialogImpl::FileBrowseDelegate::GetDialogContentURL() const {
+ std::string url_string(chrome::kChromeUIFileBrowseURL);
+
+ return GURL(url_string);
+}
+
+void SelectFileDialogImpl::FileBrowseDelegate::GetDOMMessageHandlers(
+ std::vector<DOMMessageHandler*>* handlers) const {
+ return;
+}
+
+void SelectFileDialogImpl::FileBrowseDelegate::GetDialogSize(
+ gfx::Size* size) const {
+ size->SetSize(320, 240);
+}
+
+std::string SelectFileDialogImpl::FileBrowseDelegate::GetDialogArgs() const {
+ // SelectFile inputs as json.
+ // {
+ // "type" : "open", // (or "open_multiple", "save", "folder"
+ // "all_files" : true,
+ // "file_types" : {
+ // "exts" : [ ["htm", "html"], ["txt"] ],
+ // "desc" : [ "HTML files", "Text files" ],
+ // },
+ // "file_type_index" : 1, // 1-based file type index.
+ // }
+ // See browser/shell_dialogs.h for more details.
+
+ std::string type_string;
+ switch (type_) {
+ case SELECT_FOLDER:
+ type_string = "folder";
+ break;
+ case SELECT_OPEN_FILE:
+ type_string = "open";
+ break;
+ case SELECT_OPEN_MULTI_FILE:
+ type_string = "open_multiple";
+ break;
+ case SELECT_SAVEAS_FILE:
+ type_string = "save";
+ break;
+ default:
+ NOTREACHED();
+ return std::string();
+ }
+
+ std::string exts_list;
+ std::string desc_list;
+ for (size_t i = 0; i < file_types_.extensions.size(); ++i) {
+ DCHECK(!file_types_.extensions[i].empty());
+
+ std::string exts;
+ for (size_t j = 0; j < file_types_.extensions[i].size(); ++j) {
+ if (!exts.empty())
+ exts.append(",");
+ StringAppendF(&exts, "\"%s\"", file_types_.extensions[i][j].c_str());
+ }
+
+ if (!exts_list.empty())
+ exts_list.append(",");
+ StringAppendF(&exts_list, "[%s]", exts.c_str());
+
+ std::string desc;
+ if (i < file_types_.extension_description_overrides.size()) {
+ desc = UTF16ToUTF8(file_types_.extension_description_overrides[i]);
+ } else {
+#if defined(OS_WIN)
+ desc = WideToUTF8(file_types_.extensions[i][0]);
+#elif defined(OS_POSIX)
+ desc = file_types_.extensions[i][0];
+#else
+ NOTIMPLEMENTED();
+#endif
+ }
+
+ if (!desc_list.empty())
+ desc_list.append(",");
+ StringAppendF(&desc_list, "\"%s\"", desc.c_str());
+ }
+
+ std::string filename = default_path_.BaseName().value();
+
+ return StringPrintf("{"
+ "\"type\":\"%s\","
+ "\"all_files\":%s,"
+ "\"current_file\":\"%s\","
+ "\"file_types\":{\"exts\":[%s],\"desc\":[%s]},"
+ "\"file_type_index\":%d"
+ "}",
+ type_string.c_str(),
+ file_types_.include_all_files ? "true" : "false",
+ filename.c_str(),
+ exts_list.c_str(),
+ desc_list.c_str(),
+ file_type_index_);
+}
+
+void SelectFileDialogImpl::FileBrowseDelegate::OnDialogClosed(
+ const std::string& json_retval) {
+ owner_->OnDialogClosed(this, json_retval);
+ delete this;
+ return;
+}
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 951bce7..84d9336 100755
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -1876,6 +1876,7 @@
'browser/views/restart_message_box.h',
'browser/views/sad_tab_view.cc',
'browser/views/sad_tab_view.h',
+ 'browser/views/select_file_dialog.cc',
'browser/views/select_profile_dialog.cc',
'browser/views/select_profile_dialog.h',
'browser/views/shell_dialogs_win.cc',
@@ -2219,6 +2220,7 @@
'browser/power_save_blocker_stub.cc',
'browser/views/new_browser_window_widget.cc',
'browser/views/new_browser_window_widget.h',
+ 'browser/views/select_file_dialog.cc',
'browser/views/tabs/grid.cc',
'browser/views/tabs/grid.h',
'browser/views/tabs/tab_overview_cell.cc',
@@ -2293,6 +2295,8 @@
['include', '^browser/views/detachable_toolbar_view.h'],
['include', '^browser/views/detachable_toolbar_view.cc'],
['include', '^browser/views/dialog_stubs_gtk.cc'],
+ ['include', '^browser/views/dom_view.cc'],
+ ['include', '^browser/views/dom_view.h'],
['include', '^browser/views/download_item_view.cc'],
['include', '^browser/views/download_item_view.h'],
['include', '^browser/views/download_shelf_view.cc'],
@@ -2329,6 +2333,8 @@
['include', '^browser/views/fullscreen_exit_bubble.h'],
['include', '^browser/views/go_button.cc'],
['include', '^browser/views/go_button.h'],
+ ['include', '^browser/views/html_dialog_view.cc'],
+ ['include', '^browser/views/html_dialog_view.h'],
['include', '^browser/views/theme_install_bubble_view.cc'],
['include', '^browser/views/theme_install_bubble_view.h'],
['include', '^browser/views/toolbar_star_toggle.h'],
@@ -2365,6 +2371,7 @@
#['include', '^browser/views/panels/panel_scroller_header.h'],
['include', '^browser/views/sad_tab_view.cc'],
['include', '^browser/views/sad_tab_view.h'],
+ ['include', '^browser/views/select_file_dialog.cc'],
['include', '^browser/views/status_bubble_views.cc'],
['include', '^browser/views/status_bubble_views.h'],
['include', '^browser/views/tab_contents/native_tab_contents_container_gtk.cc'],
@@ -2425,7 +2432,6 @@
['include', '^browser/gtk/clear_browsing_data_dialog_gtk.h'],
['include', '^browser/gtk/constrained_window_gtk.cc'],
['include', '^browser/gtk/constrained_window_gtk.h'],
- ['include', '^browser/gtk/dialogs_gtk.cc'],
['include', '^browser/gtk/download_started_animation_gtk.cc'],
['include', '^browser/gtk/edit_search_engine_dialog.cc'],
['include', '^browser/gtk/edit_search_engine_dialog.h'],