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

Side by Side Diff: components/ntp_snippets/breaking_news/subscription_json_request.cc

Issue 2918513002: [NTP::Push] Add the classes for sending a breaking news subscription request (Closed)
Patch Set: bauerb@ comments. Created 3 years, 6 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/ntp_snippets/breaking_news/subscription_json_request.h"
6
7 #include <algorithm>
8 #include <utility>
9 #include <vector>
10
11 #include "base/command_line.h"
12 #include "base/json/json_writer.h"
13 #include "base/memory/ptr_util.h"
14 #include "base/metrics/histogram_macros.h"
15 #include "base/metrics/sparse_histogram.h"
16 #include "base/strings/stringprintf.h"
17 #include "base/time/clock.h"
18 #include "base/values.h"
19 #include "components/data_use_measurement/core/data_use_user_data.h"
20 #include "components/ntp_snippets/breaking_news/subscription_request_params.h"
21 #include "components/ntp_snippets/category_info.h"
22 #include "components/ntp_snippets/features.h"
23 #include "components/ntp_snippets/user_classifier.h"
24 #include "components/signin/core/browser/profile_oauth2_token_service.h"
25 #include "components/signin/core/browser/signin_manager.h"
26 #include "components/signin/core/browser/signin_manager_base.h"
27 #include "components/strings/grit/components_strings.h"
28 #include "components/variations/net/variations_http_headers.h"
29 #include "components/variations/variations_associated_data.h"
30 #include "net/base/load_flags.h"
31 #include "net/http/http_response_headers.h"
32 #include "net/http/http_status_code.h"
33 #include "net/traffic_annotation/network_traffic_annotation.h"
34 #include "net/url_request/url_fetcher.h"
35 #include "net/url_request/url_request_context_getter.h"
36 #include "third_party/icu/source/common/unicode/uloc.h"
37 #include "third_party/icu/source/common/unicode/utypes.h"
38 #include "ui/base/l10n/l10n_util.h"
39
40 using net::URLFetcher;
41 using net::URLRequestContextGetter;
42 using net::HttpRequestHeaders;
43 using net::URLRequestStatus;
44
45 namespace ntp_snippets {
46
47 namespace internal {
48
49 SubscriptionJsonRequest::SubscriptionJsonRequest(
50 const ParseJSONCallback& callback)
51 : parse_json_callback_(callback), weak_ptr_factory_(this) {}
52
53 SubscriptionJsonRequest::~SubscriptionJsonRequest() {
54 if (!request_completed_callback_.is_null()) {
55 std::move(request_completed_callback_)
56 .Run(/*result=*/nullptr,
57 /*error_details=*/"The CompletionCallback was never called");
Bernhard Bauer 2017/05/31 14:45:40 Is that the right error? I would return something
mamir 2017/05/31 19:00:54 PTAL
58 }
59 }
60
61 void SubscriptionJsonRequest::Start(CompletedCallback callback) {
62 request_completed_callback_ = std::move(callback);
63 url_fetcher_->Start();
64 }
65
66 std::string SubscriptionJsonRequest::GetResponseString() const {
67 std::string response;
68 url_fetcher_->GetResponseAsString(&response);
69 return response;
70 }
71
72 ////////////////////////////////////////////////////////////////////////////////
73 // URLFetcherDelegate overrides
74 void SubscriptionJsonRequest::OnURLFetchComplete(
75 const net::URLFetcher* source) {
76 DCHECK_EQ(url_fetcher_.get(), source);
77 const URLRequestStatus& status = url_fetcher_->GetStatus();
78 int response = url_fetcher_->GetResponseCode();
79
80 if (!status.is_success()) {
81 std::move(request_completed_callback_)
82 .Run(/*result=*/nullptr,
83 /*error_details=*/base::StringPrintf(" %d", status.error()));
84 } else if (response != net::HTTP_OK) {
85 std::move(request_completed_callback_)
86 .Run(/*result=*/nullptr,
87 /*error_details=*/base::StringPrintf(" %d", response));
88 } else {
89 // request succeeded.
90 }
91 }
92
93 SubscriptionJsonRequest::Builder::Builder() {}
94 SubscriptionJsonRequest::Builder::Builder(SubscriptionJsonRequest::Builder&&) =
95 default;
96 SubscriptionJsonRequest::Builder::~Builder() = default;
97
98 std::unique_ptr<SubscriptionJsonRequest>
99 SubscriptionJsonRequest::Builder::Build() const {
100 DCHECK(!url_.is_empty());
101 DCHECK(url_request_context_getter_);
102 auto request =
103 base::WrapUnique(new SubscriptionJsonRequest(parse_json_callback_));
104
105 std::string body = BuildBody();
106 std::string headers = BuildHeaders();
107 request->url_fetcher_ = BuildURLFetcher(request.get(), headers, body);
108
109 // Log the request for debugging network issues.
110 VLOG(1) << "Sending a subscription request to " << url_ << ":\n"
111 << headers << "\n"
112 << body;
113
114 return request;
115 }
116
117 SubscriptionJsonRequest::Builder& SubscriptionJsonRequest::Builder::SetParams(
118 const SubscriptionRequestParams& params) {
119 params_ = params;
120 return *this;
121 }
122
123 SubscriptionJsonRequest::Builder& SubscriptionJsonRequest::Builder::SetUrl(
124 const GURL& url) {
125 url_ = url;
126 return *this;
127 }
128
129 SubscriptionJsonRequest::Builder&
130 SubscriptionJsonRequest::Builder::SetUrlRequestContextGetter(
131 const scoped_refptr<net::URLRequestContextGetter>& context_getter) {
132 url_request_context_getter_ = context_getter;
133 return *this;
134 }
135
136 SubscriptionJsonRequest::Builder&
137 SubscriptionJsonRequest::Builder::SetParseJsonCallback(
138 ParseJSONCallback callback) {
139 parse_json_callback_ = callback;
140 return *this;
141 }
142
143 std::string SubscriptionJsonRequest::Builder::BuildHeaders() const {
144 net::HttpRequestHeaders headers;
145 headers.SetHeader("Content-Type", "application/json; charset=UTF-8");
146 if (!auth_header_.empty()) {
147 headers.SetHeader("Authorization", auth_header_);
148 }
149 // Add X-Client-Data header with experiment IDs from field trials.
150 // Note: It's OK to pass |is_signed_in| false if it's unknown, as it does
151 // not affect transmission of experiments coming from the variations server.
152 bool is_signed_in = false;
153 variations::AppendVariationHeaders(url_,
154 false, // incognito
155 false, // uma_enabled
156 is_signed_in, &headers);
157 return headers.ToString();
158 }
159
160 std::string SubscriptionJsonRequest::Builder::BuildBody() const {
161 auto request = base::MakeUnique<base::DictionaryValue>();
162 request->SetString("token", params_.token);
163
164 std::string request_json;
165 bool success = base::JSONWriter::WriteWithOptions(
166 *request, base::JSONWriter::OPTIONS_PRETTY_PRINT, &request_json);
167 DCHECK(success);
168 return request_json;
169 }
170
171 std::unique_ptr<net::URLFetcher>
172 SubscriptionJsonRequest::Builder::BuildURLFetcher(
173 net::URLFetcherDelegate* delegate,
174 const std::string& headers,
175 const std::string& body) const {
176 net::NetworkTrafficAnnotationTag traffic_annotation =
177 net::DefineNetworkTrafficAnnotation("gcm_subscription", R"(
178 semantics {
179 sender: "Subscribe for breaking news delivered via GCM push messages"
180 description:
181 "Chromium can receive breaking news via GCM push messages. "
182 "This request suscribes the client to receiving them."
183 trigger:
184 "Subscription takes place only once per profile lifetime. "
185 data:
186 "The subscription token that identifies this Chromium profile."
187 destination: GOOGLE_OWNED_SERVICE
188 }
189 policy {
190 cookies_allowed: false
191 setting:
192 "This feature cannot be disabled by settings now"
193 chrome_policy {
194 NTPContentSuggestionsEnabled {
195 policy_options {mode: MANDATORY}
196 NTPContentSuggestionsEnabled: false
197 }
198 }
199 })");
200 std::unique_ptr<net::URLFetcher> url_fetcher = net::URLFetcher::Create(
201 url_, net::URLFetcher::POST, delegate, traffic_annotation);
202 url_fetcher->SetRequestContext(url_request_context_getter_.get());
203 url_fetcher->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES |
204 net::LOAD_DO_NOT_SAVE_COOKIES);
205 data_use_measurement::DataUseUserData::AttachToFetcher(
206 url_fetcher.get(),
207 data_use_measurement::DataUseUserData::NTP_SNIPPETS_SUGGESTIONS);
208
209 url_fetcher->SetExtraRequestHeaders(headers);
210 url_fetcher->SetUploadData("application/json", body);
211
212 // Fetchers are sometimes cancelled because a network change was detected.
213 url_fetcher->SetAutomaticallyRetryOnNetworkChanges(3);
214 return url_fetcher;
215 }
216
217 } // namespace internal
218
219 } // namespace ntp_snippets
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698