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

Side by Side Diff: chrome/browser/ui/views/tabs/tab_drag_controller.cc

Issue 23523018: Fixes use after free during drag and drop. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Merge 2 trunk Created 7 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 "chrome/browser/ui/views/tabs/tab_drag_controller.h" 5 #include "chrome/browser/ui/views/tabs/tab_drag_controller.h"
6 6
7 #include <math.h> 7 #include <math.h>
8 #include <set> 8 #include <set>
9 9
10 #include "base/auto_reset.h" 10 #include "base/auto_reset.h"
(...skipping 25 matching lines...) Expand all
36 #include "grit/theme_resources.h" 36 #include "grit/theme_resources.h"
37 #include "ui/base/animation/animation.h" 37 #include "ui/base/animation/animation.h"
38 #include "ui/base/animation/animation_delegate.h" 38 #include "ui/base/animation/animation_delegate.h"
39 #include "ui/base/animation/slide_animation.h" 39 #include "ui/base/animation/slide_animation.h"
40 #include "ui/base/events/event_constants.h" 40 #include "ui/base/events/event_constants.h"
41 #include "ui/base/events/event_utils.h" 41 #include "ui/base/events/event_utils.h"
42 #include "ui/base/resource/resource_bundle.h" 42 #include "ui/base/resource/resource_bundle.h"
43 #include "ui/gfx/canvas.h" 43 #include "ui/gfx/canvas.h"
44 #include "ui/gfx/image/image_skia.h" 44 #include "ui/gfx/image/image_skia.h"
45 #include "ui/gfx/screen.h" 45 #include "ui/gfx/screen.h"
46 #include "ui/views/focus/view_storage.h"
46 #include "ui/views/widget/root_view.h" 47 #include "ui/views/widget/root_view.h"
47 #include "ui/views/widget/widget.h" 48 #include "ui/views/widget/widget.h"
48 49
49 #if defined(USE_ASH) 50 #if defined(USE_ASH)
50 #include "ash/shell.h" 51 #include "ash/shell.h"
51 #include "ash/wm/coordinate_conversion.h" 52 #include "ash/wm/coordinate_conversion.h"
52 #include "ash/wm/property_util.h" 53 #include "ash/wm/property_util.h"
53 #include "ash/wm/window_util.h" 54 #include "ash/wm/window_util.h"
54 #include "ui/aura/env.h" 55 #include "ui/aura/env.h"
55 #include "ui/aura/root_window.h" 56 #include "ui/aura/root_window.h"
(...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after
353 const int TabDragController::kVerticalDetachMagnetism = 15; 354 const int TabDragController::kVerticalDetachMagnetism = 15;
354 355
355 TabDragController::TabDragController() 356 TabDragController::TabDragController()
356 : detach_into_browser_(ShouldDetachIntoNewBrowser()), 357 : detach_into_browser_(ShouldDetachIntoNewBrowser()),
357 event_source_(EVENT_SOURCE_MOUSE), 358 event_source_(EVENT_SOURCE_MOUSE),
358 source_tabstrip_(NULL), 359 source_tabstrip_(NULL),
359 attached_tabstrip_(NULL), 360 attached_tabstrip_(NULL),
360 screen_(NULL), 361 screen_(NULL),
361 host_desktop_type_(chrome::HOST_DESKTOP_TYPE_NATIVE), 362 host_desktop_type_(chrome::HOST_DESKTOP_TYPE_NATIVE),
362 offset_to_width_ratio_(0), 363 offset_to_width_ratio_(0),
363 old_focused_view_(NULL), 364 old_focused_view_id_(
365 views::ViewStorage::GetInstance()->CreateStorageID()),
364 last_move_screen_loc_(0), 366 last_move_screen_loc_(0),
365 started_drag_(false), 367 started_drag_(false),
366 active_(true), 368 active_(true),
367 source_tab_index_(std::numeric_limits<size_t>::max()), 369 source_tab_index_(std::numeric_limits<size_t>::max()),
368 initial_move_(true), 370 initial_move_(true),
369 detach_behavior_(DETACHABLE), 371 detach_behavior_(DETACHABLE),
370 move_behavior_(REORDER), 372 move_behavior_(REORDER),
371 mouse_move_direction_(0), 373 mouse_move_direction_(0),
372 is_dragging_window_(false), 374 is_dragging_window_(false),
373 end_run_loop_behavior_(END_RUN_LOOP_STOP_DRAGGING), 375 end_run_loop_behavior_(END_RUN_LOOP_STOP_DRAGGING),
374 waiting_for_run_loop_to_exit_(false), 376 waiting_for_run_loop_to_exit_(false),
375 tab_strip_to_attach_to_after_exit_(NULL), 377 tab_strip_to_attach_to_after_exit_(NULL),
376 move_loop_widget_(NULL), 378 move_loop_widget_(NULL),
377 destroyed_(NULL), 379 destroyed_(NULL),
378 is_mutating_(false) { 380 is_mutating_(false) {
379 instance_ = this; 381 instance_ = this;
380 } 382 }
381 383
382 TabDragController::~TabDragController() { 384 TabDragController::~TabDragController() {
385 views::ViewStorage::GetInstance()->RemoveView(old_focused_view_id_);
386
383 if (instance_ == this) 387 if (instance_ == this)
384 instance_ = NULL; 388 instance_ = NULL;
385 389
386 if (destroyed_) 390 if (destroyed_)
387 *destroyed_ = true; 391 *destroyed_ = true;
388 392
389 if (move_loop_widget_) { 393 if (move_loop_widget_) {
390 move_loop_widget_->RemoveObserver(this); 394 move_loop_widget_->RemoveObserver(this);
391 SetTrackedByWorkspace(move_loop_widget_->GetNativeView(), true); 395 SetTrackedByWorkspace(move_loop_widget_->GetNativeView(), true);
392 SetWindowPositionManaged(move_loop_widget_->GetNativeView(), true); 396 SetWindowPositionManaged(move_loop_widget_->GetNativeView(), true);
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
491 bring_to_front_timer_.Stop(); 495 bring_to_front_timer_.Stop();
492 move_stacked_timer_.Stop(); 496 move_stacked_timer_.Stop();
493 497
494 if (waiting_for_run_loop_to_exit_) 498 if (waiting_for_run_loop_to_exit_)
495 return; 499 return;
496 500
497 if (!started_drag_) { 501 if (!started_drag_) {
498 if (!CanStartDrag(point_in_screen)) 502 if (!CanStartDrag(point_in_screen))
499 return; // User hasn't dragged far enough yet. 503 return; // User hasn't dragged far enough yet.
500 504
505 // On windows SaveFocus() may trigger a capture lost, which destroys us.
506 {
507 bool destroyed = false;
508 destroyed_ = &destroyed;
509 SaveFocus();
510 if (destroyed)
511 return;
512 destroyed_ = NULL;
513 }
501 started_drag_ = true; 514 started_drag_ = true;
502 SaveFocus();
503 Attach(source_tabstrip_, gfx::Point()); 515 Attach(source_tabstrip_, gfx::Point());
504 if (detach_into_browser_ && static_cast<int>(drag_data_.size()) == 516 if (detach_into_browser_ && static_cast<int>(drag_data_.size()) ==
505 GetModel(source_tabstrip_)->count()) { 517 GetModel(source_tabstrip_)->count()) {
506 RunMoveLoop(GetWindowOffset(point_in_screen)); 518 RunMoveLoop(GetWindowOffset(point_in_screen));
507 return; 519 return;
508 } 520 }
509 } 521 }
510 522
511 ContinueDragging(point_in_screen); 523 ContinueDragging(point_in_screen);
512 } 524 }
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after
736 } 748 }
737 } else if (dock_info_.type() != DockInfo::NONE && 749 } else if (dock_info_.type() != DockInfo::NONE &&
738 !dock_controllers_.empty()) { 750 !dock_controllers_.empty()) {
739 // Current dock position is the same as last, update the controller's 751 // Current dock position is the same as last, update the controller's
740 // in_enable_area state as it may have changed. 752 // in_enable_area state as it may have changed.
741 dock_controllers_.back()->UpdateInEnabledArea(dock_info_.in_enable_area()); 753 dock_controllers_.back()->UpdateInEnabledArea(dock_info_.in_enable_area());
742 } 754 }
743 } 755 }
744 756
745 void TabDragController::SaveFocus() { 757 void TabDragController::SaveFocus() {
746 DCHECK(!old_focused_view_); // This should only be invoked once.
747 DCHECK(source_tabstrip_); 758 DCHECK(source_tabstrip_);
748 old_focused_view_ = source_tabstrip_->GetFocusManager()->GetFocusedView(); 759 views::View* focused_view =
760 source_tabstrip_->GetFocusManager()->GetFocusedView();
761 if (focused_view)
762 views::ViewStorage::GetInstance()->StoreView(old_focused_view_id_,
763 focused_view);
749 source_tabstrip_->GetFocusManager()->SetFocusedView(source_tabstrip_); 764 source_tabstrip_->GetFocusManager()->SetFocusedView(source_tabstrip_);
765 // WARNING: we may have been deleted.
750 } 766 }
751 767
752 void TabDragController::RestoreFocus() { 768 void TabDragController::RestoreFocus() {
753 if (old_focused_view_ && attached_tabstrip_ == source_tabstrip_) 769 if (attached_tabstrip_ != source_tabstrip_)
754 old_focused_view_->GetFocusManager()->SetFocusedView(old_focused_view_); 770 return;
755 old_focused_view_ = NULL; 771 views::View* old_focused_view =
772 views::ViewStorage::GetInstance()->RetrieveView(
773 old_focused_view_id_);
774 if (!old_focused_view)
775 return;
776 old_focused_view->GetFocusManager()->SetFocusedView(old_focused_view);
756 } 777 }
757 778
758 bool TabDragController::CanStartDrag(const gfx::Point& point_in_screen) const { 779 bool TabDragController::CanStartDrag(const gfx::Point& point_in_screen) const {
759 // Determine if the mouse has moved beyond a minimum elasticity distance in 780 // Determine if the mouse has moved beyond a minimum elasticity distance in
760 // any direction from the starting point. 781 // any direction from the starting point.
761 static const int kMinimumDragDistance = 10; 782 static const int kMinimumDragDistance = 10;
762 int x_offset = abs(point_in_screen.x() - start_point_in_screen_.x()); 783 int x_offset = abs(point_in_screen.x() - start_point_in_screen_.x());
763 int y_offset = abs(point_in_screen.y() - start_point_in_screen_.y()); 784 int y_offset = abs(point_in_screen.y() - start_point_in_screen_.y());
764 return sqrt(pow(static_cast<float>(x_offset), 2) + 785 return sqrt(pow(static_cast<float>(x_offset), 2) +
765 pow(static_cast<float>(y_offset), 2)) > kMinimumDragDistance; 786 pow(static_cast<float>(y_offset), 2)) > kMinimumDragDistance;
(...skipping 1379 matching lines...) Expand 10 before | Expand all | Expand 10 after
2145 gfx::Vector2d TabDragController::GetWindowOffset( 2166 gfx::Vector2d TabDragController::GetWindowOffset(
2146 const gfx::Point& point_in_screen) { 2167 const gfx::Point& point_in_screen) {
2147 TabStrip* owning_tabstrip = (attached_tabstrip_ && detach_into_browser_) ? 2168 TabStrip* owning_tabstrip = (attached_tabstrip_ && detach_into_browser_) ?
2148 attached_tabstrip_ : source_tabstrip_; 2169 attached_tabstrip_ : source_tabstrip_;
2149 views::View* toplevel_view = owning_tabstrip->GetWidget()->GetContentsView(); 2170 views::View* toplevel_view = owning_tabstrip->GetWidget()->GetContentsView();
2150 2171
2151 gfx::Point point = point_in_screen; 2172 gfx::Point point = point_in_screen;
2152 views::View::ConvertPointFromScreen(toplevel_view, &point); 2173 views::View::ConvertPointFromScreen(toplevel_view, &point);
2153 return point.OffsetFromOrigin(); 2174 return point.OffsetFromOrigin();
2154 } 2175 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698