• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 The Chromium Embedded Framework Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be found
3 // in the LICENSE file.
4 
5 #include "libcef/browser/views/browser_view_impl.h"
6 
7 #include "libcef/browser/browser_host_base.h"
8 #include "libcef/browser/browser_util.h"
9 #include "libcef/browser/chrome/views/chrome_browser_view.h"
10 #include "libcef/browser/context.h"
11 #include "libcef/browser/request_context_impl.h"
12 #include "libcef/browser/thread_util.h"
13 #include "libcef/browser/views/window_impl.h"
14 
15 #include "content/public/browser/native_web_keyboard_event.h"
16 #include "ui/content_accelerators/accelerator_util.h"
17 
18 // static
CreateBrowserView(CefRefPtr<CefClient> client,const CefString & url,const CefBrowserSettings & settings,CefRefPtr<CefDictionaryValue> extra_info,CefRefPtr<CefRequestContext> request_context,CefRefPtr<CefBrowserViewDelegate> delegate)19 CefRefPtr<CefBrowserView> CefBrowserView::CreateBrowserView(
20     CefRefPtr<CefClient> client,
21     const CefString& url,
22     const CefBrowserSettings& settings,
23     CefRefPtr<CefDictionaryValue> extra_info,
24     CefRefPtr<CefRequestContext> request_context,
25     CefRefPtr<CefBrowserViewDelegate> delegate) {
26   return CefBrowserViewImpl::Create(client, url, settings, extra_info,
27                                     request_context, delegate);
28 }
29 
30 // static
GetForBrowser(CefRefPtr<CefBrowser> browser)31 CefRefPtr<CefBrowserView> CefBrowserView::GetForBrowser(
32     CefRefPtr<CefBrowser> browser) {
33   CEF_REQUIRE_UIT_RETURN(nullptr);
34 
35   CefBrowserHostBase* browser_impl =
36       static_cast<CefBrowserHostBase*>(browser.get());
37   if (browser_impl && browser_impl->is_views_hosted())
38     return browser_impl->GetBrowserView();
39   return nullptr;
40 }
41 
42 // static
Create(CefRefPtr<CefClient> client,const CefString & url,const CefBrowserSettings & settings,CefRefPtr<CefDictionaryValue> extra_info,CefRefPtr<CefRequestContext> request_context,CefRefPtr<CefBrowserViewDelegate> delegate)43 CefRefPtr<CefBrowserViewImpl> CefBrowserViewImpl::Create(
44     CefRefPtr<CefClient> client,
45     const CefString& url,
46     const CefBrowserSettings& settings,
47     CefRefPtr<CefDictionaryValue> extra_info,
48     CefRefPtr<CefRequestContext> request_context,
49     CefRefPtr<CefBrowserViewDelegate> delegate) {
50   CEF_REQUIRE_UIT_RETURN(nullptr);
51 
52   if (!request_context) {
53     request_context = CefRequestContext::GetGlobalContext();
54   }
55 
56   // Verify that the browser context is valid. Do this here instead of risking
57   // potential browser creation failure when this view is added to the window.
58   auto request_context_impl =
59       static_cast<CefRequestContextImpl*>(request_context.get());
60   if (!request_context_impl->VerifyBrowserContext()) {
61     return nullptr;
62   }
63 
64   CefRefPtr<CefBrowserViewImpl> browser_view = new CefBrowserViewImpl(delegate);
65   browser_view->SetPendingBrowserCreateParams(client, url, settings, extra_info,
66                                               request_context);
67   browser_view->Initialize();
68   browser_view->SetDefaults(settings);
69   return browser_view;
70 }
71 
72 // static
CreateForPopup(const CefBrowserSettings & settings,CefRefPtr<CefBrowserViewDelegate> delegate)73 CefRefPtr<CefBrowserViewImpl> CefBrowserViewImpl::CreateForPopup(
74     const CefBrowserSettings& settings,
75     CefRefPtr<CefBrowserViewDelegate> delegate) {
76   CEF_REQUIRE_UIT_RETURN(nullptr);
77 
78   CefRefPtr<CefBrowserViewImpl> browser_view = new CefBrowserViewImpl(delegate);
79   browser_view->Initialize();
80   browser_view->SetDefaults(settings);
81   return browser_view;
82 }
83 
WebContentsCreated(content::WebContents * web_contents)84 void CefBrowserViewImpl::WebContentsCreated(
85     content::WebContents* web_contents) {
86   if (web_view())
87     web_view()->SetWebContents(web_contents);
88 }
89 
BrowserCreated(CefBrowserHostBase * browser,base::RepeatingClosure on_bounds_changed)90 void CefBrowserViewImpl::BrowserCreated(
91     CefBrowserHostBase* browser,
92     base::RepeatingClosure on_bounds_changed) {
93   browser_ = browser;
94   on_bounds_changed_ = on_bounds_changed;
95 }
96 
BrowserDestroyed(CefBrowserHostBase * browser)97 void CefBrowserViewImpl::BrowserDestroyed(CefBrowserHostBase* browser) {
98   DCHECK_EQ(browser, browser_);
99   browser_ = nullptr;
100 
101   if (web_view())
102     web_view()->SetWebContents(nullptr);
103 }
104 
HandleKeyboardEvent(const content::NativeWebKeyboardEvent & event)105 bool CefBrowserViewImpl::HandleKeyboardEvent(
106     const content::NativeWebKeyboardEvent& event) {
107   if (!root_view())
108     return false;
109 
110   views::FocusManager* focus_manager = root_view()->GetFocusManager();
111   if (!focus_manager)
112     return false;
113 
114   if (HandleAccelerator(event, focus_manager))
115     return true;
116 
117   // Give the CefWindowDelegate a chance to handle the event.
118   CefRefPtr<CefWindow> window =
119       view_util::GetWindowFor(root_view()->GetWidget());
120   CefWindowImpl* window_impl = static_cast<CefWindowImpl*>(window.get());
121   if (window_impl) {
122     CefKeyEvent cef_event;
123     if (browser_util::GetCefKeyEvent(event, cef_event) &&
124         window_impl->OnKeyEvent(cef_event)) {
125       return true;
126     }
127   }
128 
129   // Proceed with default native handling.
130   return unhandled_keyboard_event_handler_.HandleKeyboardEvent(event,
131                                                                focus_manager);
132 }
133 
GetBrowser()134 CefRefPtr<CefBrowser> CefBrowserViewImpl::GetBrowser() {
135   CEF_REQUIRE_VALID_RETURN(nullptr);
136   return browser_;
137 }
138 
GetChromeToolbar()139 CefRefPtr<CefView> CefBrowserViewImpl::GetChromeToolbar() {
140   CEF_REQUIRE_VALID_RETURN(nullptr);
141   if (cef::IsChromeRuntimeEnabled()) {
142     return static_cast<ChromeBrowserView*>(root_view())->cef_toolbar();
143   }
144 
145   return nullptr;
146 }
147 
SetPreferAccelerators(bool prefer_accelerators)148 void CefBrowserViewImpl::SetPreferAccelerators(bool prefer_accelerators) {
149   CEF_REQUIRE_VALID_RETURN_VOID();
150   if (web_view())
151     web_view()->set_allow_accelerators(prefer_accelerators);
152 }
153 
RequestFocus()154 void CefBrowserViewImpl::RequestFocus() {
155   CEF_REQUIRE_VALID_RETURN_VOID();
156   // Always execute asynchronously to work around issue #3040.
157   CEF_POST_TASK(CEF_UIT,
158                 base::BindOnce(&CefBrowserViewImpl::RequestFocusInternal,
159                                weak_ptr_factory_.GetWeakPtr()));
160 }
161 
SetBackgroundColor(cef_color_t color)162 void CefBrowserViewImpl::SetBackgroundColor(cef_color_t color) {
163   CEF_REQUIRE_VALID_RETURN_VOID();
164   ParentClass::SetBackgroundColor(color);
165   if (web_view())
166     web_view()->SetResizeBackgroundColor(color);
167 }
168 
Detach()169 void CefBrowserViewImpl::Detach() {
170   ParentClass::Detach();
171 
172   // root_view() will be nullptr now.
173   DCHECK(!root_view());
174 
175   if (browser_) {
176     // With the Alloy runtime |browser_| will disappear when WindowDestroyed()
177     // indirectly calls BrowserDestroyed() so keep a reference.
178     CefRefPtr<CefBrowserHostBase> browser = browser_;
179 
180     // Force the browser to be destroyed.
181     browser->WindowDestroyed();
182   }
183 }
184 
GetDebugInfo(base::DictionaryValue * info,bool include_children)185 void CefBrowserViewImpl::GetDebugInfo(base::DictionaryValue* info,
186                                       bool include_children) {
187   ParentClass::GetDebugInfo(info, include_children);
188   if (browser_)
189     info->SetString("url", browser_->GetMainFrame()->GetURL().ToString());
190 }
191 
OnBrowserViewAdded()192 void CefBrowserViewImpl::OnBrowserViewAdded() {
193   if (!browser_ && pending_browser_create_params_) {
194     // Top-level browsers will be created when this view is added to the views
195     // hierarchy.
196     pending_browser_create_params_->browser_view = this;
197 
198     CefBrowserHostBase::Create(*pending_browser_create_params_);
199     DCHECK(browser_);
200 
201     pending_browser_create_params_.reset(nullptr);
202   }
203 }
204 
OnBoundsChanged()205 void CefBrowserViewImpl::OnBoundsChanged() {
206   if (!on_bounds_changed_.is_null())
207     on_bounds_changed_.Run();
208 }
209 
CefBrowserViewImpl(CefRefPtr<CefBrowserViewDelegate> delegate)210 CefBrowserViewImpl::CefBrowserViewImpl(
211     CefRefPtr<CefBrowserViewDelegate> delegate)
212     : ParentClass(delegate), weak_ptr_factory_(this) {}
213 
SetPendingBrowserCreateParams(CefRefPtr<CefClient> client,const CefString & url,const CefBrowserSettings & settings,CefRefPtr<CefDictionaryValue> extra_info,CefRefPtr<CefRequestContext> request_context)214 void CefBrowserViewImpl::SetPendingBrowserCreateParams(
215     CefRefPtr<CefClient> client,
216     const CefString& url,
217     const CefBrowserSettings& settings,
218     CefRefPtr<CefDictionaryValue> extra_info,
219     CefRefPtr<CefRequestContext> request_context) {
220   DCHECK(!pending_browser_create_params_);
221   pending_browser_create_params_.reset(new CefBrowserCreateParams());
222   pending_browser_create_params_->client = client;
223   pending_browser_create_params_->url = url;
224   pending_browser_create_params_->settings = settings;
225   pending_browser_create_params_->extra_info = extra_info;
226   pending_browser_create_params_->request_context = request_context;
227 }
228 
SetDefaults(const CefBrowserSettings & settings)229 void CefBrowserViewImpl::SetDefaults(const CefBrowserSettings& settings) {
230   SetBackgroundColor(
231       CefContext::Get()->GetBackgroundColor(&settings, STATE_DISABLED));
232 }
233 
CreateRootView()234 views::View* CefBrowserViewImpl::CreateRootView() {
235   if (cef::IsChromeRuntimeEnabled()) {
236     return new ChromeBrowserView(delegate(), this);
237   }
238 
239   return new CefBrowserViewView(delegate(), this);
240 }
241 
InitializeRootView()242 void CefBrowserViewImpl::InitializeRootView() {
243   if (cef::IsChromeRuntimeEnabled()) {
244     static_cast<ChromeBrowserView*>(root_view())->Initialize();
245   } else {
246     static_cast<CefBrowserViewView*>(root_view())->Initialize();
247   }
248 }
249 
web_view() const250 views::WebView* CefBrowserViewImpl::web_view() const {
251   if (cef::IsChromeRuntimeEnabled()) {
252     return static_cast<ChromeBrowserView*>(root_view())->contents_web_view();
253   }
254 
255   return static_cast<CefBrowserViewView*>(root_view());
256 }
257 
HandleAccelerator(const content::NativeWebKeyboardEvent & event,views::FocusManager * focus_manager)258 bool CefBrowserViewImpl::HandleAccelerator(
259     const content::NativeWebKeyboardEvent& event,
260     views::FocusManager* focus_manager) {
261   // Previous calls to TranslateMessage can generate Char events as well as
262   // RawKeyDown events, even if the latter triggered an accelerator.  In these
263   // cases, we discard the Char events.
264   if (event.GetType() == blink::WebInputEvent::Type::kChar &&
265       ignore_next_char_event_) {
266     ignore_next_char_event_ = false;
267     return true;
268   }
269 
270   // It's necessary to reset this flag, because a RawKeyDown event may not
271   // always generate a Char event.
272   ignore_next_char_event_ = false;
273 
274   if (event.GetType() == blink::WebInputEvent::Type::kRawKeyDown) {
275     ui::Accelerator accelerator =
276         ui::GetAcceleratorFromNativeWebKeyboardEvent(event);
277 
278     // This is tricky: we want to set ignore_next_char_event_ if
279     // ProcessAccelerator returns true. But ProcessAccelerator might delete
280     // |this| if the accelerator is a "close tab" one. So we speculatively
281     // set the flag and fix it if no event was handled.
282     ignore_next_char_event_ = true;
283 
284     if (focus_manager->ProcessAccelerator(accelerator))
285       return true;
286 
287     // ProcessAccelerator didn't handle the accelerator, so we know both
288     // that |this| is still valid, and that we didn't want to set the flag.
289     ignore_next_char_event_ = false;
290   }
291 
292   return false;
293 }
294 
RequestFocusInternal()295 void CefBrowserViewImpl::RequestFocusInternal() {
296   ParentClass::RequestFocus();
297 }
298