1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "chrome/browser/ui/views/tab_contents/chrome_web_contents_view_focus_helper.h"
6 
7 #include "base/memory/ptr_util.h"
8 #include "chrome/browser/ui/sad_tab_helper.h"
9 #include "chrome/browser/ui/views/sad_tab_view.h"
10 #include "components/web_modal/web_contents_modal_dialog_manager.h"
11 #include "content/public/browser/render_widget_host_view.h"
12 #include "content/public/browser/web_contents.h"
13 #include "ui/views/focus/focus_manager.h"
14 #include "ui/views/widget/widget.h"
15 
16 // static
CreateForWebContents(content::WebContents * web_contents)17 void ChromeWebContentsViewFocusHelper::CreateForWebContents(
18     content::WebContents* web_contents) {
19   if (!ChromeWebContentsViewFocusHelper::FromWebContents(web_contents)) {
20     web_contents->SetUserData(
21         ChromeWebContentsViewFocusHelper::UserDataKey(),
22         base::WrapUnique(new ChromeWebContentsViewFocusHelper(web_contents)));
23   }
24 }
25 
ChromeWebContentsViewFocusHelper(content::WebContents * web_contents)26 ChromeWebContentsViewFocusHelper::ChromeWebContentsViewFocusHelper(
27     content::WebContents* web_contents)
28     : web_contents_(web_contents) {}
29 
Focus()30 bool ChromeWebContentsViewFocusHelper::Focus() {
31   SadTabHelper* sad_tab_helper = SadTabHelper::FromWebContents(web_contents_);
32   if (sad_tab_helper) {
33     SadTabView* sad_tab = static_cast<SadTabView*>(sad_tab_helper->sad_tab());
34     if (sad_tab) {
35       sad_tab->RequestFocus();
36       return true;
37     }
38   }
39 
40   const web_modal::WebContentsModalDialogManager* manager =
41       web_modal::WebContentsModalDialogManager::FromWebContents(web_contents_);
42   if (manager && manager->IsDialogActive()) {
43     manager->FocusTopmostDialog();
44     return true;
45   }
46 
47   return false;
48 }
49 
TakeFocus(bool reverse)50 bool ChromeWebContentsViewFocusHelper::TakeFocus(bool reverse) {
51   views::FocusManager* focus_manager = GetFocusManager();
52   if (focus_manager) {
53     focus_manager->AdvanceFocus(reverse);
54     return true;
55   }
56   return false;
57 }
58 
StoreFocus()59 void ChromeWebContentsViewFocusHelper::StoreFocus() {
60   last_focused_view_tracker_.SetView(nullptr);
61   if (GetFocusManager())
62     last_focused_view_tracker_.SetView(GetFocusManager()->GetFocusedView());
63 }
64 
RestoreFocus()65 bool ChromeWebContentsViewFocusHelper::RestoreFocus() {
66   views::View* view_to_focus = GetStoredFocus();
67   last_focused_view_tracker_.SetView(nullptr);
68   if (view_to_focus) {
69     view_to_focus->RequestFocus();
70     return true;
71   }
72   return false;
73 }
74 
ResetStoredFocus()75 void ChromeWebContentsViewFocusHelper::ResetStoredFocus() {
76   last_focused_view_tracker_.SetView(nullptr);
77 }
78 
GetStoredFocus()79 views::View* ChromeWebContentsViewFocusHelper::GetStoredFocus() {
80   views::View* last_focused_view = last_focused_view_tracker_.view();
81   if (last_focused_view && last_focused_view->IsFocusable() &&
82       GetFocusManager()->ContainsView(last_focused_view)) {
83     return last_focused_view;
84   }
85   return nullptr;
86 }
87 
GetActiveNativeView()88 gfx::NativeView ChromeWebContentsViewFocusHelper::GetActiveNativeView() {
89   return web_contents_->GetNativeView();
90 }
91 
GetTopLevelWidget()92 views::Widget* ChromeWebContentsViewFocusHelper::GetTopLevelWidget() {
93   return views::Widget::GetTopLevelWidgetForNativeView(GetActiveNativeView());
94 }
95 
GetFocusManager()96 views::FocusManager* ChromeWebContentsViewFocusHelper::GetFocusManager() {
97   views::Widget* toplevel_widget = GetTopLevelWidget();
98   return toplevel_widget ? toplevel_widget->GetFocusManager() : NULL;
99 }
100 
101 WEB_CONTENTS_USER_DATA_KEY_IMPL(ChromeWebContentsViewFocusHelper)
102