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
3 // found in the LICENSE file.
4
5 #include "libcef/browser/views/browser_platform_delegate_views.h"
6
7 #include <utility>
8
9 #include "include/views/cef_window.h"
10 #include "libcef/browser/alloy/alloy_browser_host_impl.h"
11 #include "libcef/browser/views/browser_view_impl.h"
12 #include "libcef/browser/views/menu_runner_views.h"
13
14 #include "content/public/browser/render_view_host.h"
15 #include "content/public/browser/render_widget_host.h"
16 #include "ui/views/widget/widget.h"
17
18 namespace {
19
20 // Default popup window delegate implementation.
21 class PopupWindowDelegate : public CefWindowDelegate {
22 public:
PopupWindowDelegate(CefRefPtr<CefBrowserView> browser_view)23 explicit PopupWindowDelegate(CefRefPtr<CefBrowserView> browser_view)
24 : browser_view_(browser_view) {}
25
26 PopupWindowDelegate(const PopupWindowDelegate&) = delete;
27 PopupWindowDelegate& operator=(const PopupWindowDelegate&) = delete;
28
OnWindowCreated(CefRefPtr<CefWindow> window)29 void OnWindowCreated(CefRefPtr<CefWindow> window) override {
30 window->AddChildView(browser_view_);
31 window->Show();
32 browser_view_->RequestFocus();
33 }
34
OnWindowDestroyed(CefRefPtr<CefWindow> window)35 void OnWindowDestroyed(CefRefPtr<CefWindow> window) override {
36 browser_view_ = nullptr;
37 }
38
CanClose(CefRefPtr<CefWindow> window)39 bool CanClose(CefRefPtr<CefWindow> window) override {
40 CefRefPtr<CefBrowser> browser = browser_view_->GetBrowser();
41 if (browser)
42 return browser->GetHost()->TryCloseBrowser();
43 return true;
44 }
45
46 private:
47 CefRefPtr<CefBrowserView> browser_view_;
48
49 IMPLEMENT_REFCOUNTING(PopupWindowDelegate);
50 };
51
52 } // namespace
53
CefBrowserPlatformDelegateViews(std::unique_ptr<CefBrowserPlatformDelegateNative> native_delegate,CefRefPtr<CefBrowserViewImpl> browser_view)54 CefBrowserPlatformDelegateViews::CefBrowserPlatformDelegateViews(
55 std::unique_ptr<CefBrowserPlatformDelegateNative> native_delegate,
56 CefRefPtr<CefBrowserViewImpl> browser_view)
57 : native_delegate_(std::move(native_delegate)) {
58 if (browser_view)
59 SetBrowserView(browser_view);
60 native_delegate_->set_windowless_handler(this);
61 }
62
SetBrowserView(CefRefPtr<CefBrowserViewImpl> browser_view)63 void CefBrowserPlatformDelegateViews::SetBrowserView(
64 CefRefPtr<CefBrowserViewImpl> browser_view) {
65 DCHECK(!browser_view_);
66 DCHECK(browser_view);
67 browser_view_ = browser_view;
68 }
69
WebContentsCreated(content::WebContents * web_contents,bool owned)70 void CefBrowserPlatformDelegateViews::WebContentsCreated(
71 content::WebContents* web_contents,
72 bool owned) {
73 CefBrowserPlatformDelegateAlloy::WebContentsCreated(web_contents, owned);
74 native_delegate_->WebContentsCreated(web_contents, /*owned=*/false);
75 browser_view_->WebContentsCreated(web_contents);
76 }
77
WebContentsDestroyed(content::WebContents * web_contents)78 void CefBrowserPlatformDelegateViews::WebContentsDestroyed(
79 content::WebContents* web_contents) {
80 CefBrowserPlatformDelegateAlloy::WebContentsDestroyed(web_contents);
81 native_delegate_->WebContentsDestroyed(web_contents);
82 }
83
BrowserCreated(CefBrowserHostBase * browser)84 void CefBrowserPlatformDelegateViews::BrowserCreated(
85 CefBrowserHostBase* browser) {
86 CefBrowserPlatformDelegateAlloy::BrowserCreated(browser);
87
88 native_delegate_->BrowserCreated(browser);
89 browser_view_->BrowserCreated(browser, GetBoundsChangedCallback());
90 }
91
NotifyBrowserCreated()92 void CefBrowserPlatformDelegateViews::NotifyBrowserCreated() {
93 DCHECK(browser_view_);
94 DCHECK(browser_);
95 if (browser_view_->delegate())
96 browser_view_->delegate()->OnBrowserCreated(browser_view_, browser_);
97 }
98
NotifyBrowserDestroyed()99 void CefBrowserPlatformDelegateViews::NotifyBrowserDestroyed() {
100 DCHECK(browser_view_);
101 DCHECK(browser_);
102 if (browser_view_->delegate())
103 browser_view_->delegate()->OnBrowserDestroyed(browser_view_, browser_);
104 }
105
BrowserDestroyed(CefBrowserHostBase * browser)106 void CefBrowserPlatformDelegateViews::BrowserDestroyed(
107 CefBrowserHostBase* browser) {
108 CefBrowserPlatformDelegateAlloy::BrowserDestroyed(browser);
109
110 browser_view_->BrowserDestroyed(browser);
111 browser_view_ = nullptr;
112 native_delegate_->BrowserDestroyed(browser);
113 }
114
CreateHostWindow()115 bool CefBrowserPlatformDelegateViews::CreateHostWindow() {
116 // Nothing to do here.
117 return true;
118 }
119
CloseHostWindow()120 void CefBrowserPlatformDelegateViews::CloseHostWindow() {
121 views::Widget* widget = GetWindowWidget();
122 if (widget && !widget->IsClosed())
123 widget->Close();
124 }
125
GetHostWindowHandle() const126 CefWindowHandle CefBrowserPlatformDelegateViews::GetHostWindowHandle() const {
127 return view_util::GetWindowHandle(GetWindowWidget());
128 }
129
GetWindowWidget() const130 views::Widget* CefBrowserPlatformDelegateViews::GetWindowWidget() const {
131 if (browser_view_->root_view())
132 return browser_view_->root_view()->GetWidget();
133 return nullptr;
134 }
135
GetBrowserView() const136 CefRefPtr<CefBrowserView> CefBrowserPlatformDelegateViews::GetBrowserView()
137 const {
138 return browser_view_.get();
139 }
140
PopupWebContentsCreated(const CefBrowserSettings & settings,CefRefPtr<CefClient> client,content::WebContents * new_web_contents,CefBrowserPlatformDelegate * new_platform_delegate,bool is_devtools)141 void CefBrowserPlatformDelegateViews::PopupWebContentsCreated(
142 const CefBrowserSettings& settings,
143 CefRefPtr<CefClient> client,
144 content::WebContents* new_web_contents,
145 CefBrowserPlatformDelegate* new_platform_delegate,
146 bool is_devtools) {
147 DCHECK(new_platform_delegate->IsViewsHosted());
148 CefBrowserPlatformDelegateViews* new_platform_delegate_impl =
149 static_cast<CefBrowserPlatformDelegateViews*>(new_platform_delegate);
150
151 CefRefPtr<CefBrowserViewDelegate> new_delegate;
152 if (browser_view_->delegate()) {
153 new_delegate = browser_view_->delegate()->GetDelegateForPopupBrowserView(
154 browser_view_.get(), settings, client, is_devtools);
155 }
156
157 // Create a new BrowserView for the popup.
158 CefRefPtr<CefBrowserViewImpl> new_browser_view =
159 CefBrowserViewImpl::CreateForPopup(settings, new_delegate);
160
161 // Associate the PlatformDelegate with the new BrowserView.
162 new_platform_delegate_impl->SetBrowserView(new_browser_view);
163 }
164
PopupBrowserCreated(CefBrowserHostBase * new_browser,bool is_devtools)165 void CefBrowserPlatformDelegateViews::PopupBrowserCreated(
166 CefBrowserHostBase* new_browser,
167 bool is_devtools) {
168 CefRefPtr<CefBrowserView> new_browser_view =
169 CefBrowserView::GetForBrowser(new_browser);
170 DCHECK(new_browser_view);
171
172 bool popup_handled = false;
173 if (browser_view_->delegate()) {
174 popup_handled = browser_view_->delegate()->OnPopupBrowserViewCreated(
175 browser_view_.get(), new_browser_view.get(), is_devtools);
176 }
177
178 if (!popup_handled) {
179 CefWindow::CreateTopLevelWindow(
180 new PopupWindowDelegate(new_browser_view.get()));
181 }
182 }
183
GetBackgroundColor() const184 SkColor CefBrowserPlatformDelegateViews::GetBackgroundColor() const {
185 return native_delegate_->GetBackgroundColor();
186 }
187
WasResized()188 void CefBrowserPlatformDelegateViews::WasResized() {
189 native_delegate_->WasResized();
190 }
191
SendKeyEvent(const CefKeyEvent & event)192 void CefBrowserPlatformDelegateViews::SendKeyEvent(const CefKeyEvent& event) {
193 native_delegate_->SendKeyEvent(event);
194 }
195
SendMouseClickEvent(const CefMouseEvent & event,CefBrowserHost::MouseButtonType type,bool mouseUp,int clickCount)196 void CefBrowserPlatformDelegateViews::SendMouseClickEvent(
197 const CefMouseEvent& event,
198 CefBrowserHost::MouseButtonType type,
199 bool mouseUp,
200 int clickCount) {
201 native_delegate_->SendMouseClickEvent(event, type, mouseUp, clickCount);
202 }
203
SendMouseMoveEvent(const CefMouseEvent & event,bool mouseLeave)204 void CefBrowserPlatformDelegateViews::SendMouseMoveEvent(
205 const CefMouseEvent& event,
206 bool mouseLeave) {
207 native_delegate_->SendMouseMoveEvent(event, mouseLeave);
208 }
209
SendMouseWheelEvent(const CefMouseEvent & event,int deltaX,int deltaY)210 void CefBrowserPlatformDelegateViews::SendMouseWheelEvent(
211 const CefMouseEvent& event,
212 int deltaX,
213 int deltaY) {
214 native_delegate_->SendMouseWheelEvent(event, deltaX, deltaY);
215 }
216
SendTouchEvent(const CefTouchEvent & event)217 void CefBrowserPlatformDelegateViews::SendTouchEvent(
218 const CefTouchEvent& event) {
219 native_delegate_->SendTouchEvent(event);
220 }
221
SetFocus(bool setFocus)222 void CefBrowserPlatformDelegateViews::SetFocus(bool setFocus) {
223 // Will activate the Widget and result in a call to WebContents::Focus().
224 if (setFocus && browser_view_->root_view()) {
225 if (auto widget = GetWindowWidget()) {
226 // Don't activate a minimized Widget, or it will be shown.
227 if (widget->IsMinimized())
228 return;
229 }
230 browser_view_->root_view()->RequestFocus();
231 }
232 }
233
GetScreenPoint(const gfx::Point & view_pt) const234 gfx::Point CefBrowserPlatformDelegateViews::GetScreenPoint(
235 const gfx::Point& view_pt) const {
236 if (!browser_view_->root_view())
237 return view_pt;
238
239 gfx::Point screen_point = view_pt;
240 view_util::ConvertPointToScreen(browser_view_->root_view(), &screen_point,
241 true);
242 return screen_point;
243 }
244
ViewText(const std::string & text)245 void CefBrowserPlatformDelegateViews::ViewText(const std::string& text) {
246 native_delegate_->ViewText(text);
247 }
248
HandleKeyboardEvent(const content::NativeWebKeyboardEvent & event)249 bool CefBrowserPlatformDelegateViews::HandleKeyboardEvent(
250 const content::NativeWebKeyboardEvent& event) {
251 // The BrowserView will handle accelerators.
252 return browser_view_->HandleKeyboardEvent(event);
253 }
254
GetEventHandle(const content::NativeWebKeyboardEvent & event) const255 CefEventHandle CefBrowserPlatformDelegateViews::GetEventHandle(
256 const content::NativeWebKeyboardEvent& event) const {
257 return native_delegate_->GetEventHandle(event);
258 }
259
260 std::unique_ptr<CefFileDialogRunner>
CreateFileDialogRunner()261 CefBrowserPlatformDelegateViews::CreateFileDialogRunner() {
262 return native_delegate_->CreateFileDialogRunner();
263 }
264
265 std::unique_ptr<CefJavaScriptDialogRunner>
CreateJavaScriptDialogRunner()266 CefBrowserPlatformDelegateViews::CreateJavaScriptDialogRunner() {
267 return native_delegate_->CreateJavaScriptDialogRunner();
268 }
269
270 std::unique_ptr<CefMenuRunner>
CreateMenuRunner()271 CefBrowserPlatformDelegateViews::CreateMenuRunner() {
272 return base::WrapUnique(new CefMenuRunnerViews(browser_view_.get()));
273 }
274
IsViewsHosted() const275 bool CefBrowserPlatformDelegateViews::IsViewsHosted() const {
276 return true;
277 }
278
GetDialogPosition(const gfx::Size & size)279 gfx::Point CefBrowserPlatformDelegateViews::GetDialogPosition(
280 const gfx::Size& size) {
281 const gfx::Rect& bounds = browser_view_->root_view()->GetBoundsInScreen();
282
283 // Offset relative to the top-level content view.
284 gfx::Point offset = bounds.origin();
285 view_util::ConvertPointFromScreen(
286 browser_view_->root_view()->GetWidget()->GetRootView(), &offset, false);
287
288 return gfx::Point(offset.x() + (bounds.width() - size.width()) / 2,
289 offset.y() + (bounds.height() - size.height()) / 2);
290 }
291
GetMaximumDialogSize()292 gfx::Size CefBrowserPlatformDelegateViews::GetMaximumDialogSize() {
293 return browser_view_->root_view()->GetBoundsInScreen().size();
294 }
295
GetParentWindowHandle() const296 CefWindowHandle CefBrowserPlatformDelegateViews::GetParentWindowHandle() const {
297 return GetHostWindowHandle();
298 }
299
GetParentScreenPoint(const gfx::Point & view) const300 gfx::Point CefBrowserPlatformDelegateViews::GetParentScreenPoint(
301 const gfx::Point& view) const {
302 return GetScreenPoint(view);
303 }
304