17dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// Copyright 2013 The Chromium Authors. All rights reserved. 27dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// Use of this source code is governed by a BSD-style license that can be 37dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// found in the LICENSE file. 47dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 57dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/profile_resetter/brandcode_config_fetcher.h" 67dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 77dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "base/strings/utf_string_conversions.h" 87dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/browser_process.h" 97dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/profile_resetter/brandcoded_default_settings.h" 107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "libxml/parser.h" 117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "net/base/load_flags.h" 127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "net/http/http_response_headers.h" 137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "net/url_request/url_fetcher.h" 147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "net/url_request/url_request_status.h" 157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochnamespace { 177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochconst int kDownloadTimeoutSec = 10; 197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochconst char kPostXml[] = 207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" 217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch"<request version=\"1.3.17.0\" protocol=\"3.0\" testsource=\"dev\" " 227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch "shell_version=\"1.2.3.5\">\n" 237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch" <os platform=\"win\" version=\"6.1\" sp=\"\" arch=\"x86\" />\n" 247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch" <app\n" 257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch" appid=\"{8A69D345-D564-463C-AFF1-A69D9E530F96}\"\n" 267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch" version=\"0.0.0.0\"\n" 277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch" >\n" 287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch" <updatecheck />\n" 297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch" <data name=\"install\" " 3058e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch "index=\"__BRANDCODE_PLACEHOLDER__\" />\n" 317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch" </app>\n" 327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch"</request>"; 337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 3458e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch// Returns the query to the server which can be used to retrieve the config. 3558e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch// |brand| is a brand code, it mustn't be empty. 3658e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdochstd::string GetUploadData(const std::string& brand) { 3758e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch DCHECK(!brand.empty()); 3858e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch std::string data(kPostXml); 3958e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch const std::string placeholder("__BRANDCODE_PLACEHOLDER__"); 4058e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch size_t placeholder_pos = data.find(placeholder); 4158e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch DCHECK(placeholder_pos != std::string::npos); 4258e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch data.replace(placeholder_pos, placeholder.size(), brand); 4358e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch return data; 447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// Extracts json master prefs from xml. 477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochclass XmlConfigParser { 487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch public: 497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch XmlConfigParser(); 507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ~XmlConfigParser(); 517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // Returns the content of /response/app/data tag. 537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch static void Parse(const std::string& input_buffer, 547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch std::string* output_buffer); 557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch private: 577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch static XmlConfigParser* FromContext(void* ctx); 587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch static std::string XMLCharToString(const xmlChar* value); 597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch static void StartElementImpl(void* ctx, 607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch const xmlChar* name, 617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch const xmlChar** atts); 627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch static void EndElementImpl(void* ctx, const xmlChar* name); 637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch static void CharactersImpl(void* ctx, const xmlChar* ch, int len); 647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch bool IsParsingData() const; 667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // Extracted json file. 687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch std::string master_prefs_; 697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // Current stack of the elements being parsed. 717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch std::vector<std::string> elements_; 727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch DISALLOW_COPY_AND_ASSIGN(XmlConfigParser); 747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}; 757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 767dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochXmlConfigParser::XmlConfigParser() {} 777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 787dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochXmlConfigParser::~XmlConfigParser() {} 797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid XmlConfigParser::Parse(const std::string& input_buffer, 817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch std::string* output_buffer) { 827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch using logging::LOG_WARNING; 837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch DCHECK(output_buffer); 857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch xmlSAXHandler sax_handler = {}; 867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch sax_handler.startElement = &XmlConfigParser::StartElementImpl; 877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch sax_handler.endElement = &XmlConfigParser::EndElementImpl; 887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch sax_handler.characters = &XmlConfigParser::CharactersImpl; 897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch XmlConfigParser parser; 907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch int error = xmlSAXUserParseMemory(&sax_handler, 917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch &parser, 927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch input_buffer.c_str(), 937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch input_buffer.size()); 947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (error) { 957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch VLOG(LOG_WARNING) << "Error parsing brandcoded master prefs, err=" << error; 967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } else { 977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch output_buffer->swap(parser.master_prefs_); 987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 1007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1017dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochXmlConfigParser* XmlConfigParser::FromContext(void* ctx) { 1027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return static_cast<XmlConfigParser*>(ctx); 1037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 1047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochstd::string XmlConfigParser::XMLCharToString(const xmlChar* value) { 1067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return std::string(reinterpret_cast<const char*>(value)); 1077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 1087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid XmlConfigParser::StartElementImpl(void* ctx, 1107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch const xmlChar* name, 1117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch const xmlChar** atts) { 1127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch std::string node_name(XMLCharToString(name)); 1137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch XmlConfigParser* context = FromContext(ctx); 1147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch context->elements_.push_back(node_name); 1157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (context->IsParsingData()) 1167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch context->master_prefs_.clear(); 1177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 1187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid XmlConfigParser::EndElementImpl(void* ctx, const xmlChar* name) { 1207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch XmlConfigParser* context = FromContext(ctx); 1217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch context->elements_.pop_back(); 1227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 1237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid XmlConfigParser::CharactersImpl(void* ctx, const xmlChar* ch, int len) { 1257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch XmlConfigParser* context = FromContext(ctx); 1267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (context->IsParsingData()) { 1277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch context->master_prefs_ += 1287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch std::string(reinterpret_cast<const char*>(ch), len); 1297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 1307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 1317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool XmlConfigParser::IsParsingData() const { 1337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch const std::string data_path[] = {"response", "app", "data"}; 1347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return elements_.size() == arraysize(data_path) && 1357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch std::equal(elements_.begin(), elements_.end(), data_path); 1367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 1377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} // namespace 1397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1407dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochBrandcodeConfigFetcher::BrandcodeConfigFetcher(const FetchCallback& callback, 14158e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch const GURL& url, 14258e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch const std::string& brandcode) 1437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch : fetch_callback_(callback) { 14458e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch DCHECK(!brandcode.empty()); 1457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch config_fetcher_.reset(net::URLFetcher::Create(0 /* ID used for testing */, 1467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch url, 1477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch net::URLFetcher::POST, 1487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch this)); 1497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch config_fetcher_->SetRequestContext( 1507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch g_browser_process->system_request_context()); 15158e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch config_fetcher_->SetUploadData("text/xml", GetUploadData(brandcode)); 1527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch config_fetcher_->AddExtraRequestHeader("Accept: text/xml"); 1537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch config_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | 1547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch net::LOAD_DO_NOT_SAVE_COOKIES | 1557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch net::LOAD_DISABLE_CACHE); 1567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch config_fetcher_->Start(); 1577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // Abort the download attempt if it takes too long. 1587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch download_timer_.Start(FROM_HERE, 1597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch base::TimeDelta::FromSeconds(kDownloadTimeoutSec), 1607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch this, 1617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch &BrandcodeConfigFetcher::OnDownloadTimeout); 1627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 1637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1647dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochBrandcodeConfigFetcher::~BrandcodeConfigFetcher() {} 1657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid BrandcodeConfigFetcher::SetCallback(const FetchCallback& callback) { 1677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch fetch_callback_ = callback; 1687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 1697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid BrandcodeConfigFetcher::OnURLFetchComplete(const net::URLFetcher* source) { 1717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (source != config_fetcher_.get()) { 1727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch NOTREACHED() << "Callback from foreign URL fetcher"; 1737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return; 1747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 1757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch std::string response_string; 1767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch std::string mime_type; 1777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (config_fetcher_ && 1787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch config_fetcher_->GetStatus().is_success() && 1797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch config_fetcher_->GetResponseCode() == 200 && 1807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch config_fetcher_->GetResponseHeaders()->GetMimeType(&mime_type) && 1817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch mime_type == "text/xml" && 1827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch config_fetcher_->GetResponseAsString(&response_string)) { 1837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch std::string master_prefs; 1847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch XmlConfigParser::Parse(response_string, &master_prefs); 1857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch default_settings_.reset(new BrandcodedDefaultSettings(master_prefs)); 1867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 1877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch config_fetcher_.reset(); 1887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch download_timer_.Stop(); 1897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch fetch_callback_.Run(); 1907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 1917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid BrandcodeConfigFetcher::OnDownloadTimeout() { 1937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (config_fetcher_) { 1947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch config_fetcher_.reset(); 1957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch fetch_callback_.Run(); 1967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 1977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 198