Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(851)

Side by Side Diff: components/safe_browsing/base_blocking_page.cc

Issue 2623733002: Componentize SafeBrowsingBlockingPage for WebView use (Closed)
Patch Set: address comments from meacer@ Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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/safe_browsing/base_blocking_page.h"
6
7 #include "base/bind.h"
8 #include "base/lazy_instance.h"
9 #include "base/memory/ptr_util.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "base/time/time.h"
12 #include "components/safe_browsing_db/safe_browsing_prefs.h"
13 #include "components/security_interstitials/content/security_interstitial_contro ller_client.h"
14 #include "components/security_interstitials/core/metrics_helper.h"
15 #include "content/public/browser/interstitial_page.h"
16 #include "content/public/browser/navigation_entry.h"
17 #include "content/public/browser/user_metrics.h"
18 #include "content/public/browser/web_contents.h"
19
20 using base::UserMetricsAction;
21 using content::InterstitialPage;
22 using content::WebContents;
23 using security_interstitials::SafeBrowsingErrorUI;
24 using security_interstitials::SecurityInterstitialControllerClient;
25
26 namespace safe_browsing {
27
28 namespace {
29
30 base::LazyInstance<BaseBlockingPage::UnsafeResourceMap>::Leaky
31 g_unsafe_resource_map = LAZY_INSTANCE_INITIALIZER;
32
33 } // namespace
34
35 BaseBlockingPage::BaseBlockingPage(
36 BaseUIManager* ui_manager,
37 WebContents* web_contents,
38 const GURL& main_frame_url,
39 const UnsafeResourceList& unsafe_resources,
40 std::unique_ptr<SecurityInterstitialControllerClient> controller_client,
41 const SafeBrowsingErrorUI::SBErrorDisplayOptions& display_options)
42 : SecurityInterstitialPage(web_contents,
43 unsafe_resources[0].url,
44 std::move(controller_client)),
45 main_frame_url_(main_frame_url),
46 navigation_entry_index_to_remove_(
47 IsMainPageLoadBlocked(unsafe_resources) ?
48 -1 :
49 web_contents->GetController().GetLastCommittedEntryIndex()),
50 unsafe_resources_(unsafe_resources),
51 sb_error_ui_(base::MakeUnique<SafeBrowsingErrorUI>(
52 unsafe_resources_[0].url, main_frame_url_,
53 GetInterstitialReason(unsafe_resources_),
54 display_options,
55 ui_manager->app_locale(),
56 base::Time::NowFromSystemTime(),
57 controller())),
58 proceeded_(false),
59 ui_manager_(ui_manager) {}
60
61 BaseBlockingPage::~BaseBlockingPage() {}
62
63 // static
64 const SafeBrowsingErrorUI::SBErrorDisplayOptions
65 BaseBlockingPage::CreateDefaultDisplayOptions(
66 const UnsafeResourceList& unsafe_resources) {
67 return SafeBrowsingErrorUI::SBErrorDisplayOptions(
68 IsMainPageLoadBlocked(unsafe_resources),
69 true, // kSafeBrowsingExtendedReportingOptInAllowed
70 false, // is_off_the_record
71 false, // is_extended_reporting
72 false, // is_scout
73 false); // kSafeBrowsingProceedAnywayDisabled
74 }
75
76 // static
77 void BaseBlockingPage::ShowBlockingPage(
78 BaseUIManager* ui_manager,
79 const UnsafeResource& unsafe_resource) {
80 WebContents* web_contents = unsafe_resource.web_contents_getter.Run();
81
82 if (!InterstitialPage::GetInterstitialPage(web_contents) ||
83 !unsafe_resource.is_subresource) {
84 // There is no interstitial currently showing in that tab, or we are about
85 // to display a new one for the main frame. If there is already an
86 // interstitial, showing the new one will automatically hide the old one.
87 content::NavigationEntry* entry =
88 unsafe_resource.GetNavigationEntryForResource();
89 const UnsafeResourceList resources{unsafe_resource};
meacer 2017/01/11 18:59:40 nit: Inline this? new BaseBlockingPage( ...,
Jialiu Lin 2017/01/11 20:13:29 acknowledged. |resources| is used 3 times in this
90 BaseBlockingPage* blocking_page =
91 new BaseBlockingPage(
92 ui_manager, web_contents,
93 entry ? entry->GetURL() : GURL(),
94 resources,
95 CreateControllerClient(
96 web_contents, resources,
97 ui_manager->history_service(web_contents),
98 ui_manager->app_locale(),
99 ui_manager->default_safe_page()),
100 CreateDefaultDisplayOptions(resources));
101 blocking_page->Show();
102 return;
103 }
104
105 // This is an interstitial for a page's resource, let's queue it.
106 UnsafeResourceMap* unsafe_resource_map = GetUnsafeResourcesMap();
107 (*unsafe_resource_map)[web_contents].push_back(unsafe_resource);
108 }
109
110 // static
111 bool BaseBlockingPage::IsMainPageLoadBlocked(
112 const UnsafeResourceList& unsafe_resources) {
113 // If there is more than one unsafe resource, the main page load must not be
114 // blocked. Otherwise, check if the one resource is.
115 return unsafe_resources.size() == 1 &&
116 unsafe_resources[0].IsMainPageLoadBlocked();
117 }
118
119 void BaseBlockingPage::OnProceed() {
120 proceeded_ = true;
121
122 ui_manager_->OnBlockingPageDone(unsafe_resources_, true /* proceed */,
123 web_contents(), main_frame_url_);
124 }
125
126 void BaseBlockingPage::OnDontProceed() {
127 // We could have already called Proceed(), in which case we must not notify
128 // the SafeBrowsingUIManager again, as the client has been deleted.
129 if (proceeded_)
130 return;
131
132 if (!sb_error_ui_->is_proceed_anyway_disabled()) {
133 controller()->metrics_helper()->RecordUserDecision(
134 security_interstitials::MetricsHelper::DONT_PROCEED);
135 }
136
137 // Send the malware details, if we opted to.
138 FinishThreatDetails(base::TimeDelta(), false /* did_proceed */,
139 controller()->metrics_helper()->NumVisits()); // No delay
140
141 ui_manager_->OnBlockingPageDone(unsafe_resources_, false /* proceed */,
142 web_contents(), main_frame_url_);
143
144 // The user does not want to proceed, clear the queued unsafe resources
145 // notifications we received while the interstitial was showing.
146 UnsafeResourceMap* unsafe_resource_map = GetUnsafeResourcesMap();
147 UnsafeResourceMap::iterator iter = unsafe_resource_map->find(web_contents());
148 if (iter != unsafe_resource_map->end() && !iter->second.empty()) {
149 ui_manager_->OnBlockingPageDone(iter->second, false, web_contents(),
150 main_frame_url_);
151 unsafe_resource_map->erase(iter);
152 }
153
154 // We don't remove the navigation entry if the tab is being destroyed as this
155 // would trigger a navigation that would cause trouble as the render view host
156 // for the tab has by then already been destroyed. We also don't delete the
157 // current entry if it has been committed again, which is possible on a page
158 // that had a subresource warning.
159 const int last_committed_index =
160 web_contents()->GetController().GetLastCommittedEntryIndex();
161 if (navigation_entry_index_to_remove_ != -1 &&
162 navigation_entry_index_to_remove_ != last_committed_index &&
163 !web_contents()->IsBeingDestroyed()) {
164 CHECK(web_contents()->GetController().RemoveEntryAtIndex(
165 navigation_entry_index_to_remove_));
166 }
167 }
168
169 void BaseBlockingPage::CommandReceived(
170 const std::string& page_cmd) {
171 if (page_cmd == "\"pageLoadComplete\"") {
172 // content::WaitForRenderFrameReady sends this message when the page
173 // load completes. Ignore it.
174 return;
175 }
176
177 int command = 0;
178 bool retval = base::StringToInt(page_cmd, &command);
179 DCHECK(retval) << page_cmd;
180
181 sb_error_ui_->HandleCommand(
182 static_cast<security_interstitials::SecurityInterstitialCommands>(
183 command));
184 }
185
186 bool BaseBlockingPage::ShouldCreateNewNavigation() const {
187 return sb_error_ui_->is_main_frame_load_blocked();
188 }
189
190 void BaseBlockingPage::PopulateInterstitialStrings(
191 base::DictionaryValue* load_time_data) {
192 sb_error_ui_->PopulateStringsForHTML(load_time_data);
193 }
194
195 void BaseBlockingPage::FinishThreatDetails(const base::TimeDelta& delay,
196 bool did_proceed,
197 int num_visits) {}
198
199 // static
200 BaseBlockingPage::UnsafeResourceMap*
201 BaseBlockingPage::GetUnsafeResourcesMap() {
202 return g_unsafe_resource_map.Pointer();
203 }
204
205 // static
206 std::string BaseBlockingPage::GetMetricPrefix(
207 const UnsafeResourceList& unsafe_resources,
208 SafeBrowsingErrorUI::SBInterstitialReason interstitial_reason) {
209 bool primary_subresource = unsafe_resources[0].is_subresource;
210 switch (interstitial_reason) {
211 case SafeBrowsingErrorUI::SB_REASON_MALWARE:
212 return primary_subresource ? "malware_subresource" : "malware";
213 case SafeBrowsingErrorUI::SB_REASON_HARMFUL:
214 return primary_subresource ? "harmful_subresource" : "harmful";
215 case SafeBrowsingErrorUI::SB_REASON_PHISHING:
216 ThreatPatternType threat_pattern_type =
217 unsafe_resources[0].threat_metadata.threat_pattern_type;
218 if (threat_pattern_type == ThreatPatternType::PHISHING ||
219 threat_pattern_type == ThreatPatternType::NONE)
220 return primary_subresource ? "phishing_subresource" : "phishing";
221 else if (threat_pattern_type == ThreatPatternType::SOCIAL_ENGINEERING_ADS)
222 return primary_subresource ? "social_engineering_ads_subresource"
223 : "social_engineering_ads";
224 else if (threat_pattern_type ==
225 ThreatPatternType::SOCIAL_ENGINEERING_LANDING)
226 return primary_subresource ? "social_engineering_landing_subresource"
227 : "social_engineering_landing";
228 }
229 NOTREACHED();
230 return "unkown_metric_prefix";
231 }
232
233 // We populate a parallel set of metrics to differentiate some threat sources.
234 // static
235 std::string BaseBlockingPage::GetExtraMetricsSuffix(
236 const UnsafeResourceList& unsafe_resources) {
237 switch (unsafe_resources[0].threat_source) {
238 case safe_browsing::ThreatSource::DATA_SAVER:
239 return "from_data_saver";
240 case safe_browsing::ThreatSource::REMOTE:
241 case safe_browsing::ThreatSource::LOCAL_PVER3:
242 // REMOTE and LOCAL_PVER3 can be distinguished in the logs
243 // by platform type: Remote is mobile, local_pver3 is desktop.
244 return "from_device";
245 case safe_browsing::ThreatSource::LOCAL_PVER4:
246 return "from_device_v4";
247 case safe_browsing::ThreatSource::CLIENT_SIDE_DETECTION:
248 return "from_client_side_detection";
249 case safe_browsing::ThreatSource::UNKNOWN:
250 break;
251 }
252 NOTREACHED();
253 return std::string();
254 }
255
256 // static
257 SafeBrowsingErrorUI::SBInterstitialReason
258 BaseBlockingPage::GetInterstitialReason(
259 const UnsafeResourceList& unsafe_resources) {
260 bool harmful = false;
261 for (UnsafeResourceList::const_iterator iter = unsafe_resources.begin();
262 iter != unsafe_resources.end(); ++iter) {
263 const BaseUIManager::UnsafeResource& resource = *iter;
264 safe_browsing::SBThreatType threat_type = resource.threat_type;
265 if (threat_type == SB_THREAT_TYPE_URL_MALWARE ||
266 threat_type == SB_THREAT_TYPE_CLIENT_SIDE_MALWARE_URL) {
267 return SafeBrowsingErrorUI::SB_REASON_MALWARE;
268 } else if (threat_type == SB_THREAT_TYPE_URL_UNWANTED) {
269 harmful = true;
270 } else {
271 DCHECK(threat_type == SB_THREAT_TYPE_URL_PHISHING ||
272 threat_type == SB_THREAT_TYPE_CLIENT_SIDE_PHISHING_URL);
273 }
274 }
275
276 if (harmful)
277 return SafeBrowsingErrorUI::SB_REASON_HARMFUL;
278 return SafeBrowsingErrorUI::SB_REASON_PHISHING;
279 }
280
281 BaseUIManager* BaseBlockingPage::ui_manager() {
282 return ui_manager_;
283 }
284
285 // static
286 std::unique_ptr<SecurityInterstitialControllerClient>
287 BaseBlockingPage::CreateControllerClient(
288 content::WebContents* web_contents,
289 const UnsafeResourceList& unsafe_resources,
290 history::HistoryService* history_service,
291 const std::string& app_locale,
292 const GURL& default_safe_page) {
293 SafeBrowsingErrorUI::SBInterstitialReason interstitial_reason =
294 GetInterstitialReason(unsafe_resources);
295 security_interstitials::MetricsHelper::ReportDetails reporting_info;
296 reporting_info.metric_prefix =
297 GetMetricPrefix(unsafe_resources, interstitial_reason);
298 reporting_info.extra_suffix = GetExtraMetricsSuffix(unsafe_resources);
299
300 std::unique_ptr<security_interstitials::MetricsHelper> metrics_helper =
301 base::MakeUnique<security_interstitials::MetricsHelper>(
302 unsafe_resources[0].url, reporting_info, history_service);
303
304 return base::MakeUnique<SecurityInterstitialControllerClient>(
305 web_contents, std::move(metrics_helper), nullptr, app_locale,
306 default_safe_page);
307 }
308
309 } // namespace safe_browsing
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698