summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
authorpaul@chromium.org <paul@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-08-18 22:29:58 +0000
committerpaul@chromium.org <paul@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-08-18 22:29:58 +0000
commit8b6ff019c982f3929cf09b7090c9ec38c2751fc1 (patch)
tree015a4b4a26fd5c8729fa1f3a3f57e25e8666e586 /chrome/browser
parent7c23cfc44c6fa5d224acd7cae942dc7310138c7b (diff)
downloadchromium_src-8b6ff019c982f3929cf09b7090c9ec38c2751fc1.zip
chromium_src-8b6ff019c982f3929cf09b7090c9ec38c2751fc1.tar.gz
chromium_src-8b6ff019c982f3929cf09b7090c9ec38c2751fc1.tar.bz2
Show or open downloaded items on the UI thread for Mac. This is
required because NSWorkspace, which is used for the open or show operation, must be called on the main thread. BUG=19447 (http://crbug.com/19447) TEST=Repro steps fully described in the bug report. Review URL: http://codereview.chromium.org/172074 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@23667 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r--chrome/browser/download/download_file.cc5
-rw-r--r--chrome/browser/download/download_file.h6
-rw-r--r--chrome/browser/download/download_manager.cc12
-rw-r--r--chrome/browser/download/save_file_manager.cc30
-rw-r--r--chrome/browser/download/save_file_manager.h11
-rw-r--r--chrome/browser/download/save_package.cc24
-rw-r--r--chrome/browser/renderer_host/save_file_resource_handler.cc6
7 files changed, 64 insertions, 30 deletions
diff --git a/chrome/browser/download/download_file.cc b/chrome/browser/download/download_file.cc
index 970cc49..bf439f0 100644
--- a/chrome/browser/download/download_file.cc
+++ b/chrome/browser/download/download_file.cc
@@ -526,14 +526,17 @@ void DownloadFileManager::OnDownloadUrl(const GURL& url,
// Open a download, or show it in a file explorer window. We run on this
// thread to avoid blocking the UI with (potentially) slow Shell operations.
// TODO(paulg): File 'stat' operations.
+#if !defined(OS_MACOSX)
void DownloadFileManager::OnShowDownloadInShell(const FilePath& full_path) {
DCHECK(MessageLoop::current() == file_loop_);
platform_util::ShowItemInFolder(full_path);
}
+#endif
// Launches the selected download using ShellExecute 'open' verb. For windows,
// if there is a valid parent window, the 'safer' version will be used which can
// display a modal dialog asking for user consent on dangerous files.
+#if !defined(OS_MACOSX)
void DownloadFileManager::OnOpenDownloadInShell(const FilePath& full_path,
const GURL& url,
gfx::NativeView parent_window) {
@@ -545,9 +548,9 @@ void DownloadFileManager::OnOpenDownloadInShell(const FilePath& full_path,
return;
}
#endif
-
platform_util::OpenItem(full_path);
}
+#endif // OS_MACOSX
// The DownloadManager in the UI thread has provided a final name for the
// download specified by 'id'. Rename the in progress download, and remove it
diff --git a/chrome/browser/download/download_file.h b/chrome/browser/download/download_file.h
index 9706d4a..3527131 100644
--- a/chrome/browser/download/download_file.h
+++ b/chrome/browser/download/download_file.h
@@ -201,12 +201,18 @@ class DownloadFileManager
void RemoveDownloadManager(DownloadManager* manager);
void RemoveDownload(int id, DownloadManager* manager);
+#if !defined(OS_MACOSX)
+ // The open and show methods run on the file thread, which does not work on
+ // Mac OS X (which uses the UI thread for opens).
+
// Handler for shell operations sent from the UI to the download thread.
void OnShowDownloadInShell(const FilePath& full_path);
+
// Handler to open or execute a downloaded file.
void OnOpenDownloadInShell(const FilePath& full_path,
const GURL& url,
gfx::NativeView parent_window);
+#endif
// The download manager has provided a final name for a download. Sent from
// the UI thread and run on the download thread.
diff --git a/chrome/browser/download/download_manager.cc b/chrome/browser/download/download_manager.cc
index 930bec7..da4ccd8 100644
--- a/chrome/browser/download/download_manager.cc
+++ b/chrome/browser/download/download_manager.cc
@@ -1233,10 +1233,16 @@ void DownloadManager::RemoveObserver(Observer* observer) {
// user interface.
void DownloadManager::ShowDownloadInShell(const DownloadItem* download) {
DCHECK(file_manager_);
+ DCHECK(MessageLoop::current() == ui_loop_);
+#if defined(OS_MACOSX)
+ // Mac needs to run this operation on the UI thread.
+ platform_util::ShowItemInFolder(download->full_path());
+#else
file_loop_->PostTask(FROM_HERE,
NewRunnableMethod(file_manager_,
&DownloadFileManager::OnShowDownloadInShell,
FilePath(download->full_path())));
+#endif
}
void DownloadManager::OpenDownload(const DownloadItem* download,
@@ -1271,10 +1277,16 @@ void DownloadManager::OpenChromeExtension(const FilePath& full_path,
void DownloadManager::OpenDownloadInShell(const DownloadItem* download,
gfx::NativeView parent_window) {
DCHECK(file_manager_);
+ DCHECK(MessageLoop::current() == ui_loop_);
+#if defined(OS_MACOSX)
+ // Mac OS X requires opening downloads on the UI thread.
+ platform_util::OpenItem(download->full_path());
+#else
file_loop_->PostTask(FROM_HERE,
NewRunnableMethod(file_manager_,
&DownloadFileManager::OnOpenDownloadInShell,
download->full_path(), download->url(), parent_window));
+#endif
}
void DownloadManager::OpenFilesOfExtension(
diff --git a/chrome/browser/download/save_file_manager.cc b/chrome/browser/download/save_file_manager.cc
index 83106a2..20b97bb 100644
--- a/chrome/browser/download/save_file_manager.cc
+++ b/chrome/browser/download/save_file_manager.cc
@@ -56,7 +56,7 @@ SaveFileManager::~SaveFileManager() {
// Called during the browser shutdown process to clean up any state (open files,
// timers) that live on the saving thread (file thread).
void SaveFileManager::Shutdown() {
- MessageLoop* loop = GetSaveLoop();
+ MessageLoop* loop = file_loop();
if (loop) {
loop->PostTask(FROM_HERE,
NewRunnableMethod(this, &SaveFileManager::OnShutdown));
@@ -65,7 +65,7 @@ void SaveFileManager::Shutdown() {
// Stop file thread operations.
void SaveFileManager::OnShutdown() {
- DCHECK(MessageLoop::current() == GetSaveLoop());
+ DCHECK(MessageLoop::current() == file_loop());
STLDeleteValues(&save_file_map_);
}
@@ -225,7 +225,7 @@ SavePackage* SaveFileManager::GetSavePackageFromRenderIds(
void SaveFileManager::DeleteDirectoryOrFile(const FilePath& full_path,
bool is_dir) {
DCHECK(MessageLoop::current() == ui_loop_);
- MessageLoop* loop = GetSaveLoop();
+ MessageLoop* loop = file_loop();
DCHECK(loop);
loop->PostTask(FROM_HERE,
NewRunnableMethod(this,
@@ -237,7 +237,7 @@ void SaveFileManager::DeleteDirectoryOrFile(const FilePath& full_path,
void SaveFileManager::SendCancelRequest(int save_id) {
// Cancel the request which has specific save id.
DCHECK(save_id > -1);
- MessageLoop* loop = GetSaveLoop();
+ MessageLoop* loop = file_loop();
DCHECK(loop);
loop->PostTask(FROM_HERE,
NewRunnableMethod(this,
@@ -251,7 +251,7 @@ void SaveFileManager::SendCancelRequest(int save_id) {
// to create a SaveFile which will hold and finally destroy |info|. It will
// then passes |info| to the UI thread for reporting saving status.
void SaveFileManager::StartSave(SaveFileCreateInfo* info) {
- DCHECK(MessageLoop::current() == GetSaveLoop());
+ DCHECK(MessageLoop::current() == file_loop());
DCHECK(info);
SaveFile* save_file = new SaveFile(info);
DCHECK(LookupSaveFile(info->save_id) == NULL);
@@ -271,7 +271,7 @@ void SaveFileManager::StartSave(SaveFileCreateInfo* info) {
void SaveFileManager::UpdateSaveProgress(int save_id,
net::IOBuffer* data,
int data_len) {
- DCHECK(MessageLoop::current() == GetSaveLoop());
+ DCHECK(MessageLoop::current() == file_loop());
SaveFile* save_file = LookupSaveFile(save_id);
if (save_file) {
bool write_success = save_file->AppendDataToFile(data->data(), data_len);
@@ -295,7 +295,7 @@ void SaveFileManager::SaveFinished(int save_id,
GURL save_url,
int render_process_id,
bool is_success) {
- DCHECK(MessageLoop::current() == GetSaveLoop());
+ DCHECK(MessageLoop::current() == file_loop());
SaveFileMap::iterator it = save_file_map_.find(save_id);
if (it != save_file_map_.end()) {
SaveFile* save_file = it->second;
@@ -412,7 +412,7 @@ void SaveFileManager::OnRequireSaveJobFromOtherSource(
// Generate a unique save id.
info->save_id = GetNextId();
// Start real saving action.
- MessageLoop* loop = GetSaveLoop();
+ MessageLoop* loop = file_loop();
DCHECK(loop);
loop->PostTask(FROM_HERE,
NewRunnableMethod(this,
@@ -436,7 +436,7 @@ void SaveFileManager::ExecuteCancelSaveRequest(int render_process_id,
// sent from the UI thread, the saving job may have already completed and
// won't exist in our map.
void SaveFileManager::CancelSave(int save_id) {
- DCHECK(MessageLoop::current() == GetSaveLoop());
+ DCHECK(MessageLoop::current() == file_loop());
SaveFileMap::iterator it = save_file_map_.find(save_id);
if (it != save_file_map_.end()) {
SaveFile* save_file = it->second;
@@ -473,7 +473,7 @@ void SaveFileManager::CancelSave(int save_id) {
void SaveFileManager::SaveLocalFile(const GURL& original_file_url,
int save_id,
int render_process_id) {
- DCHECK(MessageLoop::current() == GetSaveLoop());
+ DCHECK(MessageLoop::current() == file_loop());
SaveFile* save_file = LookupSaveFile(save_id);
if (!save_file)
return;
@@ -503,7 +503,7 @@ void SaveFileManager::SaveLocalFile(const GURL& original_file_url,
void SaveFileManager::OnDeleteDirectoryOrFile(const FilePath& full_path,
bool is_dir) {
- DCHECK(MessageLoop::current() == GetSaveLoop());
+ DCHECK(MessageLoop::current() == file_loop());
DCHECK(!full_path.empty());
file_util::Delete(full_path, is_dir);
@@ -511,17 +511,19 @@ void SaveFileManager::OnDeleteDirectoryOrFile(const FilePath& full_path,
// Open a saved page package, show it in a Windows Explorer window.
// We run on this thread to avoid blocking the UI with slow Shell operations.
+#if !defined(OS_MACOSX)
void SaveFileManager::OnShowSavedFileInShell(const FilePath full_path) {
- DCHECK(MessageLoop::current() == GetSaveLoop());
+ DCHECK(MessageLoop::current() == file_loop());
platform_util::ShowItemInFolder(full_path);
}
+#endif
void SaveFileManager::RenameAllFiles(
const FinalNameList& final_names,
const FilePath& resource_dir,
int render_process_id,
int render_view_id) {
- DCHECK(MessageLoop::current() == GetSaveLoop());
+ DCHECK(MessageLoop::current() == file_loop());
if (!resource_dir.empty() && !file_util::PathExists(resource_dir))
file_util::CreateDirectory(resource_dir);
@@ -560,7 +562,7 @@ void SaveFileManager::OnFinishSavePageJob(int render_process_id,
void SaveFileManager::RemoveSavedFileFromFileMap(
const SaveIDList& save_ids) {
- DCHECK(MessageLoop::current() == GetSaveLoop());
+ DCHECK(MessageLoop::current() == file_loop());
for (SaveIDList::const_iterator i = save_ids.begin();
i != save_ids.end(); ++i) {
diff --git a/chrome/browser/download/save_file_manager.h b/chrome/browser/download/save_file_manager.h
index 34c2f12..db1e866 100644
--- a/chrome/browser/download/save_file_manager.h
+++ b/chrome/browser/download/save_file_manager.h
@@ -115,14 +115,19 @@ class SaveFileManager
void RemoveSaveFile(int save_id, const GURL& save_url,
SavePackage* package);
- // Handler for shell operations sent from the UI to the file thread.
+#if !defined(OS_MACOSX)
+ // Handler for shell operations sent from the UI to the file thread. Mac OS X
+ // requires opening downloads on the UI thread, so it does not use this
+ // method.
void OnShowSavedFileInShell(const FilePath full_path);
+#endif
// Helper function for deleting specified file.
void DeleteDirectoryOrFile(const FilePath& full_path, bool is_dir);
- // For posting notifications from the UI and IO threads.
- MessageLoop* GetSaveLoop() const { return file_loop_; }
+ // For posting notifications from the UI and file threads.
+ MessageLoop* ui_loop() const { return ui_loop_; }
+ MessageLoop* file_loop() const { return file_loop_; }
// Runs on file thread to save a file by copying from file system when
// original url is using file scheme.
diff --git a/chrome/browser/download/save_package.cc b/chrome/browser/download/save_package.cc
index cfd6e05..c6003e7 100644
--- a/chrome/browser/download/save_package.cc
+++ b/chrome/browser/download/save_package.cc
@@ -437,7 +437,7 @@ void SavePackage::StartSave(const SaveFileCreateInfo* info) {
// If the save source is from file system, inform SaveFileManager to copy
// corresponding file to the file path which this SaveItem specifies.
if (info->save_source == SaveFileCreateInfo::SAVE_FILE_FROM_FILE) {
- file_manager_->GetSaveLoop()->PostTask(FROM_HERE,
+ file_manager_->file_loop()->PostTask(FROM_HERE,
NewRunnableMethod(file_manager_,
&SaveFileManager::SaveLocalFile,
save_item->url(),
@@ -543,7 +543,7 @@ void SavePackage::Stop() {
it != saved_failed_items_.end(); ++it)
save_ids.push_back(it->second->save_id());
- file_manager_->GetSaveLoop()->PostTask(FROM_HERE,
+ file_manager_->file_loop()->PostTask(FROM_HERE,
NewRunnableMethod(file_manager_,
&SaveFileManager::RemoveSavedFileFromFileMap,
save_ids));
@@ -572,7 +572,7 @@ void SavePackage::CheckFinish() {
final_names.push_back(std::make_pair(it->first,
it->second->full_path()));
- file_manager_->GetSaveLoop()->PostTask(FROM_HERE,
+ file_manager_->file_loop()->PostTask(FROM_HERE,
NewRunnableMethod(file_manager_,
&SaveFileManager::RenameAllFiles,
final_names,
@@ -597,7 +597,7 @@ void SavePackage::Finish() {
it != saved_failed_items_.end(); ++it)
save_ids.push_back(it->second->save_id());
- file_manager_->GetSaveLoop()->PostTask(FROM_HERE,
+ file_manager_->file_loop()->PostTask(FROM_HERE,
NewRunnableMethod(file_manager_,
&SaveFileManager::RemoveSavedFileFromFileMap,
save_ids));
@@ -693,7 +693,7 @@ void SavePackage::SaveCanceled(SaveItem* save_item) {
save_item->url(),
this);
if (save_item->save_id() != -1)
- file_manager_->GetSaveLoop()->PostTask(FROM_HERE,
+ file_manager_->file_loop()->PostTask(FROM_HERE,
NewRunnableMethod(file_manager_,
&SaveFileManager::CancelSave,
save_item->save_id()));
@@ -735,10 +735,16 @@ void SavePackage::SaveNextFile(bool process_all_remaining_items) {
void SavePackage::ShowDownloadInShell() {
DCHECK(file_manager_);
DCHECK(finished_ && !canceled() && !saved_main_file_path_.empty());
- file_manager_->GetSaveLoop()->PostTask(FROM_HERE,
+ DCHECK(MessageLoop::current() == file_manager_->ui_loop());
+#if defined(OS_MACOSX)
+ // Mac OS X requires opening downloads on the UI thread.
+ platform_util::ShowItemInFolder(saved_main_file_path_);
+#else
+ file_manager_->file_loop()->PostTask(FROM_HERE,
NewRunnableMethod(file_manager_,
&SaveFileManager::OnShowSavedFileInShell,
saved_main_file_path_));
+#endif
}
// Calculate the percentage of whole save page job.
@@ -855,7 +861,7 @@ void SavePackage::OnReceivedSerializedHtmlData(const GURL& frame_url,
if (flag == webkit_glue::DomSerializerDelegate::ALL_FRAMES_ARE_FINISHED) {
for (SaveUrlItemMap::iterator it = in_progress_items_.begin();
it != in_progress_items_.end(); ++it) {
- file_manager_->GetSaveLoop()->PostTask(FROM_HERE,
+ file_manager_->file_loop()->PostTask(FROM_HERE,
NewRunnableMethod(file_manager_,
&SaveFileManager::SaveFinished,
it->second->save_id(),
@@ -879,7 +885,7 @@ void SavePackage::OnReceivedSerializedHtmlData(const GURL& frame_url,
memcpy(new_data->data(), data.data(), data.size());
// Call write file functionality in file thread.
- file_manager_->GetSaveLoop()->PostTask(FROM_HERE,
+ file_manager_->file_loop()->PostTask(FROM_HERE,
NewRunnableMethod(file_manager_,
&SaveFileManager::UpdateSaveProgress,
save_item->save_id(),
@@ -889,7 +895,7 @@ void SavePackage::OnReceivedSerializedHtmlData(const GURL& frame_url,
// Current frame is completed saving, call finish in file thread.
if (flag == webkit_glue::DomSerializerDelegate::CURRENT_FRAME_IS_FINISHED) {
- file_manager_->GetSaveLoop()->PostTask(FROM_HERE,
+ file_manager_->file_loop()->PostTask(FROM_HERE,
NewRunnableMethod(file_manager_,
&SaveFileManager::SaveFinished,
save_item->save_id(),
diff --git a/chrome/browser/renderer_host/save_file_resource_handler.cc b/chrome/browser/renderer_host/save_file_resource_handler.cc
index 22f3441..bb426ce 100644
--- a/chrome/browser/renderer_host/save_file_resource_handler.cc
+++ b/chrome/browser/renderer_host/save_file_resource_handler.cc
@@ -44,7 +44,7 @@ bool SaveFileResourceHandler::OnResponseStarted(int request_id,
info->request_id = request_id;
info->content_disposition = content_disposition_;
info->save_source = SaveFileCreateInfo::SAVE_FILE_FROM_NET;
- save_manager_->GetSaveLoop()->PostTask(FROM_HERE,
+ save_manager_->file_loop()->PostTask(FROM_HERE,
NewRunnableMethod(save_manager_,
&SaveFileManager::StartSave,
info));
@@ -69,7 +69,7 @@ bool SaveFileResourceHandler::OnReadCompleted(int request_id, int* bytes_read) {
// We are passing ownership of this buffer to the save file manager.
net::IOBuffer* buffer = NULL;
read_buffer_.swap(&buffer);
- save_manager_->GetSaveLoop()->PostTask(FROM_HERE,
+ save_manager_->file_loop()->PostTask(FROM_HERE,
NewRunnableMethod(save_manager_,
&SaveFileManager::UpdateSaveProgress,
save_id_,
@@ -82,7 +82,7 @@ bool SaveFileResourceHandler::OnResponseCompleted(
int request_id,
const URLRequestStatus& status,
const std::string& security_info) {
- save_manager_->GetSaveLoop()->PostTask(FROM_HERE,
+ save_manager_->file_loop()->PostTask(FROM_HERE,
NewRunnableMethod(save_manager_,
&SaveFileManager::SaveFinished,
save_id_,