1 // Copyright (c) 2012 The Chromium Embedded Framework Authors. All rights
2 // reserved. Use of this source code is governed by a BSD-style license that can
3 // be found in the LICENSE file.
4
5 #include "libcef/browser/frame_host_impl.h"
6
7 #include "include/cef_request.h"
8 #include "include/cef_stream.h"
9 #include "include/cef_v8.h"
10 #include "include/test/cef_test_helpers.h"
11 #include "libcef/browser/browser_host_base.h"
12 #include "libcef/browser/navigate_params.h"
13 #include "libcef/browser/net_service/browser_urlrequest_impl.h"
14 #include "libcef/common/cef_messages.h"
15 #include "libcef/common/frame_util.h"
16 #include "libcef/common/net/url_util.h"
17 #include "libcef/common/process_message_impl.h"
18 #include "libcef/common/request_impl.h"
19 #include "libcef/common/task_runner_impl.h"
20
21 #include "content/browser/renderer_host/frame_tree_node.h"
22 #include "content/public/browser/render_process_host.h"
23 #include "content/public/browser/render_view_host.h"
24
25 namespace {
26
27 // Implementation of CommandResponseHandler for calling a CefStringVisitor.
28 class StringVisitHandler : public CefResponseManager::Handler {
29 public:
StringVisitHandler(CefRefPtr<CefStringVisitor> visitor)30 explicit StringVisitHandler(CefRefPtr<CefStringVisitor> visitor)
31 : visitor_(visitor) {}
OnResponse(const Cef_Response_Params & params)32 void OnResponse(const Cef_Response_Params& params) override {
33 visitor_->Visit(params.response);
34 }
35
36 private:
37 CefRefPtr<CefStringVisitor> visitor_;
38
39 IMPLEMENT_REFCOUNTING(StringVisitHandler);
40 };
41
42 // Implementation of CommandResponseHandler for calling ViewText().
43 class ViewTextHandler : public CefResponseManager::Handler {
44 public:
ViewTextHandler(CefRefPtr<CefFrameHostImpl> frame)45 explicit ViewTextHandler(CefRefPtr<CefFrameHostImpl> frame) : frame_(frame) {}
OnResponse(const Cef_Response_Params & params)46 void OnResponse(const Cef_Response_Params& params) override {
47 CefRefPtr<CefBrowser> browser = frame_->GetBrowser();
48 if (browser.get()) {
49 static_cast<CefBrowserHostBase*>(browser.get())
50 ->ViewText(params.response);
51 }
52 }
53
54 private:
55 CefRefPtr<CefFrameHostImpl> frame_;
56
57 IMPLEMENT_REFCOUNTING(ViewTextHandler);
58 };
59
60 } // namespace
61
CefFrameHostImpl(scoped_refptr<CefBrowserInfo> browser_info,bool is_main_frame,int64_t parent_frame_id)62 CefFrameHostImpl::CefFrameHostImpl(scoped_refptr<CefBrowserInfo> browser_info,
63 bool is_main_frame,
64 int64_t parent_frame_id)
65 : is_main_frame_(is_main_frame),
66 frame_id_(kInvalidFrameId),
67 browser_info_(browser_info),
68 is_focused_(is_main_frame_), // The main frame always starts focused.
69 parent_frame_id_(parent_frame_id) {
70 #if DCHECK_IS_ON()
71 DCHECK(browser_info_);
72 if (is_main_frame_) {
73 DCHECK_EQ(parent_frame_id_, kInvalidFrameId);
74 } else {
75 DCHECK_GT(parent_frame_id_, 0);
76 }
77 #endif
78 }
79
CefFrameHostImpl(scoped_refptr<CefBrowserInfo> browser_info,content::RenderFrameHost * render_frame_host)80 CefFrameHostImpl::CefFrameHostImpl(scoped_refptr<CefBrowserInfo> browser_info,
81 content::RenderFrameHost* render_frame_host)
82 : is_main_frame_(render_frame_host->GetParent() == nullptr),
83 frame_id_(MakeFrameId(render_frame_host)),
84 browser_info_(browser_info),
85 is_focused_(is_main_frame_), // The main frame always starts focused.
86 url_(render_frame_host->GetLastCommittedURL().spec()),
87 name_(render_frame_host->GetFrameName()),
88 parent_frame_id_(is_main_frame_
89 ? kInvalidFrameId
90 : MakeFrameId(render_frame_host->GetParent())),
91 render_frame_host_(render_frame_host),
92 response_manager_(new CefResponseManager) {
93 DCHECK(browser_info_);
94 }
95
~CefFrameHostImpl()96 CefFrameHostImpl::~CefFrameHostImpl() {}
97
SetRenderFrameHost(content::RenderFrameHost * host)98 void CefFrameHostImpl::SetRenderFrameHost(content::RenderFrameHost* host) {
99 CEF_REQUIRE_UIT();
100
101 base::AutoLock lock_scope(state_lock_);
102
103 // We should not be detached.
104 CHECK(browser_info_);
105 // We should be the main frame.
106 CHECK(is_main_frame_);
107
108 render_frame_host_ = host;
109 frame_id_ = MakeFrameId(host);
110 url_ = host->GetLastCommittedURL().spec();
111 name_ = host->GetFrameName();
112
113 // Cancel any existing messages.
114 response_manager_.reset(new CefResponseManager);
115 }
116
IsValid()117 bool CefFrameHostImpl::IsValid() {
118 return !!GetBrowserHostBase();
119 }
120
Undo()121 void CefFrameHostImpl::Undo() {
122 SendCommand("Undo", nullptr);
123 }
124
Redo()125 void CefFrameHostImpl::Redo() {
126 SendCommand("Redo", nullptr);
127 }
128
Cut()129 void CefFrameHostImpl::Cut() {
130 SendCommand("Cut", nullptr);
131 }
132
Copy()133 void CefFrameHostImpl::Copy() {
134 SendCommand("Copy", nullptr);
135 }
136
Paste()137 void CefFrameHostImpl::Paste() {
138 SendCommand("Paste", nullptr);
139 }
140
Delete()141 void CefFrameHostImpl::Delete() {
142 SendCommand("Delete", nullptr);
143 }
144
SelectAll()145 void CefFrameHostImpl::SelectAll() {
146 SendCommand("SelectAll", nullptr);
147 }
148
ViewSource()149 void CefFrameHostImpl::ViewSource() {
150 SendCommand("GetSource", new ViewTextHandler(this));
151 }
152
GetSource(CefRefPtr<CefStringVisitor> visitor)153 void CefFrameHostImpl::GetSource(CefRefPtr<CefStringVisitor> visitor) {
154 SendCommand("GetSource", new StringVisitHandler(visitor));
155 }
156
GetText(CefRefPtr<CefStringVisitor> visitor)157 void CefFrameHostImpl::GetText(CefRefPtr<CefStringVisitor> visitor) {
158 SendCommand("GetText", new StringVisitHandler(visitor));
159 }
160
LoadRequest(CefRefPtr<CefRequest> request)161 void CefFrameHostImpl::LoadRequest(CefRefPtr<CefRequest> request) {
162 CefNavigateParams params(GURL(), kPageTransitionExplicit);
163 static_cast<CefRequestImpl*>(request.get())->Get(params);
164 Navigate(params);
165 }
166
LoadURL(const CefString & url)167 void CefFrameHostImpl::LoadURL(const CefString& url) {
168 LoadURLWithExtras(url, content::Referrer(), kPageTransitionExplicit,
169 std::string());
170 }
171
ExecuteJavaScript(const CefString & jsCode,const CefString & scriptUrl,int startLine)172 void CefFrameHostImpl::ExecuteJavaScript(const CefString& jsCode,
173 const CefString& scriptUrl,
174 int startLine) {
175 SendJavaScript(jsCode, scriptUrl, startLine);
176 }
177
IsMain()178 bool CefFrameHostImpl::IsMain() {
179 return is_main_frame_;
180 }
181
IsFocused()182 bool CefFrameHostImpl::IsFocused() {
183 base::AutoLock lock_scope(state_lock_);
184 return is_focused_;
185 }
186
GetName()187 CefString CefFrameHostImpl::GetName() {
188 base::AutoLock lock_scope(state_lock_);
189 return name_;
190 }
191
GetIdentifier()192 int64 CefFrameHostImpl::GetIdentifier() {
193 base::AutoLock lock_scope(state_lock_);
194 return frame_id_;
195 }
196
GetParent()197 CefRefPtr<CefFrame> CefFrameHostImpl::GetParent() {
198 int64 parent_frame_id;
199
200 {
201 base::AutoLock lock_scope(state_lock_);
202 if (is_main_frame_ || parent_frame_id_ == kInvalidFrameId)
203 return nullptr;
204 parent_frame_id = parent_frame_id_;
205 }
206
207 auto browser = GetBrowserHostBase();
208 if (browser)
209 return browser->GetFrame(parent_frame_id);
210
211 return nullptr;
212 }
213
GetURL()214 CefString CefFrameHostImpl::GetURL() {
215 base::AutoLock lock_scope(state_lock_);
216 return url_;
217 }
218
GetBrowser()219 CefRefPtr<CefBrowser> CefFrameHostImpl::GetBrowser() {
220 return GetBrowserHostBase().get();
221 }
222
GetV8Context()223 CefRefPtr<CefV8Context> CefFrameHostImpl::GetV8Context() {
224 NOTREACHED() << "GetV8Context cannot be called from the browser process";
225 return nullptr;
226 }
227
VisitDOM(CefRefPtr<CefDOMVisitor> visitor)228 void CefFrameHostImpl::VisitDOM(CefRefPtr<CefDOMVisitor> visitor) {
229 NOTREACHED() << "VisitDOM cannot be called from the browser process";
230 }
231
CreateURLRequest(CefRefPtr<CefRequest> request,CefRefPtr<CefURLRequestClient> client)232 CefRefPtr<CefURLRequest> CefFrameHostImpl::CreateURLRequest(
233 CefRefPtr<CefRequest> request,
234 CefRefPtr<CefURLRequestClient> client) {
235 if (!request || !client)
236 return nullptr;
237
238 if (!CefTaskRunnerImpl::GetCurrentTaskRunner()) {
239 NOTREACHED() << "called on invalid thread";
240 return nullptr;
241 }
242
243 auto browser = GetBrowserHostBase();
244 if (!browser)
245 return nullptr;
246
247 auto request_context = browser->request_context();
248
249 CefRefPtr<CefBrowserURLRequest> impl =
250 new CefBrowserURLRequest(this, request, client, request_context);
251 if (impl->Start())
252 return impl.get();
253 return nullptr;
254 }
255
SendProcessMessage(CefProcessId target_process,CefRefPtr<CefProcessMessage> message)256 void CefFrameHostImpl::SendProcessMessage(
257 CefProcessId target_process,
258 CefRefPtr<CefProcessMessage> message) {
259 DCHECK_EQ(PID_RENDERER, target_process);
260 DCHECK(message.get());
261
262 Cef_Request_Params params;
263 CefProcessMessageImpl* impl =
264 static_cast<CefProcessMessageImpl*>(message.get());
265 if (!impl->CopyTo(params))
266 return;
267
268 DCHECK(!params.name.empty());
269
270 params.user_initiated = true;
271 params.request_id = -1;
272 params.expect_response = false;
273
274 Send(new CefMsg_Request(MSG_ROUTING_NONE, params));
275 }
276
SetFocused(bool focused)277 void CefFrameHostImpl::SetFocused(bool focused) {
278 base::AutoLock lock_scope(state_lock_);
279 is_focused_ = focused;
280 }
281
RefreshAttributes()282 void CefFrameHostImpl::RefreshAttributes() {
283 CEF_REQUIRE_UIT();
284
285 base::AutoLock lock_scope(state_lock_);
286 if (!render_frame_host_)
287 return;
288 url_ = render_frame_host_->GetLastCommittedURL().spec();
289
290 // Use the assigned name if it is non-empty. This represents the name property
291 // on the frame DOM element. If the assigned name is empty, revert to the
292 // internal unique name. This matches the logic in render_frame_util::GetName.
293 name_ = render_frame_host_->GetFrameName();
294 if (name_.empty()) {
295 const auto node = content::FrameTreeNode::GloballyFindByID(
296 render_frame_host_->GetFrameTreeNodeId());
297 if (node) {
298 name_ = node->unique_name();
299 }
300 }
301
302 if (!is_main_frame_)
303 parent_frame_id_ = MakeFrameId(render_frame_host_->GetParent());
304 }
305
NotifyMoveOrResizeStarted()306 void CefFrameHostImpl::NotifyMoveOrResizeStarted() {
307 Send(new CefMsg_MoveOrResizeStarted(MSG_ROUTING_NONE));
308 }
309
Navigate(const CefNavigateParams & params)310 void CefFrameHostImpl::Navigate(const CefNavigateParams& params) {
311 CefMsg_LoadRequest_Params request;
312
313 request.url = params.url;
314 if (!url_util::FixupGURL(request.url))
315 return;
316
317 request.method = params.method;
318 request.referrer = params.referrer.url;
319 request.referrer_policy =
320 CefRequestImpl::BlinkReferrerPolicyToNetReferrerPolicy(
321 params.referrer.policy);
322 request.site_for_cookies = params.site_for_cookies;
323 request.headers = params.headers;
324 request.load_flags = params.load_flags;
325 request.upload_data = params.upload_data;
326
327 Send(new CefMsg_LoadRequest(MSG_ROUTING_NONE, request));
328
329 auto browser = GetBrowserHostBase();
330 if (browser)
331 browser->OnSetFocus(FOCUS_SOURCE_NAVIGATION);
332 }
333
LoadURLWithExtras(const std::string & url,const content::Referrer & referrer,ui::PageTransition transition,const std::string & extra_headers)334 void CefFrameHostImpl::LoadURLWithExtras(const std::string& url,
335 const content::Referrer& referrer,
336 ui::PageTransition transition,
337 const std::string& extra_headers) {
338 // Only known frame ids or kMainFrameId are supported.
339 const auto frame_id = GetFrameId();
340 if (frame_id < CefFrameHostImpl::kMainFrameId)
341 return;
342
343 // Any necessary fixup will occur in Navigate.
344 GURL gurl = url_util::MakeGURL(url, /*fixup=*/false);
345
346 if (frame_id == CefFrameHostImpl::kMainFrameId) {
347 // Load via the browser using NavigationController.
348 auto browser = GetBrowserHostBase();
349 if (browser) {
350 content::OpenURLParams params(
351 gurl, referrer, WindowOpenDisposition::CURRENT_TAB, transition,
352 /*is_renderer_initiated=*/false);
353 params.extra_headers = extra_headers;
354
355 browser->LoadMainFrameURL(params);
356 }
357 } else {
358 CefNavigateParams params(gurl, transition);
359 params.referrer = referrer;
360 params.headers = extra_headers;
361 Navigate(params);
362 }
363 }
364
SendCommand(const std::string & command,CefRefPtr<CefResponseManager::Handler> responseHandler)365 void CefFrameHostImpl::SendCommand(
366 const std::string& command,
367 CefRefPtr<CefResponseManager::Handler> responseHandler) {
368 DCHECK(!command.empty());
369
370 if (!CEF_CURRENTLY_ON_UIT()) {
371 CEF_POST_TASK(CEF_UIT, base::BindOnce(&CefFrameHostImpl::SendCommand, this,
372 command, responseHandler));
373 return;
374 }
375
376 // Only known frame ids or kMainFrameId are supported.
377 const auto frame_id = GetFrameId();
378 if (frame_id < CefFrameHostImpl::kMainFrameId)
379 return;
380
381 if (!render_frame_host_ || !response_manager_) {
382 // detached frame has no response_manager_
383 return;
384 }
385
386 TRACE_EVENT2("cef", "CefFrameHostImpl::SendCommand", "frame_id", frame_id,
387 "needsResponse", responseHandler.get() ? 1 : 0);
388 Cef_Request_Params params;
389 params.name = "execute-command";
390 params.user_initiated = false;
391
392 if (responseHandler.get()) {
393 params.request_id = response_manager_->RegisterHandler(responseHandler);
394 params.expect_response = true;
395 } else {
396 params.request_id = -1;
397 params.expect_response = false;
398 }
399
400 params.arguments.AppendString(command);
401
402 Send(new CefMsg_Request(MSG_ROUTING_NONE, params));
403 }
404
SendCode(bool is_javascript,const std::string & code,const std::string & script_url,int script_start_line,CefRefPtr<CefResponseManager::Handler> responseHandler)405 void CefFrameHostImpl::SendCode(
406 bool is_javascript,
407 const std::string& code,
408 const std::string& script_url,
409 int script_start_line,
410 CefRefPtr<CefResponseManager::Handler> responseHandler) {
411 DCHECK(!code.empty());
412 DCHECK_GE(script_start_line, 0);
413
414 if (!CEF_CURRENTLY_ON_UIT()) {
415 CEF_POST_TASK(CEF_UIT, base::BindOnce(&CefFrameHostImpl::SendCode, this,
416 is_javascript, code, script_url,
417 script_start_line, responseHandler));
418 return;
419 }
420
421 // Only known frame ids or kMainFrameId are supported.
422 auto frame_id = GetFrameId();
423 if (frame_id < CefFrameHostImpl::kMainFrameId)
424 return;
425
426 if (!render_frame_host_ || !response_manager_) {
427 // detached frame has no response_manager_
428 return;
429 }
430
431 TRACE_EVENT2("cef", "CefFrameHostImpl::SendCommand", "frame_id", frame_id,
432 "needsResponse", responseHandler.get() ? 1 : 0);
433 Cef_Request_Params params;
434 params.name = "execute-code";
435 params.user_initiated = false;
436
437 if (responseHandler.get()) {
438 params.request_id = response_manager_->RegisterHandler(responseHandler);
439 params.expect_response = true;
440 } else {
441 params.request_id = -1;
442 params.expect_response = false;
443 }
444
445 params.arguments.AppendBoolean(is_javascript);
446 params.arguments.AppendString(code);
447 params.arguments.AppendString(script_url);
448 params.arguments.AppendInteger(script_start_line);
449
450 Send(new CefMsg_Request(MSG_ROUTING_NONE, params));
451 }
452
SendJavaScript(const std::string & jsCode,const std::string & scriptUrl,int startLine)453 void CefFrameHostImpl::SendJavaScript(const std::string& jsCode,
454 const std::string& scriptUrl,
455 int startLine) {
456 if (jsCode.empty())
457 return;
458 if (startLine <= 0) {
459 // A value of 0 is v8::Message::kNoLineNumberInfo in V8. There is code in
460 // V8 that will assert on that value (e.g. V8StackTraceImpl::Frame::Frame
461 // if a JS exception is thrown) so make sure |startLine| > 0.
462 startLine = 1;
463 }
464
465 SendCode(true, jsCode, scriptUrl, startLine, nullptr);
466 }
467
MaybeSendDidStopLoading()468 void CefFrameHostImpl::MaybeSendDidStopLoading() {
469 auto rfh = GetRenderFrameHost();
470 if (!rfh)
471 return;
472
473 // We only want to notify for the highest-level LocalFrame in this frame's
474 // renderer process subtree. If this frame has a parent in the same process
475 // then the notification will be sent via the parent instead.
476 auto rfh_parent = rfh->GetParent();
477 if (rfh_parent && rfh_parent->GetProcess() == rfh->GetProcess()) {
478 return;
479 }
480
481 Send(new CefMsg_DidStopLoading(MSG_ROUTING_NONE));
482 }
483
OnMessageReceived(const IPC::Message & message)484 bool CefFrameHostImpl::OnMessageReceived(const IPC::Message& message) {
485 bool handled = true;
486 IPC_BEGIN_MESSAGE_MAP(CefFrameHostImpl, message)
487 IPC_MESSAGE_HANDLER(CefHostMsg_FrameAttached, OnAttached)
488 IPC_MESSAGE_HANDLER(CefHostMsg_DidFinishLoad, OnDidFinishLoad)
489 IPC_MESSAGE_HANDLER(CefHostMsg_UpdateDraggableRegions,
490 OnUpdateDraggableRegions)
491 IPC_MESSAGE_HANDLER(CefHostMsg_Request, OnRequest)
492 IPC_MESSAGE_HANDLER(CefHostMsg_Response, OnResponse)
493 IPC_MESSAGE_HANDLER(CefHostMsg_ResponseAck, OnResponseAck)
494 IPC_MESSAGE_UNHANDLED(handled = false)
495 IPC_END_MESSAGE_MAP()
496 return handled;
497 }
498
ExecuteJavaScriptWithUserGestureForTests(const CefString & javascript)499 void CefFrameHostImpl::ExecuteJavaScriptWithUserGestureForTests(
500 const CefString& javascript) {
501 if (!CEF_CURRENTLY_ON_UIT()) {
502 CEF_POST_TASK(
503 CEF_UIT,
504 base::BindOnce(
505 &CefFrameHostImpl::ExecuteJavaScriptWithUserGestureForTests, this,
506 javascript));
507 return;
508 }
509
510 content::RenderFrameHost* rfh = GetRenderFrameHost();
511 if (rfh)
512 rfh->ExecuteJavaScriptWithUserGestureForTests(javascript);
513 }
514
GetRenderFrameHost() const515 content::RenderFrameHost* CefFrameHostImpl::GetRenderFrameHost() const {
516 CEF_REQUIRE_UIT();
517 return render_frame_host_;
518 }
519
Detach()520 void CefFrameHostImpl::Detach() {
521 CEF_REQUIRE_UIT();
522
523 {
524 base::AutoLock lock_scope(state_lock_);
525 browser_info_ = nullptr;
526 }
527
528 // In case we never attached, clean up.
529 while (!queued_messages_.empty()) {
530 queued_messages_.pop();
531 }
532
533 response_manager_.reset();
534 render_frame_host_ = nullptr;
535 }
536
537 // static
MakeFrameId(const content::RenderFrameHost * host)538 int64_t CefFrameHostImpl::MakeFrameId(const content::RenderFrameHost* host) {
539 CEF_REQUIRE_UIT();
540 auto host_nonconst = const_cast<content::RenderFrameHost*>(host);
541 return MakeFrameId(host_nonconst->GetProcess()->GetID(),
542 host_nonconst->GetRoutingID());
543 }
544
545 // static
MakeFrameId(int32_t render_process_id,int32_t render_routing_id)546 int64_t CefFrameHostImpl::MakeFrameId(int32_t render_process_id,
547 int32_t render_routing_id) {
548 return frame_util::MakeFrameId(render_process_id, render_routing_id);
549 }
550
551 // kMainFrameId must be -1 to align with renderer expectations.
552 const int64_t CefFrameHostImpl::kMainFrameId = -1;
553 const int64_t CefFrameHostImpl::kFocusedFrameId = -2;
554 const int64_t CefFrameHostImpl::kUnspecifiedFrameId = -3;
555 const int64_t CefFrameHostImpl::kInvalidFrameId = -4;
556
557 // This equates to (TT_EXPLICIT | TT_DIRECT_LOAD_FLAG).
558 const ui::PageTransition CefFrameHostImpl::kPageTransitionExplicit =
559 static_cast<ui::PageTransition>(ui::PAGE_TRANSITION_TYPED |
560 ui::PAGE_TRANSITION_FROM_ADDRESS_BAR);
561
GetFrameId() const562 int64 CefFrameHostImpl::GetFrameId() const {
563 base::AutoLock lock_scope(state_lock_);
564 return is_main_frame_ ? kMainFrameId : frame_id_;
565 }
566
GetBrowserHostBase() const567 CefRefPtr<CefBrowserHostBase> CefFrameHostImpl::GetBrowserHostBase() const {
568 base::AutoLock lock_scope(state_lock_);
569 if (browser_info_)
570 return browser_info_->browser();
571 return nullptr;
572 }
573
OnAttached()574 void CefFrameHostImpl::OnAttached() {
575 if (!is_attached_) {
576 is_attached_ = true;
577 while (!queued_messages_.empty()) {
578 Send(queued_messages_.front().release());
579 queued_messages_.pop();
580 }
581 }
582 }
583
OnDidFinishLoad(const GURL & validated_url,int http_status_code)584 void CefFrameHostImpl::OnDidFinishLoad(const GURL& validated_url,
585 int http_status_code) {
586 auto browser = GetBrowserHostBase();
587 if (browser)
588 browser->OnDidFinishLoad(this, validated_url, http_status_code);
589 }
590
OnUpdateDraggableRegions(const std::vector<Cef_DraggableRegion_Params> & regions)591 void CefFrameHostImpl::OnUpdateDraggableRegions(
592 const std::vector<Cef_DraggableRegion_Params>& regions) {
593 auto browser = GetBrowserHostBase();
594 if (!browser)
595 return;
596
597 CefRefPtr<CefDragHandler> handler;
598 auto client = browser->GetClient();
599 if (client)
600 handler = client->GetDragHandler();
601 if (!handler)
602 return;
603
604 std::vector<CefDraggableRegion> draggable_regions;
605 draggable_regions.reserve(regions.size());
606
607 std::vector<Cef_DraggableRegion_Params>::const_iterator it = regions.begin();
608 for (; it != regions.end(); ++it) {
609 const gfx::Rect& rect(it->bounds);
610 const CefRect bounds(rect.x(), rect.y(), rect.width(), rect.height());
611 draggable_regions.push_back(CefDraggableRegion(bounds, it->draggable));
612 }
613
614 handler->OnDraggableRegionsChanged(browser.get(), this, draggable_regions);
615 }
616
OnRequest(const Cef_Request_Params & params)617 void CefFrameHostImpl::OnRequest(const Cef_Request_Params& params) {
618 CEF_REQUIRE_UIT();
619
620 bool success = false;
621 std::string response;
622 bool expect_response_ack = false;
623
624 if (params.user_initiated) {
625 auto browser = GetBrowserHostBase();
626 if (browser && browser->GetClient()) {
627 // Give the user a chance to handle the request.
628 CefRefPtr<CefProcessMessageImpl> message(new CefProcessMessageImpl(
629 const_cast<Cef_Request_Params*>(¶ms), false, true));
630 success = browser->GetClient()->OnProcessMessageReceived(
631 browser.get(), this, PID_RENDERER, message.get());
632 message->Detach(nullptr);
633 }
634 } else {
635 // Invalid request.
636 NOTREACHED();
637 }
638
639 if (params.expect_response) {
640 DCHECK_GE(params.request_id, 0);
641
642 // Send a response to the renderer.
643 Cef_Response_Params response_params;
644 response_params.request_id = params.request_id;
645 response_params.success = success;
646 response_params.response = response;
647 response_params.expect_response_ack = expect_response_ack;
648 Send(new CefMsg_Response(MSG_ROUTING_NONE, response_params));
649 }
650 }
651
OnResponse(const Cef_Response_Params & params)652 void CefFrameHostImpl::OnResponse(const Cef_Response_Params& params) {
653 CEF_REQUIRE_UIT();
654
655 response_manager_->RunHandler(params);
656 if (params.expect_response_ack)
657 Send(new CefMsg_ResponseAck(MSG_ROUTING_NONE, params.request_id));
658 }
659
OnResponseAck(int request_id)660 void CefFrameHostImpl::OnResponseAck(int request_id) {
661 response_manager_->RunAckHandler(request_id);
662 }
663
Send(IPC::Message * message)664 void CefFrameHostImpl::Send(IPC::Message* message) {
665 if (!CEF_CURRENTLY_ON_UIT()) {
666 CEF_POST_TASK(CEF_UIT,
667 base::BindOnce(base::IgnoreResult(&CefFrameHostImpl::Send),
668 this, message));
669 return;
670 }
671
672 if (!render_frame_host_) {
673 // Either we're a placeholder frame without a renderer representation, or
674 // we've been detached.
675 delete message;
676 return;
677 }
678
679 if (!is_attached_) {
680 // Queue messages until we're notified by the renderer that it's ready to
681 // handle them.
682 queued_messages_.push(base::WrapUnique(message));
683 return;
684 }
685
686 message->set_routing_id(render_frame_host_->GetRoutingID());
687 render_frame_host_->Send(message);
688 }
689
CefExecuteJavaScriptWithUserGestureForTests(CefRefPtr<CefFrame> frame,const CefString & javascript)690 void CefExecuteJavaScriptWithUserGestureForTests(CefRefPtr<CefFrame> frame,
691 const CefString& javascript) {
692 CefFrameHostImpl* impl = static_cast<CefFrameHostImpl*>(frame.get());
693 if (impl)
694 impl->ExecuteJavaScriptWithUserGestureForTests(javascript);
695 }
696