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

Unified 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: Created 3 years, 7 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 side-by-side diff with in-line comments
Download patch
Index: components/ntp_snippets/breaking_news/subscription_json_request.cc
diff --git a/components/ntp_snippets/breaking_news/subscription_json_request.cc b/components/ntp_snippets/breaking_news/subscription_json_request.cc
new file mode 100644
index 0000000000000000000000000000000000000000..cc19aa9f122701117ffad52e2b4cdf3dd607792c
--- /dev/null
+++ b/components/ntp_snippets/breaking_news/subscription_json_request.cc
@@ -0,0 +1,214 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/ntp_snippets/breaking_news/subscription_json_request.h"
+
+#include <algorithm>
+#include <utility>
+#include <vector>
+
+#include "base/command_line.h"
+#include "base/json/json_writer.h"
+#include "base/memory/ptr_util.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/metrics/sparse_histogram.h"
+#include "base/strings/stringprintf.h"
+#include "base/time/clock.h"
+#include "base/values.h"
+#include "components/data_use_measurement/core/data_use_user_data.h"
+#include "components/ntp_snippets/breaking_news/subscription_request_params.h"
+#include "components/ntp_snippets/category_info.h"
+#include "components/ntp_snippets/features.h"
+#include "components/ntp_snippets/user_classifier.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/signin_manager.h"
+#include "components/signin/core/browser/signin_manager_base.h"
+#include "components/strings/grit/components_strings.h"
+#include "components/variations/net/variations_http_headers.h"
+#include "components/variations/variations_associated_data.h"
+#include "net/base/load_flags.h"
+#include "net/http/http_response_headers.h"
+#include "net/http/http_status_code.h"
+#include "net/traffic_annotation/network_traffic_annotation.h"
+#include "net/url_request/url_fetcher.h"
+#include "net/url_request/url_request_context_getter.h"
+#include "third_party/icu/source/common/unicode/uloc.h"
+#include "third_party/icu/source/common/unicode/utypes.h"
+#include "ui/base/l10n/l10n_util.h"
+
+using net::URLFetcher;
+using net::URLRequestContextGetter;
+using net::HttpRequestHeaders;
+using net::URLRequestStatus;
+
+namespace ntp_snippets {
+
+namespace internal {
+
+SubscriptionJsonRequest::SubscriptionJsonRequest(
+ const ParseJSONCallback& callback)
+ : parse_json_callback_(callback), weak_ptr_factory_(this) {}
+
+SubscriptionJsonRequest::~SubscriptionJsonRequest() {
+ LOG_IF(DFATAL, !request_completed_callback_.is_null())
Bernhard Bauer 2017/05/31 13:12:45 It's illegal to destroy a request before it has co
mamir 2017/05/31 14:25:03 Done.
+ << "The CompletionCallback was never called!";
+}
+
+void SubscriptionJsonRequest::Start(CompletedCallback callback) {
+ request_completed_callback_ = std::move(callback);
+ url_fetcher_->Start();
+}
+
+std::string SubscriptionJsonRequest::GetResponseString() const {
+ std::string response;
+ url_fetcher_->GetResponseAsString(&response);
+ return response;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// URLFetcherDelegate overrides
+void SubscriptionJsonRequest::OnURLFetchComplete(
+ const net::URLFetcher* source) {
+ DCHECK_EQ(url_fetcher_.get(), source);
+ const URLRequestStatus& status = url_fetcher_->GetStatus();
+ int response = url_fetcher_->GetResponseCode();
+
+ if (!status.is_success()) {
+ std::move(request_completed_callback_)
+ .Run(/*result=*/nullptr,
+ /*error_details=*/base::StringPrintf(" %d", status.error()));
+ } else if (response != net::HTTP_OK) {
+ std::move(request_completed_callback_)
+ .Run(/*result=*/nullptr,
+ /*error_details=*/base::StringPrintf(" %d", response));
+ } else {
+ // request succeeded.
Bernhard Bauer 2017/05/31 13:12:44 So the callback is never called if the request suc
mamir 2017/05/31 14:25:03 After an offline discussion with fhorschig@ this i
+ }
+}
+
+SubscriptionJsonRequest::Builder::Builder() {}
+SubscriptionJsonRequest::Builder::Builder(SubscriptionJsonRequest::Builder&&) =
+ default;
+SubscriptionJsonRequest::Builder::~Builder() = default;
+
+std::unique_ptr<SubscriptionJsonRequest>
+SubscriptionJsonRequest::Builder::Build() const {
+ DCHECK(!url_.is_empty());
+ DCHECK(url_request_context_getter_);
+ auto request =
+ base::MakeUnique<SubscriptionJsonRequest>(parse_json_callback_);
+ std::string body = BuildBody();
+ std::string headers = BuildHeaders();
+ request->url_fetcher_ = BuildURLFetcher(request.get(), headers, body);
+
+ // Log the request for debugging network issues.
+ VLOG(1) << "Sending a subscription request to " << url_ << ":\n"
+ << headers << "\n"
+ << body;
+
+ return request;
+}
+
+SubscriptionJsonRequest::Builder& SubscriptionJsonRequest::Builder::SetParams(
+ const SubscriptionRequestParams& params) {
+ params_ = params;
+ return *this;
+}
+
+SubscriptionJsonRequest::Builder& SubscriptionJsonRequest::Builder::SetUrl(
+ const GURL& url) {
+ url_ = url;
+ return *this;
+}
+
+SubscriptionJsonRequest::Builder&
+SubscriptionJsonRequest::Builder::SetUrlRequestContextGetter(
+ const scoped_refptr<net::URLRequestContextGetter>& context_getter) {
+ url_request_context_getter_ = context_getter;
+ return *this;
+}
+
+SubscriptionJsonRequest::Builder&
+SubscriptionJsonRequest::Builder::SetParseJsonCallback(
+ ParseJSONCallback callback) {
+ parse_json_callback_ = callback;
+ return *this;
+}
+
+std::string SubscriptionJsonRequest::Builder::BuildHeaders() const {
+ net::HttpRequestHeaders headers;
+ headers.SetHeader("Content-Type", "application/json; charset=UTF-8");
+ if (!auth_header_.empty()) {
+ headers.SetHeader("Authorization", auth_header_);
+ }
+ // Add X-Client-Data header with experiment IDs from field trials.
+ // Note: It's OK to pass |is_signed_in| false if it's unknown, as it does
+ // not affect transmission of experiments coming from the variations server.
+ bool is_signed_in = false;
+ variations::AppendVariationHeaders(url_,
+ false, // incognito
+ false, // uma_enabled
+ is_signed_in, &headers);
+ return headers.ToString();
+}
+
+std::string SubscriptionJsonRequest::Builder::BuildBody() const {
+ auto request = base::MakeUnique<base::DictionaryValue>();
+
+ std::string request_json;
+ bool success = base::JSONWriter::WriteWithOptions(
+ *request, base::JSONWriter::OPTIONS_PRETTY_PRINT, &request_json);
+ DCHECK(success);
+ return request_json;
+}
+
+std::unique_ptr<net::URLFetcher>
+SubscriptionJsonRequest::Builder::BuildURLFetcher(
+ net::URLFetcherDelegate* delegate,
+ const std::string& headers,
+ const std::string& body) const {
+ net::NetworkTrafficAnnotationTag traffic_annotation =
+ net::DefineNetworkTrafficAnnotation("gcm_subscription", R"(
+ semantics {
+ sender: "Subscribe for breaking news delivered via GCM push messages"
+ description:
+ "Chromium can received breaking news via GCM push messages. "
Bernhard Bauer 2017/05/31 13:12:44 "receive"
mamir 2017/05/31 14:25:03 Done.
+ "This request suscribes the client to receiving them."
+ trigger:
+ "Suscrpion takes place only once per profile lifetime. "
Bernhard Bauer 2017/05/31 13:12:44 "Subscription"
mamir 2017/05/31 14:25:03 Done.
+ data:
+ "The sunscrption token that identifies this Chromium profile."
Bernhard Bauer 2017/05/31 13:12:44 "subscription"
mamir 2017/05/31 14:25:03 Done.
+ destination: GOOGLE_OWNED_SERVICE
+ }
+ policy {
+ cookies_allowed: false
+ setting:
+ "This feature cannot be disabled by settings now"
+ chrome_policy {
+ NTPContentSuggestionsEnabled {
+ policy_options {mode: MANDATORY}
+ NTPContentSuggestionsEnabled: false
+ }
+ }
+ })");
+ std::unique_ptr<net::URLFetcher> url_fetcher = net::URLFetcher::Create(
+ url_, net::URLFetcher::POST, delegate, traffic_annotation);
+ url_fetcher->SetRequestContext(url_request_context_getter_.get());
+ url_fetcher->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES |
+ net::LOAD_DO_NOT_SAVE_COOKIES);
+ data_use_measurement::DataUseUserData::AttachToFetcher(
+ url_fetcher.get(),
+ data_use_measurement::DataUseUserData::NTP_SNIPPETS_SUGGESTIONS);
+
+ url_fetcher->SetExtraRequestHeaders(headers);
+ url_fetcher->SetUploadData("application/json", body);
+
+ // Fetchers are sometimes cancelled because a network change was detected.
+ url_fetcher->SetAutomaticallyRetryOnNetworkChanges(3);
+ return url_fetcher;
+}
+
+} // namespace internal
+
+} // namespace ntp_snippets

Powered by Google App Engine
This is Rietveld 408576698