Add new certificateProvider extension API.
[chromium-blink-merge.git] / chrome / browser / profile_resetter / brandcode_config_fetcher.cc
blob117fa1633e165d00456bb6d6231ae81f861d9af5
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/profile_resetter/brandcode_config_fetcher.h"
7 #include "base/strings/utf_string_conversions.h"
8 #include "chrome/browser/browser_process.h"
9 #include "chrome/browser/profile_resetter/brandcoded_default_settings.h"
10 #include "libxml/parser.h"
11 #include "net/base/load_flags.h"
12 #include "net/http/http_response_headers.h"
13 #include "net/url_request/url_fetcher.h"
14 #include "net/url_request/url_request_status.h"
16 namespace {
18 const int kDownloadTimeoutSec = 10;
19 const char kPostXml[] =
20 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
21 "<request version=\"1.3.17.0\" protocol=\"3.0\" testsource=\"dev\" "
22 "shell_version=\"1.2.3.5\">\n"
23 " <os platform=\"win\" version=\"6.1\" sp=\"\" arch=\"x86\" />\n"
24 " <app\n"
25 " appid=\"{8A69D345-D564-463C-AFF1-A69D9E530F96}\"\n"
26 " version=\"0.0.0.0\"\n"
27 " >\n"
28 " <updatecheck />\n"
29 " <data name=\"install\" "
30 "index=\"__BRANDCODE_PLACEHOLDER__\" />\n"
31 " </app>\n"
32 "</request>";
34 // Returns the query to the server which can be used to retrieve the config.
35 // |brand| is a brand code, it mustn't be empty.
36 std::string GetUploadData(const std::string& brand) {
37 DCHECK(!brand.empty());
38 std::string data(kPostXml);
39 const std::string placeholder("__BRANDCODE_PLACEHOLDER__");
40 size_t placeholder_pos = data.find(placeholder);
41 DCHECK(placeholder_pos != std::string::npos);
42 data.replace(placeholder_pos, placeholder.size(), brand);
43 return data;
46 // Extracts json master prefs from xml.
47 class XmlConfigParser {
48 public:
49 XmlConfigParser();
50 ~XmlConfigParser();
52 // Returns the content of /response/app/data tag.
53 static void Parse(const std::string& input_buffer,
54 std::string* output_buffer);
56 private:
57 static XmlConfigParser* FromContext(void* ctx);
58 static std::string XMLCharToString(const xmlChar* value);
59 static void StartElementImpl(void* ctx,
60 const xmlChar* name,
61 const xmlChar** atts);
62 static void EndElementImpl(void* ctx, const xmlChar* name);
63 static void CharactersImpl(void* ctx, const xmlChar* ch, int len);
65 bool IsParsingData() const;
67 // Extracted json file.
68 std::string master_prefs_;
70 // Current stack of the elements being parsed.
71 std::vector<std::string> elements_;
73 DISALLOW_COPY_AND_ASSIGN(XmlConfigParser);
76 XmlConfigParser::XmlConfigParser() {}
78 XmlConfigParser::~XmlConfigParser() {}
80 void XmlConfigParser::Parse(const std::string& input_buffer,
81 std::string* output_buffer) {
82 using logging::LOG_WARNING;
84 DCHECK(output_buffer);
85 xmlSAXHandler sax_handler = {};
86 sax_handler.startElement = &XmlConfigParser::StartElementImpl;
87 sax_handler.endElement = &XmlConfigParser::EndElementImpl;
88 sax_handler.characters = &XmlConfigParser::CharactersImpl;
89 XmlConfigParser parser;
90 int error = xmlSAXUserParseMemory(&sax_handler,
91 &parser,
92 input_buffer.c_str(),
93 input_buffer.size());
94 if (error) {
95 VLOG(LOG_WARNING) << "Error parsing brandcoded master prefs, err=" << error;
96 } else {
97 output_buffer->swap(parser.master_prefs_);
101 XmlConfigParser* XmlConfigParser::FromContext(void* ctx) {
102 return static_cast<XmlConfigParser*>(ctx);
105 std::string XmlConfigParser::XMLCharToString(const xmlChar* value) {
106 return std::string(reinterpret_cast<const char*>(value));
109 void XmlConfigParser::StartElementImpl(void* ctx,
110 const xmlChar* name,
111 const xmlChar** atts) {
112 std::string node_name(XMLCharToString(name));
113 XmlConfigParser* context = FromContext(ctx);
114 context->elements_.push_back(node_name);
115 if (context->IsParsingData())
116 context->master_prefs_.clear();
119 void XmlConfigParser::EndElementImpl(void* ctx, const xmlChar* name) {
120 XmlConfigParser* context = FromContext(ctx);
121 context->elements_.pop_back();
124 void XmlConfigParser::CharactersImpl(void* ctx, const xmlChar* ch, int len) {
125 XmlConfigParser* context = FromContext(ctx);
126 if (context->IsParsingData()) {
127 context->master_prefs_ +=
128 std::string(reinterpret_cast<const char*>(ch), len);
132 bool XmlConfigParser::IsParsingData() const {
133 const std::string data_path[] = {"response", "app", "data"};
134 return elements_.size() == arraysize(data_path) &&
135 std::equal(elements_.begin(), elements_.end(), data_path);
138 } // namespace
140 BrandcodeConfigFetcher::BrandcodeConfigFetcher(const FetchCallback& callback,
141 const GURL& url,
142 const std::string& brandcode)
143 : fetch_callback_(callback) {
144 DCHECK(!brandcode.empty());
145 config_fetcher_ = net::URLFetcher::Create(0 /* ID used for testing */, url,
146 net::URLFetcher::POST, this);
147 config_fetcher_->SetRequestContext(
148 g_browser_process->system_request_context());
149 config_fetcher_->SetUploadData("text/xml", GetUploadData(brandcode));
150 config_fetcher_->AddExtraRequestHeader("Accept: text/xml");
151 config_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES |
152 net::LOAD_DO_NOT_SAVE_COOKIES |
153 net::LOAD_DISABLE_CACHE);
154 config_fetcher_->Start();
155 // Abort the download attempt if it takes too long.
156 download_timer_.Start(FROM_HERE,
157 base::TimeDelta::FromSeconds(kDownloadTimeoutSec),
158 this,
159 &BrandcodeConfigFetcher::OnDownloadTimeout);
162 BrandcodeConfigFetcher::~BrandcodeConfigFetcher() {}
164 void BrandcodeConfigFetcher::SetCallback(const FetchCallback& callback) {
165 fetch_callback_ = callback;
168 void BrandcodeConfigFetcher::OnURLFetchComplete(const net::URLFetcher* source) {
169 if (source != config_fetcher_.get()) {
170 NOTREACHED() << "Callback from foreign URL fetcher";
171 return;
173 std::string response_string;
174 std::string mime_type;
175 if (config_fetcher_ &&
176 config_fetcher_->GetStatus().is_success() &&
177 config_fetcher_->GetResponseCode() == 200 &&
178 config_fetcher_->GetResponseHeaders()->GetMimeType(&mime_type) &&
179 mime_type == "text/xml" &&
180 config_fetcher_->GetResponseAsString(&response_string)) {
181 std::string master_prefs;
182 XmlConfigParser::Parse(response_string, &master_prefs);
183 default_settings_.reset(new BrandcodedDefaultSettings(master_prefs));
185 config_fetcher_.reset();
186 download_timer_.Stop();
187 fetch_callback_.Run();
190 void BrandcodeConfigFetcher::OnDownloadTimeout() {
191 if (config_fetcher_) {
192 config_fetcher_.reset();
193 fetch_callback_.Run();