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

Side by Side Diff: chrome/browser/ui/ash/launcher/chrome_launcher_controller_per_app.cc

Issue 12022002: Fixing activation states from the new launcher. Also adding a whole bunch of unit tests for the new… (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fixed problem with ASAN unittest Created 7 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/ash/launcher/chrome_launcher_controller_per_app.h" 5 #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller_per_app.h"
6 6
7 #include <vector> 7 #include <vector>
8 8
9 #include "ash/launcher/launcher_model.h" 9 #include "ash/launcher/launcher_model.h"
10 #include "ash/launcher/launcher_util.h" 10 #include "ash/launcher/launcher_util.h"
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
158 // Use the original profile as on chromeos we may get a temporary off the 158 // Use the original profile as on chromeos we may get a temporary off the
159 // record profile. 159 // record profile.
160 profile_ = ProfileManager::GetDefaultProfile()->GetOriginalProfile(); 160 profile_ = ProfileManager::GetDefaultProfile()->GetOriginalProfile();
161 161
162 app_sync_ui_state_ = AppSyncUIState::Get(profile_); 162 app_sync_ui_state_ = AppSyncUIState::Get(profile_);
163 if (app_sync_ui_state_) 163 if (app_sync_ui_state_)
164 app_sync_ui_state_->AddObserver(this); 164 app_sync_ui_state_->AddObserver(this);
165 } 165 }
166 166
167 model_->AddObserver(this); 167 model_->AddObserver(this);
168 BrowserList::AddObserver(this);
168 // TODO(stevenjb): Find a better owner for shell_window_controller_? 169 // TODO(stevenjb): Find a better owner for shell_window_controller_?
169 shell_window_controller_.reset(new ShellWindowLauncherController(this)); 170 shell_window_controller_.reset(new ShellWindowLauncherController(this));
170 app_tab_helper_.reset(new LauncherAppTabHelper(profile_)); 171 app_tab_helper_.reset(new LauncherAppTabHelper(profile_));
171 app_icon_loader_.reset(new LauncherAppIconLoader(profile_, this)); 172 app_icon_loader_.reset(new LauncherAppIconLoader(profile_, this));
172 173
173 notification_registrar_.Add(this, 174 notification_registrar_.Add(this,
174 chrome::NOTIFICATION_EXTENSION_LOADED, 175 chrome::NOTIFICATION_EXTENSION_LOADED,
175 content::Source<Profile>(profile_)); 176 content::Source<Profile>(profile_));
176 notification_registrar_.Add(this, 177 notification_registrar_.Add(this,
177 chrome::NOTIFICATION_EXTENSION_UNLOADED, 178 chrome::NOTIFICATION_EXTENSION_UNLOADED,
(...skipping 12 matching lines...) Expand all
190 base::Bind(&ChromeLauncherControllerPerApp:: 191 base::Bind(&ChromeLauncherControllerPerApp::
191 SetShelfAutoHideBehaviorFromPrefs, 192 SetShelfAutoHideBehaviorFromPrefs,
192 base::Unretained(this))); 193 base::Unretained(this)));
193 } 194 }
194 195
195 ChromeLauncherControllerPerApp::~ChromeLauncherControllerPerApp() { 196 ChromeLauncherControllerPerApp::~ChromeLauncherControllerPerApp() {
196 // Reset the shell window controller here since it has a weak pointer to this. 197 // Reset the shell window controller here since it has a weak pointer to this.
197 shell_window_controller_.reset(); 198 shell_window_controller_.reset();
198 199
199 model_->RemoveObserver(this); 200 model_->RemoveObserver(this);
201 BrowserList::RemoveObserver(this);
200 for (IDToItemControllerMap::iterator i = id_to_item_controller_map_.begin(); 202 for (IDToItemControllerMap::iterator i = id_to_item_controller_map_.begin();
201 i != id_to_item_controller_map_.end(); ++i) { 203 i != id_to_item_controller_map_.end(); ++i) {
202 i->second->OnRemoved(); 204 i->second->OnRemoved();
203 // TODO(skuhne): After getting rid of the old launcher, get also rid of the 205 // TODO(skuhne): After getting rid of the old launcher, get also rid of the
204 // BrowserLauncherItemController (since it is only used for activation 206 // BrowserLauncherItemController (since it is only used for activation
205 // tracking at that point. 207 // tracking at that point.
206 int index = model_->ItemIndexByID(i->first); 208 int index = model_->ItemIndexByID(i->first);
207 // A "browser proxy" is not known to the model and this removal does 209 // A "browser proxy" is not known to the model and this removal does
208 // therefore not need to be propagated to the model. 210 // therefore not need to be propagated to the model.
209 if (index != -1) 211 if (index != -1)
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
278 // Since ordinary browser windows are not registered, we might get a negative 280 // Since ordinary browser windows are not registered, we might get a negative
279 // index here. 281 // index here.
280 if (index >= 0) { 282 if (index >= 0) {
281 ash::LauncherItem item = model_->items()[index]; 283 ash::LauncherItem item = model_->items()[index];
282 item.status = status; 284 item.status = status;
283 model_->Set(index, item); 285 model_->Set(index, item);
284 286
285 if (model_->items()[index].type == ash::TYPE_BROWSER_SHORTCUT) 287 if (model_->items()[index].type == ash::TYPE_BROWSER_SHORTCUT)
286 return; 288 return;
287 } 289 }
288 // Determine the new browser's active state and change if necessary. 290 UpdateBrowserItemStatus();
289 int browser_index = ash::launcher::GetBrowserItemIndex(*model_);
290 DCHECK(browser_index >= 0);
291 ash::LauncherItem browser_item = model_->items()[browser_index];
292 ash::LauncherItemStatus browser_status = browser_item.status;
293 // See if the active window is a browser.
294 if (chrome::FindBrowserWithWindow(ash::wm::GetActiveWindow())) {
295 browser_status = ash::STATUS_ACTIVE;
296 } else if (!BrowserList::empty()) {
297 browser_status = ash::STATUS_RUNNING;
298 } else {
299 browser_status = ash::STATUS_CLOSED;
300 }
301 if (browser_status != browser_item.status) {
302 browser_item.status = browser_status;
303 model_->Set(browser_index, browser_item);
304 }
305 } 291 }
306 292
307 void ChromeLauncherControllerPerApp::SetItemController( 293 void ChromeLauncherControllerPerApp::SetItemController(
308 ash::LauncherID id, 294 ash::LauncherID id,
309 LauncherItemController* controller) { 295 LauncherItemController* controller) {
310 IDToItemControllerMap::iterator iter = id_to_item_controller_map_.find(id); 296 IDToItemControllerMap::iterator iter = id_to_item_controller_map_.find(id);
311 DCHECK(iter != id_to_item_controller_map_.end()); 297 DCHECK(iter != id_to_item_controller_map_.end());
312 iter->second->OnRemoved(); 298 iter->second->OnRemoved();
313 iter->second = controller; 299 iter->second = controller;
314 controller->set_launcher_id(id); 300 controller->set_launcher_id(id);
(...skipping 11 matching lines...) Expand all
326 iter->second->set_launcher_id(id); 312 iter->second->set_launcher_id(id);
327 } else { 313 } else {
328 LauncherItemClosed(id); 314 LauncherItemClosed(id);
329 } 315 }
330 } 316 }
331 317
332 void ChromeLauncherControllerPerApp::Pin(ash::LauncherID id) { 318 void ChromeLauncherControllerPerApp::Pin(ash::LauncherID id) {
333 DCHECK(HasItemController(id)); 319 DCHECK(HasItemController(id));
334 320
335 int index = model_->ItemIndexByID(id); 321 int index = model_->ItemIndexByID(id);
322 DCHECK_GE(index, 0);
323
336 ash::LauncherItem item = model_->items()[index]; 324 ash::LauncherItem item = model_->items()[index];
337 325
338 if (item.type != ash::TYPE_PLATFORM_APP) 326 if (item.type != ash::TYPE_PLATFORM_APP)
339 return; 327 return;
340 328
341 item.type = ash::TYPE_APP_SHORTCUT; 329 item.type = ash::TYPE_APP_SHORTCUT;
342 model_->Set(index, item); 330 model_->Set(index, item);
343 331
344 if (CanPin()) 332 if (CanPin())
345 PersistPinnedState(); 333 PersistPinnedState();
346 } 334 }
347 335
348 void ChromeLauncherControllerPerApp::Unpin(ash::LauncherID id) { 336 void ChromeLauncherControllerPerApp::Unpin(ash::LauncherID id) {
349 DCHECK(HasItemController(id)); 337 DCHECK(HasItemController(id));
350 338
351 LauncherItemController* controller = id_to_item_controller_map_[id]; 339 LauncherItemController* controller = id_to_item_controller_map_[id];
352 if (controller->type() == LauncherItemController::TYPE_APP) { 340 if (controller->type() == LauncherItemController::TYPE_APP) {
353 int index = model_->ItemIndexByID(id); 341 int index = model_->ItemIndexByID(id);
342 DCHECK_GE(index, 0);
354 ash::LauncherItem item = model_->items()[index]; 343 ash::LauncherItem item = model_->items()[index];
355 item.type = ash::TYPE_PLATFORM_APP; 344 item.type = ash::TYPE_PLATFORM_APP;
356 model_->Set(index, item); 345 model_->Set(index, item);
357 } else { 346 } else {
358 LauncherItemClosed(id); 347 LauncherItemClosed(id);
359 } 348 }
360 if (CanPin()) 349 if (CanPin())
361 PersistPinnedState(); 350 PersistPinnedState();
362 } 351 }
363 352
364 bool ChromeLauncherControllerPerApp::IsPinned(ash::LauncherID id) { 353 bool ChromeLauncherControllerPerApp::IsPinned(ash::LauncherID id) {
365 int index = model_->ItemIndexByID(id); 354 int index = model_->ItemIndexByID(id);
355 if (index < 0)
356 return false;
366 ash::LauncherItemType type = model_->items()[index].type; 357 ash::LauncherItemType type = model_->items()[index].type;
367 return type == ash::TYPE_APP_SHORTCUT; 358 return type == ash::TYPE_APP_SHORTCUT;
368 } 359 }
369 360
370 void ChromeLauncherControllerPerApp::TogglePinned(ash::LauncherID id) { 361 void ChromeLauncherControllerPerApp::TogglePinned(ash::LauncherID id) {
371 if (!HasItemController(id)) 362 if (!HasItemController(id))
372 return; // May happen if item closed with menu open. 363 return; // May happen if item closed with menu open.
373 364
374 if (IsPinned(id)) 365 if (IsPinned(id))
375 Unpin(id); 366 Unpin(id);
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
450 } 441 }
451 442
452 // If there is an existing non-shortcut controller for this app, open it. 443 // If there is an existing non-shortcut controller for this app, open it.
453 ash::LauncherID id = GetLauncherIDForAppID(app_id); 444 ash::LauncherID id = GetLauncherIDForAppID(app_id);
454 if (id) { 445 if (id) {
455 LauncherItemController* controller = id_to_item_controller_map_[id]; 446 LauncherItemController* controller = id_to_item_controller_map_[id];
456 controller->Activate(); 447 controller->Activate();
457 return; 448 return;
458 } 449 }
459 450
460 // Otherwise launch the app. 451 // Create a temporary application launcher item and use it to see if there are
461 LaunchApp(app_id, event_flags); 452 // running instances.
453 scoped_ptr<AppShortcutLauncherItemController> app_controller(
454 new AppShortcutLauncherItemController(app_id, this));
455 if (!app_controller->GetRunningApplications().empty())
456 app_controller->Activate();
457 else
458 LaunchApp(app_id, event_flags);
462 } 459 }
463 460
464 extensions::ExtensionPrefs::LaunchType 461 extensions::ExtensionPrefs::LaunchType
465 ChromeLauncherControllerPerApp::GetLaunchType(ash::LauncherID id) { 462 ChromeLauncherControllerPerApp::GetLaunchType(ash::LauncherID id) {
466 DCHECK(HasItemController(id)); 463 DCHECK(HasItemController(id));
467 464
468 const Extension* extension = GetExtensionForAppID( 465 const Extension* extension = GetExtensionForAppID(
469 id_to_item_controller_map_[id]->app_id()); 466 id_to_item_controller_map_[id]->app_id());
470 return profile_->GetExtensionService()->extension_prefs()->GetLaunchType( 467 return profile_->GetExtensionService()->extension_prefs()->GetLaunchType(
471 extension, 468 extension,
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
506 continue; 503 continue;
507 504
508 // Panel items may share the same app_id as the app that created them, 505 // Panel items may share the same app_id as the app that created them,
509 // but they set their icon image in 506 // but they set their icon image in
510 // BrowserLauncherItemController::UpdateLauncher(), so do not set panel 507 // BrowserLauncherItemController::UpdateLauncher(), so do not set panel
511 // images here. 508 // images here.
512 if (i->second->type() == LauncherItemController::TYPE_EXTENSION_PANEL) 509 if (i->second->type() == LauncherItemController::TYPE_EXTENSION_PANEL)
513 continue; 510 continue;
514 511
515 int index = model_->ItemIndexByID(i->first); 512 int index = model_->ItemIndexByID(i->first);
513 if (index == -1)
514 continue;
516 ash::LauncherItem item = model_->items()[index]; 515 ash::LauncherItem item = model_->items()[index];
517 item.image = image; 516 item.image = image;
518 model_->Set(index, item); 517 model_->Set(index, item);
519 // It's possible we're waiting on more than one item, so don't break. 518 // It's possible we're waiting on more than one item, so don't break.
520 } 519 }
521 } 520 }
522 521
523 void ChromeLauncherControllerPerApp::SetLauncherItemImage( 522 void ChromeLauncherControllerPerApp::SetLauncherItemImage(
524 ash::LauncherID launcher_id, 523 ash::LauncherID launcher_id,
525 const gfx::ImageSkia& image) { 524 const gfx::ImageSkia& image) {
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after
687 std::string app_id = GetAppID(contents); 686 std::string app_id = GetAppID(contents);
688 687
689 // Check the old |app_id| for a tab. If the contents has changed we need to 688 // Check the old |app_id| for a tab. If the contents has changed we need to
690 // remove it from the previous app. 689 // remove it from the previous app.
691 if (web_contents_to_app_id_.find(contents) != web_contents_to_app_id_.end()) { 690 if (web_contents_to_app_id_.find(contents) != web_contents_to_app_id_.end()) {
692 std::string last_app_id = web_contents_to_app_id_[contents]; 691 std::string last_app_id = web_contents_to_app_id_[contents];
693 if (last_app_id != app_id) 692 if (last_app_id != app_id)
694 RemoveTabFromRunningApp(contents, last_app_id); 693 RemoveTabFromRunningApp(contents, last_app_id);
695 } 694 }
696 695
697 if (app_id.empty()) 696 if (app_id.empty()) {
697 // Even if there is no application running, we should update the activation
698 // state of the associated browser.
699 UpdateBrowserItemStatus();
698 return; 700 return;
701 }
699 702
700 web_contents_to_app_id_[contents] = app_id; 703 web_contents_to_app_id_[contents] = app_id;
701 704
702 if (app_state == APP_STATE_REMOVED) { 705 if (app_state == APP_STATE_REMOVED) {
703 // The tab has gone away. 706 // The tab has gone away.
704 RemoveTabFromRunningApp(contents, app_id); 707 RemoveTabFromRunningApp(contents, app_id);
705 } else { 708 } else {
706 WebContentsList& tab_list(app_id_to_web_contents_list_[app_id]); 709 WebContentsList& tab_list(app_id_to_web_contents_list_[app_id]);
707 710
708 if (app_state == APP_STATE_INACTIVE) { 711 if (app_state == APP_STATE_INACTIVE) {
(...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after
1010 Profile::FromBrowserContext(web_contents->GetBrowserContext()); 1013 Profile::FromBrowserContext(web_contents->GetBrowserContext());
1011 if (profile->IsOffTheRecord() && !profile->IsGuestSession()) { 1014 if (profile->IsOffTheRecord() && !profile->IsGuestSession()) {
1012 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); 1015 ResourceBundle& rb = ResourceBundle::GetSharedInstance();
1013 return rb.GetImageNamed(IDR_AURA_LAUNCHER_INCOGNITO_BROWSER); 1016 return rb.GetImageNamed(IDR_AURA_LAUNCHER_INCOGNITO_BROWSER);
1014 } 1017 }
1015 FaviconTabHelper* favicon_tab_helper = 1018 FaviconTabHelper* favicon_tab_helper =
1016 FaviconTabHelper::FromWebContents(web_contents); 1019 FaviconTabHelper::FromWebContents(web_contents);
1017 return favicon_tab_helper->GetFavicon(); 1020 return favicon_tab_helper->GetFavicon();
1018 } 1021 }
1019 1022
1023 void ChromeLauncherControllerPerApp::OnBrowserRemoved(Browser* browser) {
1024 // When called by a unit test it is possible that there is no shell.
1025 // In that case, the following function should not get called.
1026 if (ash::Shell::HasInstance())
1027 UpdateBrowserItemStatus();
1028 }
1029
1020 ash::LauncherID ChromeLauncherControllerPerApp::CreateAppShortcutLauncherItem( 1030 ash::LauncherID ChromeLauncherControllerPerApp::CreateAppShortcutLauncherItem(
1021 const std::string& app_id, 1031 const std::string& app_id,
1022 int index) { 1032 int index) {
1023 AppShortcutLauncherItemController* controller = 1033 AppShortcutLauncherItemController* controller =
1024 new AppShortcutLauncherItemController(app_id, this); 1034 new AppShortcutLauncherItemController(app_id, this);
1025 ash::LauncherID launcher_id = InsertAppLauncherItem( 1035 ash::LauncherID launcher_id = InsertAppLauncherItem(
1026 controller, app_id, ash::STATUS_CLOSED, index); 1036 controller, app_id, ash::STATUS_CLOSED, index);
1027 return launcher_id; 1037 return launcher_id;
1028 } 1038 }
1029 1039
1030 void ChromeLauncherControllerPerApp::SetAppTabHelperForTest( 1040 void ChromeLauncherControllerPerApp::SetAppTabHelperForTest(
1031 AppTabHelper* helper) { 1041 AppTabHelper* helper) {
1032 app_tab_helper_.reset(helper); 1042 app_tab_helper_.reset(helper);
1033 } 1043 }
1034 1044
1035 void ChromeLauncherControllerPerApp::SetAppIconLoaderForTest( 1045 void ChromeLauncherControllerPerApp::SetAppIconLoaderForTest(
1036 AppIconLoader* loader) { 1046 AppIconLoader* loader) {
1037 app_icon_loader_.reset(loader); 1047 app_icon_loader_.reset(loader);
1038 } 1048 }
1039 1049
1040 const std::string& 1050 const std::string&
1041 ChromeLauncherControllerPerApp::GetAppIdFromLauncherIdForTest( 1051 ChromeLauncherControllerPerApp::GetAppIdFromLauncherIdForTest(
1042 ash::LauncherID id) { 1052 ash::LauncherID id) {
1043 return id_to_item_controller_map_[id]->app_id(); 1053 return id_to_item_controller_map_[id]->app_id();
1044 } 1054 }
1045 1055
1056 void ChromeLauncherControllerPerApp::UpdateBrowserItemStatus() {
1057 // Determine the new browser's active state and change if necessary.
1058 int browser_index = ash::launcher::GetBrowserItemIndex(*model_);
1059 DCHECK(browser_index >= 0);
1060 ash::LauncherItem browser_item = model_->items()[browser_index];
1061 ash::LauncherItemStatus browser_status = browser_item.status;
1062 // See if the active window is a browser.
1063 aura::Window* window = ash::wm::GetActiveWindow();
1064 if (window && chrome::FindBrowserWithWindow(window)) {
1065 browser_status = ash::STATUS_ACTIVE;
1066 } else if (!BrowserList::empty()) {
1067 browser_status = ash::STATUS_RUNNING;
1068 } else {
1069 browser_status = ash::STATUS_CLOSED;
1070 }
1071 if (browser_status != browser_item.status) {
1072 browser_item.status = browser_status;
1073 model_->Set(browser_index, browser_item);
1074 }
1075 }
1076
1046 Profile* ChromeLauncherControllerPerApp::GetProfileForNewWindows() { 1077 Profile* ChromeLauncherControllerPerApp::GetProfileForNewWindows() {
1047 return ProfileManager::GetDefaultProfileOrOffTheRecord(); 1078 return ProfileManager::GetDefaultProfileOrOffTheRecord();
1048 } 1079 }
1049 1080
1050 void ChromeLauncherControllerPerApp::LauncherItemClosed(ash::LauncherID id) { 1081 void ChromeLauncherControllerPerApp::LauncherItemClosed(ash::LauncherID id) {
1051 IDToItemControllerMap::iterator iter = id_to_item_controller_map_.find(id); 1082 IDToItemControllerMap::iterator iter = id_to_item_controller_map_.find(id);
1052 DCHECK(iter != id_to_item_controller_map_.end()); 1083 DCHECK(iter != id_to_item_controller_map_.end());
1053 app_icon_loader_->ClearImage(iter->second->app_id()); 1084 app_icon_loader_->ClearImage(iter->second->app_id());
1054 iter->second->OnRemoved(); 1085 iter->second->OnRemoved();
1055 id_to_item_controller_map_.erase(iter); 1086 id_to_item_controller_map_.erase(iter);
(...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after
1300 WebContents* web_contents = 1331 WebContents* web_contents =
1301 tab_strip->GetWebContentsAt(tab_strip->active_index()); 1332 tab_strip->GetWebContentsAt(tab_strip->active_index());
1302 gfx::Image app_icon = GetAppListIcon(web_contents); 1333 gfx::Image app_icon = GetAppListIcon(web_contents);
1303 items->push_back(new ChromeLauncherAppMenuItemBrowser( 1334 items->push_back(new ChromeLauncherAppMenuItemBrowser(
1304 web_contents->GetTitle(), 1335 web_contents->GetTitle(),
1305 app_icon.IsEmpty() ? NULL : &app_icon, 1336 app_icon.IsEmpty() ? NULL : &app_icon,
1306 browser)); 1337 browser));
1307 } 1338 }
1308 return items; 1339 return items;
1309 } 1340 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698