1 // Copyright 2014 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 "athena/content/web_activity.h"
6
7 #include "athena/activity/public/activity_manager.h"
8 #include "athena/input/public/accelerator_manager.h"
9 #include "content/public/browser/native_web_keyboard_event.h"
10 #include "content/public/browser/web_contents.h"
11 #include "ui/views/controls/webview/unhandled_keyboard_event_handler.h"
12 #include "ui/views/controls/webview/webview.h"
13 #include "ui/views/focus/focus_manager.h"
14
15 namespace athena {
16 namespace {
17
18 class WebActivityController : public AcceleratorHandler {
19 public:
20 enum Command {
21 CMD_BACK,
22 CMD_FORWARD,
23 CMD_RELOAD,
24 CMD_RELOAD_IGNORE_CACHE,
25 };
26
WebActivityController(views::WebView * web_view)27 explicit WebActivityController(views::WebView* web_view)
28 : web_view_(web_view), reserved_accelerator_enabled_(true) {}
~WebActivityController()29 virtual ~WebActivityController() {}
30
31 // Installs accelerators for web activity.
InstallAccelerators()32 void InstallAccelerators() {
33 accelerator_manager_ = AcceleratorManager::CreateForFocusManager(
34 web_view_->GetFocusManager()).Pass();
35 const AcceleratorData accelerator_data[] = {
36 {TRIGGER_ON_PRESS, ui::VKEY_R, ui::EF_CONTROL_DOWN, CMD_RELOAD,
37 AF_NONE},
38 {TRIGGER_ON_PRESS, ui::VKEY_BROWSER_REFRESH, ui::EF_NONE, CMD_RELOAD,
39 AF_NONE},
40 {TRIGGER_ON_PRESS, ui::VKEY_BROWSER_REFRESH, ui::EF_CONTROL_DOWN,
41 CMD_RELOAD_IGNORE_CACHE, AF_NONE},
42 {TRIGGER_ON_PRESS, ui::VKEY_BROWSER_FORWARD, ui::EF_NONE, CMD_FORWARD,
43 AF_NONE},
44 {TRIGGER_ON_PRESS, ui::VKEY_BROWSER_BACK, ui::EF_NONE, CMD_BACK,
45 AF_NONE},
46 };
47 accelerator_manager_->RegisterAccelerators(
48 accelerator_data, arraysize(accelerator_data), this);
49 }
50
51 // Methods that are called before and after key events are consumed by the web
52 // contents.
53 // See the documentation in WebContentsDelegate: for more details.
PreHandleKeyboardEvent(content::WebContents * source,const content::NativeWebKeyboardEvent & event,bool * is_keyboard_shortcut)54 bool PreHandleKeyboardEvent(content::WebContents* source,
55 const content::NativeWebKeyboardEvent& event,
56 bool* is_keyboard_shortcut) {
57 ui::Accelerator accelerator(
58 static_cast<ui::KeyboardCode>(event.windowsKeyCode),
59 content::GetModifiersFromNativeWebKeyboardEvent(event));
60 if (event.type == blink::WebInputEvent::KeyUp)
61 accelerator.set_type(ui::ET_KEY_RELEASED);
62
63 if (reserved_accelerator_enabled_ &&
64 accelerator_manager_->IsRegistered(accelerator, AF_RESERVED)) {
65 return web_view_->GetFocusManager()->ProcessAccelerator(accelerator);
66 }
67 *is_keyboard_shortcut =
68 accelerator_manager_->IsRegistered(accelerator, AF_NONE);
69 return false;
70 }
71
HandleKeyboardEvent(content::WebContents * source,const content::NativeWebKeyboardEvent & event)72 void HandleKeyboardEvent(content::WebContents* source,
73 const content::NativeWebKeyboardEvent& event) {
74 unhandled_keyboard_event_handler_.HandleKeyboardEvent(
75 event, web_view_->GetFocusManager());
76 }
77
78 private:
79 // AcceleratorHandler:
IsCommandEnabled(int command_id) const80 virtual bool IsCommandEnabled(int command_id) const OVERRIDE {
81 switch (command_id) {
82 case CMD_RELOAD:
83 return true;
84 case CMD_BACK:
85 return web_view_->GetWebContents()->GetController().CanGoBack();
86 case CMD_FORWARD:
87 return web_view_->GetWebContents()->GetController().CanGoForward();
88 }
89 return false;
90 }
91
OnAcceleratorFired(int command_id,const ui::Accelerator & accelerator)92 virtual bool OnAcceleratorFired(int command_id,
93 const ui::Accelerator& accelerator) OVERRIDE {
94 switch (command_id) {
95 case CMD_RELOAD:
96 web_view_->GetWebContents()->GetController().Reload(false);
97 return true;
98 case CMD_RELOAD_IGNORE_CACHE:
99 web_view_->GetWebContents()->GetController().ReloadIgnoringCache(false);
100 return true;
101 case CMD_BACK:
102 web_view_->GetWebContents()->GetController().GoBack();
103 return true;
104 case CMD_FORWARD:
105 web_view_->GetWebContents()->GetController().GoForward();
106 return true;
107 }
108 return false;
109 }
110
111 views::WebView* web_view_;
112 bool reserved_accelerator_enabled_;
113 scoped_ptr<AcceleratorManager> accelerator_manager_;
114 views::UnhandledKeyboardEventHandler unhandled_keyboard_event_handler_;
115
116 DISALLOW_COPY_AND_ASSIGN(WebActivityController);
117 };
118
119 // A web view for athena's web activity.
120 class AthenaWebView : public views::WebView {
121 public:
AthenaWebView(content::BrowserContext * context)122 AthenaWebView(content::BrowserContext* context)
123 : views::WebView(context), controller_(new WebActivityController(this)) {}
~AthenaWebView()124 virtual ~AthenaWebView() {}
125
InstallAccelerators()126 void InstallAccelerators() { controller_->InstallAccelerators(); }
127
128 private:
129 // WebContentsDelegate:
PreHandleKeyboardEvent(content::WebContents * source,const content::NativeWebKeyboardEvent & event,bool * is_keyboard_shortcut)130 virtual bool PreHandleKeyboardEvent(
131 content::WebContents* source,
132 const content::NativeWebKeyboardEvent& event,
133 bool* is_keyboard_shortcut) OVERRIDE {
134 return controller_->PreHandleKeyboardEvent(
135 source, event, is_keyboard_shortcut);
136 }
137
HandleKeyboardEvent(content::WebContents * source,const content::NativeWebKeyboardEvent & event)138 virtual void HandleKeyboardEvent(
139 content::WebContents* source,
140 const content::NativeWebKeyboardEvent& event) OVERRIDE {
141 controller_->HandleKeyboardEvent(source, event);
142 }
143
144 scoped_ptr<WebActivityController> controller_;
145
146 DISALLOW_COPY_AND_ASSIGN(AthenaWebView);
147 };
148
149 } // namespace
150
WebActivity(content::BrowserContext * browser_context,const GURL & url)151 WebActivity::WebActivity(content::BrowserContext* browser_context,
152 const GURL& url)
153 : browser_context_(browser_context), url_(url), web_view_(NULL) {
154 }
155
~WebActivity()156 WebActivity::~WebActivity() {
157 }
158
GetActivityViewModel()159 ActivityViewModel* WebActivity::GetActivityViewModel() {
160 return this;
161 }
162
Init()163 void WebActivity::Init() {
164 DCHECK(web_view_);
165 static_cast<AthenaWebView*>(web_view_)->InstallAccelerators();
166 }
167
GetRepresentativeColor()168 SkColor WebActivity::GetRepresentativeColor() {
169 // TODO(sad): Compute the color from the favicon.
170 return SK_ColorGRAY;
171 }
172
GetTitle()173 base::string16 WebActivity::GetTitle() {
174 return web_view_->GetWebContents()->GetTitle();
175 }
176
GetContentsView()177 views::View* WebActivity::GetContentsView() {
178 if (!web_view_) {
179 web_view_ = new AthenaWebView(browser_context_);
180 web_view_->LoadInitialURL(url_);
181 Observe(web_view_->GetWebContents());
182 }
183 return web_view_;
184 }
185
TitleWasSet(content::NavigationEntry * entry,bool explicit_set)186 void WebActivity::TitleWasSet(content::NavigationEntry* entry,
187 bool explicit_set) {
188 ActivityManager::Get()->UpdateActivity(this);
189 }
190
DidUpdateFaviconURL(const std::vector<content::FaviconURL> & candidates)191 void WebActivity::DidUpdateFaviconURL(
192 const std::vector<content::FaviconURL>& candidates) {
193 ActivityManager::Get()->UpdateActivity(this);
194 }
195
196 } // namespace athena
197