OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2017 The Chromium 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 "components/subresource_filter/content/browser/content_subresource_filt er_throttle_manager.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/logging.h" | |
9 #include "base/memory/ptr_util.h" | |
10 #include "components/subresource_filter/content/browser/activation_state_computi ng_navigation_throttle.h" | |
11 #include "components/subresource_filter/content/browser/async_document_subresour ce_filter.h" | |
12 #include "components/subresource_filter/content/browser/subframe_navigation_filt ering_throttle.h" | |
13 #include "content/public/browser/navigation_handle.h" | |
14 #include "content/public/browser/render_frame_host.h" | |
15 #include "content/public/browser/web_contents.h" | |
16 | |
17 namespace subresource_filter { | |
18 | |
19 bool ContentSubresourceFilterThrottleManager::Delegate:: | |
20 ShouldSuppressActivation(content::NavigationHandle* navigation_handle) { | |
21 return false; | |
22 } | |
23 | |
24 ContentSubresourceFilterThrottleManager:: | |
25 ContentSubresourceFilterThrottleManager( | |
26 Delegate* delegate, | |
27 VerifiedRulesetDealer::Handle* dealer_handle, | |
28 content::WebContents* web_contents) | |
29 : content::WebContentsObserver(web_contents), | |
30 dealer_handle_(dealer_handle), | |
31 delegate_(delegate), | |
32 weak_ptr_factory_(this) {} | |
33 | |
34 ContentSubresourceFilterThrottleManager:: | |
35 ~ContentSubresourceFilterThrottleManager() {} | |
36 | |
37 void ContentSubresourceFilterThrottleManager::NotifyPageActivationComputed( | |
38 content::NavigationHandle* navigation_handle, | |
39 const ActivationState& activation_state) { | |
40 DCHECK(navigation_handle->IsInMainFrame()); | |
41 DCHECK(!navigation_handle->HasCommitted()); | |
42 auto it = ongoing_activation_throttles_.find(navigation_handle); | |
43 if (it != ongoing_activation_throttles_.end()) { | |
44 it->second->NotifyPageActivationWithRuleset( | |
45 EnsureRulesetHandle(), activation_state, | |
46 base::Bind(&ContentSubresourceFilterThrottleManager:: | |
47 MaybeCallFirstDisallowedLoad, | |
48 weak_ptr_factory_.GetWeakPtr())); | |
49 } | |
50 } | |
51 | |
52 void ContentSubresourceFilterThrottleManager::RenderFrameDeleted( | |
53 content::RenderFrameHost* frame_host) { | |
54 activated_frame_hosts_.erase(frame_host); | |
55 DestroyRulesetHandleIfNoLongerUsed(); | |
56 } | |
57 | |
58 // Pull the AsyncDocumentSubresourceFilter and its associated ActivationState | |
59 // out of the activation state computing throttle. Store it for later filtering | |
60 // of subframe navigations. | |
61 void ContentSubresourceFilterThrottleManager::ReadyToCommitNavigation( | |
62 content::NavigationHandle* navigation_handle) { | |
63 content::RenderFrameHost* frame_host = | |
64 navigation_handle->GetRenderFrameHost(); | |
65 // Make sure that if the committed navigation is in a RenderFrameHost that is | |
engedy
2017/03/10 17:36:20
Note that ReadyToCommitNavigation is not invoked f
engedy
2017/03/10 20:50:34
Could you please add a unit test to ensure the rul
Charlie Harrison
2017/03/14 23:18:31
Ah that is very unfortunate. To get around that an
Charlie Harrison
2017/03/14 23:18:31
Added tests for:
- Same site navigations to inacti
Charlie Harrison
2017/03/14 23:18:31
Done.
engedy
2017/03/20 18:58:14
Acknowledged, thanks!
| |
66 // already activated, the activation state is reset. This is important in the | |
67 // case where this navigation does *not* trigger activation. | |
68 activated_frame_hosts_.erase(frame_host); | |
69 | |
70 auto throttle = ongoing_activation_throttles_.find(navigation_handle); | |
71 if (throttle == ongoing_activation_throttles_.end()) { | |
72 DestroyRulesetHandleIfNoLongerUsed(); | |
73 return; | |
74 } | |
75 | |
76 // Some navigations (like about:blank) do not go through WillProcessResponse, | |
77 // and won't receive valid filters or activation states. | |
engedy
2017/03/10 17:36:20
I am not sure but I think that in all these cases
engedy
2017/03/10 17:55:55
I checked and my previous statement is not correct
Charlie Harrison
2017/03/14 23:18:31
Yeah I noticed this in tests.
| |
78 std::unique_ptr<AsyncDocumentSubresourceFilter> filter = | |
79 throttle->second->ReleaseFilter(); | |
80 if (!filter) | |
81 return; | |
82 | |
83 const ActivationState& activation_state = | |
84 throttle->second->GetActivationState(); | |
85 DCHECK_NE(ActivationLevel::DISABLED, activation_state.activation_level); | |
86 if (delegate_->ShouldSuppressActivation(navigation_handle)) { | |
87 DestroyRulesetHandleIfNoLongerUsed(); | |
88 return; | |
89 } | |
90 activated_frame_hosts_[frame_host] = std::move(filter); | |
91 // TODO(csharrison): Send an IPC to the renderer. | |
92 } | |
93 | |
94 void ContentSubresourceFilterThrottleManager::DidFinishNavigation( | |
95 content::NavigationHandle* navigation_handle) { | |
96 ongoing_activation_throttles_.erase(navigation_handle); | |
97 if (navigation_handle->IsInMainFrame() && navigation_handle->HasCommitted() && | |
98 !navigation_handle->IsSameDocument()) { | |
99 current_committed_load_has_notified_disallowed_load_ = false; | |
100 } | |
101 } | |
102 | |
103 void ContentSubresourceFilterThrottleManager::MaybeAppendNavigationThrottles( | |
104 content::NavigationHandle* navigation_handle, | |
105 std::vector<std::unique_ptr<content::NavigationThrottle>>* throttles) { | |
106 if (navigation_handle->IsSameDocument()) | |
107 return; | |
108 if (auto filtering_throttle = | |
109 MaybeCreateSubframeNavigationFilteringThrottle(navigation_handle)) { | |
110 throttles->push_back(std::move(filtering_throttle)); | |
111 } | |
112 if (auto activation_throttle = | |
113 MaybeCreateActivationStateComputingThrottle(navigation_handle)) { | |
114 ongoing_activation_throttles_[navigation_handle] = | |
115 activation_throttle.get(); | |
116 throttles->push_back(std::move(activation_throttle)); | |
117 } | |
118 } | |
119 | |
120 std::unique_ptr<SubframeNavigationFilteringThrottle> | |
121 ContentSubresourceFilterThrottleManager:: | |
122 MaybeCreateSubframeNavigationFilteringThrottle( | |
123 content::NavigationHandle* navigation_handle) { | |
124 if (navigation_handle->IsInMainFrame()) | |
125 return nullptr; | |
126 AsyncDocumentSubresourceFilter* parent_filter = | |
127 GetParentFilter(navigation_handle); | |
engedy
2017/03/10 17:36:20
nit: GetParentFrameFilter
Charlie Harrison
2017/03/14 23:18:31
Done.
| |
128 return parent_filter ? base::MakeUnique<SubframeNavigationFilteringThrottle>( | |
129 navigation_handle, parent_filter) | |
130 : nullptr; | |
131 } | |
132 | |
133 std::unique_ptr<ActivationStateComputingNavigationThrottle> | |
134 ContentSubresourceFilterThrottleManager:: | |
135 MaybeCreateActivationStateComputingThrottle( | |
136 content::NavigationHandle* navigation_handle) { | |
137 // Main frames: create unconditionally. | |
138 if (navigation_handle->IsInMainFrame()) { | |
139 return ActivationStateComputingNavigationThrottle::CreateForMainFrame( | |
140 navigation_handle); | |
141 } | |
142 | |
143 // Subframes: create only for frames with activated parents. | |
144 AsyncDocumentSubresourceFilter* parent_filter = | |
145 GetParentFilter(navigation_handle); | |
146 if (!parent_filter) | |
147 return nullptr; | |
148 DCHECK(ruleset_handle_); | |
149 return ActivationStateComputingNavigationThrottle::CreateForSubframe( | |
150 navigation_handle, ruleset_handle_.get(), | |
151 parent_filter->activation_state(), | |
152 base::Bind(&ContentSubresourceFilterThrottleManager:: | |
153 MaybeCallFirstDisallowedLoad, | |
154 weak_ptr_factory_.GetWeakPtr())); | |
155 } | |
156 | |
157 AsyncDocumentSubresourceFilter* | |
158 ContentSubresourceFilterThrottleManager::GetParentFilter( | |
159 content::NavigationHandle* child_frame_navigation) { | |
160 DCHECK(!child_frame_navigation->IsInMainFrame()); | |
161 content::RenderFrameHost* parent = web_contents()->FindFrameByFrameTreeNodeId( | |
162 child_frame_navigation->GetParentFrameTreeNodeId()); | |
163 DCHECK(parent); | |
164 auto it = activated_frame_hosts_.find(parent); | |
165 return it == activated_frame_hosts_.end() ? nullptr : it->second.get(); | |
166 } | |
167 | |
168 void ContentSubresourceFilterThrottleManager::MaybeCallFirstDisallowedLoad() { | |
169 if (current_committed_load_has_notified_disallowed_load_) | |
170 return; | |
171 delegate_->OnFirstSubresourceLoadDisallowed(); | |
172 current_committed_load_has_notified_disallowed_load_ = true; | |
173 } | |
174 | |
175 VerifiedRuleset::Handle* | |
176 ContentSubresourceFilterThrottleManager::EnsureRulesetHandle() { | |
177 if (!ruleset_handle_) | |
178 ruleset_handle_ = base::MakeUnique<VerifiedRuleset::Handle>(dealer_handle_); | |
179 return ruleset_handle_.get(); | |
180 } | |
181 | |
182 void ContentSubresourceFilterThrottleManager:: | |
183 DestroyRulesetHandleIfNoLongerUsed() { | |
184 if (activated_frame_hosts_.size() == 0) | |
185 ruleset_handle_.reset(); | |
186 } | |
187 | |
188 } // namespace subresource_filter | |
OLD | NEW |