blob: ef7904b87c61d49a60c698da5a0cf5c89e0aeae5 [file] [log] [blame]
// Copyright 2017 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 "ios/chrome/browser/payments/itunes_json_request.h"
#include <utility>
#include "base/bind.h"
#include "base/json/json_reader.h"
#include "base/memory/ptr_util.h"
#include "base/values.h"
#include "net/base/load_flags.h"
#include "net/http/http_status_code.h"
#include "net/url_request/url_fetcher.h"
#include "net/url_request/url_request_status.h"
#include "url/gurl.h"
namespace payment_request_util {
const char kBadResponse[] = "Bad iTunes Store search response";
const char kITunesStoreLookupPrefix[] = "https://itunes.apple.com/lookup?";
const char kITunesStoreSearchPrefix[] = "https://itunes.apple.com/search?";
ITunesJsonRequest::ITunesJsonRequest(
const Callback& callback,
net::URLRequestContextGetter* context_getter)
: callback_(callback),
context_getter_(context_getter),
weak_factory_(this) {
DCHECK(!callback_.is_null());
}
ITunesJsonRequest::~ITunesJsonRequest() {}
void ITunesJsonRequest::Start(ITunesStoreRequestType request_type,
const std::string& request_query) {
Stop();
std::string complete_query;
switch (request_type) {
case LOOKUP:
complete_query = kITunesStoreLookupPrefix + request_query;
case SEARCH:
complete_query = kITunesStoreSearchPrefix + request_query;
}
fetcher_ =
net::URLFetcher::Create(GURL(complete_query), net::URLFetcher::GET, this);
fetcher_->SetRequestContext(context_getter_);
fetcher_->SetLoadFlags(net::LOAD_MAYBE_USER_GESTURE |
net::LOAD_DO_NOT_SAVE_COOKIES |
net::LOAD_VERIFY_EV_CERT);
fetcher_->Start();
}
void ITunesJsonRequest::Stop() {
fetcher_.reset();
weak_factory_.InvalidateWeakPtrs();
}
void ITunesJsonRequest::ParseJson(
const std::string& json,
const payment_request_util::ITunesJsonRequest::SuccessCallback&
success_callback,
const payment_request_util::ITunesJsonRequest::ErrorCallback&
error_callback) {
DCHECK(!success_callback.is_null());
DCHECK(!error_callback.is_null());
base::JSONReader json_reader;
std::unique_ptr<base::Value> value = json_reader.ReadToValue(json);
if (value) {
success_callback.Run(std::move(value));
} else {
error_callback.Run(json_reader.GetErrorMessage());
}
}
void ITunesJsonRequest::OnJsonParseSuccess(
std::unique_ptr<base::Value> parsed_json) {
if (!parsed_json->IsType(base::Value::Type::DICTIONARY)) {
OnJsonParseError(kBadResponse);
return;
}
callback_.Run(base::WrapUnique(
static_cast<base::DictionaryValue*>(parsed_json.release())));
}
void ITunesJsonRequest::OnJsonParseError(const std::string& error) {
callback_.Run(std::unique_ptr<base::DictionaryValue>());
}
void ITunesJsonRequest::OnURLFetchComplete(const net::URLFetcher* source) {
CHECK_EQ(fetcher_.get(), source);
std::unique_ptr<net::URLFetcher> fetcher(std::move(fetcher_));
if (!fetcher->GetStatus().is_success() ||
fetcher->GetResponseCode() != net::HTTP_OK) {
OnJsonParseError(kBadResponse);
return;
}
std::string json_data;
fetcher->GetResponseAsString(&json_data);
// The parser will call us back via one of the callbacks.
ParseJson(json_data,
base::Bind(&ITunesJsonRequest::OnJsonParseSuccess,
weak_factory_.GetWeakPtr()),
base::Bind(&ITunesJsonRequest::OnJsonParseError,
weak_factory_.GetWeakPtr()));
}
} // namespace payment_request_util