OLD | NEW |
| (Empty) |
1 // Copyright (c) 2011 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/intents/web_intent_picker_controller.h" | |
6 | |
7 #include <vector> | |
8 | |
9 #include "chrome/browser/favicon/favicon_service.h" | |
10 #include "chrome/browser/intents/web_intent_data.h" | |
11 #include "chrome/browser/intents/web_intents_registry.h" | |
12 #include "chrome/browser/intents/web_intents_registry_factory.h" | |
13 #include "chrome/browser/profiles/profile.h" | |
14 #include "chrome/browser/ui/intents/web_intent_picker.h" | |
15 #include "chrome/browser/ui/intents/web_intent_picker_factory.h" | |
16 #include "chrome/browser/webdata/web_data_service.h" | |
17 #include "content/browser/tab_contents/tab_contents.h" | |
18 #include "content/common/notification_source.h" | |
19 #include "ui/gfx/codec/png_codec.h" | |
20 | |
21 namespace { | |
22 | |
23 // Gets the favicon service for the profile in |tab_contents|. | |
24 FaviconService* GetFaviconService(TabContents* tab_contents) { | |
25 Profile* profile = Profile::FromBrowserContext( | |
26 tab_contents->browser_context()); | |
27 return profile->GetFaviconService(Profile::EXPLICIT_ACCESS); | |
28 } | |
29 | |
30 // Gets the web intents registry for the profile in |tab_contents|. | |
31 WebIntentsRegistry* GetWebIntentsRegistry(TabContents* tab_contents) { | |
32 Profile* profile = Profile::FromBrowserContext( | |
33 tab_contents->browser_context()); | |
34 return WebIntentsRegistryFactory::GetForProfile(profile); | |
35 } | |
36 | |
37 } // namespace | |
38 | |
39 // A class that asynchronously fetches web intent data from the web intents | |
40 // registry. | |
41 class WebIntentPickerController::WebIntentDataFetcher | |
42 : public WebIntentsRegistry::Consumer { | |
43 public: | |
44 WebIntentDataFetcher(WebIntentPickerController* controller, | |
45 WebIntentsRegistry* web_intents_registry); | |
46 ~WebIntentDataFetcher(); | |
47 | |
48 // Asynchronously fetches WebIntentData for the given |action| |type| pair. | |
49 void Fetch(const string16& action, const string16& type); | |
50 | |
51 // Cancels the WebDataService request. | |
52 void Cancel(); | |
53 | |
54 private: | |
55 // WebIntentsRegistry::Consumer implementation. | |
56 virtual void OnIntentsQueryDone( | |
57 WebIntentsRegistry::QueryID, | |
58 const std::vector<WebIntentData>& intents) OVERRIDE; | |
59 | |
60 // A weak pointer to the picker controller. | |
61 WebIntentPickerController* controller_; | |
62 | |
63 // A weak pointer to the web intents registry. | |
64 WebIntentsRegistry* web_intents_registry_; | |
65 | |
66 // The ID of the current web intents request. The value will be -1 if | |
67 // there is no request in flight. | |
68 WebIntentsRegistry::QueryID query_id_; | |
69 }; | |
70 | |
71 // A class that asynchronously fetches favicons for a vector of URLs. | |
72 class WebIntentPickerController::FaviconFetcher { | |
73 public: | |
74 FaviconFetcher(WebIntentPickerController* controller, | |
75 FaviconService *favicon_service); | |
76 ~FaviconFetcher(); | |
77 | |
78 // Asynchronously fetches favicons for the each URL in |urls|. | |
79 void Fetch(const std::vector<GURL>& urls); | |
80 | |
81 // Cancels all favicon requests. | |
82 void Cancel(); | |
83 | |
84 private: | |
85 // Callback called when a favicon is received. | |
86 void OnFaviconDataAvailable(FaviconService::Handle handle, | |
87 history::FaviconData favicon_data); | |
88 | |
89 // A weak pointer to the picker controller. | |
90 WebIntentPickerController* controller_; | |
91 | |
92 // A weak pointer to the favicon service. | |
93 FaviconService* favicon_service_; | |
94 | |
95 // The Consumer to handle asynchronous favicon requests. | |
96 CancelableRequestConsumerTSimple<size_t> load_consumer_; | |
97 | |
98 DISALLOW_COPY_AND_ASSIGN(FaviconFetcher); | |
99 }; | |
100 | |
101 WebIntentPickerController::WebIntentPickerController( | |
102 TabContents* tab_contents, | |
103 WebIntentPickerFactory* factory) | |
104 : tab_contents_(tab_contents), | |
105 picker_factory_(factory), | |
106 web_intent_data_fetcher_( | |
107 new WebIntentDataFetcher(this, | |
108 GetWebIntentsRegistry(tab_contents))), | |
109 favicon_fetcher_( | |
110 new FaviconFetcher(this, GetFaviconService(tab_contents))), | |
111 picker_(NULL), | |
112 pending_async_count_(0) { | |
113 NavigationController* controller = &tab_contents->controller(); | |
114 registrar_.Add(this, content::NOTIFICATION_LOAD_START, | |
115 Source<NavigationController>(controller)); | |
116 registrar_.Add(this, content::NOTIFICATION_TAB_CLOSING, | |
117 Source<NavigationController>(controller)); | |
118 } | |
119 | |
120 WebIntentPickerController::~WebIntentPickerController() { | |
121 } | |
122 | |
123 void WebIntentPickerController::ShowDialog(const string16& action, | |
124 const string16& type) { | |
125 if (picker_ != NULL) | |
126 return; | |
127 | |
128 picker_ = picker_factory_->Create(tab_contents_, this); | |
129 | |
130 // TODO(binji) Remove this check when there are implementations of the picker | |
131 // for windows and mac. | |
132 if (picker_ == NULL) | |
133 return; | |
134 | |
135 web_intent_data_fetcher_->Fetch(action, type); | |
136 } | |
137 | |
138 void WebIntentPickerController::Observe(int type, | |
139 const NotificationSource& source, | |
140 const NotificationDetails& details) { | |
141 DCHECK(type == content::NOTIFICATION_LOAD_START || | |
142 type == content::NOTIFICATION_TAB_CLOSING); | |
143 ClosePicker(); | |
144 } | |
145 | |
146 void WebIntentPickerController::OnServiceChosen(size_t index) { | |
147 DCHECK(index < urls_.size()); | |
148 | |
149 // TODO(binji) Send the chosen service back to the renderer. | |
150 LOG(INFO) << "Chose index: " << index << " url: " << urls_[index]; | |
151 ClosePicker(); | |
152 } | |
153 | |
154 void WebIntentPickerController::OnCancelled() { | |
155 // TODO(binji) Tell the renderer that the intent was cancelled. | |
156 ClosePicker(); | |
157 } | |
158 | |
159 void WebIntentPickerController::OnWebIntentDataAvailable( | |
160 const std::vector<WebIntentData>& intent_data) { | |
161 urls_.clear(); | |
162 for (size_t i = 0; i < intent_data.size(); ++i) { | |
163 urls_.push_back(intent_data[i].service_url); | |
164 } | |
165 | |
166 // Tell the picker to initialize N urls to the default favicon | |
167 picker_->SetServiceURLs(urls_); | |
168 favicon_fetcher_->Fetch(urls_); | |
169 pending_async_count_--; | |
170 } | |
171 | |
172 void WebIntentPickerController::OnFaviconDataAvailable( | |
173 size_t index, | |
174 const SkBitmap& icon_bitmap) { | |
175 picker_->SetServiceIcon(index, icon_bitmap); | |
176 pending_async_count_--; | |
177 } | |
178 | |
179 void WebIntentPickerController::OnFaviconDataUnavailable(size_t index) { | |
180 picker_->SetDefaultServiceIcon(index); | |
181 pending_async_count_--; | |
182 } | |
183 | |
184 void WebIntentPickerController::ClosePicker() { | |
185 if (picker_) { | |
186 picker_factory_->ClosePicker(picker_); | |
187 picker_ = NULL; | |
188 } | |
189 } | |
190 | |
191 WebIntentPickerController::WebIntentDataFetcher::WebIntentDataFetcher( | |
192 WebIntentPickerController* controller, | |
193 WebIntentsRegistry* web_intents_registry) | |
194 : controller_(controller), | |
195 web_intents_registry_(web_intents_registry), | |
196 query_id_(-1) { | |
197 } | |
198 | |
199 WebIntentPickerController::WebIntentDataFetcher::~WebIntentDataFetcher() { | |
200 } | |
201 | |
202 void WebIntentPickerController::WebIntentDataFetcher::Fetch( | |
203 const string16& action, | |
204 const string16& type) { | |
205 DCHECK(query_id_ == -1) << "Fetch already in process."; | |
206 controller_->pending_async_count_++; | |
207 query_id_ = web_intents_registry_->GetIntentProviders(action, this); | |
208 } | |
209 | |
210 void WebIntentPickerController::WebIntentDataFetcher::OnIntentsQueryDone( | |
211 WebIntentsRegistry::QueryID, | |
212 const std::vector<WebIntentData>& intents) { | |
213 controller_->OnWebIntentDataAvailable(intents); | |
214 query_id_ = -1; | |
215 } | |
216 | |
217 WebIntentPickerController::FaviconFetcher::FaviconFetcher( | |
218 WebIntentPickerController* controller, | |
219 FaviconService* favicon_service) | |
220 : controller_(controller), | |
221 favicon_service_(favicon_service) { | |
222 } | |
223 | |
224 WebIntentPickerController::FaviconFetcher::~FaviconFetcher() { | |
225 } | |
226 | |
227 void WebIntentPickerController::FaviconFetcher::Fetch( | |
228 const std::vector<GURL>& urls) { | |
229 if (!favicon_service_) | |
230 return; | |
231 | |
232 for (size_t index = 0; index < urls.size(); ++index) { | |
233 controller_->pending_async_count_++; | |
234 FaviconService::Handle handle = favicon_service_->GetFaviconForURL( | |
235 urls[index], | |
236 history::FAVICON, | |
237 &load_consumer_, | |
238 NewCallback(this, &WebIntentPickerController::FaviconFetcher:: | |
239 OnFaviconDataAvailable)); | |
240 load_consumer_.SetClientData(favicon_service_, handle, index); | |
241 } | |
242 } | |
243 | |
244 void WebIntentPickerController::FaviconFetcher::Cancel() { | |
245 load_consumer_.CancelAllRequests(); | |
246 } | |
247 | |
248 void WebIntentPickerController::FaviconFetcher::OnFaviconDataAvailable( | |
249 FaviconService::Handle handle, | |
250 history::FaviconData favicon_data) { | |
251 size_t index = load_consumer_.GetClientDataForCurrentRequest(); | |
252 if (favicon_data.is_valid()) { | |
253 SkBitmap icon_bitmap; | |
254 | |
255 if (gfx::PNGCodec::Decode(favicon_data.image_data->front(), | |
256 favicon_data.image_data->size(), | |
257 &icon_bitmap)) { | |
258 controller_->OnFaviconDataAvailable(index, icon_bitmap); | |
259 return; | |
260 } | |
261 } | |
262 | |
263 controller_->OnFaviconDataUnavailable(index); | |
264 } | |
OLD | NEW |