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 "chrome/browser/browser_process.h"
10 #include "chrome/browser/safe_browsing/protocol_manager_helper.h"
11 #include "chrome/browser/safe_browsing/safe_browsing_service.h"
12 #include "chrome/common/safe_browsing/crx_info.pb.h"
13 #include "google_apis/google_api_keys.h"
14 #include "net/base/escape.h"
15 #include "net/url_request/url_request_context_getter.h"
16 #include "net/url_request/url_request_status.h"
19 using content::BrowserThread
;
21 namespace extensions
{
23 BlacklistStateFetcher::BlacklistStateFetcher()
24 : safe_browsing_config_initialized_(false),
28 BlacklistStateFetcher::~BlacklistStateFetcher() {
29 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
30 STLDeleteContainerPairFirstPointers(requests_
.begin(), requests_
.end());
34 void BlacklistStateFetcher::Request(const std::string
& id
,
35 const RequestCallback
& callback
) {
36 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
37 if (!safe_browsing_config_initialized_
) {
38 if (g_browser_process
&& g_browser_process
->safe_browsing_service()) {
39 SetSafeBrowsingConfig(
40 g_browser_process
->safe_browsing_service()->GetProtocolConfig());
42 // If safe browsing is not initialized, then it is probably turned off
44 base::MessageLoopProxy::current()->PostTask(
45 FROM_HERE
, base::Bind(callback
, BLACKLISTED_UNKNOWN
));
50 bool request_already_sent
= ContainsKey(callbacks_
, id
);
51 callbacks_
.insert(std::make_pair(id
, callback
));
52 if (request_already_sent
)
55 ClientCRXListInfoRequest request
;
58 std::string request_str
;
59 request
.SerializeToString(&request_str
);
61 GURL request_url
= RequestUrl();
62 net::URLFetcher
* fetcher
= net::URLFetcher::Create(url_fetcher_id_
++,
64 net::URLFetcher::POST
,
66 requests_
[fetcher
] = id
;
67 fetcher
->SetAutomaticallyRetryOn5xx(false); // Don't retry on error.
68 if (g_browser_process
&& g_browser_process
->safe_browsing_service()) {
69 // Unless we are in unit test, safebrowsing service should be initialized.
70 scoped_refptr
<net::URLRequestContextGetter
> request_context(
71 g_browser_process
->safe_browsing_service()->url_request_context());
72 fetcher
->SetRequestContext(request_context
.get());
74 fetcher
->SetUploadData("application/octet-stream", request_str
);
78 void BlacklistStateFetcher::SetSafeBrowsingConfig(
79 const SafeBrowsingProtocolConfig
& config
) {
80 safe_browsing_config_
= config
;
81 safe_browsing_config_initialized_
= true;
84 GURL
BlacklistStateFetcher::RequestUrl() const {
85 std::string url
= base::StringPrintf(
86 "%s/%s?client=%s&appver=%s&pver=2.2",
87 safe_browsing_config_
.url_prefix
.c_str(),
88 "clientreport/crx-list-info",
89 safe_browsing_config_
.client_name
.c_str(),
90 safe_browsing_config_
.version
.c_str());
91 std::string api_key
= google_apis::GetAPIKey();
92 if (!api_key
.empty()) {
93 base::StringAppendF(&url
, "&key=%s",
94 net::EscapeQueryParamValue(api_key
, true).c_str());
99 void BlacklistStateFetcher::OnURLFetchComplete(const net::URLFetcher
* source
) {
100 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
102 std::map
<const net::URLFetcher
*, std::string
>::iterator it
=
103 requests_
.find(source
);
104 if (it
== requests_
.end()) {
109 scoped_ptr
<const net::URLFetcher
> fetcher
;
111 fetcher
.reset(it
->first
);
112 std::string id
= it
->second
;
115 BlacklistState state
;
117 if (source
->GetStatus().is_success() && source
->GetResponseCode() == 200) {
119 source
->GetResponseAsString(&data
);
120 ClientCRXListInfoResponse response
;
121 if (response
.ParseFromString(data
)) {
122 state
= static_cast<BlacklistState
>(response
.verdict());
124 state
= BLACKLISTED_UNKNOWN
;
127 if (source
->GetStatus().status() == net::URLRequestStatus::FAILED
) {
128 VLOG(1) << "Blacklist request for: " << id
129 << " failed with error: " << source
->GetStatus().error();
131 VLOG(1) << "Blacklist request for: " << id
132 << " failed with error: " << source
->GetResponseCode();
135 state
= BLACKLISTED_UNKNOWN
;
138 std::pair
<CallbackMultiMap::iterator
, CallbackMultiMap::iterator
> range
=
139 callbacks_
.equal_range(id
);
140 for (CallbackMultiMap::const_iterator callback_it
= range
.first
;
141 callback_it
!= range
.second
;
143 callback_it
->second
.Run(state
);
146 callbacks_
.erase(range
.first
, range
.second
);
149 } // namespace extensions