summaryrefslogtreecommitdiffstats
path: root/base
diff options
context:
space:
mode:
authorjianli@chromium.org <jianli@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-01-15 18:49:58 +0000
committerjianli@chromium.org <jianli@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-01-15 18:49:58 +0000
commit6aa4a1c041ca9bd2c3087c3c059a87193b1a82e1 (patch)
tree8e833c393312e866250077c15bc1d90464fe99d7 /base
parent963dfb5a05c5b0e3fa8ed74d803f01cb10fd455e (diff)
downloadchromium_src-6aa4a1c041ca9bd2c3087c3c059a87193b1a82e1.zip
chromium_src-6aa4a1c041ca9bd2c3087c3c059a87193b1a82e1.tar.gz
chromium_src-6aa4a1c041ca9bd2c3087c3c059a87193b1a82e1.tar.bz2
Support dragging a virtual file out of the browser.
BUG=none TEST=none Review URL: http://codereview.chromium.org/351029 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@36378 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base')
-rw-r--r--base/base_drag_source.cc12
-rw-r--r--base/base_drag_source.h6
-rw-r--r--base/base_drop_target.cc11
-rw-r--r--base/base_drop_target.h9
-rw-r--r--base/file_util.h9
-rw-r--r--base/file_util_win.cc9
-rw-r--r--base/message_loop_unittest.cc43
-rw-r--r--base/message_pump_win.cc3
-rw-r--r--base/message_pump_win.h3
9 files changed, 86 insertions, 19 deletions
diff --git a/base/base_drag_source.cc b/base/base_drag_source.cc
index bc81395..9b335a7 100644
--- a/base/base_drag_source.cc
+++ b/base/base_drag_source.cc
@@ -7,7 +7,7 @@
///////////////////////////////////////////////////////////////////////////////
// BaseDragSource, public:
-BaseDragSource::BaseDragSource() : ref_count_(0), cancel_drag_(false) {
+BaseDragSource::BaseDragSource() : cancel_drag_(false) {
}
///////////////////////////////////////////////////////////////////////////////
@@ -51,13 +51,11 @@ HRESULT BaseDragSource::QueryInterface(const IID& iid, void** object) {
}
ULONG BaseDragSource::AddRef() {
- return ++ref_count_;
+ base::RefCountedThreadSafe<BaseDragSource>::AddRef();
+ return 0;
}
ULONG BaseDragSource::Release() {
- if (--ref_count_ == 0) {
- delete this;
- return 0U;
- }
- return ref_count_;
+ base::RefCountedThreadSafe<BaseDragSource>::Release();
+ return 0;
}
diff --git a/base/base_drag_source.h b/base/base_drag_source.h
index 3a4a94c..2ea531f 100644
--- a/base/base_drag_source.h
+++ b/base/base_drag_source.h
@@ -8,6 +8,7 @@
#include <objidl.h>
#include "base/basictypes.h"
+#include "base/ref_counted.h"
///////////////////////////////////////////////////////////////////////////////
//
@@ -18,7 +19,8 @@
// system. This object tells Windows whether or not the drag should continue,
// and supplies the appropriate cursors.
//
-class BaseDragSource : public IDropSource {
+class BaseDragSource : public IDropSource,
+ public base::RefCountedThreadSafe<BaseDragSource> {
public:
BaseDragSource();
virtual ~BaseDragSource() { }
@@ -45,8 +47,6 @@ class BaseDragSource : public IDropSource {
virtual void OnDragSourceMove() { }
private:
- LONG ref_count_;
-
// Set to true if we want to cancel the drag operation.
bool cancel_drag_;
diff --git a/base/base_drop_target.cc b/base/base_drop_target.cc
index 77fe675..1ee878f 100644
--- a/base/base_drop_target.cc
+++ b/base/base_drop_target.cc
@@ -15,7 +15,7 @@ int32 BaseDropTarget::drag_identity_ = 0;
BaseDropTarget::BaseDropTarget(HWND hwnd)
: hwnd_(hwnd),
- suspend_(false),
+ suspended_(false),
ref_count_(0) {
DCHECK(hwnd);
HRESULT result = RegisterDragDrop(hwnd, this);
@@ -50,7 +50,7 @@ HRESULT BaseDropTarget::DragEnter(IDataObject* data_object,
}
// You can't drag and drop within the same HWND.
- if (suspend_) {
+ if (suspended_) {
*effect = DROPEFFECT_NONE;
return S_OK;
}
@@ -73,7 +73,7 @@ HRESULT BaseDropTarget::DragOver(DWORD key_state,
if (drop_helper)
drop_helper->DragOver(reinterpret_cast<POINT*>(&cursor_position), *effect);
- if (suspend_) {
+ if (suspended_) {
*effect = DROPEFFECT_NONE;
return S_OK;
}
@@ -89,6 +89,9 @@ HRESULT BaseDropTarget::DragLeave() {
if (drop_helper)
drop_helper->DragLeave();
+ if (suspended_)
+ return S_OK;
+
OnDragLeave(current_data_object_);
current_data_object_ = NULL;
@@ -106,7 +109,7 @@ HRESULT BaseDropTarget::Drop(IDataObject* data_object,
reinterpret_cast<POINT*>(&cursor_position), *effect);
}
- if (suspend_) {
+ if (suspended_) {
*effect = DROPEFFECT_NONE;
return S_OK;
}
diff --git a/base/base_drop_target.h b/base/base_drop_target.h
index cf63be28..8be0d36 100644
--- a/base/base_drop_target.h
+++ b/base/base_drop_target.h
@@ -26,12 +26,13 @@ class BaseDropTarget : public IDropTarget {
explicit BaseDropTarget(HWND hwnd);
virtual ~BaseDropTarget();
- // When suspend is set to |true|, the drop target does not receive drops from
- // drags initiated within the owning HWND.
+ // When suspended is set to |true|, the drop target does not receive drops
+ // from drags initiated within the owning HWND.
// TODO(beng): (http://b/1085385) figure out how we will handle legitimate
// drag-drop operations within the same HWND, such as dragging
// selected text to an edit field.
- void set_suspend(bool suspend) { suspend_ = suspend; }
+ bool suspended() const { return suspended_; }
+ void set_suspended(bool suspended) { suspended_ = suspended; }
// IDropTarget implementation:
HRESULT __stdcall DragEnter(IDataObject* data_object,
@@ -120,7 +121,7 @@ class BaseDropTarget : public IDropTarget {
// Whether or not we are currently processing drag notifications for drags
// initiated in this window.
- bool suspend_;
+ bool suspended_;
LONG ref_count_;
diff --git a/base/file_util.h b/base/file_util.h
index 543a86c..efa4633 100644
--- a/base/file_util.h
+++ b/base/file_util.h
@@ -128,6 +128,15 @@ bool Delete(const FilePath& path, bool recursive);
// Deprecated temporary compatibility function.
bool Delete(const std::wstring& path, bool recursive);
+#if defined(OS_WIN)
+// Schedules to delete the given path, whether it's a file or a directory, until
+// the operating system is restarted.
+// Note:
+// 1) The file/directory to be deleted should exist in a temp folder.
+// 2) The directory to be deleted must be empty.
+bool DeleteAfterReboot(const FilePath& path);
+#endif
+
// Moves the given path, whether it's a file or a directory.
// If a simple rename is not possible, such as in the case where the paths are
// on different volumes, this will attempt to copy and delete. Returns
diff --git a/base/file_util_win.cc b/base/file_util_win.cc
index e066422..7c3de4d 100644
--- a/base/file_util_win.cc
+++ b/base/file_util_win.cc
@@ -98,6 +98,15 @@ bool Delete(const FilePath& path, bool recursive) {
return (err == 0 || err == ERROR_FILE_NOT_FOUND);
}
+bool DeleteAfterReboot(const FilePath& path) {
+ if (path.value().length() >= MAX_PATH)
+ return false;
+
+ return MoveFileEx(path.value().c_str(), NULL,
+ MOVEFILE_DELAY_UNTIL_REBOOT |
+ MOVEFILE_REPLACE_EXISTING) != FALSE;
+}
+
bool Move(const FilePath& from_path, const FilePath& to_path) {
// NOTE: I suspect we could support longer paths, but that would involve
// analyzing all our usage of files.
diff --git a/base/message_loop_unittest.cc b/base/message_loop_unittest.cc
index 74491ce..00a1dfe 100644
--- a/base/message_loop_unittest.cc
+++ b/base/message_loop_unittest.cc
@@ -1107,7 +1107,12 @@ class DispatcherImpl : public MessageLoopForUI::Dispatcher {
virtual bool Dispatch(const MSG& msg) {
::TranslateMessage(&msg);
::DispatchMessage(&msg);
- return (++dispatch_count_ != 2);
+ // Do not count WM_TIMER since it is not what we post and it will cause
+ // flakiness.
+ if (msg.message != WM_TIMER)
+ ++dispatch_count_;
+ // We treat WM_LBUTTONUP as the last message.
+ return msg.message != WM_LBUTTONUP;
}
int dispatch_count_;
@@ -1130,6 +1135,37 @@ void RunTest_Dispatcher(MessageLoop::Type message_loop_type) {
ASSERT_EQ(2, dispatcher.dispatch_count_);
}
+LRESULT CALLBACK MsgFilterProc(int code, WPARAM wparam, LPARAM lparam) {
+ if (code == base::MessagePumpForUI::kMessageFilterCode) {
+ MSG* msg = reinterpret_cast<MSG*>(lparam);
+ if (msg->message == WM_LBUTTONDOWN)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+void RunTest_DispatcherWithMessageHook(MessageLoop::Type message_loop_type) {
+ MessageLoop loop(message_loop_type);
+
+ class MyTask : public Task {
+ public:
+ virtual void Run() {
+ PostMessage(NULL, WM_LBUTTONDOWN, 0, 0);
+ PostMessage(NULL, WM_LBUTTONUP, 'A', 0);
+ }
+ };
+ Task* task = new MyTask();
+ MessageLoop::current()->PostDelayedTask(FROM_HERE, task, 100);
+ HHOOK msg_hook = SetWindowsHookEx(WH_MSGFILTER,
+ MsgFilterProc,
+ NULL,
+ GetCurrentThreadId());
+ DispatcherImpl dispatcher;
+ MessageLoopForUI::current()->Run(&dispatcher);
+ ASSERT_EQ(1, dispatcher.dispatch_count_);
+ UnhookWindowsHookEx(msg_hook);
+}
+
class TestIOHandler : public MessageLoopForIO::IOHandler {
public:
TestIOHandler(const wchar_t* name, HANDLE signal, bool wait);
@@ -1423,6 +1459,11 @@ TEST(MessageLoopTest, Dispatcher) {
RunTest_Dispatcher(MessageLoop::TYPE_UI);
}
+TEST(MessageLoopTest, DispatcherWithMessageHook) {
+ // This test requires a UI loop
+ RunTest_DispatcherWithMessageHook(MessageLoop::TYPE_UI);
+}
+
TEST(MessageLoopTest, IOHandler) {
RunTest_IOHandler();
}
diff --git a/base/message_pump_win.cc b/base/message_pump_win.cc
index 737676c..f40c872 100644
--- a/base/message_pump_win.cc
+++ b/base/message_pump_win.cc
@@ -351,6 +351,9 @@ bool MessagePumpForUI::ProcessMessageHelper(const MSG& msg) {
if (msg.message == kMsgHaveWork && msg.hwnd == message_hwnd_)
return ProcessPumpReplacementMessage();
+ if (CallMsgFilter(const_cast<MSG*>(&msg), kMessageFilterCode))
+ return true;
+
WillProcessMessage(msg);
if (state_->dispatcher) {
diff --git a/base/message_pump_win.h b/base/message_pump_win.h
index 63222a8..e6ea233 100644
--- a/base/message_pump_win.h
+++ b/base/message_pump_win.h
@@ -157,6 +157,9 @@ class MessagePumpWin : public MessagePump {
//
class MessagePumpForUI : public MessagePumpWin {
public:
+ // The application-defined code passed to the hook procedure.
+ static const int kMessageFilterCode = 0x5001;
+
MessagePumpForUI();
virtual ~MessagePumpForUI();