blob: b72fe60a91e83274239190fbe75019937fcf3ed7 [file] [log] [blame]
// Copyright 2013 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 "chrome/browser/extensions/webstore_data_fetcher.h"
#include <utility>
#include "base/bind.h"
#include "base/values.h"
#include "chrome/browser/extensions/webstore_data_fetcher_delegate.h"
#include "components/safe_json/safe_json_parser.h"
#include "extensions/common/extension_urls.h"
#include "net/base/load_flags.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "net/url_request/url_fetcher.h"
#include "net/url_request/url_request_status.h"
namespace {
const char kInvalidWebstoreResponseError[] = "Invalid Chrome Web Store reponse";
} // namespace
namespace extensions {
WebstoreDataFetcher::WebstoreDataFetcher(
WebstoreDataFetcherDelegate* delegate,
net::URLRequestContextGetter* request_context,
const GURL& referrer_url,
const std::string webstore_item_id)
: delegate_(delegate),
request_context_(request_context),
referrer_url_(referrer_url),
id_(webstore_item_id),
max_auto_retries_(0) {
}
WebstoreDataFetcher::~WebstoreDataFetcher() {}
void WebstoreDataFetcher::SetJsonPostData(const std::string& json) {
json_post_data_ = json;
}
void WebstoreDataFetcher::Start() {
GURL webstore_data_url(extension_urls::GetWebstoreItemJsonDataURL(id_));
net::URLFetcher::RequestType request_type =
json_post_data_.empty() ? net::URLFetcher::GET : net::URLFetcher::POST;
net::NetworkTrafficAnnotationTag traffic_annotation =
net::DefineNetworkTrafficAnnotation("webstore_data_fetcher", R"(
semantics {
sender: "Webstore Data Fetcher"
description:
"Fetches metadata about an extension from the Chrome Web Store."
trigger:
"The user or another program triggers some action where Chrome "
"will show metadata about an extension. This includes extension "
"installation flows, triggering an install for a disabled "
"extension, and an extension being added to Chrome through "
"third-party sideloading. It also happens when a kiosk app account "
"whose metadata (app icon, name, required platform version) is not "
"cached locally is detected in device local accounts list. The "
"account can be set either by device policy or through extensions "
"web UI, by the device owner (user that was initially added to the "
"device; implies non managed device). The latter case is "
"deprecated and not supported on newer Chrome OS boards."
data:
"The extension id and referrer url. The referrer chain is also "
"included if the user has not opted out of SafeBrowsing."
destination: GOOGLE_OWNED_SERVICE
}
policy {
cookies_allowed: false
setting:
"This feature cannot be disabled in settings. It will only be "
"triggered if the user uses extensions."
policy_exception_justification: "Not implemented."
})");
webstore_data_url_fetcher_ = net::URLFetcher::Create(
webstore_data_url, request_type, this, traffic_annotation);
webstore_data_url_fetcher_->SetRequestContext(request_context_);
webstore_data_url_fetcher_->SetReferrer(referrer_url_.spec());
webstore_data_url_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES |
net::LOAD_DISABLE_CACHE);
if (!json_post_data_.empty()) {
webstore_data_url_fetcher_->SetUploadData("application/json",
json_post_data_);
}
if (max_auto_retries_ > 0) {
webstore_data_url_fetcher_->SetMaxRetriesOn5xx(max_auto_retries_);
webstore_data_url_fetcher_->SetAutomaticallyRetryOnNetworkChanges(
max_auto_retries_);
}
webstore_data_url_fetcher_->Start();
}
void WebstoreDataFetcher::OnJsonParseSuccess(
std::unique_ptr<base::Value> parsed_json) {
if (!parsed_json->IsType(base::Value::Type::DICTIONARY)) {
OnJsonParseFailure(kInvalidWebstoreResponseError);
return;
}
delegate_->OnWebstoreResponseParseSuccess(
std::unique_ptr<base::DictionaryValue>(
static_cast<base::DictionaryValue*>(parsed_json.release())));
}
void WebstoreDataFetcher::OnJsonParseFailure(
const std::string& error) {
delegate_->OnWebstoreResponseParseFailure(error);
}
void WebstoreDataFetcher::OnURLFetchComplete(const net::URLFetcher* source) {
CHECK_EQ(webstore_data_url_fetcher_.get(), source);
std::unique_ptr<net::URLFetcher> fetcher(
std::move(webstore_data_url_fetcher_));
if (!fetcher->GetStatus().is_success() ||
fetcher->GetResponseCode() != 200) {
delegate_->OnWebstoreRequestFailure();
return;
}
std::string webstore_json_data;
fetcher->GetResponseAsString(&webstore_json_data);
// The parser will call us back via one of the callbacks.
safe_json::SafeJsonParser::Parse(
webstore_json_data,
base::Bind(&WebstoreDataFetcher::OnJsonParseSuccess, AsWeakPtr()),
base::Bind(&WebstoreDataFetcher::OnJsonParseFailure, AsWeakPtr()));
}
} // namespace extensions