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 #include "net/base/net_errors.h" |
| 17 |
| 18 namespace subresource_filter { |
| 19 |
| 20 bool ContentSubresourceFilterThrottleManager::Delegate:: |
| 21 ShouldSuppressActivation(content::NavigationHandle* navigation_handle) { |
| 22 return false; |
| 23 } |
| 24 |
| 25 ContentSubresourceFilterThrottleManager:: |
| 26 ContentSubresourceFilterThrottleManager( |
| 27 Delegate* delegate, |
| 28 VerifiedRulesetDealer::Handle* dealer_handle, |
| 29 content::WebContents* web_contents) |
| 30 : content::WebContentsObserver(web_contents), |
| 31 dealer_handle_(dealer_handle), |
| 32 delegate_(delegate), |
| 33 weak_ptr_factory_(this) {} |
| 34 |
| 35 ContentSubresourceFilterThrottleManager:: |
| 36 ~ContentSubresourceFilterThrottleManager() {} |
| 37 |
| 38 void ContentSubresourceFilterThrottleManager::NotifyPageActivationComputed( |
| 39 content::NavigationHandle* navigation_handle, |
| 40 const ActivationState& activation_state) { |
| 41 DCHECK(navigation_handle->IsInMainFrame()); |
| 42 DCHECK(!navigation_handle->HasCommitted()); |
| 43 auto it = ongoing_activation_throttles_.find(navigation_handle); |
| 44 if (it != ongoing_activation_throttles_.end()) { |
| 45 it->second->NotifyPageActivationWithRuleset(EnsureRulesetHandle(), |
| 46 activation_state); |
| 47 } |
| 48 } |
| 49 |
| 50 void ContentSubresourceFilterThrottleManager::RenderFrameDeleted( |
| 51 content::RenderFrameHost* frame_host) { |
| 52 activated_frame_hosts_.erase(frame_host); |
| 53 DestroyRulesetHandleIfNoLongerUsed(); |
| 54 } |
| 55 |
| 56 // Pull the AsyncDocumentSubresourceFilter and its associated ActivationState |
| 57 // out of the activation state computing throttle. Store it for later filtering |
| 58 // of subframe navigations. |
| 59 void ContentSubresourceFilterThrottleManager::ReadyToCommitNavigation( |
| 60 content::NavigationHandle* navigation_handle) { |
| 61 auto throttle = ongoing_activation_throttles_.find(navigation_handle); |
| 62 if (throttle == ongoing_activation_throttles_.end()) |
| 63 return; |
| 64 |
| 65 AsyncDocumentSubresourceFilter* filter = throttle->second->filter(); |
| 66 if (!filter || navigation_handle->GetNetErrorCode() != net::OK || |
| 67 delegate_->ShouldSuppressActivation(navigation_handle)) { |
| 68 return; |
| 69 } |
| 70 |
| 71 DCHECK_NE(ActivationLevel::DISABLED, |
| 72 filter->activation_state().activation_level); |
| 73 |
| 74 throttle->second->WillSendActivationToRenderer(); |
| 75 // TODO(csharrison): Send an IPC to the renderer. |
| 76 } |
| 77 |
| 78 void ContentSubresourceFilterThrottleManager::DidFinishNavigation( |
| 79 content::NavigationHandle* navigation_handle) { |
| 80 // Do nothing if the navigation finished in the same document. Just make sure |
| 81 // to not leak throttle pointers. |
| 82 if (!navigation_handle->HasCommitted() || |
| 83 navigation_handle->IsSameDocument()) { |
| 84 ongoing_activation_throttles_.erase(navigation_handle); |
| 85 return; |
| 86 } |
| 87 |
| 88 auto throttle = ongoing_activation_throttles_.find(navigation_handle); |
| 89 std::unique_ptr<AsyncDocumentSubresourceFilter> filter; |
| 90 if (throttle != ongoing_activation_throttles_.end()) { |
| 91 filter = throttle->second->ReleaseFilter(); |
| 92 ongoing_activation_throttles_.erase(throttle); |
| 93 } |
| 94 |
| 95 // Make sure |activated_frame_hosts_| is updated or cleaned up depending on |
| 96 // this navigation's activation state. |
| 97 content::RenderFrameHost* frame_host = |
| 98 navigation_handle->GetRenderFrameHost(); |
| 99 if (filter) { |
| 100 filter->set_first_disallowed_load_callback(base::Bind( |
| 101 &ContentSubresourceFilterThrottleManager::MaybeCallFirstDisallowedLoad, |
| 102 weak_ptr_factory_.GetWeakPtr())); |
| 103 activated_frame_hosts_[frame_host] = std::move(filter); |
| 104 } else { |
| 105 activated_frame_hosts_.erase(frame_host); |
| 106 } |
| 107 |
| 108 if (navigation_handle->IsInMainFrame()) |
| 109 current_committed_load_has_notified_disallowed_load_ = false; |
| 110 DestroyRulesetHandleIfNoLongerUsed(); |
| 111 } |
| 112 |
| 113 void ContentSubresourceFilterThrottleManager::MaybeAppendNavigationThrottles( |
| 114 content::NavigationHandle* navigation_handle, |
| 115 std::vector<std::unique_ptr<content::NavigationThrottle>>* throttles) { |
| 116 DCHECK(!navigation_handle->IsSameDocument()); |
| 117 if (auto filtering_throttle = |
| 118 MaybeCreateSubframeNavigationFilteringThrottle(navigation_handle)) { |
| 119 throttles->push_back(std::move(filtering_throttle)); |
| 120 } |
| 121 if (auto activation_throttle = |
| 122 MaybeCreateActivationStateComputingThrottle(navigation_handle)) { |
| 123 ongoing_activation_throttles_[navigation_handle] = |
| 124 activation_throttle.get(); |
| 125 throttles->push_back(std::move(activation_throttle)); |
| 126 } |
| 127 } |
| 128 |
| 129 std::unique_ptr<SubframeNavigationFilteringThrottle> |
| 130 ContentSubresourceFilterThrottleManager:: |
| 131 MaybeCreateSubframeNavigationFilteringThrottle( |
| 132 content::NavigationHandle* navigation_handle) { |
| 133 if (navigation_handle->IsInMainFrame()) |
| 134 return nullptr; |
| 135 AsyncDocumentSubresourceFilter* parent_filter = |
| 136 GetParentFrameFilter(navigation_handle); |
| 137 return parent_filter ? base::MakeUnique<SubframeNavigationFilteringThrottle>( |
| 138 navigation_handle, parent_filter) |
| 139 : nullptr; |
| 140 } |
| 141 |
| 142 std::unique_ptr<ActivationStateComputingNavigationThrottle> |
| 143 ContentSubresourceFilterThrottleManager:: |
| 144 MaybeCreateActivationStateComputingThrottle( |
| 145 content::NavigationHandle* navigation_handle) { |
| 146 // Main frames: create unconditionally. |
| 147 if (navigation_handle->IsInMainFrame()) { |
| 148 return ActivationStateComputingNavigationThrottle::CreateForMainFrame( |
| 149 navigation_handle); |
| 150 } |
| 151 |
| 152 // Subframes: create only for frames with activated parents. |
| 153 AsyncDocumentSubresourceFilter* parent_filter = |
| 154 GetParentFrameFilter(navigation_handle); |
| 155 if (!parent_filter) |
| 156 return nullptr; |
| 157 DCHECK(ruleset_handle_); |
| 158 return ActivationStateComputingNavigationThrottle::CreateForSubframe( |
| 159 navigation_handle, ruleset_handle_.get(), |
| 160 parent_filter->activation_state()); |
| 161 } |
| 162 |
| 163 AsyncDocumentSubresourceFilter* |
| 164 ContentSubresourceFilterThrottleManager::GetParentFrameFilter( |
| 165 content::NavigationHandle* child_frame_navigation) { |
| 166 DCHECK(!child_frame_navigation->IsInMainFrame()); |
| 167 content::RenderFrameHost* parent = web_contents()->FindFrameByFrameTreeNodeId( |
| 168 child_frame_navigation->GetParentFrameTreeNodeId()); |
| 169 DCHECK(parent); |
| 170 auto it = activated_frame_hosts_.find(parent); |
| 171 return it == activated_frame_hosts_.end() ? nullptr : it->second.get(); |
| 172 } |
| 173 |
| 174 void ContentSubresourceFilterThrottleManager::MaybeCallFirstDisallowedLoad() { |
| 175 if (current_committed_load_has_notified_disallowed_load_) |
| 176 return; |
| 177 delegate_->OnFirstSubresourceLoadDisallowed(); |
| 178 current_committed_load_has_notified_disallowed_load_ = true; |
| 179 } |
| 180 |
| 181 VerifiedRuleset::Handle* |
| 182 ContentSubresourceFilterThrottleManager::EnsureRulesetHandle() { |
| 183 if (!ruleset_handle_) |
| 184 ruleset_handle_ = base::MakeUnique<VerifiedRuleset::Handle>(dealer_handle_); |
| 185 return ruleset_handle_.get(); |
| 186 } |
| 187 |
| 188 void ContentSubresourceFilterThrottleManager:: |
| 189 DestroyRulesetHandleIfNoLongerUsed() { |
| 190 if (activated_frame_hosts_.size() + ongoing_activation_throttles_.size() == |
| 191 0u) { |
| 192 ruleset_handle_.reset(); |
| 193 } |
| 194 } |
| 195 |
| 196 } // namespace subresource_filter |
OLD | NEW |