1 // Copyright 2013 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.
5 #include "chrome/browser/extensions/blacklist_state_fetcher.h"
7 #include "base/stl_util.h"
8 #include "base/strings/stringprintf.h"
9 #include "base/thread_task_runner_handle.h"
10 #include "chrome/browser/browser_process.h"
11 #include "chrome/browser/safe_browsing/protocol_manager_helper.h"
12 #include "chrome/browser/safe_browsing/safe_browsing_service.h"
13 #include "chrome/common/safe_browsing/crx_info.pb.h"
14 #include "google_apis/google_api_keys.h"
15 #include "net/base/escape.h"
16 #include "net/url_request/url_request_context.h"
17 #include "net/url_request/url_request_context_getter.h"
18 #include "net/url_request/url_request_status.h"
21 using content::BrowserThread
;
23 namespace extensions
{
25 BlacklistStateFetcher::BlacklistStateFetcher()
27 weak_ptr_factory_(this) {}
29 BlacklistStateFetcher::~BlacklistStateFetcher() {
30 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
31 STLDeleteContainerPairFirstPointers(requests_
.begin(), requests_
.end());
35 void BlacklistStateFetcher::Request(const std::string
& id
,
36 const RequestCallback
& callback
) {
37 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
38 if (!safe_browsing_config_
) {
39 if (g_browser_process
&& g_browser_process
->safe_browsing_service()) {
40 SetSafeBrowsingConfig(
41 g_browser_process
->safe_browsing_service()->GetProtocolConfig());
43 base::ThreadTaskRunnerHandle::Get()->PostTask(
44 FROM_HERE
, base::Bind(callback
, BLACKLISTED_UNKNOWN
));
49 bool request_already_sent
= ContainsKey(callbacks_
, id
);
50 callbacks_
.insert(std::make_pair(id
, callback
));
51 if (request_already_sent
)
54 if (!url_request_context_getter_
&& g_browser_process
&&
55 g_browser_process
->safe_browsing_service()) {
56 url_request_context_getter_
=
57 g_browser_process
->safe_browsing_service()->url_request_context();
63 void BlacklistStateFetcher::SendRequest(const std::string
& id
) {
64 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
66 ClientCRXListInfoRequest request
;
68 std::string request_str
;
69 request
.SerializeToString(&request_str
);
71 GURL request_url
= RequestUrl();
72 net::URLFetcher
* fetcher
=
73 net::URLFetcher::Create(url_fetcher_id_
++, request_url
,
74 net::URLFetcher::POST
, this).release();
75 requests_
[fetcher
] = id
;
76 fetcher
->SetAutomaticallyRetryOn5xx(false); // Don't retry on error.
77 fetcher
->SetRequestContext(url_request_context_getter_
.get());
78 fetcher
->SetUploadData("application/octet-stream", request_str
);
82 void BlacklistStateFetcher::SetSafeBrowsingConfig(
83 const SafeBrowsingProtocolConfig
& config
) {
84 safe_browsing_config_
.reset(new SafeBrowsingProtocolConfig(config
));
87 void BlacklistStateFetcher::SetURLRequestContextForTest(
88 net::URLRequestContextGetter
* request_context
) {
89 url_request_context_getter_
= request_context
;
92 GURL
BlacklistStateFetcher::RequestUrl() const {
93 std::string url
= base::StringPrintf(
94 "%s/%s?client=%s&appver=%s&pver=2.2",
95 safe_browsing_config_
->url_prefix
.c_str(),
96 "clientreport/crx-list-info",
97 safe_browsing_config_
->client_name
.c_str(),
98 safe_browsing_config_
->version
.c_str());
99 std::string api_key
= google_apis::GetAPIKey();
100 if (!api_key
.empty()) {
101 base::StringAppendF(&url
, "&key=%s",
102 net::EscapeQueryParamValue(api_key
, true).c_str());
107 void BlacklistStateFetcher::OnURLFetchComplete(const net::URLFetcher
* source
) {
108 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
110 std::map
<const net::URLFetcher
*, std::string
>::iterator it
=
111 requests_
.find(source
);
112 if (it
== requests_
.end()) {
117 scoped_ptr
<const net::URLFetcher
> fetcher
;
119 fetcher
.reset(it
->first
);
120 std::string id
= it
->second
;
123 BlacklistState state
;
125 if (source
->GetStatus().is_success() && source
->GetResponseCode() == 200) {
127 source
->GetResponseAsString(&data
);
128 ClientCRXListInfoResponse response
;
129 if (response
.ParseFromString(data
)) {
130 state
= static_cast<BlacklistState
>(response
.verdict());
132 state
= BLACKLISTED_UNKNOWN
;
135 if (source
->GetStatus().status() == net::URLRequestStatus::FAILED
) {
136 VLOG(1) << "Blacklist request for: " << id
137 << " failed with error: " << source
->GetStatus().error();
139 VLOG(1) << "Blacklist request for: " << id
140 << " failed with error: " << source
->GetResponseCode();
143 state
= BLACKLISTED_UNKNOWN
;
146 std::pair
<CallbackMultiMap::iterator
, CallbackMultiMap::iterator
> range
=
147 callbacks_
.equal_range(id
);
148 for (CallbackMultiMap::const_iterator callback_it
= range
.first
;
149 callback_it
!= range
.second
;
151 callback_it
->second
.Run(state
);
154 callbacks_
.erase(range
.first
, range
.second
);
157 } // namespace extensions