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.
4
5#include "chrome/browser/extensions/webstore_data_fetcher.h"
6
7#include "base/bind.h"
8#include "base/values.h"
9#include "chrome/browser/extensions/webstore_data_fetcher_delegate.h"
10#include "chrome/browser/safe_json_parser.h"
11#include "extensions/common/extension_urls.h"
12#include "net/base/load_flags.h"
13#include "net/url_request/url_fetcher.h"
14#include "net/url_request/url_request_status.h"
15
16namespace {
17
18const char kInvalidWebstoreResponseError[] = "Invalid Chrome Web Store reponse";
19
20}  // namespace
21
22namespace extensions {
23
24WebstoreDataFetcher::WebstoreDataFetcher(
25    WebstoreDataFetcherDelegate* delegate,
26    net::URLRequestContextGetter* request_context,
27    const GURL& referrer_url,
28    const std::string webstore_item_id)
29    : delegate_(delegate),
30      request_context_(request_context),
31      referrer_url_(referrer_url),
32      id_(webstore_item_id),
33      max_auto_retries_(0) {
34}
35
36WebstoreDataFetcher::~WebstoreDataFetcher() {}
37
38void WebstoreDataFetcher::Start() {
39  GURL webstore_data_url(extension_urls::GetWebstoreItemJsonDataURL(id_));
40
41  webstore_data_url_fetcher_.reset(net::URLFetcher::Create(
42      webstore_data_url, net::URLFetcher::GET, this));
43  webstore_data_url_fetcher_->SetRequestContext(request_context_);
44  webstore_data_url_fetcher_->SetReferrer(referrer_url_.spec());
45  webstore_data_url_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES |
46                                           net::LOAD_DISABLE_CACHE);
47  if (max_auto_retries_ > 0) {
48    webstore_data_url_fetcher_->SetMaxRetriesOn5xx(max_auto_retries_);
49    webstore_data_url_fetcher_->SetAutomaticallyRetryOnNetworkChanges(
50        max_auto_retries_);
51  }
52  webstore_data_url_fetcher_->Start();
53}
54
55void WebstoreDataFetcher::OnJsonParseSuccess(
56    scoped_ptr<base::Value> parsed_json) {
57  if (!parsed_json->IsType(base::Value::TYPE_DICTIONARY)) {
58    OnJsonParseFailure(kInvalidWebstoreResponseError);
59    return;
60  }
61
62  delegate_->OnWebstoreResponseParseSuccess(scoped_ptr<base::DictionaryValue>(
63      static_cast<base::DictionaryValue*>(parsed_json.release())));
64}
65
66void WebstoreDataFetcher::OnJsonParseFailure(
67    const std::string& error) {
68  delegate_->OnWebstoreResponseParseFailure(error);
69}
70
71void WebstoreDataFetcher::OnURLFetchComplete(const net::URLFetcher* source) {
72  CHECK_EQ(webstore_data_url_fetcher_.get(), source);
73
74  scoped_ptr<net::URLFetcher> fetcher(webstore_data_url_fetcher_.Pass());
75
76  if (!fetcher->GetStatus().is_success() ||
77      fetcher->GetResponseCode() != 200) {
78    delegate_->OnWebstoreRequestFailure();
79    return;
80  }
81
82  std::string webstore_json_data;
83  fetcher->GetResponseAsString(&webstore_json_data);
84
85  scoped_refptr<SafeJsonParser> parser =
86      new SafeJsonParser(webstore_json_data,
87                         base::Bind(&WebstoreDataFetcher::OnJsonParseSuccess,
88                                    AsWeakPtr()),
89                         base::Bind(&WebstoreDataFetcher::OnJsonParseFailure,
90                                    AsWeakPtr()));
91  // The parser will call us back via one of the callbacks.
92  parser->Start();
93}
94
95}  // namespace extensions
96