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

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: Minor 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 "base/json/json_writer.h"
8 #include "base/memory/ptr_util.h"
9 #include "base/strings/stringprintf.h"
10 #include "base/values.h"
11 #include "components/data_use_measurement/core/data_use_user_data.h"
12 #include "components/variations/net/variations_http_headers.h"
13 #include "net/base/load_flags.h"
14 #include "net/http/http_status_code.h"
15 #include "net/url_request/url_fetcher.h"
16 #include "net/url_request/url_request_context_getter.h"
17
18 using net::URLFetcher;
19 using net::URLRequestContextGetter;
20 using net::HttpRequestHeaders;
21 using net::URLRequestStatus;
22
23 namespace ntp_snippets {
24
25 namespace internal {
26
27 SubscriptionJsonRequest::SubscriptionJsonRequest() = default;
28
29 SubscriptionJsonRequest::~SubscriptionJsonRequest() {
30 if (!request_completed_callback_.is_null()) {
31 std::move(request_completed_callback_)
32 .Run(ntp_snippets::Status(ntp_snippets::StatusCode::TEMPORARY_ERROR,
33 "cancelled"));
34 }
35 }
36
37 void SubscriptionJsonRequest::Start(CompletedCallback callback) {
38 DCHECK(request_completed_callback_.is_null()) << "Request already running!";
39 request_completed_callback_ = std::move(callback);
40 url_fetcher_->Start();
41 }
42
43 ////////////////////////////////////////////////////////////////////////////////
44 // URLFetcherDelegate overrides
45 void SubscriptionJsonRequest::OnURLFetchComplete(const URLFetcher* source) {
46 DCHECK_EQ(url_fetcher_.get(), source);
47 const URLRequestStatus& status = url_fetcher_->GetStatus();
48 int response = url_fetcher_->GetResponseCode();
49
50 if (!status.is_success()) {
51 std::move(request_completed_callback_)
52 .Run(ntp_snippets::Status(
53 ntp_snippets::StatusCode::TEMPORARY_ERROR,
54 base::StringPrintf("Internal Error: %d", status.error())));
55 } else if (response != net::HTTP_OK) {
56 std::move(request_completed_callback_)
57 .Run(ntp_snippets::Status(
58 ntp_snippets::StatusCode::PERMANENT_ERROR,
59 base::StringPrintf("HTTP Error: %d", response)));
60 } else {
61 std::move(request_completed_callback_)
62 .Run(ntp_snippets::Status(ntp_snippets::StatusCode::SUCCESS,
63 std::string()));
64 }
65 }
66
67 SubscriptionJsonRequest::Builder::Builder() = default;
68 SubscriptionJsonRequest::Builder::Builder(SubscriptionJsonRequest::Builder&&) =
69 default;
70 SubscriptionJsonRequest::Builder::~Builder() = default;
71
72 std::unique_ptr<SubscriptionJsonRequest>
73 SubscriptionJsonRequest::Builder::Build() const {
74 DCHECK(!url_.is_empty());
75 DCHECK(url_request_context_getter_);
76 auto request = base::WrapUnique(new SubscriptionJsonRequest());
77
78 std::string body = BuildBody();
79 std::string headers = BuildHeaders();
80 request->url_fetcher_ = BuildURLFetcher(request.get(), headers, body);
81
82 // Log the request for debugging network issues.
83 VLOG(1) << "Sending a subscription request to " << url_ << ":\n"
84 << headers << "\n"
85 << body;
86
87 return request;
88 }
89
90 SubscriptionJsonRequest::Builder& SubscriptionJsonRequest::Builder::SetToken(
91 const std::string& token) {
92 token_ = token;
93 return *this;
94 }
95
96 SubscriptionJsonRequest::Builder& SubscriptionJsonRequest::Builder::SetUrl(
97 const GURL& url) {
98 url_ = url;
99 return *this;
100 }
101
102 SubscriptionJsonRequest::Builder&
103 SubscriptionJsonRequest::Builder::SetUrlRequestContextGetter(
104 const scoped_refptr<URLRequestContextGetter>& context_getter) {
105 url_request_context_getter_ = context_getter;
106 return *this;
107 }
108
109 std::string SubscriptionJsonRequest::Builder::BuildHeaders() const {
110 HttpRequestHeaders headers;
111 headers.SetHeader("Content-Type", "application/json; charset=UTF-8");
112
113 // Add X-Client-Data header with experiment IDs from field trials.
114 // Note: It's OK to pass |is_signed_in| false if it's unknown, as it does
115 // not affect transmission of experiments coming from the variations server.
116 variations::AppendVariationHeaders(url_,
117 false, // incognito
118 false, // uma_enabled
119 false, // is_signed_in
120 &headers);
121 return headers.ToString();
122 }
123
124 std::string SubscriptionJsonRequest::Builder::BuildBody() const {
125 base::DictionaryValue request;
126 request.SetString("token", token_);
127
128 std::string request_json;
129 bool success = base::JSONWriter::Write(request, &request_json);
130 DCHECK(success);
131 return request_json;
132 }
133
134 std::unique_ptr<URLFetcher> SubscriptionJsonRequest::Builder::BuildURLFetcher(
135 URLFetcherDelegate* delegate,
136 const std::string& headers,
137 const std::string& body) const {
138 net::NetworkTrafficAnnotationTag traffic_annotation =
139 net::DefineNetworkTrafficAnnotation("gcm_subscription", R"(
140 semantics {
141 sender: "Subscribe for breaking news delivered via GCM push messages"
142 description:
143 "Chromium can receive breaking news via GCM push messages. "
144 "This request suscribes the client to receiving them."
145 trigger:
146 "Subscription takes place only once per profile lifetime. "
147 data:
148 "The subscription token that identifies this Chromium profile."
149 destination: GOOGLE_OWNED_SERVICE
150 }
151 policy {
152 cookies_allowed: false
153 setting:
154 "This feature cannot be disabled by settings now"
155 chrome_policy {
156 NTPContentSuggestionsEnabled {
157 policy_options {mode: MANDATORY}
158 NTPContentSuggestionsEnabled: false
159 }
160 }
161 })");
162 std::unique_ptr<URLFetcher> url_fetcher =
163 URLFetcher::Create(url_, URLFetcher::POST, delegate, traffic_annotation);
164 url_fetcher->SetRequestContext(url_request_context_getter_.get());
165 url_fetcher->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES |
166 net::LOAD_DO_NOT_SAVE_COOKIES);
167 data_use_measurement::DataUseUserData::AttachToFetcher(
168 url_fetcher.get(),
169 data_use_measurement::DataUseUserData::NTP_SNIPPETS_SUGGESTIONS);
170
171 url_fetcher->SetExtraRequestHeaders(headers);
172 url_fetcher->SetUploadData("application/json", body);
173
174 // Fetchers are sometimes cancelled because a network change was detected.
175 url_fetcher->SetAutomaticallyRetryOnNetworkChanges(1);
176 return url_fetcher;
177 }
178
179 } // namespace internal
180
181 } // namespace ntp_snippets
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698