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

Side by Side Diff: components/quirks/quirks_client.cc

Issue 1528963002: Quirks Client for downloading and providing display profiles (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Small cleanup Created 4 years, 9 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 2016 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/quirks/quirks_client.h"
6
7 #include "base/base64.h"
8 #include "base/files/file_util.h"
9 #include "base/json/json_reader.h"
10 #include "base/strings/stringprintf.h"
11 #include "base/task_runner_util.h"
12 #include "base/thread_task_runner_handle.h"
13 #include "base/threading/thread_restrictions.h"
14 #include "components/prefs/scoped_user_pref_update.h"
15 #include "components/quirks/quirks_manager.h"
16 #include "components/version_info/version_info.h"
17 #include "net/base/load_flags.h"
18 #include "net/http/http_status_code.h"
19 #include "net/url_request/url_fetcher.h"
20 #include "net/url_request/url_request_context_getter.h"
21
22 namespace quirks {
23
24 namespace {
25
26 const char kQuirksUrlFormat[] =
27 "https://qa-quirksserver-pa.sandbox.googleapis.com/v2/display/%s/clients"
28 "/chromeos/M%d";
29
30 const net::BackoffEntry::Policy kDefaultBackoffPolicy = {
31 1, // Initial errors before applying backoff
32 10000, // 10 seconds.
33 2, // Factor by which the waiting time will be multiplied.
34 0, // Random fuzzing percentage.
35 1000 * 3600 * 6, // Max wait between requests = 6 hours.
36 -1, // Don't discard entry.
37 true, // Use initial delay after first error.
38 };
39
40 bool WriteIccFile(const base::FilePath file_path, const std::string& data) {
41 base::ThreadRestrictions::AssertIOAllowed();
42 int bytes_written = base::WriteFile(file_path, data.data(), data.length());
43 if (bytes_written == -1)
44 LOG(ERROR) << "Write failed: " << file_path.value() << ", err = " << errno;
45 else
46 VLOG(1) << bytes_written << "bytes written to: " << file_path.value();
47
48 return (bytes_written != -1);
49 }
50
51 } // namespace
52
53 ////////////////////////////////////////////////////////////////////////////////
54 // QuirksClient
55
56 QuirksClient::QuirksClient(int64_t product_id,
57 const RequestFinishedCallback& on_request_finished,
58 QuirksManager* manager)
59 : product_id_(product_id),
60 on_request_finished_(on_request_finished),
61 manager_(manager),
62 icc_path_(
63 manager->delegate()->GetDownloadDisplayProfileDirectory().Append(
64 IdToFileName(product_id))),
65 request_reason_(FIRST),
66 backoff_entry_(&kDefaultBackoffPolicy),
67 weak_ptr_factory_(this) {}
68
69 QuirksClient::~QuirksClient() {}
70
71 void QuirksClient::StartDownload() {
72 DCHECK(base::ThreadTaskRunnerHandle::IsSet());
73
74 // URL of icc file on Quirks Server.
75 int major_version = atoi(version_info::GetVersionNumber().c_str());
76 std::string url = base::StringPrintf(
77 kQuirksUrlFormat, IdToHexString(product_id_).c_str(), major_version);
78
79 VLOG(2) << "Preparing to download\n " << url << "\nto file "
80 << icc_path_.value();
81
82 url += "?key=";
83 url += manager_->delegate()->GetApiKey();
84
85 url_fetcher_ = manager_->CreateURLFetcher(url, this);
86 url_fetcher_->SetRequestContext(manager_->url_context_getter());
87 url_fetcher_->SetLoadFlags(net::LOAD_BYPASS_CACHE | net::LOAD_DISABLE_CACHE |
88 net::LOAD_DO_NOT_SAVE_COOKIES |
89 net::LOAD_DO_NOT_SEND_COOKIES |
90 net::LOAD_DO_NOT_SEND_AUTH_DATA);
91 url_fetcher_->Start();
92 }
93
94 void QuirksClient::OnURLFetchComplete(const net::URLFetcher* source) {
95 DCHECK(base::ThreadTaskRunnerHandle::IsSet());
96 DCHECK_EQ(url_fetcher_.get(), source);
97
98 const int HTTP_INTERNAL_SERVER_ERROR_LAST =
99 net::HTTP_INTERNAL_SERVER_ERROR + 99;
100 const net::URLRequestStatus status = source->GetStatus();
101 const int response_code = source->GetResponseCode();
102 const bool server_error = !status.is_success() ||
103 (response_code >= net::HTTP_INTERNAL_SERVER_ERROR &&
104 response_code <= HTTP_INTERNAL_SERVER_ERROR_LAST);
105
106 VLOG(2) << "QuirksClient::OnURLFetchComplete():"
107 << " status=" << status.status()
108 << ", response_code=" << response_code
109 << ", server_error=" << server_error;
110
111 manager_->RecordReasonUmaStat(request_reason_);
112
113 if (response_code == net::HTTP_NOT_FOUND) {
114 VLOG(1) << IdToFileName(product_id_) << " not found on Quirks server.";
115 manager_->RecordFileFoundUmaStat(false);
116 Shutdown(false);
117 return;
118 }
119
120 if (server_error) {
121 url_fetcher_.reset();
122 Retry();
123 return;
124 }
125
126 manager_->RecordFileFoundUmaStat(true);
127 std::string response;
128 url_fetcher_->GetResponseAsString(&response);
129 VLOG(2) << "Quirks server response:\n" << response;
130
131 // Parse response data and write to file on file thread.
132 std::string data;
133 if (!ParseResult(response, &data)) {
134 Shutdown(false);
135 return;
136 }
137
138 base::PostTaskAndReplyWithResult(
139 manager_->blocking_pool(), FROM_HERE,
140 base::Bind(&WriteIccFile, icc_path_, data),
141 base::Bind(&QuirksClient::Shutdown, weak_ptr_factory_.GetWeakPtr()));
142 }
143
144 void QuirksClient::Shutdown(bool success) {
145 DCHECK(base::ThreadTaskRunnerHandle::IsSet());
146 on_request_finished_.Run(success ? icc_path_ : base::FilePath(), true);
147 manager_->ClientFinished(this);
148 }
149
150 void QuirksClient::Retry() {
151 DCHECK(base::ThreadTaskRunnerHandle::IsSet());
152 backoff_entry_.InformOfRequest(false);
153 const base::TimeDelta delay = backoff_entry_.GetTimeUntilRelease();
154
155 VLOG(1) << "Schedule next Quirks download attempt in " << delay.InSecondsF()
156 << " seconds (retry = " << backoff_entry_.failure_count() << ").";
157 request_scheduled_.Start(FROM_HERE, delay, this,
158 &QuirksClient::StartDownload);
159 }
160
161 bool QuirksClient::ParseResult(const std::string& result, std::string* data) {
162 std::string data64;
163 const base::DictionaryValue* dict;
164 scoped_ptr<base::Value> json = base::JSONReader::Read(result);
165 if (!json || !json->GetAsDictionary(&dict) ||
166 !dict->GetString("icc", &data64)) {
167 VLOG(1) << "Failed to parse JSON icc data";
168 return false;
169 }
170
171 if (!base::Base64Decode(data64, data)) {
172 VLOG(1) << "Failed to decode Base64 icc data";
173 return false;
174 }
175
176 return true;
177 }
178
179 } // namespace quirks
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698