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

Side by Side Diff: ui/views/focus/focus_manager.cc

Issue 2750633004: Adds code to isolate use-after-free in Views (Closed)
Patch Set: rename to observed_view Created 3 years, 9 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
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 "ui/views/focus/focus_manager.h" 5 #include "ui/views/focus/focus_manager.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <cstring>
8 #include <vector> 9 #include <vector>
9 10
10 #include "base/auto_reset.h" 11 #include "base/auto_reset.h"
12 #include "base/debug/alias.h"
13 #include "base/debug/dump_without_crashing.h"
14 #include "base/debug/stack_trace.h"
11 #include "base/logging.h" 15 #include "base/logging.h"
12 #include "ui/base/accelerators/accelerator.h" 16 #include "ui/base/accelerators/accelerator.h"
13 #include "ui/base/ime/input_method.h" 17 #include "ui/base/ime/input_method.h"
14 #include "ui/base/ime/text_input_client.h" 18 #include "ui/base/ime/text_input_client.h"
15 #include "ui/events/event.h" 19 #include "ui/events/event.h"
16 #include "ui/events/keycodes/keyboard_codes.h" 20 #include "ui/events/keycodes/keyboard_codes.h"
17 #include "ui/views/focus/focus_manager_delegate.h" 21 #include "ui/views/focus/focus_manager_delegate.h"
18 #include "ui/views/focus/focus_search.h" 22 #include "ui/views/focus/focus_search.h"
19 #include "ui/views/focus/view_storage.h" 23 #include "ui/views/focus/view_storage.h"
20 #include "ui/views/focus/widget_focus_manager.h" 24 #include "ui/views/focus/widget_focus_manager.h"
21 #include "ui/views/view.h" 25 #include "ui/views/view.h"
22 #include "ui/views/widget/root_view.h" 26 #include "ui/views/widget/root_view.h"
23 #include "ui/views/widget/widget.h" 27 #include "ui/views/widget/widget.h"
24 #include "ui/views/widget/widget_delegate.h" 28 #include "ui/views/widget/widget_delegate.h"
25 29
26 namespace views { 30 namespace views {
31 namespace {
32
33 #if defined(OS_CHROMEOS)
34 // Crash appears to be specific to chromeos, so only log there.
35 bool should_log_focused_view = true;
36 #else
37 bool should_log_focused_view = false;
38 #endif
39
40 } // namespace
27 41
28 bool FocusManager::arrow_key_traversal_enabled_ = false; 42 bool FocusManager::arrow_key_traversal_enabled_ = false;
29 43
30 FocusManager::FocusManager(Widget* widget, 44 FocusManager::FocusManager(Widget* widget,
31 std::unique_ptr<FocusManagerDelegate> delegate) 45 std::unique_ptr<FocusManagerDelegate> delegate)
32 : widget_(widget), 46 : widget_(widget),
33 delegate_(std::move(delegate)), 47 delegate_(std::move(delegate)),
34 stored_focused_view_storage_id_( 48 stored_focused_view_storage_id_(
35 ViewStorage::GetInstance()->CreateStorageID()) { 49 ViewStorage::GetInstance()->CreateStorageID()) {
36 DCHECK(widget_); 50 DCHECK(widget_);
37 } 51 }
38 52
39 FocusManager::~FocusManager() { 53 FocusManager::~FocusManager() {
54 if (focused_view_)
55 focused_view_->RemoveObserver(this);
40 } 56 }
41 57
42 bool FocusManager::OnKeyEvent(const ui::KeyEvent& event) { 58 bool FocusManager::OnKeyEvent(const ui::KeyEvent& event) {
43 const int key_code = event.key_code(); 59 const int key_code = event.key_code();
44 60
45 if (event.type() != ui::ET_KEY_PRESSED && event.type() != ui::ET_KEY_RELEASED) 61 if (event.type() != ui::ET_KEY_PRESSED && event.type() != ui::ET_KEY_RELEASED)
46 return false; 62 return false;
47 63
48 if (shortcut_handling_suspended()) 64 if (shortcut_handling_suspended())
49 return true; 65 return true;
(...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after
321 #endif 337 #endif
322 338
323 // Update the reason for the focus change (since this is checked by 339 // Update the reason for the focus change (since this is checked by
324 // some listeners), then notify all listeners. 340 // some listeners), then notify all listeners.
325 focus_change_reason_ = reason; 341 focus_change_reason_ = reason;
326 for (FocusChangeListener& observer : focus_change_listeners_) 342 for (FocusChangeListener& observer : focus_change_listeners_)
327 observer.OnWillChangeFocus(focused_view_, view); 343 observer.OnWillChangeFocus(focused_view_, view);
328 344
329 View* old_focused_view = focused_view_; 345 View* old_focused_view = focused_view_;
330 focused_view_ = view; 346 focused_view_ = view;
331 if (old_focused_view) 347 if (old_focused_view) {
348 old_focused_view->RemoveObserver(this);
332 old_focused_view->Blur(); 349 old_focused_view->Blur();
350 }
333 // Also make |focused_view_| the stored focus view. This way the stored focus 351 // Also make |focused_view_| the stored focus view. This way the stored focus
334 // view is remembered if focus changes are requested prior to a show or while 352 // view is remembered if focus changes are requested prior to a show or while
335 // hidden. 353 // hidden.
336 SetStoredFocusView(focused_view_); 354 SetStoredFocusView(focused_view_);
337 if (focused_view_) 355 if (focused_view_) {
356 focused_view_->AddObserver(this);
338 focused_view_->Focus(); 357 focused_view_->Focus();
358 if (should_log_focused_view) {
359 stack_when_focused_view_set_ =
360 base::MakeUnique<base::debug::StackTrace>();
361 }
362 } else {
363 stack_when_focused_view_set_.reset();
364 }
339 365
340 for (FocusChangeListener& observer : focus_change_listeners_) 366 for (FocusChangeListener& observer : focus_change_listeners_)
341 observer.OnDidChangeFocus(old_focused_view, focused_view_); 367 observer.OnDidChangeFocus(old_focused_view, focused_view_);
342 } 368 }
343 369
344 void FocusManager::ClearFocus() { 370 void FocusManager::ClearFocus() {
345 // SetFocusedView(NULL) is going to clear out the stored view to. We need to 371 // SetFocusedView(NULL) is going to clear out the stored view to. We need to
346 // persist it in this case. 372 // persist it in this case.
347 views::View* focused_view = GetStoredFocusView(); 373 views::View* focused_view = GetStoredFocusView();
348 SetFocusedView(NULL); 374 SetFocusedView(NULL);
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after
558 584
559 // |keyboard_accessible_| is only used on Mac. 585 // |keyboard_accessible_| is only used on Mac.
560 #if defined(OS_MACOSX) 586 #if defined(OS_MACOSX)
561 return keyboard_accessible_ ? view->IsAccessibilityFocusable() 587 return keyboard_accessible_ ? view->IsAccessibilityFocusable()
562 : view->IsFocusable(); 588 : view->IsFocusable();
563 #else 589 #else
564 return view->IsAccessibilityFocusable(); 590 return view->IsAccessibilityFocusable();
565 #endif 591 #endif
566 } 592 }
567 593
594 void FocusManager::OnViewIsDeleting(View* view) {
595 CHECK_EQ(view, focused_view_);
596
597 // Widget forwards the appropriate calls such that we should never end up
598 // here. None-the-less crashes indicate we are. This logs the stack once when
599 // this happens.
600 // TODO(sky): remove when cause of 687232 is found.
601 if (stack_when_focused_view_set_ && should_log_focused_view) {
602 should_log_focused_view = false;
603 size_t stack_size = 0u;
604 const void* const* instruction_pointers =
605 stack_when_focused_view_set_->Addresses(&stack_size);
606 static constexpr size_t kMaxStackSize = 100;
607 const void* instruction_pointers_copy[kMaxStackSize];
608 // Insert markers bracketing the crash to make it easier to locate.
609 memset(&instruction_pointers_copy[0], 0xAB,
610 sizeof(instruction_pointers_copy[0]));
611 const size_t last_marker_index =
612 std::min(kMaxStackSize - 1, stack_size + 1);
613 memset(&instruction_pointers_copy[last_marker_index], 0xAB,
614 sizeof(instruction_pointers_copy[last_marker_index]));
615 std::memcpy(&instruction_pointers_copy[1], instruction_pointers,
616 std::min(kMaxStackSize - 2, stack_size) * sizeof(const void*));
617 base::debug::Alias(&stack_size);
618 base::debug::Alias(&instruction_pointers_copy);
619 base::debug::DumpWithoutCrashing();
620 stack_when_focused_view_set_.reset();
621 }
622
623 focused_view_->RemoveObserver(this);
624 focused_view_ = nullptr;
625 }
626
568 } // namespace views 627 } // namespace views
OLDNEW
« no previous file with comments | « ui/views/focus/focus_manager.h ('k') | ui/views/view.cc » ('j') | ui/views/view_observer.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698