190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// found in the LICENSE file.
490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
5424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "chrome/browser/ui/app_list/search/common/json_response_fetcher.h"
690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/bind.h"
890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/values.h"
990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/browser/safe_json_parser.h"
1090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "net/base/load_flags.h"
1190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "net/url_request/url_fetcher.h"
1290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "net/url_request/url_request_status.h"
13424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "url/gurl.h"
1490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace app_list {
1690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
17424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)const char kBadResponse[] = "Bad Web Service search response";
1890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
19424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)JSONResponseFetcher::JSONResponseFetcher(
2090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const Callback& callback,
2190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    net::URLRequestContextGetter* context_getter)
2290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    : callback_(callback),
2390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      context_getter_(context_getter),
2490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      weak_factory_(this) {
2590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(!callback_.is_null());
2690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
2790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
28424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)JSONResponseFetcher::~JSONResponseFetcher() {}
2990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
30424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void JSONResponseFetcher::Start(const GURL& query_url) {
3190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  Stop();
3290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
3390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  fetcher_.reset(net::URLFetcher::Create(
34424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      query_url,
3590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      net::URLFetcher::GET,
3690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      this));
3790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  fetcher_->SetRequestContext(context_getter_);
3890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES |
3990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                         net::LOAD_DISABLE_CACHE);
4090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  fetcher_->Start();
4190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
4290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
43424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void JSONResponseFetcher::Stop() {
4490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  fetcher_.reset();
4590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  weak_factory_.InvalidateWeakPtrs();
4690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
4790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
48424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void JSONResponseFetcher::OnJsonParseSuccess(
4990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    scoped_ptr<base::Value> parsed_json) {
5090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!parsed_json->IsType(base::Value::TYPE_DICTIONARY)) {
5190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    OnJsonParseError(kBadResponse);
5290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return;
5390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
5490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
5590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  callback_.Run(make_scoped_ptr(
5690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      static_cast<base::DictionaryValue*>(parsed_json.release())));
5790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
5890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
59424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void JSONResponseFetcher::OnJsonParseError(const std::string& error) {
6090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  callback_.Run(scoped_ptr<base::DictionaryValue>());
6190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
6290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
63424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void JSONResponseFetcher::OnURLFetchComplete(
64424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const net::URLFetcher* source) {
6590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  CHECK_EQ(fetcher_.get(), source);
6690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
6790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<net::URLFetcher> fetcher(fetcher_.Pass());
6890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
6990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!fetcher->GetStatus().is_success() ||
7090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      fetcher->GetResponseCode() != 200) {
7190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    OnJsonParseError(kBadResponse);
7290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return;
7390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
7490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
7558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  std::string json_data;
7658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  fetcher->GetResponseAsString(&json_data);
7790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
7890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_refptr<SafeJsonParser> parser =
7958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      new SafeJsonParser(json_data,
80424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                         base::Bind(
81424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                             &JSONResponseFetcher::OnJsonParseSuccess,
82424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                             weak_factory_.GetWeakPtr()),
83424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                         base::Bind(
84424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                             &JSONResponseFetcher::OnJsonParseError,
85424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                             weak_factory_.GetWeakPtr()));
8690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // The parser will call us back via one of the callbacks.
8790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  parser->Start();
8890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
8990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
9090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}  // namespace app_list
91