• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/renderer/frame_impl.h"
6 
7 #include "base/compiler_specific.h"
8 
9 // Enable deprecation warnings on Windows. See http://crbug.com/585142.
10 #if BUILDFLAG(IS_WIN)
11 #if defined(__clang__)
12 #pragma GCC diagnostic push
13 #pragma GCC diagnostic error "-Wdeprecated-declarations"
14 #else
15 #pragma warning(push)
16 #pragma warning(default : 4996)
17 #endif
18 #endif
19 
20 #include "libcef/common/app_manager.h"
21 #include "libcef/common/frame_util.h"
22 #include "libcef/common/net/http_header_utils.h"
23 #include "libcef/common/process_message_impl.h"
24 #include "libcef/common/request_impl.h"
25 #include "libcef/common/string_util.h"
26 #include "libcef/renderer/blink_glue.h"
27 #include "libcef/renderer/browser_impl.h"
28 #include "libcef/renderer/dom_document_impl.h"
29 #include "libcef/renderer/render_frame_util.h"
30 #include "libcef/renderer/render_urlrequest_impl.h"
31 #include "libcef/renderer/thread_util.h"
32 #include "libcef/renderer/v8_impl.h"
33 
34 #include "base/strings/utf_string_conversions.h"
35 #include "content/public/renderer/render_view.h"
36 #include "content/renderer/render_frame_impl.h"
37 #include "third_party/blink/public/mojom/frame/frame.mojom-blink.h"
38 #include "third_party/blink/public/platform/web_back_forward_cache_loader_helper.h"
39 #include "third_party/blink/public/platform/web_data.h"
40 #include "third_party/blink/public/platform/web_string.h"
41 #include "third_party/blink/public/platform/web_url.h"
42 #include "third_party/blink/public/web/blink.h"
43 #include "third_party/blink/public/web/web_document.h"
44 #include "third_party/blink/public/web/web_document_loader.h"
45 #include "third_party/blink/public/web/web_frame_content_dumper.h"
46 #include "third_party/blink/public/web/web_local_frame.h"
47 #include "third_party/blink/public/web/web_navigation_control.h"
48 #include "third_party/blink/public/web/web_script_source.h"
49 #include "third_party/blink/public/web/web_view.h"
50 
51 namespace {
52 
53 // Maximum number of times to retry the browser connection.
54 constexpr size_t kConnectionRetryMaxCt = 3U;
55 
56 // Length of time to wait before initiating a browser connection retry.
57 constexpr auto kConnectionRetryDelay = base::Seconds(1);
58 
59 // Length of time to wait for the browser connection ACK before timing out.
60 constexpr auto kConnectionTimeout = base::Seconds(4);
61 
62 }  // namespace
63 
CefFrameImpl(CefBrowserImpl * browser,blink::WebLocalFrame * frame,int64_t frame_id)64 CefFrameImpl::CefFrameImpl(CefBrowserImpl* browser,
65                            blink::WebLocalFrame* frame,
66                            int64_t frame_id)
67     : browser_(browser), frame_(frame), frame_id_(frame_id) {}
68 
~CefFrameImpl()69 CefFrameImpl::~CefFrameImpl() {}
70 
IsValid()71 bool CefFrameImpl::IsValid() {
72   CEF_REQUIRE_RT_RETURN(false);
73 
74   return (frame_ != nullptr);
75 }
76 
Undo()77 void CefFrameImpl::Undo() {
78   SendCommand("Undo");
79 }
80 
Redo()81 void CefFrameImpl::Redo() {
82   SendCommand("Redo");
83 }
84 
Cut()85 void CefFrameImpl::Cut() {
86   SendCommand("Cut");
87 }
88 
Copy()89 void CefFrameImpl::Copy() {
90   SendCommand("Copy");
91 }
92 
Paste()93 void CefFrameImpl::Paste() {
94   SendCommand("Paste");
95 }
96 
Delete()97 void CefFrameImpl::Delete() {
98   SendCommand("Delete");
99 }
100 
SelectAll()101 void CefFrameImpl::SelectAll() {
102   SendCommand("SelectAll");
103 }
104 
ViewSource()105 void CefFrameImpl::ViewSource() {
106   NOTREACHED() << "ViewSource cannot be called from the renderer process";
107 }
108 
GetSource(CefRefPtr<CefStringVisitor> visitor)109 void CefFrameImpl::GetSource(CefRefPtr<CefStringVisitor> visitor) {
110   CEF_REQUIRE_RT_RETURN_VOID();
111   if (frame_) {
112     CefString content;
113     string_util::GetCefString(blink_glue::DumpDocumentMarkup(frame_), content);
114     visitor->Visit(content);
115   }
116 }
117 
GetText(CefRefPtr<CefStringVisitor> visitor)118 void CefFrameImpl::GetText(CefRefPtr<CefStringVisitor> visitor) {
119   CEF_REQUIRE_RT_RETURN_VOID();
120   if (frame_) {
121     CefString content;
122     string_util::GetCefString(blink_glue::DumpDocumentText(frame_), content);
123     visitor->Visit(content);
124   }
125 }
126 
LoadRequest(CefRefPtr<CefRequest> request)127 void CefFrameImpl::LoadRequest(CefRefPtr<CefRequest> request) {
128   CEF_REQUIRE_RT_RETURN_VOID();
129 
130   if (!frame_)
131     return;
132 
133   auto params = cef::mojom::RequestParams::New();
134   static_cast<CefRequestImpl*>(request.get())->Get(params);
135   LoadRequest(std::move(params));
136 }
137 
LoadURL(const CefString & url)138 void CefFrameImpl::LoadURL(const CefString& url) {
139   CEF_REQUIRE_RT_RETURN_VOID();
140 
141   if (!frame_)
142     return;
143 
144   auto params = cef::mojom::RequestParams::New();
145   params->url = GURL(url.ToString());
146   params->method = "GET";
147   LoadRequest(std::move(params));
148 }
149 
ExecuteJavaScript(const CefString & jsCode,const CefString & scriptUrl,int startLine)150 void CefFrameImpl::ExecuteJavaScript(const CefString& jsCode,
151                                      const CefString& scriptUrl,
152                                      int startLine) {
153   SendJavaScript(jsCode, scriptUrl, startLine);
154 }
155 
IsMain()156 bool CefFrameImpl::IsMain() {
157   CEF_REQUIRE_RT_RETURN(false);
158 
159   if (frame_)
160     return (frame_->Parent() == nullptr);
161   return false;
162 }
163 
IsFocused()164 bool CefFrameImpl::IsFocused() {
165   CEF_REQUIRE_RT_RETURN(false);
166 
167   if (frame_ && frame_->View())
168     return (frame_->View()->FocusedFrame() == frame_);
169   return false;
170 }
171 
GetName()172 CefString CefFrameImpl::GetName() {
173   CefString name;
174   CEF_REQUIRE_RT_RETURN(name);
175 
176   if (frame_)
177     name = render_frame_util::GetName(frame_);
178   return name;
179 }
180 
GetIdentifier()181 int64 CefFrameImpl::GetIdentifier() {
182   CEF_REQUIRE_RT_RETURN(0);
183 
184   return frame_id_;
185 }
186 
GetParent()187 CefRefPtr<CefFrame> CefFrameImpl::GetParent() {
188   CEF_REQUIRE_RT_RETURN(nullptr);
189 
190   if (frame_) {
191     blink::WebFrame* parent = frame_->Parent();
192     if (parent && parent->IsWebLocalFrame())
193       return browser_->GetWebFrameImpl(parent->ToWebLocalFrame()).get();
194   }
195 
196   return nullptr;
197 }
198 
GetURL()199 CefString CefFrameImpl::GetURL() {
200   CefString url;
201   CEF_REQUIRE_RT_RETURN(url);
202 
203   if (frame_) {
204     GURL gurl = frame_->GetDocument().Url();
205     url = gurl.spec();
206   }
207   return url;
208 }
209 
GetBrowser()210 CefRefPtr<CefBrowser> CefFrameImpl::GetBrowser() {
211   CEF_REQUIRE_RT_RETURN(nullptr);
212 
213   return browser_;
214 }
215 
GetV8Context()216 CefRefPtr<CefV8Context> CefFrameImpl::GetV8Context() {
217   CEF_REQUIRE_RT_RETURN(nullptr);
218 
219   if (frame_) {
220     v8::Isolate* isolate = blink::MainThreadIsolate();
221     v8::HandleScope handle_scope(isolate);
222     return new CefV8ContextImpl(isolate, frame_->MainWorldScriptContext());
223   } else {
224     return nullptr;
225   }
226 }
227 
VisitDOM(CefRefPtr<CefDOMVisitor> visitor)228 void CefFrameImpl::VisitDOM(CefRefPtr<CefDOMVisitor> visitor) {
229   CEF_REQUIRE_RT_RETURN_VOID();
230 
231   if (!frame_)
232     return;
233 
234   // Create a CefDOMDocumentImpl object that is valid only for the scope of this
235   // method.
236   CefRefPtr<CefDOMDocumentImpl> documentImpl;
237   const blink::WebDocument& document = frame_->GetDocument();
238   if (!document.IsNull())
239     documentImpl = new CefDOMDocumentImpl(browser_, frame_);
240 
241   visitor->Visit(documentImpl.get());
242 
243   if (documentImpl.get())
244     documentImpl->Detach();
245 }
246 
CreateURLRequest(CefRefPtr<CefRequest> request,CefRefPtr<CefURLRequestClient> client)247 CefRefPtr<CefURLRequest> CefFrameImpl::CreateURLRequest(
248     CefRefPtr<CefRequest> request,
249     CefRefPtr<CefURLRequestClient> client) {
250   CEF_REQUIRE_RT_RETURN(nullptr);
251 
252   if (!request || !client || !frame_)
253     return nullptr;
254 
255   CefRefPtr<CefRenderURLRequest> impl =
256       new CefRenderURLRequest(this, request, client);
257   if (impl->Start())
258     return impl.get();
259   return nullptr;
260 }
261 
SendProcessMessage(CefProcessId target_process,CefRefPtr<CefProcessMessage> message)262 void CefFrameImpl::SendProcessMessage(CefProcessId target_process,
263                                       CefRefPtr<CefProcessMessage> message) {
264   CEF_REQUIRE_RT_RETURN_VOID();
265   DCHECK_EQ(PID_BROWSER, target_process);
266   DCHECK(message && message->IsValid());
267   if (!message || !message->IsValid())
268     return;
269 
270   SendToBrowserFrame(
271       __FUNCTION__,
272       base::BindOnce(
273           [](CefRefPtr<CefProcessMessage> message,
274              const BrowserFrameType& browser_frame) {
275             auto impl = static_cast<CefProcessMessageImpl*>(message.get());
276             browser_frame->SendMessage(impl->GetName(),
277                                        impl->TakeArgumentList());
278           },
279           message));
280 }
281 
CreateURLLoader()282 std::unique_ptr<blink::WebURLLoader> CefFrameImpl::CreateURLLoader() {
283   CEF_REQUIRE_RT();
284   if (!frame_)
285     return nullptr;
286 
287   if (!url_loader_factory_) {
288     auto render_frame = content::RenderFrameImpl::FromWebFrame(frame_);
289     if (render_frame) {
290       url_loader_factory_ = render_frame->CreateURLLoaderFactory();
291     }
292   }
293   if (!url_loader_factory_)
294     return nullptr;
295 
296   return url_loader_factory_->CreateURLLoader(
297       blink::WebURLRequest(),
298       blink_glue::CreateResourceLoadingTaskRunnerHandle(frame_),
299       blink_glue::CreateResourceLoadingMaybeUnfreezableTaskRunnerHandle(frame_),
300       /*keep_alive_handle=*/mojo::NullRemote(),
301       blink::WebBackForwardCacheLoaderHelper());
302 }
303 
304 std::unique_ptr<blink::ResourceLoadInfoNotifierWrapper>
CreateResourceLoadInfoNotifierWrapper()305 CefFrameImpl::CreateResourceLoadInfoNotifierWrapper() {
306   CEF_REQUIRE_RT();
307   if (frame_) {
308     auto render_frame = content::RenderFrameImpl::FromWebFrame(frame_);
309     if (render_frame)
310       return render_frame->CreateResourceLoadInfoNotifierWrapper();
311   }
312   return nullptr;
313 }
314 
OnAttached()315 void CefFrameImpl::OnAttached() {
316   // Called indirectly from RenderFrameCreated.
317   ConnectBrowserFrame();
318 }
319 
OnWasShown()320 void CefFrameImpl::OnWasShown() {
321   if (browser_connection_state_ == ConnectionState::DISCONNECTED) {
322     // Reconnect a frame that has exited the bfcache.
323     ConnectBrowserFrame();
324   }
325 }
326 
OnDidFinishLoad()327 void CefFrameImpl::OnDidFinishLoad() {
328   // Ignore notifications from the embedded frame hosting a mime-type plugin.
329   // We'll eventually receive a notification from the owner frame.
330   if (blink_glue::HasPluginFrameOwner(frame_))
331     return;
332 
333   blink::WebDocumentLoader* dl = frame_->GetDocumentLoader();
334   const int http_status_code = dl->GetResponse().HttpStatusCode();
335 
336   SendToBrowserFrame(__FUNCTION__,
337                      base::BindOnce(
338                          [](const GURL& url, int http_status_code,
339                             const BrowserFrameType& browser_frame) {
340                            browser_frame->DidFinishFrameLoad(url,
341                                                              http_status_code);
342                          },
343                          dl->GetUrl(), http_status_code));
344 
345   CefRefPtr<CefApp> app = CefAppManager::Get()->GetApplication();
346   if (app) {
347     CefRefPtr<CefRenderProcessHandler> handler = app->GetRenderProcessHandler();
348     if (handler) {
349       CefRefPtr<CefLoadHandler> load_handler = handler->GetLoadHandler();
350       if (load_handler) {
351         load_handler->OnLoadEnd(browser_, this, http_status_code);
352       }
353     }
354   }
355 }
356 
OnDraggableRegionsChanged()357 void CefFrameImpl::OnDraggableRegionsChanged() {
358   // Match the behavior in ChromeRenderFrameObserver::DraggableRegionsChanged.
359   // Only the main frame is allowed to control draggable regions, to avoid other
360   // frames manipulate the regions in the browser process.
361   if (frame_->Parent() != nullptr)
362     return;
363 
364   blink::WebVector<blink::WebDraggableRegion> webregions =
365       frame_->GetDocument().DraggableRegions();
366   std::vector<cef::mojom::DraggableRegionEntryPtr> regions;
367   if (!webregions.empty()) {
368     auto render_frame = content::RenderFrameImpl::FromWebFrame(frame_);
369 
370     regions.reserve(webregions.size());
371     for (const auto& webregion : webregions) {
372       auto region = cef::mojom::DraggableRegionEntry::New(webregion.bounds,
373                                                           webregion.draggable);
374       render_frame->ConvertViewportToWindow(&region->bounds);
375       regions.push_back(std::move(region));
376     }
377   }
378 
379   using RegionsArg =
380       absl::optional<std::vector<cef::mojom::DraggableRegionEntryPtr>>;
381   RegionsArg regions_arg =
382       regions.empty() ? absl::nullopt : absl::make_optional(std::move(regions));
383 
384   SendToBrowserFrame(
385       __FUNCTION__,
386       base::BindOnce(
387           [](RegionsArg regions_arg, const BrowserFrameType& browser_frame) {
388             browser_frame->UpdateDraggableRegions(std::move(regions_arg));
389           },
390           std::move(regions_arg)));
391 }
392 
OnContextCreated()393 void CefFrameImpl::OnContextCreated() {
394   context_created_ = true;
395 
396   CHECK(frame_);
397   while (!queued_context_actions_.empty()) {
398     auto& action = queued_context_actions_.front();
399     std::move(action.second).Run(frame_);
400     queued_context_actions_.pop();
401   }
402 }
403 
OnDetached()404 void CefFrameImpl::OnDetached() {
405   // Called when this frame has been detached from the view. This *will* be
406   // called for child frames when a parent frame is detached.
407   // The browser may hold the last reference to |this|. Take a reference here to
408   // keep |this| alive until after this method returns.
409   CefRefPtr<CefFrameImpl> self = this;
410 
411   frame_ = nullptr;
412 
413   browser_->FrameDetached(frame_id_);
414 
415   OnBrowserFrameDisconnect();
416 
417   browser_ = nullptr;
418   url_loader_factory_.reset();
419 
420   // In case we never attached.
421   while (!queued_browser_actions_.empty()) {
422     auto& action = queued_browser_actions_.front();
423     LOG(WARNING) << action.first << " sent to detached frame "
424                  << frame_util::GetFrameDebugString(frame_id_)
425                  << " will be ignored";
426     queued_browser_actions_.pop();
427   }
428 
429   // In case we're destroyed without the context being created.
430   while (!queued_context_actions_.empty()) {
431     auto& action = queued_context_actions_.front();
432     LOG(WARNING) << action.first << " sent to detached frame "
433                  << frame_util::GetFrameDebugString(frame_id_)
434                  << " will be ignored";
435     queued_context_actions_.pop();
436   }
437 }
438 
ExecuteOnLocalFrame(const std::string & function_name,LocalFrameAction action)439 void CefFrameImpl::ExecuteOnLocalFrame(const std::string& function_name,
440                                        LocalFrameAction action) {
441   CEF_REQUIRE_RT_RETURN_VOID();
442 
443   if (!context_created_) {
444     queued_context_actions_.push(
445         std::make_pair(function_name, std::move(action)));
446     return;
447   }
448 
449   if (frame_) {
450     std::move(action).Run(frame_);
451   } else {
452     LOG(WARNING) << function_name << " sent to detached frame "
453                  << frame_util::GetFrameDebugString(frame_id_)
454                  << " will be ignored";
455   }
456 }
457 
ConnectBrowserFrame()458 void CefFrameImpl::ConnectBrowserFrame() {
459   DCHECK(browser_connection_state_ == ConnectionState::DISCONNECTED ||
460          browser_connection_state_ == ConnectionState::RECONNECT_PENDING);
461 
462   // Don't attempt to connect an invalid or bfcache'd frame. If a bfcache'd
463   // frame returns to active status a reconnect will be triggered via
464   // OnWasShown().
465   if (!frame_ || blink_glue::IsInBackForwardCache(frame_)) {
466     browser_connection_state_ = ConnectionState::DISCONNECTED;
467     browser_connect_timer_.Stop();
468     LOG(INFO) << "Connection retry canceled for frame "
469               << frame_util::GetFrameDebugString(frame_id_);
470     return;
471   }
472 
473   if (browser_connect_retry_ct_ > 0) {
474     LOG(INFO) << "Connection retry " << browser_connect_retry_ct_ << "/"
475               << kConnectionRetryMaxCt << " for frame "
476               << frame_util::GetFrameDebugString(frame_id_);
477   }
478 
479   browser_connection_state_ = ConnectionState::CONNECTION_PENDING;
480   browser_connect_timer_.Start(FROM_HERE, kConnectionTimeout, this,
481                                &CefFrameImpl::OnBrowserFrameTimeout);
482 
483   auto& browser_frame = GetBrowserFrame(/*expect_acked=*/false);
484   CHECK(browser_frame);
485 
486   // If the channel is working we should get a call to FrameAttachedAck().
487   // Otherwise, OnBrowserFrameDisconnect() should be called to retry the
488   // connection.
489   browser_frame->FrameAttached(receiver_.BindNewPipeAndPassRemote(),
490                                browser_connect_retry_ct_ > 0);
491   receiver_.set_disconnect_handler(
492       base::BindOnce(&CefFrameImpl::OnBrowserFrameDisconnect, this));
493 }
494 
GetBrowserFrame(bool expect_acked)495 const mojo::Remote<cef::mojom::BrowserFrame>& CefFrameImpl::GetBrowserFrame(
496     bool expect_acked) {
497   DCHECK_EQ(expect_acked,
498             browser_connection_state_ == ConnectionState::CONNECTION_ACKED);
499 
500   if (!browser_frame_.is_bound()) {
501     auto render_frame = content::RenderFrameImpl::FromWebFrame(frame_);
502     if (render_frame) {
503       // Triggers creation of a CefBrowserFrame in the browser process.
504       render_frame->GetBrowserInterfaceBroker()->GetInterface(
505           browser_frame_.BindNewPipeAndPassReceiver());
506       browser_frame_.set_disconnect_handler(
507           base::BindOnce(&CefFrameImpl::OnBrowserFrameDisconnect, this));
508     }
509   }
510   return browser_frame_;
511 }
512 
OnBrowserFrameTimeout()513 void CefFrameImpl::OnBrowserFrameTimeout() {
514   LOG(ERROR) << "Connection timeout for frame "
515              << frame_util::GetFrameDebugString(frame_id_);
516   OnBrowserFrameDisconnect();
517 }
518 
OnBrowserFrameDisconnect()519 void CefFrameImpl::OnBrowserFrameDisconnect() {
520   // Ignore multiple calls in close proximity (which may occur if both
521   // |browser_frame_| and |receiver_| disconnect). |frame_| will be nullptr
522   // when called from/after OnDetached().
523   if (frame_ &&
524       browser_connection_state_ == ConnectionState::RECONNECT_PENDING) {
525     return;
526   }
527 
528   browser_frame_.reset();
529   receiver_.reset();
530   browser_connection_state_ = ConnectionState::DISCONNECTED;
531   browser_connect_timer_.Stop();
532 
533   // Only retry if the frame is still valid.
534   if (frame_) {
535     if (browser_connect_retry_ct_++ < kConnectionRetryMaxCt) {
536       // Retry after a delay in case the frame is currently navigating, being
537       // destroyed, or entering the bfcache. In the navigation case the retry
538       // will likely succeed. In the destruction case the retry will be
539       // ignored/canceled due to OnDetached(). In the bfcache case the status
540       // may not be updated immediately, so we allow the reconnect timer to
541       // trigger and check the status in ConnectBrowserFrame() instead.
542       browser_connection_state_ = ConnectionState::RECONNECT_PENDING;
543       browser_connect_timer_.Start(FROM_HERE, kConnectionRetryDelay, this,
544                                    &CefFrameImpl::ConnectBrowserFrame);
545     } else {
546       // Trigger a crash in official builds.
547       LOG(FATAL) << "Connection retry failure for frame "
548                  << frame_util::GetFrameDebugString(frame_id_);
549     }
550   }
551 }
552 
SendToBrowserFrame(const std::string & function_name,BrowserFrameAction action)553 void CefFrameImpl::SendToBrowserFrame(const std::string& function_name,
554                                       BrowserFrameAction action) {
555   if (!frame_) {
556     // We've been detached.
557     LOG(WARNING) << function_name << " sent to detached frame "
558                  << frame_util::GetFrameDebugString(frame_id_)
559                  << " will be ignored";
560     return;
561   }
562 
563   if (browser_connection_state_ != ConnectionState::CONNECTION_ACKED) {
564     // Queue actions until we're notified by the browser that it's ready to
565     // handle them.
566     queued_browser_actions_.push(
567         std::make_pair(function_name, std::move(action)));
568     return;
569   }
570 
571   auto& browser_frame = GetBrowserFrame();
572   CHECK(browser_frame);
573 
574   std::move(action).Run(browser_frame);
575 }
576 
FrameAttachedAck()577 void CefFrameImpl::FrameAttachedAck() {
578   // Sent from the browser process in response to ConnectBrowserFrame() sending
579   // FrameAttached().
580   CHECK_EQ(ConnectionState::CONNECTION_PENDING, browser_connection_state_);
581   browser_connection_state_ = ConnectionState::CONNECTION_ACKED;
582   browser_connect_retry_ct_ = 0;
583   browser_connect_timer_.Stop();
584 
585   auto& browser_frame = GetBrowserFrame();
586   CHECK(browser_frame);
587 
588   while (!queued_browser_actions_.empty()) {
589     std::move(queued_browser_actions_.front().second).Run(browser_frame);
590     queued_browser_actions_.pop();
591   }
592 }
593 
SendMessage(const std::string & name,base::Value arguments)594 void CefFrameImpl::SendMessage(const std::string& name, base::Value arguments) {
595   if (auto app = CefAppManager::Get()->GetApplication()) {
596     if (auto handler = app->GetRenderProcessHandler()) {
597       auto& list_value = base::Value::AsListValue(arguments);
598       CefRefPtr<CefProcessMessageImpl> message(new CefProcessMessageImpl(
599           name, std::move(const_cast<base::ListValue&>(list_value)),
600           /*read_only=*/true));
601       handler->OnProcessMessageReceived(browser_, this, PID_BROWSER,
602                                         message.get());
603     }
604   }
605 }
606 
SendCommand(const std::string & command)607 void CefFrameImpl::SendCommand(const std::string& command) {
608   ExecuteOnLocalFrame(
609       __FUNCTION__,
610       base::BindOnce(
611           [](const std::string& command, blink::WebLocalFrame* frame) {
612             frame->ExecuteCommand(blink::WebString::FromUTF8(command));
613           },
614           command));
615 }
616 
SendCommandWithResponse(const std::string & command,cef::mojom::RenderFrame::SendCommandWithResponseCallback callback)617 void CefFrameImpl::SendCommandWithResponse(
618     const std::string& command,
619     cef::mojom::RenderFrame::SendCommandWithResponseCallback callback) {
620   ExecuteOnLocalFrame(
621       __FUNCTION__,
622       base::BindOnce(
623           [](const std::string& command,
624              cef::mojom::RenderFrame::SendCommandWithResponseCallback callback,
625              blink::WebLocalFrame* frame) {
626             blink::WebString response;
627 
628             if (base::LowerCaseEqualsASCII(command, "getsource")) {
629               response = blink_glue::DumpDocumentMarkup(frame);
630             } else if (base::LowerCaseEqualsASCII(command, "gettext")) {
631               response = blink_glue::DumpDocumentText(frame);
632             }
633 
634             std::move(callback).Run(
635                 string_util::CreateSharedMemoryRegion(response));
636           },
637           command, std::move(callback)));
638 }
639 
SendJavaScript(const std::u16string & jsCode,const std::string & scriptUrl,int32_t startLine)640 void CefFrameImpl::SendJavaScript(const std::u16string& jsCode,
641                                   const std::string& scriptUrl,
642                                   int32_t startLine) {
643   ExecuteOnLocalFrame(
644       __FUNCTION__,
645       base::BindOnce(
646           [](const std::u16string& jsCode, const std::string& scriptUrl,
647              blink::WebLocalFrame* frame) {
648             frame->ExecuteScript(blink::WebScriptSource(
649                 blink::WebString::FromUTF16(jsCode), GURL(scriptUrl)));
650           },
651           jsCode, scriptUrl));
652 }
653 
LoadRequest(cef::mojom::RequestParamsPtr params)654 void CefFrameImpl::LoadRequest(cef::mojom::RequestParamsPtr params) {
655   ExecuteOnLocalFrame(
656       __FUNCTION__,
657       base::BindOnce(
658           [](cef::mojom::RequestParamsPtr params, blink::WebLocalFrame* frame) {
659             blink::WebURLRequest request;
660             CefRequestImpl::Get(params, request);
661             blink_glue::StartNavigation(frame, request);
662           },
663           std::move(params)));
664 }
665 
DidStopLoading()666 void CefFrameImpl::DidStopLoading() {
667   // We should only receive this notification for the highest-level LocalFrame
668   // in this frame's in-process subtree. If there are multiple of these for
669   // the same browser then the other occurrences will be discarded in
670   // OnLoadingStateChange.
671   browser_->OnLoadingStateChange(false);
672 
673   // Refresh draggable regions. Otherwise, we may not receive updated regions
674   // after navigation because LocalFrameView::UpdateDocumentAnnotatedRegion
675   // lacks sufficient context.
676   OnDraggableRegionsChanged();
677 }
678 
MoveOrResizeStarted()679 void CefFrameImpl::MoveOrResizeStarted() {
680   if (frame_) {
681     auto web_view = frame_->View();
682     if (web_view)
683       web_view->CancelPagePopup();
684   }
685 }
686 
687 // Enable deprecation warnings on Windows. See http://crbug.com/585142.
688 #if BUILDFLAG(IS_WIN)
689 #if defined(__clang__)
690 #pragma GCC diagnostic pop
691 #else
692 #pragma warning(pop)
693 #endif
694 #endif
695