[go: nahoru, domu]

Add drag started/ended to DragDropClientObserver

The observers are needed to integrate drag and drop operation with ARC++, where
Android dispatches DRAG_STARTED and DRAG_ENDED events.

The CL adds observer methods to DragDropClientObserver and adds invocations for
the methods to DragDropController and DragDropControllerMus.

Bug: 750997, b:31988797
Test: ash_unittests, aura_unittests
Change-Id: Ic886de4e17c5897d12cea5b656de0053e37341a9
Reviewed-on: https://chromium-review.googlesource.com/575295
Commit-Queue: Daichi Hirono <hirono@chromium.org>
Reviewed-by: Scott Violet <sky@chromium.org>
Cr-Commit-Position: refs/heads/master@{#490884}
diff --git a/ash/drag_drop/drag_drop_controller.cc b/ash/drag_drop/drag_drop_controller.cc
index 1a0d113..50d9f93 100644
--- a/ash/drag_drop/drag_drop_controller.cc
+++ b/ash/drag_drop/drag_drop_controller.cc
@@ -16,6 +16,7 @@
 #include "base/run_loop.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "ui/aura/client/capture_client.h"
+#include "ui/aura/client/drag_drop_client_observer.h"
 #include "ui/aura/client/drag_drop_delegate.h"
 #include "ui/aura/env.h"
 #include "ui/aura/window.h"
@@ -226,6 +227,9 @@
   if (cancel_animation_)
     cancel_animation_->End();
 
+  for (aura::client::DragDropClientObserver& observer : observers_)
+    observer.OnDragStarted();
+
   if (should_block_during_drag_drop_) {
     base::RunLoop run_loop;
     quit_closure_ = run_loop.QuitClosure();
@@ -262,6 +266,16 @@
   return !!drag_drop_tracker_.get();
 }
 
+void DragDropController::AddObserver(
+    aura::client::DragDropClientObserver* observer) {
+  observers_.AddObserver(observer);
+}
+
+void DragDropController::RemoveObserver(
+    aura::client::DragDropClientObserver* observer) {
+  observers_.RemoveObserver(observer);
+}
+
 void DragDropController::OnKeyEvent(ui::KeyEvent* event) {
   if (IsDragDropInProgress() && event->key_code() == ui::VKEY_ESCAPE) {
     DragCancel();
@@ -574,6 +588,8 @@
 }
 
 void DragDropController::Cleanup() {
+  for (aura::client::DragDropClientObserver& observer : observers_)
+    observer.OnDragEnded();
   if (drag_window_)
     drag_window_->RemoveObserver(this);
   drag_window_ = NULL;
diff --git a/ash/drag_drop/drag_drop_controller.h b/ash/drag_drop/drag_drop_controller.h
index 7780ff9..0649922 100644
--- a/ash/drag_drop/drag_drop_controller.h
+++ b/ash/drag_drop/drag_drop_controller.h
@@ -12,6 +12,7 @@
 #include "base/callback.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
+#include "base/observer_list.h"
 #include "base/time/time.h"
 #include "ui/aura/client/drag_drop_client.h"
 #include "ui/aura/window_observer.h"
@@ -56,6 +57,8 @@
                        ui::DragDropTypes::DragEventSource source) override;
   void DragCancel() override;
   bool IsDragDropInProgress() override;
+  void AddObserver(aura::client::DragDropClientObserver* observer) override;
+  void RemoveObserver(aura::client::DragDropClientObserver* observer) override;
 
   // Overridden from ui::EventHandler:
   void OnKeyEvent(ui::KeyEvent* event) override;
@@ -135,6 +138,8 @@
   // See comment in OnGestureEvent() on why we need this.
   std::unique_ptr<ui::GestureEvent> pending_long_tap_;
 
+  base::ObserverList<aura::client::DragDropClientObserver> observers_;
+
   base::WeakPtrFactory<DragDropController> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(DragDropController);
diff --git a/ash/drag_drop/drag_drop_controller_unittest.cc b/ash/drag_drop/drag_drop_controller_unittest.cc
index f5d576b..780a235 100644
--- a/ash/drag_drop/drag_drop_controller_unittest.cc
+++ b/ash/drag_drop/drag_drop_controller_unittest.cc
@@ -12,6 +12,8 @@
 #include "base/location.h"
 #include "base/strings/utf_string_conversions.h"
 #include "ui/aura/client/capture_client.h"
+#include "ui/aura/client/drag_drop_client_observer.h"
+#include "ui/aura/env.h"
 #include "ui/aura/window_event_dispatcher.h"
 #include "ui/aura/window_tree_host.h"
 #include "ui/base/clipboard/clipboard.h"
@@ -1097,4 +1099,61 @@
   EXPECT_TRUE(drag_view->drag_done_received_);
 }
 
+namespace {
+
+class TestObserver : public aura::client::DragDropClientObserver {
+ public:
+  enum class State { kNotInvoked, kDragStartedInvoked, kDragEndedInvoked };
+
+  TestObserver() : state_(State::kNotInvoked) {}
+
+  State state() const { return state_; }
+
+  // aura::client::DragDropClientObserver
+
+  void OnDragStarted() override {
+    EXPECT_EQ(State::kNotInvoked, state_);
+    state_ = State::kDragStartedInvoked;
+  }
+
+  void OnDragEnded() override {
+    EXPECT_EQ(State::kDragStartedInvoked, state_);
+    state_ = State::kDragEndedInvoked;
+  }
+
+ private:
+  State state_;
+
+  DISALLOW_COPY_AND_ASSIGN(TestObserver);
+};
+
+}  // namespace
+
+TEST_F(DragDropControllerTest, DragStartedAndEndedEvents) {
+  TestObserver observer;
+  drag_drop_controller_->AddObserver(&observer);
+
+  ui::OSExchangeData data;
+  data.SetString(base::UTF8ToUTF16("I am being dragged"));
+  {
+    std::unique_ptr<views::Widget> widget(CreateNewWidget());
+    aura::Window* window = widget->GetNativeWindow();
+    drag_drop_controller_->StartDragAndDrop(
+        data, window->GetRootWindow(), window, gfx::Point(5, 5),
+        ui::DragDropTypes::DRAG_MOVE,
+        ui::DragDropTypes::DRAG_EVENT_SOURCE_MOUSE);
+
+    EXPECT_EQ(TestObserver::State::kDragStartedInvoked, observer.state());
+
+    ui::MouseEvent e(ui::ET_MOUSE_DRAGGED, gfx::Point(200, 0),
+                     gfx::Point(200, 0), ui::EventTimeForNow(), ui::EF_NONE,
+                     ui::EF_NONE);
+    drag_drop_controller_->Drop(window, e);
+
+    EXPECT_EQ(TestObserver::State::kDragEndedInvoked, observer.state());
+  }
+
+  drag_drop_controller_->RemoveObserver(&observer);
+}
+
 }  // namespace ash
diff --git a/chrome/browser/ui/views/drag_and_drop_interactive_uitest.cc b/chrome/browser/ui/views/drag_and_drop_interactive_uitest.cc
index a5f072b..0c0fd1d 100644
--- a/chrome/browser/ui/views/drag_and_drop_interactive_uitest.cc
+++ b/chrome/browser/ui/views/drag_and_drop_interactive_uitest.cc
@@ -289,6 +289,10 @@
 
   bool IsDragDropInProgress() override { return drag_started_; }
 
+  void AddObserver(aura::client::DragDropClientObserver* observer) override {}
+  void RemoveObserver(aura::client::DragDropClientObserver* observer) override {
+  }
+
  private:
   content::WebContents* web_contents_;
   scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
diff --git a/testing/buildbot/filters/ash_unittests_mash.filter b/testing/buildbot/filters/ash_unittests_mash.filter
index 41c6ae5..b236062 100644
--- a/testing/buildbot/filters/ash_unittests_mash.filter
+++ b/testing/buildbot/filters/ash_unittests_mash.filter
@@ -102,6 +102,7 @@
 -DragDropControllerTest.TouchDragDropLongTapGestureIsForwarded
 -DragDropControllerTest.ViewRemovedWhileInDragDropTest
 -DragDropControllerTest.WindowDestroyedDuringDragDrop
+-DragDropControllerTest.DragStartedAndEndedEvents
 -DragWindowResizerTest.CursorDeviceScaleFactor
 -DragWindowResizerTest.DragWindowController
 -DragWindowResizerTest.DragWindowControllerAcrossThreeDisplays
diff --git a/ui/aura/BUILD.gn b/ui/aura/BUILD.gn
index bb0ff9b..6d67370 100644
--- a/ui/aura/BUILD.gn
+++ b/ui/aura/BUILD.gn
@@ -15,6 +15,7 @@
     "client/cursor_client_observer.h",
     "client/default_capture_client.h",
     "client/drag_drop_client.h",
+    "client/drag_drop_client_observer.h",
     "client/drag_drop_delegate.h",
     "client/event_client.h",
     "client/focus_change_observer.h",
@@ -334,6 +335,7 @@
 test("aura_unittests") {
   sources = [
     "gestures/gesture_recognizer_unittest.cc",
+    "mus/drag_drop_controller_mus_unittest.cc",
     "mus/input_method_mus_unittest.cc",
     "mus/os_exchange_data_provider_mus_unittest.cc",
     "mus/property_converter_unittest.cc",
diff --git a/ui/aura/client/drag_drop_client.h b/ui/aura/client/drag_drop_client.h
index 4015f0f1..8e96348 100644
--- a/ui/aura/client/drag_drop_client.h
+++ b/ui/aura/client/drag_drop_client.h
@@ -21,6 +21,8 @@
 class Window;
 namespace client {
 
+class DragDropClientObserver;
+
 // An interface implemented by an object that controls a drag and drop session.
 class AURA_EXPORT DragDropClient {
  public:
@@ -28,7 +30,8 @@
 
   // Initiates a drag and drop session. Returns the drag operation that was
   // applied at the end of the drag drop session. |screen_location| is in
-  // screen coordinates.
+  // screen coordinates. At most one drag and drop operation is allowed.
+  // It must not start drag operation while |IsDragDropInProgress| returns true.
   virtual int StartDragAndDrop(const ui::OSExchangeData& data,
                                aura::Window* root_window,
                                aura::Window* source_window,
@@ -41,6 +44,9 @@
 
   // Returns true if a drag and drop session is in progress.
   virtual bool IsDragDropInProgress() = 0;
+
+  virtual void AddObserver(DragDropClientObserver* observer) = 0;
+  virtual void RemoveObserver(DragDropClientObserver* observer) = 0;
 };
 
 AURA_EXPORT void SetDragDropClient(Window* root_window,
diff --git a/ui/aura/client/drag_drop_client_observer.h b/ui/aura/client/drag_drop_client_observer.h
new file mode 100644
index 0000000..e285050b
--- /dev/null
+++ b/ui/aura/client/drag_drop_client_observer.h
@@ -0,0 +1,28 @@
+// Copyright 2017 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.
+
+#ifndef UI_AURA_CLIENT_DRAG_DROP_CLIENT_OBSERVER_H_
+#define UI_AURA_CLIENT_DRAG_DROP_CLIENT_OBSERVER_H_
+
+#include "ui/aura/aura_export.h"
+
+namespace aura {
+namespace client {
+
+class AURA_EXPORT DragDropClientObserver {
+ public:
+  // Called when dragging started.
+  virtual void OnDragStarted() = 0;
+
+  // Called when dragging ended.
+  virtual void OnDragEnded() = 0;
+
+ protected:
+  virtual ~DragDropClientObserver() = default;
+};
+
+}  // namespace client
+}  // namespace aura
+
+#endif  // UI_AURA_CLIENT_DRAG_DROP_CLIENT_OBSERVER_H_
diff --git a/ui/aura/mus/drag_drop_controller_mus.cc b/ui/aura/mus/drag_drop_controller_mus.cc
index b5c41ca..1cc2a11 100644
--- a/ui/aura/mus/drag_drop_controller_mus.cc
+++ b/ui/aura/mus/drag_drop_controller_mus.cc
@@ -15,7 +15,9 @@
 #include "mojo/public/cpp/bindings/map.h"
 #include "services/ui/public/interfaces/window_tree.mojom.h"
 #include "services/ui/public/interfaces/window_tree_constants.mojom.h"
+#include "ui/aura/client/drag_drop_client_observer.h"
 #include "ui/aura/client/drag_drop_delegate.h"
+#include "ui/aura/env.h"
 #include "ui/aura/mus/drag_drop_controller_host.h"
 #include "ui/aura/mus/mus_types.h"
 #include "ui/aura/mus/os_exchange_data_provider_mus.h"
@@ -116,8 +118,11 @@
 
 void DragDropControllerMus::OnPerformDragDropCompleted(uint32_t action_taken) {
   DCHECK(current_drag_state_);
+  for (client::DragDropClientObserver& observer : observers_)
+    observer.OnDragEnded();
   current_drag_state_->completed_action = action_taken;
   current_drag_state_->runloop_quit_closure.Run();
+  current_drag_state_ = nullptr;
 }
 
 void DragDropControllerMus::OnDragDropDone() {
@@ -140,8 +145,10 @@
   CurrentDragState current_drag_state = {root_window_mus->server_id(),
                                          change_id, ui::mojom::kDropEffectNone,
                                          data, run_loop.QuitClosure()};
-  base::AutoReset<CurrentDragState*> resetter(&current_drag_state_,
-                                              &current_drag_state);
+
+  // current_drag_state_ will be reset in |OnPerformDragDropCompleted| before
+  // run_loop.Run() quits.
+  current_drag_state_ = &current_drag_state;
 
   base::MessageLoop* loop = base::MessageLoop::current();
   base::MessageLoop::ScopedNestableTaskAllower allow_nested(loop);
@@ -155,6 +162,10 @@
   std::map<std::string, std::vector<uint8_t>> drag_data =
       static_cast<const aura::OSExchangeDataProviderMus&>(data.provider())
           .GetData();
+
+  for (client::DragDropClientObserver& observer : observers_)
+    observer.OnDragStarted();
+
   window_tree_->PerformDragDrop(
       change_id, root_window_mus->server_id(), screen_location,
       mojo::MapToUnorderedMap(drag_data),
@@ -162,7 +173,6 @@
       data.provider().GetDragImageOffset(), drag_operations, mojo_source);
 
   run_loop.Run();
-
   return current_drag_state.completed_action;
 }
 
@@ -176,6 +186,16 @@
   return current_drag_state_ != nullptr;
 }
 
+void DragDropControllerMus::AddObserver(
+    client::DragDropClientObserver* observer) {
+  observers_.AddObserver(observer);
+}
+
+void DragDropControllerMus::RemoveObserver(
+    client::DragDropClientObserver* observer) {
+  observers_.RemoveObserver(observer);
+}
+
 uint32_t DragDropControllerMus::HandleDragEnterOrOver(
     WindowMus* window,
     uint32_t event_flags,
diff --git a/ui/aura/mus/drag_drop_controller_mus.h b/ui/aura/mus/drag_drop_controller_mus.h
index 92700dcb..e161339 100644
--- a/ui/aura/mus/drag_drop_controller_mus.h
+++ b/ui/aura/mus/drag_drop_controller_mus.h
@@ -11,6 +11,8 @@
 #include <memory>
 #include <vector>
 
+#include "base/observer_list.h"
+#include "ui/aura/aura_export.h"
 #include "ui/aura/client/drag_drop_client.h"
 #include "ui/aura/window_tracker.h"
 #include "ui/base/dragdrop/drag_drop_types.h"
@@ -32,7 +34,7 @@
 // DragDropControllerMus acts as the DragDropClient for aura as well as
 // handling all drag operations from the server. Drag operations are forwarded
 // to the client::DragDropDelegate set on the target Window.
-class DragDropControllerMus : public client::DragDropClient {
+class AURA_EXPORT DragDropControllerMus : public client::DragDropClient {
  public:
   DragDropControllerMus(DragDropControllerHost* drag_drop_controller_host,
                         ui::mojom::WindowTree* window_tree);
@@ -70,6 +72,8 @@
                        ui::DragDropTypes::DragEventSource source) override;
   void DragCancel() override;
   bool IsDragDropInProgress() override;
+  void AddObserver(client::DragDropClientObserver* observer) override;
+  void RemoveObserver(client::DragDropClientObserver* observer) override;
 
  private:
   struct CurrentDragState;
@@ -105,6 +109,8 @@
   // Used to track the current drop target.
   WindowTracker drop_target_window_tracker_;
 
+  base::ObserverList<client::DragDropClientObserver> observers_;
+
   DISALLOW_COPY_AND_ASSIGN(DragDropControllerMus);
 };
 
diff --git a/ui/aura/mus/drag_drop_controller_mus_unittest.cc b/ui/aura/mus/drag_drop_controller_mus_unittest.cc
new file mode 100644
index 0000000..e9ff87e6
--- /dev/null
+++ b/ui/aura/mus/drag_drop_controller_mus_unittest.cc
@@ -0,0 +1,117 @@
+// Copyright 2017 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 "ui/aura/mus/drag_drop_controller_mus.h"
+
+#include <memory>
+
+#include "base/callback_forward.h"
+#include "base/memory/ptr_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/task_scheduler/post_task.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "ui/aura/client/drag_drop_client_observer.h"
+#include "ui/aura/mus/drag_drop_controller_host.h"
+#include "ui/aura/test/aura_mus_test_base.h"
+#include "ui/aura/test/mus/test_window_tree.h"
+#include "ui/events/event_utils.h"
+
+namespace aura {
+namespace {
+
+class DragDropControllerMusTest : public test::AuraMusWmTestBase {
+ public:
+  DragDropControllerMusTest() = default;
+
+  // test::AuraMusWmTestBase
+  void SetUp() override {
+    AuraMusWmTestBase::SetUp();
+    drag_drop_controller_ = base::MakeUnique<DragDropControllerMus>(
+        &drag_drop_controller_host_, window_tree());
+  }
+
+  void TearDown() override {
+    drag_drop_controller_.reset();
+    AuraMusWmTestBase::TearDown();
+  }
+
+ protected:
+  std::unique_ptr<DragDropControllerMus> drag_drop_controller_;
+
+ private:
+  class TestDragDropControllerHost : public DragDropControllerHost {
+   public:
+    TestDragDropControllerHost() : serial_(0u) {}
+
+    // DragDropControllerHost
+    uint32_t CreateChangeIdForDrag(WindowMus* window) override {
+      return serial_++;
+    }
+
+   private:
+    uint32_t serial_;
+
+  } drag_drop_controller_host_;
+
+  DISALLOW_COPY_AND_ASSIGN(DragDropControllerMusTest);
+};
+
+class TestObserver : public client::DragDropClientObserver {
+ public:
+  enum class State { kNotInvoked, kDragStartInvoked, kDragEndInvoked };
+
+  TestObserver(DragDropControllerMus* controller)
+      : controller_(controller), state_(State::kNotInvoked) {
+    controller_->AddObserver(this);
+  }
+
+  ~TestObserver() override { controller_->RemoveObserver(this); }
+
+  State state() const { return state_; }
+
+  void OnInternalLoopRun() {
+    EXPECT_EQ(State::kDragStartInvoked, state_);
+    controller_->OnPerformDragDropCompleted(0);
+  }
+
+  // Overrides from client::DragDropClientObserver:
+  void OnDragStarted() override {
+    EXPECT_EQ(State::kNotInvoked, state_);
+    state_ = State::kDragStartInvoked;
+  }
+
+  void OnDragEnded() override {
+    EXPECT_EQ(State::kDragStartInvoked, state_);
+    state_ = State::kDragEndInvoked;
+  }
+
+ private:
+  DragDropControllerMus* controller_;
+  State state_;
+
+  DISALLOW_COPY_AND_ASSIGN(TestObserver);
+};
+
+TEST_F(DragDropControllerMusTest, DragStartedAndEndedEvents) {
+  TestObserver observer(drag_drop_controller_.get());
+  std::unique_ptr<aura::Window> window(
+      CreateNormalWindow(0, root_window(), nullptr));
+
+  ASSERT_TRUE(base::ThreadTaskRunnerHandle::IsSet());
+
+  // Posted task will be run when the inner loop runs in StartDragAndDrop.
+  base::ThreadTaskRunnerHandle::Get()->PostTask(
+      FROM_HERE, base::BindOnce(&TestObserver::OnInternalLoopRun,
+                                base::Unretained(&observer)));
+
+  drag_drop_controller_->StartDragAndDrop(
+      ui::OSExchangeData(), window->GetRootWindow(), window.get(),
+      gfx::Point(5, 5), ui::DragDropTypes::DRAG_MOVE,
+      ui::DragDropTypes::DRAG_EVENT_SOURCE_MOUSE);
+
+  EXPECT_EQ(TestObserver::State::kDragEndInvoked, observer.state());
+}
+
+}  // namespace
+}  // namespace aura
diff --git a/ui/views/controls/button/menu_button_unittest.cc b/ui/views/controls/button/menu_button_unittest.cc
index 21eb775..56af2a8c 100644
--- a/ui/views/controls/button/menu_button_unittest.cc
+++ b/ui/views/controls/button/menu_button_unittest.cc
@@ -21,6 +21,7 @@
 
 #if defined(USE_AURA)
 #include "ui/aura/client/drag_drop_client.h"
+#include "ui/aura/client/drag_drop_client_observer.h"
 #include "ui/events/event.h"
 #include "ui/events/event_handler.h"
 #endif
@@ -253,6 +254,9 @@
                        ui::DragDropTypes::DragEventSource source) override;
   void DragCancel() override;
   bool IsDragDropInProgress() override;
+  void AddObserver(aura::client::DragDropClientObserver* observer) override {}
+  void RemoveObserver(aura::client::DragDropClientObserver* observer) override {
+  }
 
   // ui::EventHandler:
   void OnMouseEvent(ui::MouseEvent* event) override;
diff --git a/ui/views/controls/menu/menu_controller_unittest.cc b/ui/views/controls/menu/menu_controller_unittest.cc
index c5aa7ab..4bb1ec6 100644
--- a/ui/views/controls/menu/menu_controller_unittest.cc
+++ b/ui/views/controls/menu/menu_controller_unittest.cc
@@ -36,6 +36,7 @@
 
 #if defined(USE_AURA)
 #include "ui/aura/client/drag_drop_client.h"
+#include "ui/aura/client/drag_drop_client_observer.h"
 #include "ui/aura/scoped_window_targeter.h"
 #include "ui/aura/window.h"
 #include "ui/views/controls/menu/menu_pre_target_handler.h"
@@ -172,6 +173,10 @@
   void DragCancel() override;
   bool IsDragDropInProgress() override;
 
+  void AddObserver(aura::client::DragDropClientObserver* observer) override {}
+  void RemoveObserver(aura::client::DragDropClientObserver* observer) override {
+  }
+
  private:
   base::Closure start_drag_and_drop_callback_;
   bool drag_in_progress_;
diff --git a/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.cc b/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.cc
index d53d9c7..5df66d7 100644
--- a/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.cc
+++ b/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.cc
@@ -836,6 +836,16 @@
   return !!g_current_drag_drop_client;
 }
 
+void DesktopDragDropClientAuraX11::AddObserver(
+    aura::client::DragDropClientObserver* observer) {
+  NOTIMPLEMENTED();
+}
+
+void DesktopDragDropClientAuraX11::RemoveObserver(
+    aura::client::DragDropClientObserver* observer) {
+  NOTIMPLEMENTED();
+}
+
 void DesktopDragDropClientAuraX11::OnWindowDestroyed(aura::Window* window) {
   DCHECK_EQ(target_window_, window);
   target_window_ = NULL;
diff --git a/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.h b/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.h
index b8792c2..53a8f23 100644
--- a/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.h
+++ b/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.h
@@ -26,6 +26,7 @@
 
 namespace aura {
 namespace client {
+class DragDropClientObserver;
 class DragDropDelegate;
 }
 }
@@ -89,6 +90,8 @@
                        ui::DragDropTypes::DragEventSource source) override;
   void DragCancel() override;
   bool IsDragDropInProgress() override;
+  void AddObserver(aura::client::DragDropClientObserver* observer) override;
+  void RemoveObserver(aura::client::DragDropClientObserver* observer) override;
 
   // Overridden from aura::WindowObserver:
   void OnWindowDestroyed(aura::Window* window) override;
diff --git a/ui/views/widget/desktop_aura/desktop_drag_drop_client_win.cc b/ui/views/widget/desktop_aura/desktop_drag_drop_client_win.cc
index 67fd2fa..1267b56 100644
--- a/ui/views/widget/desktop_aura/desktop_drag_drop_client_win.cc
+++ b/ui/views/widget/desktop_aura/desktop_drag_drop_client_win.cc
@@ -84,6 +84,16 @@
   return drag_drop_in_progress_;
 }
 
+void DesktopDragDropClientWin::AddObserver(
+    aura::client::DragDropClientObserver* observer) {
+  NOTIMPLEMENTED();
+}
+
+void DesktopDragDropClientWin::RemoveObserver(
+    aura::client::DragDropClientObserver* observer) {
+  NOTIMPLEMENTED();
+}
+
 void DesktopDragDropClientWin::OnNativeWidgetDestroying(HWND window) {
   if (drop_target_.get()) {
     RevokeDragDrop(window);
diff --git a/ui/views/widget/desktop_aura/desktop_drag_drop_client_win.h b/ui/views/widget/desktop_aura/desktop_drag_drop_client_win.h
index 44c28416..25845e08 100644
--- a/ui/views/widget/desktop_aura/desktop_drag_drop_client_win.h
+++ b/ui/views/widget/desktop_aura/desktop_drag_drop_client_win.h
@@ -14,6 +14,12 @@
 #include "ui/aura/client/drag_drop_client.h"
 #include "ui/views/views_export.h"
 
+namespace aura {
+namespace client {
+class DragDropClientObserver;
+}
+}  // namespace aura
+
 namespace ui {
 class DragSourceWin;
 }
@@ -36,6 +42,8 @@
                        ui::DragDropTypes::DragEventSource source) override;
   void DragCancel() override;
   bool IsDragDropInProgress() override;
+  void AddObserver(aura::client::DragDropClientObserver* observer) override;
+  void RemoveObserver(aura::client::DragDropClientObserver* observer) override;
 
   void OnNativeWidgetDestroying(HWND window);
 
diff --git a/ui/wm/public/scoped_drag_drop_disabler.cc b/ui/wm/public/scoped_drag_drop_disabler.cc
index 4ca3572..2f30f64 100644
--- a/ui/wm/public/scoped_drag_drop_disabler.cc
+++ b/ui/wm/public/scoped_drag_drop_disabler.cc
@@ -24,6 +24,9 @@
   bool IsDragDropInProgress() override {
     return false;
   }
+  void AddObserver(aura::client::DragDropClientObserver* observer) override {}
+  void RemoveObserver(aura::client::DragDropClientObserver* observer) override {
+  }
 };
 
 ScopedDragDropDisabler::ScopedDragDropDisabler(aura::Window* window)