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

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: Created 8 years, 3 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)
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 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
361 void WebContentsViewAura::StoreFocus() { 389 void WebContentsViewAura::StoreFocus() {
362 if (delegate_.get()) 390 if (delegate_.get())
363 delegate_->StoreFocus(); 391 delegate_->StoreFocus();
364 } 392 }
365 393
366 void WebContentsViewAura::RestoreFocus() { 394 void WebContentsViewAura::RestoreFocus() {
367 if (delegate_.get()) 395 if (delegate_.get())
368 delegate_->RestoreFocus(); 396 delegate_->RestoreFocus();
369 } 397 }
370 398
371 bool WebContentsViewAura::IsDoingDrag() const {
372 aura::RootWindow* root_window = GetNativeView()->GetRootWindow();
373 if (aura::client::GetDragDropClient(root_window))
374 return aura::client::GetDragDropClient(root_window)->IsDragDropInProgress();
375 return false;
376 }
377
378 void WebContentsViewAura::CancelDragAndCloseTab() {
379 DCHECK(IsDoingDrag());
380 // We can't close the tab while we're in the drag and
381 // |drag_handler_->CancelDrag()| is async. Instead, set a flag to cancel
382 // the drag and when the drag nested message loop ends, close the tab.
383 aura::RootWindow* root_window = GetNativeView()->GetRootWindow();
384 if (aura::client::GetDragDropClient(root_window))
385 aura::client::GetDragDropClient(root_window)->DragCancel();
386
387 close_tab_after_drag_ends_ = true;
388 }
389
390 WebDropData* WebContentsViewAura::GetDropData() const { 399 WebDropData* WebContentsViewAura::GetDropData() const {
391 return NULL; 400 return NULL;
392 } 401 }
393 402
394 bool WebContentsViewAura::IsEventTracking() const { 403 bool WebContentsViewAura::IsEventTracking() const {
395 return false; 404 return false;
396 } 405 }
397 406
398 void WebContentsViewAura::CloseTabAfterEventTracking() { 407 void WebContentsViewAura::CloseTabAfterEventTracking() {
399 } 408 }
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
434 443
435 ui::OSExchangeDataProviderAura* provider = new ui::OSExchangeDataProviderAura; 444 ui::OSExchangeDataProviderAura* provider = new ui::OSExchangeDataProviderAura;
436 PrepareDragData(drop_data, provider); 445 PrepareDragData(drop_data, provider);
437 if (!image.isNull()) { 446 if (!image.isNull()) {
438 provider->set_drag_image(image); 447 provider->set_drag_image(image);
439 provider->set_drag_image_offset(image_offset); 448 provider->set_drag_image_offset(image_offset);
440 } 449 }
441 ui::OSExchangeData data(provider); // takes ownership of |provider|. 450 ui::OSExchangeData data(provider); // takes ownership of |provider|.
442 451
443 scoped_ptr<WebDragSourceAura> drag_source( 452 scoped_ptr<WebDragSourceAura> drag_source(
444 new WebDragSourceAura(web_contents_)); 453 new WebDragSourceAura(GetNativeView(), web_contents_));
445 454
446 // We need to enable recursive tasks on the message loop so we can get 455 // We need to enable recursive tasks on the message loop so we can get
447 // updates while in the system DoDragDrop loop. 456 // updates while in the system DoDragDrop loop.
448 int result_op = 0; 457 int result_op = 0;
449 { 458 {
450 // TODO(sad): Avoid using GetCursorScreenPoint here, since the drag may not 459 // TODO(sad): Avoid using GetCursorScreenPoint here, since the drag may not
451 // always start from a mouse-event (e.g. a touch or gesture event could 460 // always start from a mouse-event (e.g. a touch or gesture event could
452 // initiate the drag). The location information should be carried over from 461 // initiate the drag). The location information should be carried over from
453 // webkit. http://crbug.com/114754 462 // webkit. http://crbug.com/114754
454 gfx::Point location(gfx::Screen::GetCursorScreenPoint()); 463 gfx::Point location(gfx::Screen::GetCursorScreenPoint());
455 MessageLoop::ScopedNestableTaskAllower allow(MessageLoop::current()); 464 MessageLoop::ScopedNestableTaskAllower allow(MessageLoop::current());
456 result_op = aura::client::GetDragDropClient(root_window)->StartDragAndDrop( 465 result_op = aura::client::GetDragDropClient(root_window)->StartDragAndDrop(
457 data, root_window, location, ConvertFromWeb(operations)); 466 data, root_window, location, ConvertFromWeb(operations));
458 } 467 }
459 468
469 // Bail out immediately if the contents view window is gone. Note that it is
470 // not safe to access any class members after system drag-and-drop returns
471 // since the class instance might be gone. The local variable |drag_source|
472 // is still valid and we can check its window property that is set to NULL
473 // when the contents are gone.
474 if (!drag_source->window())
475 return;
476
460 EndDrag(ConvertToWeb(result_op)); 477 EndDrag(ConvertToWeb(result_op));
461 web_contents_->GetRenderViewHost()->DragSourceSystemDragEnded(); 478 web_contents_->GetRenderViewHost()->DragSourceSystemDragEnded();
462 } 479 }
463 480
464 void WebContentsViewAura::UpdateDragCursor(WebKit::WebDragOperation operation) { 481 void WebContentsViewAura::UpdateDragCursor(WebKit::WebDragOperation operation) {
465 current_drag_op_ = operation; 482 current_drag_op_ = operation;
466 } 483 }
467 484
468 void WebContentsViewAura::GotFocus() { 485 void WebContentsViewAura::GotFocus() {
469 if (web_contents_->GetDelegate()) 486 if (web_contents_->GetDelegate())
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after
656 OnDragEntered(event); 673 OnDragEntered(event);
657 674
658 web_contents_->GetRenderViewHost()->DragTargetDrop( 675 web_contents_->GetRenderViewHost()->DragTargetDrop(
659 event.location(), 676 event.location(),
660 gfx::Screen::GetCursorScreenPoint(), 677 gfx::Screen::GetCursorScreenPoint(),
661 ConvertAuraEventFlagsToWebInputEventModifiers(event.flags())); 678 ConvertAuraEventFlagsToWebInputEventModifiers(event.flags()));
662 if (drag_dest_delegate_) 679 if (drag_dest_delegate_)
663 drag_dest_delegate_->OnDrop(); 680 drag_dest_delegate_->OnDrop();
664 return current_drag_op_; 681 return current_drag_op_;
665 } 682 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698