Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5960)

Unified Diff: chrome/browser/download/drag_download_file_win.cc

Issue 351029: Support dragging a virtual file out of the browser. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 10 years, 12 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/browser/download/drag_download_file_win.h ('k') | chrome/browser/download/save_package.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/download/drag_download_file_win.cc
===================================================================
--- chrome/browser/download/drag_download_file_win.cc (revision 0)
+++ chrome/browser/download/drag_download_file_win.cc (revision 0)
@@ -0,0 +1,217 @@
+// Copyright (c) 2009 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/download/drag_download_file_win.h"
+
+#include "base/file_util.h"
+#include "base/message_loop.h"
+#include "chrome/browser/chrome_thread.h"
+#include "chrome/browser/download/download_manager.h"
+#include "chrome/browser/profile.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+
+DragDownloadFile::DragDownloadFile(
+ const GURL& url,
+ const GURL& referrer,
+ const std::string& referrer_encoding,
+ TabContents* tab_contents)
+ : url_(url),
+ referrer_(referrer),
+ referrer_encoding_(referrer_encoding),
+ tab_contents_(tab_contents),
+ drag_message_loop_(MessageLoop::current()),
+ is_started_(false),
+ is_running_nested_message_loop_(false),
+ initiate_download_result_(false),
+ format_(0),
+ download_manager_(NULL),
+ download_item_observer_added_(false) {
+}
+
+DragDownloadFile::~DragDownloadFile() {
+ DCHECK(drag_message_loop_ == MessageLoop::current());
+
+ // Since the target application can still hold and use the dragged file,
+ // we do not know the time that it can be safely deleted. To solve this
+ // problem, we schedule it to be removed after the system is restarted.
+#if defined(OS_WIN)
+ if (!dir_path_.empty()) {
+ if (!file_path_.empty())
+ file_util::DeleteAfterReboot(file_path_);
+ file_util::DeleteAfterReboot(dir_path_);
+ }
+#endif
+
+ if (download_manager_)
+ download_manager_->RemoveObserver(this);
+}
+
+bool DragDownloadFile::Start(OSExchangeData::DownloadFileObserver* observer,
+ int format) {
+ DCHECK(drag_message_loop_ == MessageLoop::current());
+
+ if (is_started_)
+ return true;
+ is_started_ = true;
+
+ DCHECK(!observer_.get());
+ observer_ = observer;
+ format_ = format;
+
+ if (!InitiateDownload())
+ return false;
+
+ // Wait till the download is fully initiated.
+ StartNestedMessageLoop();
+
+ return initiate_download_result_;
+}
+
+void DragDownloadFile::Stop() {
+}
+
+bool DragDownloadFile::InitiateDownload() {
+ DCHECK(drag_message_loop_ == MessageLoop::current());
+
+ // Create a temporary directory to save the temporary download file. We do
+ // not want to use the default download directory since we do not want the
+ // twisted file name shown in the download shelf if the file with the same
+ // name already exists.
+ if (!file_util::CreateNewTempDirectory(FILE_PATH_LITERAL("chrome"),
+ &dir_path_))
+ return false;
+
+ // DownloadManager could only be invoked from the UI thread.
+ ChromeThread::PostTask(
+ ChromeThread::UI, FROM_HERE,
+ NewRunnableMethod(this,
+ &DragDownloadFile::OnInitiateDownload,
+ dir_path_));
+
+ return true;
+}
+
+void DragDownloadFile::OnInitiateDownload(const FilePath& dir_path) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
+
+ download_manager_ = tab_contents_->profile()->GetDownloadManager();
+ download_manager_->AddObserver(this);
+
+ // Start the download.
+ download_manager_->DownloadUrlToFile(url_,
+ referrer_,
+ referrer_encoding_,
+ dir_path,
+ tab_contents_);
+}
+
+void DragDownloadFile::InitiateDownloadSucceeded(
+ const std::vector<OSExchangeData::DownloadFileInfo*>& downloads) {
+ DCHECK(drag_message_loop_ == MessageLoop::current());
+
+ // Notify the drag-and-drop observer about the file info.
+ DCHECK(observer_);
+ observer_->OnDataReady(format_, downloads);
+
+ InitiateDownloadCompleted(true);
+}
+
+void DragDownloadFile::InitiateDownloadFailed() {
+ DCHECK(drag_message_loop_ == MessageLoop::current());
+
+ InitiateDownloadCompleted(false);
+}
+
+void DragDownloadFile::InitiateDownloadCompleted(bool result) {
+ DCHECK(drag_message_loop_ == MessageLoop::current());
+
+ // Release the observer since we do not need it any more.
+ observer_ = NULL;
+
+ initiate_download_result_ = result;
+ QuitNestedMessageLoopIfNeeded();
+}
+
+void DragDownloadFile::StartNestedMessageLoop() {
+ DCHECK(drag_message_loop_ == MessageLoop::current());
+
+ bool old_state = MessageLoop::current()->NestableTasksAllowed();
+ MessageLoop::current()->SetNestableTasksAllowed(true);
+ is_running_nested_message_loop_ = true;
+ MessageLoop::current()->Run();
+ MessageLoop::current()->SetNestableTasksAllowed(old_state);
+}
+
+void DragDownloadFile::QuitNestedMessageLoopIfNeeded() {
+ DCHECK(drag_message_loop_ == MessageLoop::current());
+
+ if (is_running_nested_message_loop_) {
+ is_running_nested_message_loop_ = false;
+ MessageLoop::current()->Quit();
+ }
+}
+
+void DragDownloadFile::ModelChanged() {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
+
+ download_manager_->GetTemporaryDownloads(this, dir_path_);
+}
+
+void DragDownloadFile::SetDownloads(std::vector<DownloadItem*>& downloads) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
+
+ std::vector<DownloadItem*>::const_iterator it = downloads.begin();
+ for (; it != downloads.end(); ++it) {
+ if (!download_item_observer_added_ && (*it)->url() == url_) {
+ download_item_observer_added_ = true;
+ (*it)->AddObserver(this);
+ }
+ }
+}
+
+void DragDownloadFile::OnDownloadUpdated(DownloadItem* download) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
+
+ if (download->state() == DownloadItem::CANCELLED) {
+ download->RemoveObserver(this);
+ download_manager_->RemoveObserver(this);
+
+ drag_message_loop_->PostTask(
+ FROM_HERE,
+ NewRunnableMethod(this,
+ &DragDownloadFile::DownloadCancelled));
+ }
+}
+
+void DragDownloadFile::OnDownloadFileCompleted(DownloadItem* download) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
+ DCHECK(download->state() == DownloadItem::COMPLETE);
+
+ download->RemoveObserver(this);
+ download_manager_->RemoveObserver(this);
+
+ drag_message_loop_->PostTask(
+ FROM_HERE,
+ NewRunnableMethod(this,
+ &DragDownloadFile::DownloadCompleted,
+ download->full_path()));
+}
+
+void DragDownloadFile::DownloadCancelled() {
+ DCHECK(drag_message_loop_ == MessageLoop::current());
+
+ InitiateDownloadFailed();
+}
+
+void DragDownloadFile::DownloadCompleted(const FilePath& file_path) {
+ DCHECK(drag_message_loop_ == MessageLoop::current());
+
+ file_path_ = file_path;
+
+ // The download has been successfully initiated.
+ std::vector<OSExchangeData::DownloadFileInfo*> downloads;
+ downloads.push_back(
+ new OSExchangeData::DownloadFileInfo(file_path, 0, NULL));
+ InitiateDownloadSucceeded(downloads);
+}
Property changes on: chrome\browser\download\drag_download_file_win.cc
___________________________________________________________________
Added: svn:eol-style
+ LF
« no previous file with comments | « chrome/browser/download/drag_download_file_win.h ('k') | chrome/browser/download/save_package.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698