Index: content/browser/tab_contents/web_contents_drag_win.cc |
diff --git a/content/browser/tab_contents/web_contents_drag_win.cc b/content/browser/tab_contents/web_contents_drag_win.cc |
deleted file mode 100644 |
index cbf0178717f5cd191fd37a0250be1070746799be..0000000000000000000000000000000000000000 |
--- a/content/browser/tab_contents/web_contents_drag_win.cc |
+++ /dev/null |
@@ -1,371 +0,0 @@ |
-// 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 "content/browser/tab_contents/web_contents_drag_win.h" |
- |
-#include <windows.h> |
- |
-#include <string> |
- |
-#include "base/bind.h" |
-#include "base/file_path.h" |
-#include "base/message_loop.h" |
-#include "base/pickle.h" |
-#include "base/threading/platform_thread.h" |
-#include "base/threading/thread.h" |
-#include "base/utf_string_conversions.h" |
-#include "content/browser/download/drag_download_file.h" |
-#include "content/browser/download/drag_download_util.h" |
-#include "content/browser/web_contents/web_drag_dest_win.h" |
-#include "content/browser/web_contents/web_drag_source_win.h" |
-#include "content/browser/web_contents/web_drag_utils_win.h" |
-#include "content/public/browser/browser_thread.h" |
-#include "content/public/browser/content_browser_client.h" |
-#include "content/public/browser/web_contents.h" |
-#include "content/public/browser/web_drag_dest_delegate.h" |
-#include "net/base/net_util.h" |
-#include "ui/base/clipboard/clipboard_util_win.h" |
-#include "ui/base/clipboard/custom_data_helper.h" |
-#include "ui/base/dragdrop/drag_utils.h" |
-#include "ui/gfx/size.h" |
-#include "webkit/glue/webdropdata.h" |
- |
-using content::BrowserThread; |
-using WebKit::WebDragOperationsMask; |
-using WebKit::WebDragOperationCopy; |
-using WebKit::WebDragOperationLink; |
-using WebKit::WebDragOperationMove; |
- |
-namespace { |
- |
-HHOOK msg_hook = NULL; |
-DWORD drag_out_thread_id = 0; |
-bool mouse_up_received = false; |
- |
-LRESULT CALLBACK MsgFilterProc(int code, WPARAM wparam, LPARAM lparam) { |
- if (code == base::MessagePumpForUI::kMessageFilterCode && |
- !mouse_up_received) { |
- MSG* msg = reinterpret_cast<MSG*>(lparam); |
- // We do not care about WM_SYSKEYDOWN and WM_SYSKEYUP because when ALT key |
- // is pressed down on drag-and-drop, it means to create a link. |
- if (msg->message == WM_MOUSEMOVE || msg->message == WM_LBUTTONUP || |
- msg->message == WM_KEYDOWN || msg->message == WM_KEYUP) { |
- // Forward the message from the UI thread to the drag-and-drop thread. |
- PostThreadMessage(drag_out_thread_id, |
- msg->message, |
- msg->wParam, |
- msg->lParam); |
- |
- // If the left button is up, we do not need to forward the message any |
- // more. |
- if (msg->message == WM_LBUTTONUP || !(GetKeyState(VK_LBUTTON) & 0x8000)) |
- mouse_up_received = true; |
- |
- return TRUE; |
- } |
- } |
- return CallNextHookEx(msg_hook, code, wparam, lparam); |
-} |
- |
-} // namespace |
- |
-class DragDropThread : public base::Thread { |
- public: |
- explicit DragDropThread(WebContentsDragWin* drag_handler) |
- : base::Thread("Chrome_DragDropThread"), |
- drag_handler_(drag_handler) { |
- } |
- |
- virtual ~DragDropThread() { |
- Thread::Stop(); |
- } |
- |
- protected: |
- // base::Thread implementations: |
- virtual void Init() { |
- int ole_result = OleInitialize(NULL); |
- DCHECK(ole_result == S_OK); |
- } |
- |
- virtual void CleanUp() { |
- OleUninitialize(); |
- } |
- |
- private: |
- // Hold a reference count to WebContentsDragWin to make sure that it is always |
- // alive in the thread lifetime. |
- scoped_refptr<WebContentsDragWin> drag_handler_; |
- |
- DISALLOW_COPY_AND_ASSIGN(DragDropThread); |
-}; |
- |
-WebContentsDragWin::WebContentsDragWin( |
- gfx::NativeWindow source_window, |
- content::WebContents* web_contents, |
- WebDragDest* drag_dest, |
- const base::Callback<void()>& drag_end_callback) |
- : drag_drop_thread_id_(0), |
- source_window_(source_window), |
- web_contents_(web_contents), |
- drag_dest_(drag_dest), |
- drag_ended_(false), |
- old_drop_target_suspended_state_(false), |
- drag_end_callback_(drag_end_callback) { |
-} |
- |
-WebContentsDragWin::~WebContentsDragWin() { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- DCHECK(!drag_drop_thread_.get()); |
-} |
- |
-void WebContentsDragWin::StartDragging(const WebDropData& drop_data, |
- WebDragOperationsMask ops, |
- const SkBitmap& image, |
- const gfx::Point& image_offset) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
- drag_source_ = new WebDragSource(source_window_, web_contents_); |
- |
- const GURL& page_url = web_contents_->GetURL(); |
- const std::string& page_encoding = web_contents_->GetEncoding(); |
- |
- // If it is not drag-out, do the drag-and-drop in the current UI thread. |
- if (drop_data.download_metadata.empty()) { |
- DoDragging(drop_data, ops, page_url, page_encoding, image, image_offset); |
- EndDragging(false); |
- return; |
- } |
- |
- // We do not want to drag and drop the download to itself. |
- old_drop_target_suspended_state_ = drag_dest_->suspended(); |
- drag_dest_->set_suspended(true); |
- |
- // Start a background thread to do the drag-and-drop. |
- DCHECK(!drag_drop_thread_.get()); |
- drag_drop_thread_.reset(new DragDropThread(this)); |
- base::Thread::Options options; |
- options.message_loop_type = MessageLoop::TYPE_UI; |
- if (drag_drop_thread_->StartWithOptions(options)) { |
- drag_drop_thread_->message_loop()->PostTask( |
- FROM_HERE, |
- base::Bind(&WebContentsDragWin::StartBackgroundDragging, this, |
- drop_data, ops, page_url, page_encoding, image, |
- image_offset)); |
- } |
- |
- // Install a hook procedure to monitor the messages so that we can forward |
- // the appropriate ones to the background thread. |
- drag_out_thread_id = drag_drop_thread_->thread_id(); |
- mouse_up_received = false; |
- DCHECK(!msg_hook); |
- msg_hook = SetWindowsHookEx(WH_MSGFILTER, |
- MsgFilterProc, |
- NULL, |
- GetCurrentThreadId()); |
- |
- // Attach the input state of the background thread to the UI thread so that |
- // SetCursor can work from the background thread. |
- AttachThreadInput(drag_out_thread_id, GetCurrentThreadId(), TRUE); |
-} |
- |
-void WebContentsDragWin::StartBackgroundDragging( |
- const WebDropData& drop_data, |
- WebDragOperationsMask ops, |
- const GURL& page_url, |
- const std::string& page_encoding, |
- const SkBitmap& image, |
- const gfx::Point& image_offset) { |
- drag_drop_thread_id_ = base::PlatformThread::CurrentId(); |
- |
- DoDragging(drop_data, ops, page_url, page_encoding, image, image_offset); |
- BrowserThread::PostTask( |
- BrowserThread::UI, |
- FROM_HERE, |
- base::Bind(&WebContentsDragWin::EndDragging, this, true)); |
-} |
- |
-void WebContentsDragWin::PrepareDragForDownload( |
- const WebDropData& drop_data, |
- ui::OSExchangeData* data, |
- const GURL& page_url, |
- const std::string& page_encoding) { |
- // Parse the download metadata. |
- string16 mime_type; |
- FilePath file_name; |
- GURL download_url; |
- if (!drag_download_util::ParseDownloadMetadata(drop_data.download_metadata, |
- &mime_type, |
- &file_name, |
- &download_url)) |
- return; |
- |
- // Generate the file name based on both mime type and proposed file name. |
- std::string default_name = |
- content::GetContentClient()->browser()->GetDefaultDownloadName(); |
- FilePath generated_download_file_name = |
- net::GenerateFileName(download_url, |
- std::string(), |
- std::string(), |
- UTF16ToUTF8(file_name.value()), |
- UTF16ToUTF8(mime_type), |
- default_name); |
- |
- // Provide the data as file (CF_HDROP). A temporary download file with the |
- // Zone.Identifier ADS (Alternate Data Stream) attached will be created. |
- linked_ptr<net::FileStream> empty_file_stream; |
- scoped_refptr<DragDownloadFile> download_file = |
- new DragDownloadFile(generated_download_file_name, |
- empty_file_stream, |
- download_url, |
- page_url, |
- page_encoding, |
- web_contents_); |
- ui::OSExchangeData::DownloadFileInfo file_download(FilePath(), |
- download_file.get()); |
- data->SetDownloadFileInfo(file_download); |
- |
- // Enable asynchronous operation. |
- ui::OSExchangeDataProviderWin::GetIAsyncOperation(*data)->SetAsyncMode(TRUE); |
-} |
- |
-void WebContentsDragWin::PrepareDragForFileContents( |
- const WebDropData& drop_data, ui::OSExchangeData* data) { |
- static const int kMaxFilenameLength = 255; // FAT and NTFS |
- FilePath file_name(drop_data.file_description_filename); |
- string16 extension = file_name.Extension(); |
- file_name = file_name.BaseName().RemoveExtension(); |
- // Images without ALT text will only have a file extension so we need to |
- // synthesize one from the provided extension and URL. |
- if (file_name.value().empty()) { |
- // Retrieve the name from the URL. |
- file_name = FilePath( |
- net::GetSuggestedFilename(drop_data.url, "", "", "", "", "")); |
- if (file_name.value().size() + extension.size() > kMaxFilenameLength) { |
- file_name = FilePath(file_name.value().substr( |
- 0, kMaxFilenameLength - extension.size())); |
- } |
- } |
- file_name = file_name.ReplaceExtension(extension); |
- data->SetFileContents(file_name, drop_data.file_contents); |
-} |
- |
-void WebContentsDragWin::PrepareDragForUrl(const WebDropData& drop_data, |
- ui::OSExchangeData* data) { |
- if (drag_dest_->delegate()->AddDragData(drop_data, data)) |
- return; |
- |
- data->SetURL(drop_data.url, drop_data.url_title); |
-} |
- |
-void WebContentsDragWin::DoDragging(const WebDropData& drop_data, |
- WebDragOperationsMask ops, |
- const GURL& page_url, |
- const std::string& page_encoding, |
- const SkBitmap& image, |
- const gfx::Point& image_offset) { |
- ui::OSExchangeData data; |
- |
- // TODO(dcheng): Figure out why this is mutually exclusive. |
- if (!drop_data.download_metadata.empty()) { |
- PrepareDragForDownload(drop_data, &data, page_url, page_encoding); |
- |
- // Set the observer. |
- ui::OSExchangeDataProviderWin::GetDataObjectImpl(data)->set_observer(this); |
- } else { |
- // We set the file contents before the URL because the URL also sets file |
- // contents (to a .URL shortcut). We want to prefer file content data over |
- // a shortcut so we add it first. |
- if (!drop_data.file_contents.empty()) |
- PrepareDragForFileContents(drop_data, &data); |
- if (!drop_data.text_html.empty()) |
- data.SetHtml(drop_data.text_html, drop_data.html_base_url); |
- // We set the text contents before the URL because the URL also sets text |
- // content. |
- if (!drop_data.plain_text.empty()) |
- data.SetString(drop_data.plain_text); |
- if (drop_data.url.is_valid()) |
- PrepareDragForUrl(drop_data, &data); |
- if (!drop_data.custom_data.empty()) { |
- Pickle pickle; |
- ui::WriteCustomDataToPickle(drop_data.custom_data, &pickle); |
- data.SetPickledData(ui::ClipboardUtil::GetWebCustomDataFormat()->cfFormat, |
- pickle); |
- } |
- } |
- |
- // Set drag image. |
- if (!image.isNull()) { |
- drag_utils::SetDragImageOnDataObject( |
- image, gfx::Size(image.width(), image.height()), image_offset, &data); |
- } |
- |
- // We need to enable recursive tasks on the message loop so we can get |
- // updates while in the system DoDragDrop loop. |
- DWORD effect; |
- { |
- MessageLoop::ScopedNestableTaskAllower allow(MessageLoop::current()); |
- DoDragDrop(ui::OSExchangeDataProviderWin::GetIDataObject(data), |
- drag_source_, |
- web_drag_utils_win::WebDragOpMaskToWinDragOpMask(ops), |
- &effect); |
- } |
- |
- // This works because WebDragSource::OnDragSourceDrop uses PostTask to |
- // dispatch the actual event. |
- drag_source_->set_effect(effect); |
-} |
- |
-void WebContentsDragWin::EndDragging(bool restore_suspended_state) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
- if (drag_ended_) |
- return; |
- drag_ended_ = true; |
- |
- if (restore_suspended_state) |
- drag_dest_->set_suspended(old_drop_target_suspended_state_); |
- |
- if (msg_hook) { |
- AttachThreadInput(drag_out_thread_id, GetCurrentThreadId(), FALSE); |
- UnhookWindowsHookEx(msg_hook); |
- msg_hook = NULL; |
- } |
- |
- drag_end_callback_.Run(); |
-} |
- |
-void WebContentsDragWin::CancelDrag() { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
- drag_source_->CancelDrag(); |
-} |
- |
-void WebContentsDragWin::CloseThread() { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
- drag_drop_thread_.reset(); |
-} |
- |
-void WebContentsDragWin::OnWaitForData() { |
- DCHECK(drag_drop_thread_id_ == base::PlatformThread::CurrentId()); |
- |
- // When the left button is release and we start to wait for the data, end |
- // the dragging before DoDragDrop returns. This makes the page leave the drag |
- // mode so that it can start to process the normal input events. |
- BrowserThread::PostTask( |
- BrowserThread::UI, |
- FROM_HERE, |
- base::Bind(&WebContentsDragWin::EndDragging, this, true)); |
-} |
- |
-void WebContentsDragWin::OnDataObjectDisposed() { |
- DCHECK(drag_drop_thread_id_ == base::PlatformThread::CurrentId()); |
- |
- // The drag-and-drop thread is only closed after OLE is done with |
- // DataObjectImpl. |
- BrowserThread::PostTask( |
- BrowserThread::UI, |
- FROM_HERE, |
- base::Bind(&WebContentsDragWin::CloseThread, this)); |
-} |