Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(27)

Side by Side Diff: chrome/browser/ui/intents/web_intent_picker_controller.cc

Issue 9148032: [Web Intents] Refactor picker to use WebIntentPickerModel. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: vertical layout for views Created 8 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/ui/intents/web_intent_picker_controller.h" 5 #include "chrome/browser/ui/intents/web_intent_picker_controller.h"
6 6
7 #include <vector> 7 #include <vector>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/bind_helpers.h" 10 #include "base/bind_helpers.h"
11 #include "chrome/browser/ui/browser.h" 11 #include "chrome/browser/ui/browser.h"
12 #include "chrome/browser/favicon/favicon_service.h" 12 #include "chrome/browser/favicon/favicon_service.h"
13 #include "chrome/browser/intents/web_intents_registry.h" 13 #include "chrome/browser/intents/web_intents_registry.h"
14 #include "chrome/browser/intents/web_intents_registry_factory.h" 14 #include "chrome/browser/intents/web_intents_registry_factory.h"
15 #include "chrome/browser/profiles/profile.h" 15 #include "chrome/browser/profiles/profile.h"
16 #include "chrome/browser/tabs/tab_strip_model.h" 16 #include "chrome/browser/tabs/tab_strip_model.h"
17 #include "chrome/browser/ui/browser_navigator.h" 17 #include "chrome/browser/ui/browser_navigator.h"
18 #include "chrome/browser/ui/intents/web_intent_picker.h" 18 #include "chrome/browser/ui/intents/web_intent_picker.h"
19 #include "chrome/browser/ui/intents/web_intent_picker_factory.h" 19 #include "chrome/browser/ui/intents/web_intent_picker_model.h"
20 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" 20 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
21 #include "chrome/browser/webdata/web_data_service.h" 21 #include "chrome/browser/webdata/web_data_service.h"
22 #include "chrome/common/chrome_notification_types.h" 22 #include "chrome/common/chrome_notification_types.h"
23 #include "content/browser/intents/intent_injector.h" 23 #include "content/browser/intents/intent_injector.h"
24 #include "content/public/browser/notification_source.h" 24 #include "content/public/browser/notification_source.h"
25 #include "content/public/browser/web_contents.h" 25 #include "content/public/browser/web_contents.h"
26 #include "content/public/browser/web_intents_dispatcher.h" 26 #include "content/public/browser/web_intents_dispatcher.h"
27 #include "ui/gfx/codec/png_codec.h" 27 #include "ui/gfx/codec/png_codec.h"
28 #include "ui/gfx/image/image.h"
28 #include "webkit/glue/web_intent_service_data.h" 29 #include "webkit/glue/web_intent_service_data.h"
29 30
30 using content::NavigationController;
31 using content::WebContents;
32
33 namespace { 31 namespace {
34 32
35 // Gets the favicon service for the profile in |tab_contents|. 33 // Gets the favicon service for the profile in |tab_contents|.
36 FaviconService* GetFaviconService(TabContentsWrapper* wrapper) { 34 FaviconService* GetFaviconService(TabContentsWrapper* wrapper) {
37 return wrapper->profile()->GetFaviconService(Profile::EXPLICIT_ACCESS); 35 return wrapper->profile()->GetFaviconService(Profile::EXPLICIT_ACCESS);
38 } 36 }
39 37
40 // Gets the web intents registry for the profile in |tab_contents|. 38 // Gets the web intents registry for the profile in |tab_contents|.
41 WebIntentsRegistry* GetWebIntentsRegistry(TabContentsWrapper* wrapper) { 39 WebIntentsRegistry* GetWebIntentsRegistry(TabContentsWrapper* wrapper) {
42 return WebIntentsRegistryFactory::GetForProfile(wrapper->profile()); 40 return WebIntentsRegistryFactory::GetForProfile(wrapper->profile());
43 } 41 }
44 42
43 WebIntentPickerModel::Disposition ConvertDisposition(
44 webkit_glue::WebIntentServiceData::Disposition disposition) {
45 switch (disposition) {
46 case webkit_glue::WebIntentServiceData::DISPOSITION_INLINE:
47 return WebIntentPickerModel::DISPOSITION_INLINE;
48 case webkit_glue::WebIntentServiceData::DISPOSITION_WINDOW:
49 return WebIntentPickerModel::DISPOSITION_WINDOW;
50 default:
51 NOTREACHED();
52 return WebIntentPickerModel::DISPOSITION_WINDOW;
53 }
54 }
55
45 } // namespace 56 } // namespace
46 57
47 // A class that asynchronously fetches web intent data from the web intents 58 // A class that asynchronously fetches web intent data from the web intents
48 // registry. 59 // registry.
49 class WebIntentPickerController::WebIntentDataFetcher 60 class WebIntentPickerController::WebIntentDataFetcher
50 : public WebIntentsRegistry::Consumer { 61 : public WebIntentsRegistry::Consumer {
51 public: 62 public:
52 WebIntentDataFetcher(WebIntentPickerController* controller, 63 WebIntentDataFetcher(WebIntentPickerController* controller,
53 WebIntentsRegistry* web_intents_registry); 64 WebIntentsRegistry* web_intents_registry);
54 ~WebIntentDataFetcher(); 65 ~WebIntentDataFetcher();
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
101 // A weak pointer to the favicon service. 112 // A weak pointer to the favicon service.
102 FaviconService* favicon_service_; 113 FaviconService* favicon_service_;
103 114
104 // The Consumer to handle asynchronous favicon requests. 115 // The Consumer to handle asynchronous favicon requests.
105 CancelableRequestConsumerTSimple<size_t> load_consumer_; 116 CancelableRequestConsumerTSimple<size_t> load_consumer_;
106 117
107 DISALLOW_COPY_AND_ASSIGN(FaviconFetcher); 118 DISALLOW_COPY_AND_ASSIGN(FaviconFetcher);
108 }; 119 };
109 120
110 WebIntentPickerController::WebIntentPickerController( 121 WebIntentPickerController::WebIntentPickerController(
111 TabContentsWrapper* wrapper, 122 TabContentsWrapper* wrapper)
112 WebIntentPickerFactory* factory)
113 : wrapper_(wrapper), 123 : wrapper_(wrapper),
groby-ooo-7-16 2012/01/25 22:03:13 nit: Shouldn't this only be indented 4 spaces?
binji 2012/01/26 00:27:41 Looks like you're right. The line-wrap rules are t
114 picker_factory_(factory),
115 web_intent_data_fetcher_( 124 web_intent_data_fetcher_(
116 new WebIntentDataFetcher(this, 125 new WebIntentDataFetcher(this,
117 GetWebIntentsRegistry(wrapper))), 126 GetWebIntentsRegistry(wrapper))),
118 favicon_fetcher_( 127 favicon_fetcher_(
119 new FaviconFetcher(this, GetFaviconService(wrapper))), 128 new FaviconFetcher(this, GetFaviconService(wrapper))),
120 picker_(NULL), 129 picker_(NULL),
130 picker_model_(new WebIntentPickerModel()),
121 pending_async_count_(0), 131 pending_async_count_(0),
132 picker_shown_(false),
122 service_tab_(NULL) { 133 service_tab_(NULL) {
123 NavigationController* controller = &wrapper->web_contents()->GetController(); 134 content::NavigationController* controller =
135 &wrapper->web_contents()->GetController();
124 registrar_.Add(this, content::NOTIFICATION_LOAD_START, 136 registrar_.Add(this, content::NOTIFICATION_LOAD_START,
125 content::Source<NavigationController>(controller)); 137 content::Source<content::NavigationController>(controller));
126 registrar_.Add(this, content::NOTIFICATION_TAB_CLOSING, 138 registrar_.Add(this, content::NOTIFICATION_TAB_CLOSING,
127 content::Source<NavigationController>(controller)); 139 content::Source<content::NavigationController>(controller));
128 } 140 }
129 141
130 WebIntentPickerController::~WebIntentPickerController() { 142 WebIntentPickerController::~WebIntentPickerController() {
131 } 143 }
132 144
133 void WebIntentPickerController::SetIntentsDispatcher( 145 void WebIntentPickerController::SetIntentsDispatcher(
134 content::WebIntentsDispatcher* intents_dispatcher) { 146 content::WebIntentsDispatcher* intents_dispatcher) {
135 intents_dispatcher_.reset(intents_dispatcher); 147 intents_dispatcher_.reset(intents_dispatcher);
136 intents_dispatcher_->RegisterReplyNotification( 148 intents_dispatcher_->RegisterReplyNotification(
137 base::Bind(&WebIntentPickerController::OnSendReturnMessage, 149 base::Bind(&WebIntentPickerController::OnSendReturnMessage,
138 base::Unretained(this))); 150 base::Unretained(this)));
139 } 151 }
140 152
141 void WebIntentPickerController::ShowDialog(Browser* browser, 153 void WebIntentPickerController::ShowDialog(Browser* browser,
142 const string16& action, 154 const string16& action,
143 const string16& type) { 155 const string16& type) {
144 if (picker_ != NULL) 156 // Only show a picker once.
157 if (picker_shown_)
145 return; 158 return;
146 159
147 picker_ = picker_factory_->Create(browser, wrapper_, this); 160 picker_model_->Clear();
148 161
149 // TODO(binji) Remove this check when there are implementations of the picker 162 // If picker is non-NULL, it was set by a test.
150 // for windows and mac. 163 if (picker_ == NULL) {
151 if (picker_ == NULL) 164 picker_ = WebIntentPicker::Create(browser, wrapper_, this,
152 return; 165 picker_model_.get());
166 }
153 167
168 picker_shown_ = true;
154 web_intent_data_fetcher_->Fetch(action, type); 169 web_intent_data_fetcher_->Fetch(action, type);
155 } 170 }
156 171
157 void WebIntentPickerController::Observe( 172 void WebIntentPickerController::Observe(
158 int type, 173 int type,
159 const content::NotificationSource& source, 174 const content::NotificationSource& source,
160 const content::NotificationDetails& details) { 175 const content::NotificationDetails& details) {
161 DCHECK(type == content::NOTIFICATION_LOAD_START || 176 DCHECK(type == content::NOTIFICATION_LOAD_START ||
162 type == content::NOTIFICATION_TAB_CLOSING); 177 type == content::NOTIFICATION_TAB_CLOSING);
163 ClosePicker(); 178 ClosePicker();
164 } 179 }
165 180
166 void WebIntentPickerController::OnServiceChosen(size_t index) { 181 void WebIntentPickerController::OnServiceChosen(size_t index,
167 DCHECK(index < urls_.size()); 182 Disposition disposition) {
183 switch (disposition) {
184 case WebIntentPickerModel::DISPOSITION_INLINE:
185 // Set the model to inline disposition. It will notify the picker which
186 // will respond (via OnInlineDispositionWebContentsCreated) with the
187 // WebContents to dispatch the intent to.
188 picker_model_->SetInlineDisposition(index);
189 break;
168 190
169 bool inline_disposition = service_data_[index].disposition == 191 case WebIntentPickerModel::DISPOSITION_WINDOW: {
170 webkit_glue::WebIntentServiceData::DISPOSITION_INLINE; 192 // TODO(gbillock): This really only handles the 'window' disposition in a
171 WebContents* new_web_contents = NULL; 193 // quite prototype way. We need to flesh out what happens to the picker
172 if (inline_disposition) 194 // during the lifetime of the service url context, and that may mean we
173 new_web_contents = picker_->SetInlineDisposition(urls_[index]); 195 // need to pass more information into the injector to find the picker
196 // again and close it.
197 const WebIntentPickerModel::Item& item = picker_model_->GetItemAt(index);
174 198
175 if (new_web_contents == NULL) { 199 browser::NavigateParams params(NULL, item.url,
176 // TODO(gbillock): This really only handles the 'window' disposition in a 200 content::PAGE_TRANSITION_AUTO_BOOKMARK);
177 // quite prototype way. We need to flesh out what happens to the picker 201 params.disposition = NEW_FOREGROUND_TAB;
178 // during the lifetime of the service url context, and that may mean we 202 params.profile = wrapper_->profile();
179 // need to pass more information into the injector to find the picker again 203 browser::Navigate(&params);
180 // and close it. Also: the above conditional construction is just because 204 content::WebContents* web_contents =
181 // there isn't Mac/Win support yet. When that's there, it'll be an else. 205 params.target_contents->web_contents();
182 browser::NavigateParams params(NULL, urls_[index], 206 service_tab_ = web_contents;
183 content::PAGE_TRANSITION_AUTO_BOOKMARK);
184 params.disposition = NEW_FOREGROUND_TAB;
185 params.profile = wrapper_->profile();
186 browser::Navigate(&params);
187 new_web_contents = params.target_contents->web_contents();
188 service_tab_ = new_web_contents;
189 207
190 ClosePicker(); 208 ClosePicker();
209
210 intents_dispatcher_->DispatchIntent(web_contents);
211 break;
212 }
213
214 default:
215 NOTREACHED();
216 break;
191 } 217 }
218 }
192 219
193 intents_dispatcher_->DispatchIntent(new_web_contents); 220 void WebIntentPickerController::OnInlineDispositionWebContentsCreated(
221 content::WebContents* web_contents) {
222 if (web_contents) {
223 intents_dispatcher_->DispatchIntent(web_contents);
224 } else {
225 // TODO(binji): tab_contents should never be NULL; it is in this case
groby-ooo-7-16 2012/01/25 22:03:13 nit: web_contens
binji 2012/01/26 00:27:41 Done.
226 // because views doesn't have an implementation for inline disposition yet.
227 // Remove this else when it does. In the meantime, just reforward as if it
228 // were the window disposition.
229 OnServiceChosen(picker_model_->inline_disposition_index(),
230 WebIntentPickerModel::DISPOSITION_WINDOW);
231 }
194 } 232 }
195 233
196 void WebIntentPickerController::OnCancelled() { 234 void WebIntentPickerController::OnCancelled() {
197 if (!intents_dispatcher_.get()) 235 if (!intents_dispatcher_.get())
198 return; 236 return;
199 237
200 if (service_tab_) { 238 if (service_tab_) {
201 intents_dispatcher_->SendReplyMessage( 239 intents_dispatcher_->SendReplyMessage(
202 webkit_glue::WEB_INTENT_SERVICE_TAB_CLOSED, string16()); 240 webkit_glue::WEB_INTENT_SERVICE_TAB_CLOSED, string16());
203 } else { 241 } else {
204 intents_dispatcher_->SendReplyMessage( 242 intents_dispatcher_->SendReplyMessage(
205 webkit_glue::WEB_INTENT_PICKER_CANCELLED, string16()); 243 webkit_glue::WEB_INTENT_PICKER_CANCELLED, string16());
206 } 244 }
207 245
208 ClosePicker(); 246 ClosePicker();
209 } 247 }
210 248
211 void WebIntentPickerController::OnClosing() { 249 void WebIntentPickerController::OnClosing() {
250 picker_shown_ = false;
251 picker_ = NULL;
212 } 252 }
213 253
214 void WebIntentPickerController::OnSendReturnMessage() { 254 void WebIntentPickerController::OnSendReturnMessage() {
215 ClosePicker(); 255 ClosePicker();
216 256
217 if (service_tab_) { 257 if (service_tab_) {
218 int index = TabStripModel::kNoTab; 258 int index = TabStripModel::kNoTab;
219 Browser* browser = Browser::GetBrowserForController( 259 Browser* browser = Browser::GetBrowserForController(
220 &service_tab_->GetController(), &index); 260 &service_tab_->GetController(), &index);
221 if (browser) { 261 if (browser) {
222 browser->tabstrip_model()->CloseTabContentsAt( 262 browser->tabstrip_model()->CloseTabContentsAt(
223 index, TabStripModel::CLOSE_CREATE_HISTORICAL_TAB); 263 index, TabStripModel::CLOSE_CREATE_HISTORICAL_TAB);
224 } 264 }
225 service_tab_ = NULL; 265 service_tab_ = NULL;
226 } 266 }
227 } 267 }
228 268
229 void WebIntentPickerController::OnWebIntentDataAvailable( 269 void WebIntentPickerController::OnWebIntentDataAvailable(
230 const std::vector<webkit_glue::WebIntentServiceData>& services) { 270 const std::vector<webkit_glue::WebIntentServiceData>& services) {
231 urls_.clear(); 271 std::vector<GURL> urls;
232 for (size_t i = 0; i < services.size(); ++i) { 272 for (size_t i = 0; i < services.size(); ++i) {
233 urls_.push_back(services[i].service_url); 273 picker_model_->AddItem(services[i].title, services[i].service_url,
274 ConvertDisposition(services[i].disposition));
275 urls.push_back(services[i].service_url);
234 } 276 }
235 service_data_ = services;
236 277
237 // Tell the picker to initialize N urls to the default favicon 278 // Tell the picker to initialize N urls to the default favicon
238 picker_->SetServiceURLs(urls_); 279 favicon_fetcher_->Fetch(urls);
239 favicon_fetcher_->Fetch(urls_);
240 pending_async_count_--; 280 pending_async_count_--;
241 } 281 }
242 282
243 void WebIntentPickerController::OnFaviconDataAvailable( 283 void WebIntentPickerController::OnFaviconDataAvailable(size_t index,
244 size_t index, 284 const gfx::Image& icon) {
245 const SkBitmap& icon_bitmap) { 285 picker_model_->UpdateFaviconAt(index, icon);
246 picker_->SetServiceIcon(index, icon_bitmap);
247 pending_async_count_--; 286 pending_async_count_--;
248 } 287 }
249 288
250 void WebIntentPickerController::OnFaviconDataUnavailable(size_t index) { 289 void WebIntentPickerController::OnFaviconDataUnavailable(size_t index) {
251 picker_->SetDefaultServiceIcon(index);
252 pending_async_count_--; 290 pending_async_count_--;
253 } 291 }
254 292
255 void WebIntentPickerController::ClosePicker() { 293 void WebIntentPickerController::ClosePicker() {
256 if (picker_) { 294 if (picker_) {
257 picker_factory_->ClosePicker(picker_); 295 picker_->Close();
258 picker_ = NULL;
259 } 296 }
260 } 297 }
261 298
262 WebIntentPickerController::WebIntentDataFetcher::WebIntentDataFetcher( 299 WebIntentPickerController::WebIntentDataFetcher::WebIntentDataFetcher(
263 WebIntentPickerController* controller, 300 WebIntentPickerController* controller,
264 WebIntentsRegistry* web_intents_registry) 301 WebIntentsRegistry* web_intents_registry)
265 : controller_(controller), 302 : controller_(controller),
266 web_intents_registry_(web_intents_registry), 303 web_intents_registry_(web_intents_registry),
267 query_id_(-1) { 304 query_id_(-1) {
268 } 305 }
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
320 void WebIntentPickerController::FaviconFetcher::OnFaviconDataAvailable( 357 void WebIntentPickerController::FaviconFetcher::OnFaviconDataAvailable(
321 FaviconService::Handle handle, 358 FaviconService::Handle handle,
322 history::FaviconData favicon_data) { 359 history::FaviconData favicon_data) {
323 size_t index = load_consumer_.GetClientDataForCurrentRequest(); 360 size_t index = load_consumer_.GetClientDataForCurrentRequest();
324 if (favicon_data.is_valid()) { 361 if (favicon_data.is_valid()) {
325 SkBitmap icon_bitmap; 362 SkBitmap icon_bitmap;
326 363
327 if (gfx::PNGCodec::Decode(favicon_data.image_data->front(), 364 if (gfx::PNGCodec::Decode(favicon_data.image_data->front(),
328 favicon_data.image_data->size(), 365 favicon_data.image_data->size(),
329 &icon_bitmap)) { 366 &icon_bitmap)) {
330 controller_->OnFaviconDataAvailable(index, icon_bitmap); 367 gfx::Image icon_image(new SkBitmap(icon_bitmap));
368 controller_->OnFaviconDataAvailable(index, icon_image);
331 return; 369 return;
332 } 370 }
333 } 371 }
334 372
335 controller_->OnFaviconDataUnavailable(index); 373 controller_->OnFaviconDataUnavailable(index);
336 } 374 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698