mirror of
				https://bitbucket.org/chromiumembedded/cef
				synced 2025-06-05 21:39:12 +02:00 
			
		
		
		
	
		
			
				
	
	
		
			402 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			402 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| // Copyright (c) 2012 The Chromium Embedded Framework Authors.
 | |
| // Portions copyright (c) 2011 The Chromium Authors. All rights reserved.
 | |
| // Use of this source code is governed by a BSD-style license that can be
 | |
| // found in the LICENSE file.
 | |
| 
 | |
| #include "libcef/renderer/browser_impl.h"
 | |
| 
 | |
| #include <string>
 | |
| #include <vector>
 | |
| 
 | |
| #include "libcef/common/cef_messages.h"
 | |
| #include "libcef/common/content_client.h"
 | |
| #include "libcef/renderer/blink_glue.h"
 | |
| #include "libcef/renderer/content_renderer_client.h"
 | |
| #include "libcef/renderer/render_frame_util.h"
 | |
| #include "libcef/renderer/thread_util.h"
 | |
| 
 | |
| #include "base/strings/string16.h"
 | |
| #include "base/strings/string_util.h"
 | |
| #include "base/strings/utf_string_conversions.h"
 | |
| #include "content/public/renderer/document_state.h"
 | |
| #include "content/public/renderer/render_frame.h"
 | |
| #include "content/public/renderer/render_view.h"
 | |
| #include "content/renderer/navigation_state.h"
 | |
| #include "third_party/blink/public/platform/web_string.h"
 | |
| #include "third_party/blink/public/platform/web_url_error.h"
 | |
| #include "third_party/blink/public/platform/web_url_response.h"
 | |
| #include "third_party/blink/public/web/web_document.h"
 | |
| #include "third_party/blink/public/web/web_frame.h"
 | |
| #include "third_party/blink/public/web/web_frame_content_dumper.h"
 | |
| #include "third_party/blink/public/web/web_local_frame.h"
 | |
| #include "third_party/blink/public/web/web_security_policy.h"
 | |
| #include "third_party/blink/public/web/web_view.h"
 | |
| 
 | |
| // CefBrowserImpl static methods.
 | |
| // -----------------------------------------------------------------------------
 | |
| 
 | |
| // static
 | |
| CefRefPtr<CefBrowserImpl> CefBrowserImpl::GetBrowserForView(
 | |
|     content::RenderView* view) {
 | |
|   return CefContentRendererClient::Get()->GetBrowserForView(view);
 | |
| }
 | |
| 
 | |
| // static
 | |
| CefRefPtr<CefBrowserImpl> CefBrowserImpl::GetBrowserForMainFrame(
 | |
|     blink::WebFrame* frame) {
 | |
|   return CefContentRendererClient::Get()->GetBrowserForMainFrame(frame);
 | |
| }
 | |
| 
 | |
| // CefBrowser methods.
 | |
| // -----------------------------------------------------------------------------
 | |
| 
 | |
| CefRefPtr<CefBrowserHost> CefBrowserImpl::GetHost() {
 | |
|   NOTREACHED() << "GetHost cannot be called from the render process";
 | |
|   return nullptr;
 | |
| }
 | |
| 
 | |
| bool CefBrowserImpl::CanGoBack() {
 | |
|   CEF_REQUIRE_RT_RETURN(false);
 | |
| 
 | |
|   return blink_glue::CanGoBack(render_view()->GetWebView());
 | |
| }
 | |
| 
 | |
| void CefBrowserImpl::GoBack() {
 | |
|   CEF_REQUIRE_RT_RETURN_VOID();
 | |
| 
 | |
|   blink_glue::GoBack(render_view()->GetWebView());
 | |
| }
 | |
| 
 | |
| bool CefBrowserImpl::CanGoForward() {
 | |
|   CEF_REQUIRE_RT_RETURN(false);
 | |
| 
 | |
|   return blink_glue::CanGoForward(render_view()->GetWebView());
 | |
| }
 | |
| 
 | |
| void CefBrowserImpl::GoForward() {
 | |
|   CEF_REQUIRE_RT_RETURN_VOID();
 | |
| 
 | |
|   blink_glue::GoForward(render_view()->GetWebView());
 | |
| }
 | |
| 
 | |
| bool CefBrowserImpl::IsLoading() {
 | |
|   CEF_REQUIRE_RT_RETURN(false);
 | |
| 
 | |
|   if (render_view()->GetWebView()) {
 | |
|     blink::WebFrame* main_frame = render_view()->GetWebView()->MainFrame();
 | |
|     if (main_frame)
 | |
|       return main_frame->ToWebLocalFrame()->IsLoading();
 | |
|   }
 | |
|   return false;
 | |
| }
 | |
| 
 | |
| void CefBrowserImpl::Reload() {
 | |
|   CEF_REQUIRE_RT_RETURN_VOID();
 | |
| 
 | |
|   if (render_view()->GetWebView()) {
 | |
|     blink::WebFrame* main_frame = render_view()->GetWebView()->MainFrame();
 | |
|     if (main_frame && main_frame->IsWebLocalFrame()) {
 | |
|       main_frame->ToWebLocalFrame()->StartReload(
 | |
|           blink::WebFrameLoadType::kReload);
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| void CefBrowserImpl::ReloadIgnoreCache() {
 | |
|   CEF_REQUIRE_RT_RETURN_VOID();
 | |
| 
 | |
|   if (render_view()->GetWebView()) {
 | |
|     blink::WebFrame* main_frame = render_view()->GetWebView()->MainFrame();
 | |
|     if (main_frame && main_frame->IsWebLocalFrame()) {
 | |
|       main_frame->ToWebLocalFrame()->StartReload(
 | |
|           blink::WebFrameLoadType::kReloadBypassingCache);
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| void CefBrowserImpl::StopLoad() {
 | |
|   CEF_REQUIRE_RT_RETURN_VOID();
 | |
| 
 | |
|   if (render_view()->GetWebView()) {
 | |
|     blink::WebFrame* main_frame = render_view()->GetWebView()->MainFrame();
 | |
|     if (main_frame && main_frame->IsWebLocalFrame()) {
 | |
|       main_frame->ToWebLocalFrame()->StopLoading();
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| int CefBrowserImpl::GetIdentifier() {
 | |
|   CEF_REQUIRE_RT_RETURN(0);
 | |
| 
 | |
|   return browser_id();
 | |
| }
 | |
| 
 | |
| bool CefBrowserImpl::IsSame(CefRefPtr<CefBrowser> that) {
 | |
|   CEF_REQUIRE_RT_RETURN(false);
 | |
| 
 | |
|   CefBrowserImpl* impl = static_cast<CefBrowserImpl*>(that.get());
 | |
|   return (impl == this);
 | |
| }
 | |
| 
 | |
| bool CefBrowserImpl::IsPopup() {
 | |
|   CEF_REQUIRE_RT_RETURN(false);
 | |
| 
 | |
|   return is_popup();
 | |
| }
 | |
| 
 | |
| bool CefBrowserImpl::HasDocument() {
 | |
|   CEF_REQUIRE_RT_RETURN(false);
 | |
| 
 | |
|   if (render_view()->GetWebView()) {
 | |
|     blink::WebFrame* main_frame = render_view()->GetWebView()->MainFrame();
 | |
|     if (main_frame && main_frame->IsWebLocalFrame()) {
 | |
|       return !main_frame->ToWebLocalFrame()->GetDocument().IsNull();
 | |
|     }
 | |
|   }
 | |
|   return false;
 | |
| }
 | |
| 
 | |
| CefRefPtr<CefFrame> CefBrowserImpl::GetMainFrame() {
 | |
|   CEF_REQUIRE_RT_RETURN(nullptr);
 | |
| 
 | |
|   if (render_view()->GetWebView()) {
 | |
|     blink::WebFrame* main_frame = render_view()->GetWebView()->MainFrame();
 | |
|     if (main_frame && main_frame->IsWebLocalFrame()) {
 | |
|       return GetWebFrameImpl(main_frame->ToWebLocalFrame()).get();
 | |
|     }
 | |
|   }
 | |
|   return nullptr;
 | |
| }
 | |
| 
 | |
| CefRefPtr<CefFrame> CefBrowserImpl::GetFocusedFrame() {
 | |
|   CEF_REQUIRE_RT_RETURN(nullptr);
 | |
| 
 | |
|   if (render_view()->GetWebView() &&
 | |
|       render_view()->GetWebView()->FocusedFrame()) {
 | |
|     return GetWebFrameImpl(render_view()->GetWebView()->FocusedFrame()).get();
 | |
|   }
 | |
|   return nullptr;
 | |
| }
 | |
| 
 | |
| CefRefPtr<CefFrame> CefBrowserImpl::GetFrame(int64 identifier) {
 | |
|   CEF_REQUIRE_RT_RETURN(nullptr);
 | |
| 
 | |
|   return GetWebFrameImpl(identifier).get();
 | |
| }
 | |
| 
 | |
| CefRefPtr<CefFrame> CefBrowserImpl::GetFrame(const CefString& name) {
 | |
|   CEF_REQUIRE_RT_RETURN(nullptr);
 | |
| 
 | |
|   blink::WebView* web_view = render_view()->GetWebView();
 | |
|   if (web_view) {
 | |
|     const blink::WebString& frame_name =
 | |
|         blink::WebString::FromUTF16(name.ToString16());
 | |
|     // Search by assigned frame name (Frame::name).
 | |
|     blink::WebFrame* frame = web_view->MainFrame();
 | |
|     if (frame && frame->IsWebLocalFrame())
 | |
|       frame = frame->ToWebLocalFrame()->FindFrameByName(frame_name);
 | |
|     if (!frame) {
 | |
|       // Search by unique frame name (Frame::uniqueName).
 | |
|       const std::string& searchname = name;
 | |
|       for (blink::WebFrame* cur_frame = web_view->MainFrame(); cur_frame;
 | |
|            cur_frame = cur_frame->TraverseNext()) {
 | |
|         if (cur_frame->IsWebLocalFrame() &&
 | |
|             render_frame_util::GetName(cur_frame->ToWebLocalFrame()) ==
 | |
|                 searchname) {
 | |
|           frame = cur_frame;
 | |
|           break;
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|     if (frame && frame->IsWebLocalFrame())
 | |
|       return GetWebFrameImpl(frame->ToWebLocalFrame()).get();
 | |
|   }
 | |
| 
 | |
|   return nullptr;
 | |
| }
 | |
| 
 | |
| size_t CefBrowserImpl::GetFrameCount() {
 | |
|   CEF_REQUIRE_RT_RETURN(0);
 | |
| 
 | |
|   int count = 0;
 | |
| 
 | |
|   if (render_view()->GetWebView()) {
 | |
|     for (blink::WebFrame* frame = render_view()->GetWebView()->MainFrame();
 | |
|          frame; frame = frame->TraverseNext()) {
 | |
|       count++;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return count;
 | |
| }
 | |
| 
 | |
| void CefBrowserImpl::GetFrameIdentifiers(std::vector<int64>& identifiers) {
 | |
|   CEF_REQUIRE_RT_RETURN_VOID();
 | |
| 
 | |
|   if (identifiers.size() > 0)
 | |
|     identifiers.clear();
 | |
| 
 | |
|   if (render_view()->GetWebView()) {
 | |
|     for (blink::WebFrame* frame = render_view()->GetWebView()->MainFrame();
 | |
|          frame; frame = frame->TraverseNext()) {
 | |
|       if (frame->IsWebLocalFrame())
 | |
|         identifiers.push_back(
 | |
|             render_frame_util::GetIdentifier(frame->ToWebLocalFrame()));
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| void CefBrowserImpl::GetFrameNames(std::vector<CefString>& names) {
 | |
|   CEF_REQUIRE_RT_RETURN_VOID();
 | |
| 
 | |
|   if (names.size() > 0)
 | |
|     names.clear();
 | |
| 
 | |
|   if (render_view()->GetWebView()) {
 | |
|     for (blink::WebFrame* frame = render_view()->GetWebView()->MainFrame();
 | |
|          frame; frame = frame->TraverseNext()) {
 | |
|       if (frame->IsWebLocalFrame())
 | |
|         names.push_back(render_frame_util::GetName(frame->ToWebLocalFrame()));
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| // CefBrowserImpl public methods.
 | |
| // -----------------------------------------------------------------------------
 | |
| 
 | |
| CefBrowserImpl::CefBrowserImpl(content::RenderView* render_view,
 | |
|                                int browser_id,
 | |
|                                bool is_popup,
 | |
|                                bool is_windowless)
 | |
|     : content::RenderViewObserver(render_view),
 | |
|       browser_id_(browser_id),
 | |
|       is_popup_(is_popup),
 | |
|       is_windowless_(is_windowless) {}
 | |
| 
 | |
| CefBrowserImpl::~CefBrowserImpl() {}
 | |
| 
 | |
| CefRefPtr<CefFrameImpl> CefBrowserImpl::GetWebFrameImpl(
 | |
|     blink::WebLocalFrame* frame) {
 | |
|   DCHECK(frame);
 | |
|   int64_t frame_id = render_frame_util::GetIdentifier(frame);
 | |
| 
 | |
|   // Frames are re-used between page loads. Only add the frame to the map once.
 | |
|   FrameMap::const_iterator it = frames_.find(frame_id);
 | |
|   if (it != frames_.end())
 | |
|     return it->second;
 | |
| 
 | |
|   CefRefPtr<CefFrameImpl> framePtr(new CefFrameImpl(this, frame, frame_id));
 | |
|   frames_.insert(std::make_pair(frame_id, framePtr));
 | |
| 
 | |
|   return framePtr;
 | |
| }
 | |
| 
 | |
| CefRefPtr<CefFrameImpl> CefBrowserImpl::GetWebFrameImpl(int64_t frame_id) {
 | |
|   if (frame_id == blink_glue::kInvalidFrameId) {
 | |
|     if (render_view()->GetWebView()) {
 | |
|       blink::WebFrame* main_frame = render_view()->GetWebView()->MainFrame();
 | |
|       if (main_frame && main_frame->IsWebLocalFrame()) {
 | |
|         return GetWebFrameImpl(main_frame->ToWebLocalFrame());
 | |
|       }
 | |
|     }
 | |
|     return nullptr;
 | |
|   }
 | |
| 
 | |
|   // Check if we already know about the frame.
 | |
|   FrameMap::const_iterator it = frames_.find(frame_id);
 | |
|   if (it != frames_.end())
 | |
|     return it->second;
 | |
| 
 | |
|   if (render_view()->GetWebView()) {
 | |
|     // Check if the frame exists but we don't know about it yet.
 | |
|     for (blink::WebFrame* frame = render_view()->GetWebView()->MainFrame();
 | |
|          frame; frame = frame->TraverseNext()) {
 | |
|       if (frame->IsWebLocalFrame() &&
 | |
|           render_frame_util::GetIdentifier(frame->ToWebLocalFrame()) ==
 | |
|               frame_id) {
 | |
|         return GetWebFrameImpl(frame->ToWebLocalFrame());
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return nullptr;
 | |
| }
 | |
| 
 | |
| void CefBrowserImpl::AddFrameObject(int64_t frame_id,
 | |
|                                     CefTrackNode* tracked_object) {
 | |
|   CefRefPtr<CefTrackManager> manager;
 | |
| 
 | |
|   if (!frame_objects_.empty()) {
 | |
|     FrameObjectMap::const_iterator it = frame_objects_.find(frame_id);
 | |
|     if (it != frame_objects_.end())
 | |
|       manager = it->second;
 | |
|   }
 | |
| 
 | |
|   if (!manager.get()) {
 | |
|     manager = new CefTrackManager();
 | |
|     frame_objects_.insert(std::make_pair(frame_id, manager));
 | |
|   }
 | |
| 
 | |
|   manager->Add(tracked_object);
 | |
| }
 | |
| 
 | |
| // RenderViewObserver methods.
 | |
| // -----------------------------------------------------------------------------
 | |
| 
 | |
| void CefBrowserImpl::OnDestruct() {
 | |
|   // Notify that the browser window has been destroyed.
 | |
|   CefRefPtr<CefApp> app = CefContentClient::Get()->application();
 | |
|   if (app.get()) {
 | |
|     CefRefPtr<CefRenderProcessHandler> handler = app->GetRenderProcessHandler();
 | |
|     if (handler.get())
 | |
|       handler->OnBrowserDestroyed(this);
 | |
|   }
 | |
| 
 | |
|   CefContentRendererClient::Get()->OnBrowserDestroyed(this);
 | |
| }
 | |
| 
 | |
| void CefBrowserImpl::FrameDetached(int64_t frame_id) {
 | |
|   if (!frames_.empty()) {
 | |
|     // Remove the frame from the map.
 | |
|     FrameMap::iterator it = frames_.find(frame_id);
 | |
|     if (it != frames_.end()) {
 | |
|       frames_.erase(it);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (!frame_objects_.empty()) {
 | |
|     // Remove any tracked objects associated with the frame.
 | |
|     FrameObjectMap::iterator it = frame_objects_.find(frame_id);
 | |
|     if (it != frame_objects_.end())
 | |
|       frame_objects_.erase(it);
 | |
|   }
 | |
| }
 | |
| 
 | |
| void CefBrowserImpl::OnLoadingStateChange(bool isLoading) {
 | |
|   CefRefPtr<CefApp> app = CefContentClient::Get()->application();
 | |
|   if (app.get()) {
 | |
|     CefRefPtr<CefRenderProcessHandler> handler = app->GetRenderProcessHandler();
 | |
|     if (handler.get()) {
 | |
|       CefRefPtr<CefLoadHandler> load_handler = handler->GetLoadHandler();
 | |
|       if (load_handler.get()) {
 | |
|         blink::WebView* web_view = render_view()->GetWebView();
 | |
|         const bool canGoBack = blink_glue::CanGoBack(web_view);
 | |
|         const bool canGoForward = blink_glue::CanGoForward(web_view);
 | |
| 
 | |
|         // Don't call OnLoadingStateChange multiple times with the same status.
 | |
|         // This can occur in cases where there are multiple highest-level
 | |
|         // LocalFrames in-process for the same browser.
 | |
|         if (last_loading_state_ &&
 | |
|             last_loading_state_->IsMatch(isLoading, canGoBack, canGoForward)) {
 | |
|           return;
 | |
|         }
 | |
| 
 | |
|         load_handler->OnLoadingStateChange(this, isLoading, canGoBack,
 | |
|                                            canGoForward);
 | |
|         last_loading_state_.reset(
 | |
|             new LoadingState(isLoading, canGoBack, canGoForward));
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| }
 |