1 // Copyright 2020 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/net/throttle_handler.h"
6
7 #include "libcef/browser/browser_host_base.h"
8 #include "libcef/browser/browser_info_manager.h"
9 #include "libcef/browser/frame_host_impl.h"
10 #include "libcef/common/frame_util.h"
11 #include "libcef/common/request_impl.h"
12
13 #include "components/navigation_interception/intercept_navigation_throttle.h"
14 #include "components/navigation_interception/navigation_params.h"
15 #include "content/public/browser/navigation_handle.h"
16 #include "content/public/browser/navigation_throttle.h"
17 #include "content/public/browser/page_navigator.h"
18
19 namespace throttle {
20
21 namespace {
22
23 // TODO(cef): We can't currently trust NavigationParams::is_main_frame() because
24 // it's always set to true in
25 // InterceptNavigationThrottle::CheckIfShouldIgnoreNavigation. Remove the
26 // |is_main_frame| argument once this problem is fixed.
NavigationOnUIThread(bool is_main_frame,bool is_pdf,const content::GlobalRenderFrameHostId & global_id,const content::GlobalRenderFrameHostId & parent_global_id,content::WebContents * source,const navigation_interception::NavigationParams & params)27 bool NavigationOnUIThread(
28 bool is_main_frame,
29 bool is_pdf,
30 const content::GlobalRenderFrameHostId& global_id,
31 const content::GlobalRenderFrameHostId& parent_global_id,
32 content::WebContents* source,
33 const navigation_interception::NavigationParams& params) {
34 CEF_REQUIRE_UIT();
35
36 content::OpenURLParams open_params(
37 params.url(), params.referrer(), WindowOpenDisposition::CURRENT_TAB,
38 params.transition_type(), params.is_renderer_initiated());
39 open_params.user_gesture = params.has_user_gesture();
40 open_params.initiator_origin = params.initiator_origin();
41 open_params.is_pdf = is_pdf;
42
43 CefRefPtr<CefBrowserHostBase> browser;
44 if (!CefBrowserInfoManager::GetInstance()->MaybeAllowNavigation(
45 source->GetMainFrame(), open_params, browser)) {
46 // Cancel the navigation.
47 return true;
48 }
49
50 bool ignore_navigation = false;
51
52 if (browser) {
53 if (auto client = browser->GetClient()) {
54 if (auto handler = client->GetRequestHandler()) {
55 CefRefPtr<CefFrame> frame;
56 if (is_main_frame) {
57 frame = browser->GetMainFrame();
58 } else {
59 frame = browser->GetFrameForGlobalId(global_id);
60 }
61 if (!frame) {
62 // Create a temporary frame object for navigation of sub-frames that
63 // don't yet exist.
64 frame = browser->browser_info()->CreateTempSubFrame(parent_global_id);
65 }
66
67 CefRefPtr<CefRequestImpl> request = new CefRequestImpl();
68 request->Set(params, is_main_frame);
69 request->SetReadOnly(true);
70
71 // Initiating a new navigation in OnBeforeBrowse will delete the
72 // InterceptNavigationThrottle that currently owns this callback,
73 // resulting in a crash. Use the lock to prevent that.
74 auto navigation_lock = browser->browser_info()->CreateNavigationLock();
75 ignore_navigation = handler->OnBeforeBrowse(
76 browser.get(), frame, request.get(), params.has_user_gesture(),
77 params.is_redirect());
78 }
79 }
80 }
81
82 return ignore_navigation;
83 }
84
85 } // namespace
86
CreateThrottlesForNavigation(content::NavigationHandle * navigation_handle,NavigationThrottleList & throttles)87 void CreateThrottlesForNavigation(content::NavigationHandle* navigation_handle,
88 NavigationThrottleList& throttles) {
89 CEF_REQUIRE_UIT();
90
91 const bool is_main_frame = navigation_handle->IsInMainFrame();
92 const bool is_pdf = navigation_handle->IsPdf();
93 const auto global_id = frame_util::GetGlobalId(navigation_handle);
94
95 // Identify the RenderFrameHost that originated the navigation.
96 const auto parent_global_id =
97 !is_main_frame ? navigation_handle->GetParentFrame()->GetGlobalId()
98 : frame_util::InvalidGlobalId();
99
100 // Must use SynchronyMode::kSync to ensure that OnBeforeBrowse is always
101 // called before OnBeforeResourceLoad.
102 std::unique_ptr<content::NavigationThrottle> throttle =
103 std::make_unique<navigation_interception::InterceptNavigationThrottle>(
104 navigation_handle,
105 base::BindRepeating(&NavigationOnUIThread, is_main_frame, is_pdf,
106 global_id, parent_global_id),
107 navigation_interception::SynchronyMode::kSync);
108 throttles.push_back(std::move(throttle));
109 }
110
111 } // namespace throttle
112