Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / app_list / search / webstore / webstore_provider.cc
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/ui/app_list/search/webstore/webstore_provider.h"
6
7 #include <string>
8
9 #include "base/bind.h"
10 #include "base/callback.h"
11 #include "base/strings/string_util.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "base/values.h"
14 #include "chrome/browser/browser_process.h"
15 #include "chrome/browser/profiles/profile.h"
16 #include "chrome/browser/search/search.h"
17 #include "chrome/browser/ui/app_list/search/common/json_response_fetcher.h"
18 #include "chrome/browser/ui/app_list/search/search_webstore_result.h"
19 #include "chrome/browser/ui/app_list/search/webstore/webstore_result.h"
20 #include "extensions/common/extension_urls.h"
21 #include "url/gurl.h"
22
23 namespace app_list {
24
25 namespace {
26
27 const char kKeyResults[] = "results";
28 const char kKeyId[] = "id";
29 const char kKeyLocalizedName[] = "localized_name";
30 const char kKeyIconUrl[] = "icon_url";
31 const char kKeyIsPaid[] = "is_paid";
32 const char kKeyItemType[] = "item_type";
33
34 const char kPlatformAppType[] = "platform_app";
35 const char kHostedAppType[] = "hosted_app";
36 const char kLegacyPackagedAppType[] = "legacy_packaged_app";
37
38 // Converts the item type string from the web store to an
39 // extensions::Manifest::Type.
40 extensions::Manifest::Type ParseItemType(const std::string& item_type_str) {
41   if (LowerCaseEqualsASCII(item_type_str, kPlatformAppType))
42     return extensions::Manifest::TYPE_PLATFORM_APP;
43
44   if (LowerCaseEqualsASCII(item_type_str, kLegacyPackagedAppType))
45     return extensions::Manifest::TYPE_LEGACY_PACKAGED_APP;
46
47   if (LowerCaseEqualsASCII(item_type_str, kHostedAppType))
48     return extensions::Manifest::TYPE_HOSTED_APP;
49
50   return extensions::Manifest::TYPE_UNKNOWN;
51 }
52
53 }  // namespace
54
55 WebstoreProvider::WebstoreProvider(Profile* profile,
56                                    AppListControllerDelegate* controller)
57   :  WebserviceSearchProvider(profile),
58      controller_(controller){}
59
60 WebstoreProvider::~WebstoreProvider() {}
61
62 void WebstoreProvider::Start(const base::string16& query) {
63   ClearResults();
64   if (!IsValidQuery(query)) {
65     query_.clear();
66     return;
67   }
68
69   query_ = base::UTF16ToUTF8(query);
70   const CacheResult result = cache_->Get(WebserviceCache::WEBSTORE, query_);
71   if (result.second) {
72     ProcessWebstoreSearchResults(result.second);
73     if (!webstore_search_fetched_callback_.is_null())
74       webstore_search_fetched_callback_.Run();
75     if (result.first == FRESH)
76       return;
77   }
78
79   if (!webstore_search_) {
80     webstore_search_.reset(new JSONResponseFetcher(
81         base::Bind(&WebstoreProvider::OnWebstoreSearchFetched,
82                    base::Unretained(this)),
83         profile_->GetRequestContext()));
84   }
85
86   StartThrottledQuery(base::Bind(&WebstoreProvider::StartQuery,
87                                  base::Unretained(this)));
88
89   // Add a placeholder result which when clicked will run the user's query in a
90   // browser. This placeholder is removed when the search results arrive.
91   Add(scoped_ptr<SearchResult>(
92       new SearchWebstoreResult(profile_, controller_, query_)));
93 }
94
95 void WebstoreProvider::Stop() {
96   if (webstore_search_)
97     webstore_search_->Stop();
98 }
99
100 void WebstoreProvider::StartQuery() {
101   // |query_| can be NULL when the query is scheduled but then canceled.
102   if (!webstore_search_ || query_.empty())
103     return;
104
105   webstore_search_->Start(extension_urls::GetWebstoreJsonSearchUrl(
106       query_, g_browser_process->GetApplicationLocale()));
107 }
108
109 void WebstoreProvider::OnWebstoreSearchFetched(
110     scoped_ptr<base::DictionaryValue> json) {
111   ProcessWebstoreSearchResults(json.get());
112   cache_->Put(WebserviceCache::WEBSTORE, query_, json.Pass());
113
114   if (!webstore_search_fetched_callback_.is_null())
115     webstore_search_fetched_callback_.Run();
116 }
117
118 void WebstoreProvider::ProcessWebstoreSearchResults(
119     const base::DictionaryValue* json) {
120   const base::ListValue* result_list = NULL;
121   if (!json ||
122       !json->GetList(kKeyResults, &result_list) ||
123       !result_list ||
124       result_list->empty()) {
125     return;
126   }
127
128   bool first_result = true;
129   for (base::ListValue::const_iterator it = result_list->begin();
130        it != result_list->end();
131        ++it) {
132     const base::DictionaryValue* dict;
133     if (!(*it)->GetAsDictionary(&dict))
134       continue;
135
136     scoped_ptr<SearchResult> result(CreateResult(*dict));
137     if (!result)
138       continue;
139
140     if (first_result) {
141       // Clears "search in webstore" place holder results.
142       ClearResults();
143       first_result = false;
144     }
145
146     Add(result.Pass());
147   }
148 }
149
150 scoped_ptr<SearchResult> WebstoreProvider::CreateResult(
151     const base::DictionaryValue& dict) {
152   scoped_ptr<SearchResult> result;
153
154   std::string app_id;
155   std::string localized_name;
156   std::string icon_url_string;
157   bool is_paid = false;
158   if (!dict.GetString(kKeyId, &app_id) ||
159       !dict.GetString(kKeyLocalizedName, &localized_name) ||
160       !dict.GetString(kKeyIconUrl, &icon_url_string) ||
161       !dict.GetBoolean(kKeyIsPaid, &is_paid)) {
162     return result.Pass();
163   }
164
165   GURL icon_url(icon_url_string);
166   if (!icon_url.is_valid())
167     return result.Pass();
168
169   std::string item_type_string;
170   dict.GetString(kKeyItemType, &item_type_string);
171   extensions::Manifest::Type item_type = ParseItemType(item_type_string);
172
173   result.reset(new WebstoreResult(profile_,
174                                   app_id,
175                                   localized_name,
176                                   icon_url,
177                                   is_paid,
178                                   item_type,
179                                   controller_));
180   return result.Pass();
181 }
182
183 }  // namespace app_list