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

Side by Side Diff: content/browser/web_contents/web_contents_view_aura.cc

Issue 10966023: Fix the crash that could occur when the window is closed while web contents drag is in progress. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Patch to land Created 8 years, 2 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/web_contents/web_contents_view_aura.h" 5 #include "content/browser/web_contents/web_contents_view_aura.h"
6 6
7 #include "base/utf_string_conversions.h" 7 #include "base/utf_string_conversions.h"
8 #include "content/browser/renderer_host/dip_util.h" 8 #include "content/browser/renderer_host/dip_util.h"
9 #include "content/browser/renderer_host/render_view_host_factory.h" 9 #include "content/browser/renderer_host/render_view_host_factory.h"
10 #include "content/browser/web_contents/interstitial_page_impl.h" 10 #include "content/browser/web_contents/interstitial_page_impl.h"
11 #include "content/browser/web_contents/web_contents_impl.h" 11 #include "content/browser/web_contents/web_contents_impl.h"
12 #include "content/public/browser/notification_observer.h"
13 #include "content/public/browser/notification_registrar.h"
14 #include "content/public/browser/notification_source.h"
15 #include "content/public/browser/notification_types.h"
12 #include "content/public/browser/render_view_host.h" 16 #include "content/public/browser/render_view_host.h"
13 #include "content/public/browser/render_widget_host.h" 17 #include "content/public/browser/render_widget_host.h"
14 #include "content/public/browser/render_widget_host_view.h" 18 #include "content/public/browser/render_widget_host_view.h"
15 #include "content/public/browser/web_contents_delegate.h" 19 #include "content/public/browser/web_contents_delegate.h"
16 #include "content/public/browser/web_contents_view_delegate.h" 20 #include "content/public/browser/web_contents_view_delegate.h"
17 #include "content/public/browser/web_drag_dest_delegate.h" 21 #include "content/public/browser/web_drag_dest_delegate.h"
18 #include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h" 22 #include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h"
19 #include "ui/aura/client/aura_constants.h" 23 #include "ui/aura/client/aura_constants.h"
20 #include "ui/aura/client/drag_drop_client.h" 24 #include "ui/aura/client/drag_drop_client.h"
21 #include "ui/aura/client/drag_drop_delegate.h" 25 #include "ui/aura/client/drag_drop_delegate.h"
(...skipping 17 matching lines...) Expand all
39 WebContentsViewAura* rv = new WebContentsViewAura(web_contents, delegate); 43 WebContentsViewAura* rv = new WebContentsViewAura(web_contents, delegate);
40 *render_view_host_delegate_view = rv; 44 *render_view_host_delegate_view = rv;
41 return rv; 45 return rv;
42 } 46 }
43 } 47 }
44 48
45 namespace { 49 namespace {
46 50
47 // Listens to all mouse drag events during a drag and drop and sends them to 51 // Listens to all mouse drag events during a drag and drop and sends them to
48 // the renderer. 52 // the renderer.
49 class WebDragSourceAura : public MessageLoopForUI::Observer { 53 class WebDragSourceAura : public MessageLoopForUI::Observer,
54 public content::NotificationObserver {
50 public: 55 public:
51 explicit WebDragSourceAura(WebContentsImpl* contents) 56 WebDragSourceAura(aura::Window* window, WebContentsImpl* contents)
52 : contents_(contents) { 57 : window_(window),
58 contents_(contents) {
53 MessageLoopForUI::current()->AddObserver(this); 59 MessageLoopForUI::current()->AddObserver(this);
60 registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED,
61 content::Source<content::WebContents>(contents));
54 } 62 }
55 63
56 virtual ~WebDragSourceAura() { 64 virtual ~WebDragSourceAura() {
57 MessageLoopForUI::current()->RemoveObserver(this); 65 MessageLoopForUI::current()->RemoveObserver(this);
58 } 66 }
59 67
60 // MessageLoop::Observer implementation: 68 // MessageLoop::Observer implementation:
61 virtual base::EventStatus WillProcessEvent( 69 virtual base::EventStatus WillProcessEvent(
62 const base::NativeEvent& event) OVERRIDE { 70 const base::NativeEvent& event) OVERRIDE {
63 return base::EVENT_CONTINUE; 71 return base::EVENT_CONTINUE;
64 } 72 }
65 virtual void DidProcessEvent(const base::NativeEvent& event) OVERRIDE { 73 virtual void DidProcessEvent(const base::NativeEvent& event) OVERRIDE {
74 if (!contents_)
75 return;
66 ui::EventType type = ui::EventTypeFromNative(event); 76 ui::EventType type = ui::EventTypeFromNative(event);
67 content::RenderViewHost* rvh = NULL; 77 content::RenderViewHost* rvh = NULL;
68 switch (type) { 78 switch (type) {
69 case ui::ET_MOUSE_DRAGGED: 79 case ui::ET_MOUSE_DRAGGED:
70 rvh = contents_->GetRenderViewHost(); 80 rvh = contents_->GetRenderViewHost();
71 if (rvh) { 81 if (rvh) {
72 gfx::Point screen_loc_in_pixel = ui::EventLocationFromNative(event); 82 gfx::Point screen_loc_in_pixel = ui::EventLocationFromNative(event);
73 gfx::Point screen_loc = content::ConvertPointToDIP(rvh->GetView(), 83 gfx::Point screen_loc = content::ConvertPointToDIP(rvh->GetView(),
74 screen_loc_in_pixel); 84 screen_loc_in_pixel);
75 gfx::Point client_loc = screen_loc; 85 gfx::Point client_loc = screen_loc;
76 aura::Window* window = rvh->GetView()->GetNativeView(); 86 aura::Window* window = rvh->GetView()->GetNativeView();
77 aura::Window::ConvertPointToTarget(window->GetRootWindow(), 87 aura::Window::ConvertPointToTarget(window->GetRootWindow(),
78 window, &client_loc); 88 window, &client_loc);
79 rvh->DragSourceMovedTo(client_loc.x(), client_loc.y(), 89 rvh->DragSourceMovedTo(client_loc.x(), client_loc.y(),
80 screen_loc.x(), screen_loc.y()); 90 screen_loc.x(), screen_loc.y());
81 } 91 }
82 break; 92 break;
83 default: 93 default:
84 break; 94 break;
85 } 95 }
86 } 96 }
87 97
98 virtual void Observe(int type,
99 const content::NotificationSource& source,
100 const content::NotificationDetails& details) OVERRIDE {
101 if (content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED != type)
jam 2012/09/28 19:21:01 nit: type != content::...
102 return;
103
104 // Cancel the drag if it is still in progress.
105 aura::client::DragDropClient* dnd_client =
106 aura::client::GetDragDropClient(window_->GetRootWindow());
107 if (dnd_client && dnd_client->IsDragDropInProgress())
108 dnd_client->DragCancel();
109
110 window_ = NULL;
111 contents_ = NULL;
112 }
113
114 aura::Window* window() const { return window_; }
88 115
89 private: 116 private:
117 aura::Window* window_;
90 WebContentsImpl* contents_; 118 WebContentsImpl* contents_;
119 content::NotificationRegistrar registrar_;
91 120
92 DISALLOW_COPY_AND_ASSIGN(WebDragSourceAura); 121 DISALLOW_COPY_AND_ASSIGN(WebDragSourceAura);
93 }; 122 };
94 123
95 // Utility to fill a ui::OSExchangeDataProviderAura object from WebDropData. 124 // Utility to fill a ui::OSExchangeDataProviderAura object from WebDropData.
96 void PrepareDragData(const WebDropData& drop_data, 125 void PrepareDragData(const WebDropData& drop_data,
97 ui::OSExchangeDataProviderAura* provider) { 126 ui::OSExchangeDataProviderAura* provider) {
98 if (!drop_data.text.string().empty()) 127 if (!drop_data.text.string().empty())
99 provider->SetString(drop_data.text.string()); 128 provider->SetString(drop_data.text.string());
100 if (drop_data.url.is_valid()) 129 if (drop_data.url.is_valid())
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
206 //////////////////////////////////////////////////////////////////////////////// 235 ////////////////////////////////////////////////////////////////////////////////
207 // WebContentsViewAura, public: 236 // WebContentsViewAura, public:
208 237
209 WebContentsViewAura::WebContentsViewAura( 238 WebContentsViewAura::WebContentsViewAura(
210 WebContentsImpl* web_contents, 239 WebContentsImpl* web_contents,
211 content::WebContentsViewDelegate* delegate) 240 content::WebContentsViewDelegate* delegate)
212 : web_contents_(web_contents), 241 : web_contents_(web_contents),
213 view_(NULL), 242 view_(NULL),
214 delegate_(delegate), 243 delegate_(delegate),
215 current_drag_op_(WebKit::WebDragOperationNone), 244 current_drag_op_(WebKit::WebDragOperationNone),
216 close_tab_after_drag_ends_(false),
217 drag_dest_delegate_(NULL), 245 drag_dest_delegate_(NULL),
218 current_rvh_for_drag_(NULL) { 246 current_rvh_for_drag_(NULL) {
219 } 247 }
220 248
221 //////////////////////////////////////////////////////////////////////////////// 249 ////////////////////////////////////////////////////////////////////////////////
222 // WebContentsViewAura, private: 250 // WebContentsViewAura, private:
223 251
224 WebContentsViewAura::~WebContentsViewAura() { 252 WebContentsViewAura::~WebContentsViewAura() {
225 // Window needs a valid delegate during its destructor, so we explicitly 253 // Window needs a valid delegate during its destructor, so we explicitly
226 // delete it here. 254 // delete it here.
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
363 void WebContentsViewAura::StoreFocus() { 391 void WebContentsViewAura::StoreFocus() {
364 if (delegate_.get()) 392 if (delegate_.get())
365 delegate_->StoreFocus(); 393 delegate_->StoreFocus();
366 } 394 }
367 395
368 void WebContentsViewAura::RestoreFocus() { 396 void WebContentsViewAura::RestoreFocus() {
369 if (delegate_.get()) 397 if (delegate_.get())
370 delegate_->RestoreFocus(); 398 delegate_->RestoreFocus();
371 } 399 }
372 400
373 bool WebContentsViewAura::IsDoingDrag() const {
374 aura::RootWindow* root_window = GetNativeView()->GetRootWindow();
375 if (aura::client::GetDragDropClient(root_window))
376 return aura::client::GetDragDropClient(root_window)->IsDragDropInProgress();
377 return false;
378 }
379
380 void WebContentsViewAura::CancelDragAndCloseTab() {
381 DCHECK(IsDoingDrag());
382 // We can't close the tab while we're in the drag and
383 // |drag_handler_->CancelDrag()| is async. Instead, set a flag to cancel
384 // the drag and when the drag nested message loop ends, close the tab.
385 aura::RootWindow* root_window = GetNativeView()->GetRootWindow();
386 if (aura::client::GetDragDropClient(root_window))
387 aura::client::GetDragDropClient(root_window)->DragCancel();
388
389 close_tab_after_drag_ends_ = true;
390 }
391
392 WebDropData* WebContentsViewAura::GetDropData() const { 401 WebDropData* WebContentsViewAura::GetDropData() const {
393 return NULL; 402 return NULL;
394 } 403 }
395 404
396 bool WebContentsViewAura::IsEventTracking() const { 405 bool WebContentsViewAura::IsEventTracking() const {
397 return false; 406 return false;
398 } 407 }
399 408
400 void WebContentsViewAura::CloseTabAfterEventTracking() { 409 void WebContentsViewAura::CloseTabAfterEventTracking() {
401 } 410 }
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
436 445
437 ui::OSExchangeDataProviderAura* provider = new ui::OSExchangeDataProviderAura; 446 ui::OSExchangeDataProviderAura* provider = new ui::OSExchangeDataProviderAura;
438 PrepareDragData(drop_data, provider); 447 PrepareDragData(drop_data, provider);
439 if (!image.isNull()) { 448 if (!image.isNull()) {
440 provider->set_drag_image(image); 449 provider->set_drag_image(image);
441 provider->set_drag_image_offset(image_offset); 450 provider->set_drag_image_offset(image_offset);
442 } 451 }
443 ui::OSExchangeData data(provider); // takes ownership of |provider|. 452 ui::OSExchangeData data(provider); // takes ownership of |provider|.
444 453
445 scoped_ptr<WebDragSourceAura> drag_source( 454 scoped_ptr<WebDragSourceAura> drag_source(
446 new WebDragSourceAura(web_contents_)); 455 new WebDragSourceAura(GetNativeView(), web_contents_));
447 456
448 // We need to enable recursive tasks on the message loop so we can get 457 // We need to enable recursive tasks on the message loop so we can get
449 // updates while in the system DoDragDrop loop. 458 // updates while in the system DoDragDrop loop.
450 int result_op = 0; 459 int result_op = 0;
451 { 460 {
452 // TODO(sad): Avoid using GetCursorScreenPoint here, since the drag may not 461 // TODO(sad): Avoid using GetCursorScreenPoint here, since the drag may not
453 // always start from a mouse-event (e.g. a touch or gesture event could 462 // always start from a mouse-event (e.g. a touch or gesture event could
454 // initiate the drag). The location information should be carried over from 463 // initiate the drag). The location information should be carried over from
455 // webkit. http://crbug.com/114754 464 // webkit. http://crbug.com/114754
456 gfx::Point location(gfx::Screen::GetCursorScreenPoint()); 465 gfx::Point location(gfx::Screen::GetCursorScreenPoint());
457 MessageLoop::ScopedNestableTaskAllower allow(MessageLoop::current()); 466 MessageLoop::ScopedNestableTaskAllower allow(MessageLoop::current());
458 result_op = aura::client::GetDragDropClient(root_window)->StartDragAndDrop( 467 result_op = aura::client::GetDragDropClient(root_window)->StartDragAndDrop(
459 data, root_window, location, ConvertFromWeb(operations)); 468 data, root_window, location, ConvertFromWeb(operations));
460 } 469 }
461 470
471 // Bail out immediately if the contents view window is gone. Note that it is
472 // not safe to access any class members after system drag-and-drop returns
473 // since the class instance might be gone. The local variable |drag_source|
474 // is still valid and we can check its window property that is set to NULL
475 // when the contents are gone.
476 if (!drag_source->window())
477 return;
478
462 EndDrag(ConvertToWeb(result_op)); 479 EndDrag(ConvertToWeb(result_op));
463 web_contents_->GetRenderViewHost()->DragSourceSystemDragEnded(); 480 web_contents_->GetRenderViewHost()->DragSourceSystemDragEnded();
464 } 481 }
465 482
466 void WebContentsViewAura::UpdateDragCursor(WebKit::WebDragOperation operation) { 483 void WebContentsViewAura::UpdateDragCursor(WebKit::WebDragOperation operation) {
467 current_drag_op_ = operation; 484 current_drag_op_ = operation;
468 } 485 }
469 486
470 void WebContentsViewAura::GotFocus() { 487 void WebContentsViewAura::GotFocus() {
471 if (web_contents_->GetDelegate()) 488 if (web_contents_->GetDelegate())
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after
659 OnDragEntered(event); 676 OnDragEntered(event);
660 677
661 web_contents_->GetRenderViewHost()->DragTargetDrop( 678 web_contents_->GetRenderViewHost()->DragTargetDrop(
662 event.location(), 679 event.location(),
663 gfx::Screen::GetCursorScreenPoint(), 680 gfx::Screen::GetCursorScreenPoint(),
664 ConvertAuraEventFlagsToWebInputEventModifiers(event.flags())); 681 ConvertAuraEventFlagsToWebInputEventModifiers(event.flags()));
665 if (drag_dest_delegate_) 682 if (drag_dest_delegate_)
666 drag_dest_delegate_->OnDrop(); 683 drag_dest_delegate_->OnDrop();
667 return current_drag_op_; 684 return current_drag_op_;
668 } 685 }
OLDNEW
« no previous file with comments | « content/browser/web_contents/web_contents_view_aura.h ('k') | content/browser/web_contents/web_contents_view_gtk.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698