1 // Copyright 2019 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 "chrome/browser/safe_browsing/download_protection/check_native_file_system_write_request.h"
6
7 #include <algorithm>
8 #include <memory>
9
10 #include "base/bind.h"
11 #include "base/metrics/histogram_functions.h"
12 #include "base/metrics/histogram_macros.h"
13 #include "chrome/browser/browser_process.h"
14 #include "chrome/browser/safe_browsing/download_protection/download_feedback_service.h"
15 #include "chrome/browser/safe_browsing/download_protection/download_protection_service.h"
16 #include "chrome/browser/safe_browsing/download_protection/download_protection_util.h"
17 #include "chrome/common/safe_browsing/download_type_util.h"
18 #include "components/safe_browsing/core/common/utils.h"
19 #include "components/safe_browsing/core/features.h"
20 #include "components/safe_browsing/core/file_type_policies.h"
21 #include "components/safe_browsing/core/proto/csd.pb.h"
22 #include "content/public/browser/browser_context.h"
23 #include "content/public/browser/download_item_utils.h"
24 #include "content/public/browser/navigation_entry.h"
25
26 namespace safe_browsing {
27
28 using content::BrowserThread;
29
30 namespace {
31
GetDownloadUrl(const GURL & frame_url)32 GURL GetDownloadUrl(const GURL& frame_url) {
33 // Regular blob: URLs are of the form
34 // "blob:https://my-origin.com/def07373-cbd8-49d2-9ef7-20b071d34a1a". To make
35 // these URLs distinguishable from those we use a fixed string rather than a
36 // random UUID.
37 return GURL("blob:" + frame_url.GetOrigin().spec() +
38 "native-file-system-write");
39 }
40
TabUrlsFromWebContents(content::WebContents * web_contents)41 CheckClientDownloadRequestBase::TabUrls TabUrlsFromWebContents(
42 content::WebContents* web_contents) {
43 CheckClientDownloadRequestBase::TabUrls result;
44 if (web_contents) {
45 content::NavigationEntry* entry =
46 web_contents->GetController().GetVisibleEntry();
47 if (entry) {
48 result.url = entry->GetURL();
49 result.referrer = entry->GetReferrer().url;
50 }
51 }
52 return result;
53 }
54
55 } // namespace
56
CheckNativeFileSystemWriteRequest(std::unique_ptr<content::NativeFileSystemWriteItem> item,CheckDownloadCallback callback,DownloadProtectionService * service,scoped_refptr<SafeBrowsingDatabaseManager> database_manager,scoped_refptr<BinaryFeatureExtractor> binary_feature_extractor)57 CheckNativeFileSystemWriteRequest::CheckNativeFileSystemWriteRequest(
58 std::unique_ptr<content::NativeFileSystemWriteItem> item,
59 CheckDownloadCallback callback,
60 DownloadProtectionService* service,
61 scoped_refptr<SafeBrowsingDatabaseManager> database_manager,
62 scoped_refptr<BinaryFeatureExtractor> binary_feature_extractor)
63 : CheckClientDownloadRequestBase(GetDownloadUrl(item->frame_url),
64 item->target_file_path,
65 item->full_path,
66 TabUrlsFromWebContents(item->web_contents),
67 "application/octet-stream",
68 item->sha256_hash,
69 item->browser_context,
70 std::move(callback),
71 service,
72 std::move(database_manager),
73 std::move(binary_feature_extractor)),
74 item_(std::move(item)),
75 referrer_chain_data_(service->IdentifyReferrerChain(*item_)) {
76 DCHECK_CURRENTLY_ON(BrowserThread::UI);
77 }
78
79 CheckNativeFileSystemWriteRequest ::~CheckNativeFileSystemWriteRequest() =
80 default;
81
IsSupportedDownload(DownloadCheckResultReason * reason,ClientDownloadRequest::DownloadType * type)82 bool CheckNativeFileSystemWriteRequest::IsSupportedDownload(
83 DownloadCheckResultReason* reason,
84 ClientDownloadRequest::DownloadType* type) {
85 if (!FileTypePolicies::GetInstance()->IsCheckedBinaryFile(
86 item_->target_file_path)) {
87 *reason = REASON_NOT_BINARY_FILE;
88 return false;
89 }
90 *type = download_type_util::GetDownloadType(item_->target_file_path);
91 return true;
92 }
93
GetBrowserContext() const94 content::BrowserContext* CheckNativeFileSystemWriteRequest::GetBrowserContext()
95 const {
96 return item_->browser_context;
97 }
98
IsCancelled()99 bool CheckNativeFileSystemWriteRequest::IsCancelled() {
100 return false;
101 }
102
PopulateRequest(ClientDownloadRequest * request)103 void CheckNativeFileSystemWriteRequest::PopulateRequest(
104 ClientDownloadRequest* request) {
105 request->mutable_digests()->set_sha256(item_->sha256_hash);
106 request->set_length(item_->size);
107 {
108 ClientDownloadRequest::Resource* resource = request->add_resources();
109 resource->set_url(SanitizeUrl(GetDownloadUrl(item_->frame_url)));
110 resource->set_type(ClientDownloadRequest::DOWNLOAD_URL);
111 if (item_->frame_url.is_valid())
112 resource->set_referrer(SanitizeUrl(item_->frame_url));
113 }
114
115 request->set_user_initiated(item_->has_user_gesture);
116
117 if (referrer_chain_data_ &&
118 !referrer_chain_data_->GetReferrerChain()->empty()) {
119 request->mutable_referrer_chain()->Swap(
120 referrer_chain_data_->GetReferrerChain());
121 request->mutable_referrer_chain_options()
122 ->set_recent_navigations_to_collect(
123 referrer_chain_data_->recent_navigations_to_collect());
124 UMA_HISTOGRAM_COUNTS_100(
125 "SafeBrowsing.ReferrerURLChainSize.NativeFileSystemWriteAttribution",
126 referrer_chain_data_->referrer_chain_length());
127 }
128 }
129
130 base::WeakPtr<CheckClientDownloadRequestBase>
GetWeakPtr()131 CheckNativeFileSystemWriteRequest::GetWeakPtr() {
132 return weakptr_factory_.GetWeakPtr();
133 }
134
NotifySendRequest(const ClientDownloadRequest * request)135 void CheckNativeFileSystemWriteRequest::NotifySendRequest(
136 const ClientDownloadRequest* request) {
137 service()->native_file_system_write_request_callbacks_.Notify(request);
138 }
139
SetDownloadPingToken(const std::string & token)140 void CheckNativeFileSystemWriteRequest::SetDownloadPingToken(
141 const std::string& token) {
142 // TODO(https://crbug.com/996797): Actually store token for
143 // IncidentReportingService usage.
144 }
145
MaybeStorePingsForDownload(DownloadCheckResult result,bool upload_requested,const std::string & request_data,const std::string & response_body)146 void CheckNativeFileSystemWriteRequest::MaybeStorePingsForDownload(
147 DownloadCheckResult result,
148 bool upload_requested,
149 const std::string& request_data,
150 const std::string& response_body) {
151 // TODO(https://crbug.com/996797): Integrate with DownloadFeedbackService.
152 }
153
154 base::Optional<enterprise_connectors::AnalysisSettings>
ShouldUploadBinary(DownloadCheckResultReason reason)155 CheckNativeFileSystemWriteRequest::ShouldUploadBinary(
156 DownloadCheckResultReason reason) {
157 return base::nullopt;
158 }
159
UploadBinary(DownloadCheckResultReason reason,enterprise_connectors::AnalysisSettings settings)160 void CheckNativeFileSystemWriteRequest::UploadBinary(
161 DownloadCheckResultReason reason,
162 enterprise_connectors::AnalysisSettings settings) {}
163
ShouldPromptForDeepScanning(DownloadCheckResultReason reason) const164 bool CheckNativeFileSystemWriteRequest::ShouldPromptForDeepScanning(
165 DownloadCheckResultReason reason) const {
166 return false;
167 }
168
NotifyRequestFinished(DownloadCheckResult result,DownloadCheckResultReason reason)169 void CheckNativeFileSystemWriteRequest::NotifyRequestFinished(
170 DownloadCheckResult result,
171 DownloadCheckResultReason reason) {
172 DCHECK_CURRENTLY_ON(BrowserThread::UI);
173 weakptr_factory_.InvalidateWeakPtrs();
174 }
175
IsWhitelistedByPolicy() const176 bool CheckNativeFileSystemWriteRequest::IsWhitelistedByPolicy() const {
177 Profile* profile = Profile::FromBrowserContext(item_->browser_context);
178 if (!profile)
179 return false;
180 return IsURLWhitelistedByPolicy(item_->frame_url, *profile->GetPrefs());
181 }
182
183 } // namespace safe_browsing
184