| OLD | NEW |
| 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/views/ash/launcher/chrome_launcher_controller.h" | 5 #include "chrome/browser/ui/views/ash/launcher/chrome_launcher_controller.h" |
| 6 | 6 |
| 7 #include <set> | 7 #include <set> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "ash/launcher/launcher_model.h" | 10 #include "ash/launcher/launcher_model.h" |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 57 } | 57 } |
| 58 | 58 |
| 59 // ChromeLauncherController ---------------------------------------------------- | 59 // ChromeLauncherController ---------------------------------------------------- |
| 60 | 60 |
| 61 // static | 61 // static |
| 62 ChromeLauncherController* ChromeLauncherController::instance_ = NULL; | 62 ChromeLauncherController* ChromeLauncherController::instance_ = NULL; |
| 63 | 63 |
| 64 ChromeLauncherController::ChromeLauncherController(Profile* profile, | 64 ChromeLauncherController::ChromeLauncherController(Profile* profile, |
| 65 ash::LauncherModel* model) | 65 ash::LauncherModel* model) |
| 66 : model_(model), | 66 : model_(model), |
| 67 profile_(profile) { | 67 profile_(profile), |
| 68 activation_client_(NULL) { |
| 68 if (!profile_) { | 69 if (!profile_) { |
| 69 // Use the original profile as on chromeos we may get a temporary off the | 70 // Use the original profile as on chromeos we may get a temporary off the |
| 70 // record profile. | 71 // record profile. |
| 71 profile_ = ProfileManager::GetDefaultProfile()->GetOriginalProfile(); | 72 profile_ = ProfileManager::GetDefaultProfile()->GetOriginalProfile(); |
| 72 } | 73 } |
| 73 instance_ = this; | 74 instance_ = this; |
| 74 model_->AddObserver(this); | 75 model_->AddObserver(this); |
| 75 ShellWindowRegistry::Get(profile_)->AddObserver(this); | 76 ShellWindowRegistry::Get(profile_)->AddObserver(this); |
| 76 app_icon_loader_.reset(new LauncherAppIconLoader(profile_, this)); | 77 app_icon_loader_.reset(new LauncherAppIconLoader(profile_, this)); |
| 77 | 78 |
| 78 notification_registrar_.Add(this, | 79 notification_registrar_.Add(this, |
| 79 chrome::NOTIFICATION_EXTENSION_LOADED, | 80 chrome::NOTIFICATION_EXTENSION_LOADED, |
| 80 content::Source<Profile>(profile_)); | 81 content::Source<Profile>(profile_)); |
| 81 notification_registrar_.Add(this, | 82 notification_registrar_.Add(this, |
| 82 chrome::NOTIFICATION_EXTENSION_UNLOADED, | 83 chrome::NOTIFICATION_EXTENSION_UNLOADED, |
| 83 content::Source<Profile>(profile_)); | 84 content::Source<Profile>(profile_)); |
| 84 pref_change_registrar_.Init(profile_->GetPrefs()); | 85 pref_change_registrar_.Init(profile_->GetPrefs()); |
| 85 pref_change_registrar_.Add(prefs::kPinnedLauncherApps, this); | 86 pref_change_registrar_.Add(prefs::kPinnedLauncherApps, this); |
| 86 } | 87 } |
| 87 | 88 |
| 88 ChromeLauncherController::~ChromeLauncherController() { | 89 ChromeLauncherController::~ChromeLauncherController() { |
| 89 ShellWindowRegistry::Get(profile_)->RemoveObserver(this); | 90 ShellWindowRegistry::Get(profile_)->RemoveObserver(this); |
| 90 model_->RemoveObserver(this); | 91 model_->RemoveObserver(this); |
| 91 for (IDToItemMap::iterator i = id_to_item_map_.begin(); | 92 for (IDToItemMap::iterator i = id_to_item_map_.begin(); |
| 92 i != id_to_item_map_.end(); ++i) { | 93 i != id_to_item_map_.end(); ++i) { |
| 93 model_->RemoveItemAt(model_->ItemIndexByID(i->first)); | 94 model_->RemoveItemAt(model_->ItemIndexByID(i->first)); |
| 94 } | 95 } |
| 95 if (instance_ == this) | 96 if (instance_ == this) |
| 96 instance_ = NULL; | 97 instance_ = NULL; |
| 98 if (activation_client_) |
| 99 activation_client_->RemoveObserver(this); |
| 100 |
| 101 for (WindowToIDMap::iterator i = window_to_id_map_.begin(); |
| 102 i != window_to_id_map_.end(); ++i) { |
| 103 i->first->RemoveObserver(this); |
| 104 } |
| 97 } | 105 } |
| 98 | 106 |
| 99 void ChromeLauncherController::Init() { | 107 void ChromeLauncherController::Init() { |
| 100 // TODO(xiyuan): Remove migration code and kUseDefaultPinnedApp after M20. | 108 // TODO(xiyuan): Remove migration code and kUseDefaultPinnedApp after M20. |
| 101 // Migration cases: | 109 // Migration cases: |
| 102 // - Users that unpin all apps: | 110 // - Users that unpin all apps: |
| 103 // - have default pinned apps | 111 // - have default pinned apps |
| 104 // - kUseDefaultPinnedApps set to false | 112 // - kUseDefaultPinnedApps set to false |
| 105 // Migrate them by setting an empty list for kPinnedLauncherApps. | 113 // Migrate them by setting an empty list for kPinnedLauncherApps. |
| 106 // | 114 // |
| (...skipping 19 matching lines...) Expand all Loading... |
| 126 if (ash::Shell::HasInstance()) { | 134 if (ash::Shell::HasInstance()) { |
| 127 std::string behavior_value( | 135 std::string behavior_value( |
| 128 profile_->GetPrefs()->GetString(prefs::kShelfAutoHideBehavior)); | 136 profile_->GetPrefs()->GetString(prefs::kShelfAutoHideBehavior)); |
| 129 ash::ShelfAutoHideBehavior behavior = | 137 ash::ShelfAutoHideBehavior behavior = |
| 130 ash::SHELF_AUTO_HIDE_BEHAVIOR_DEFAULT; | 138 ash::SHELF_AUTO_HIDE_BEHAVIOR_DEFAULT; |
| 131 if (behavior_value == ash::kShelfAutoHideBehaviorNever) | 139 if (behavior_value == ash::kShelfAutoHideBehaviorNever) |
| 132 behavior = ash::SHELF_AUTO_HIDE_BEHAVIOR_NEVER; | 140 behavior = ash::SHELF_AUTO_HIDE_BEHAVIOR_NEVER; |
| 133 else if (behavior_value == ash::kShelfAutoHideBehaviorAlways) | 141 else if (behavior_value == ash::kShelfAutoHideBehaviorAlways) |
| 134 behavior = ash::SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS; | 142 behavior = ash::SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS; |
| 135 ash::Shell::GetInstance()->SetShelfAutoHideBehavior(behavior); | 143 ash::Shell::GetInstance()->SetShelfAutoHideBehavior(behavior); |
| 144 activation_client_ = |
| 145 aura::client::GetActivationClient( |
| 146 ash::Shell::GetInstance()->GetPrimaryRootWindow()); |
| 147 activation_client_->AddObserver(this); |
| 136 } | 148 } |
| 137 } | 149 } |
| 138 | 150 |
| 139 ash::LauncherID ChromeLauncherController::CreateTabbedLauncherItem( | 151 ash::LauncherID ChromeLauncherController::CreateTabbedLauncherItem( |
| 140 BrowserLauncherItemController* controller, | 152 BrowserLauncherItemController* controller, |
| 141 IncognitoState is_incognito, | 153 IncognitoState is_incognito, |
| 142 ash::LauncherItemStatus status) { | 154 ash::LauncherItemStatus status) { |
| 143 ash::LauncherID id = model_->next_id(); | 155 ash::LauncherID id = model_->next_id(); |
| 144 DCHECK(id_to_item_map_.find(id) == id_to_item_map_.end()); | 156 DCHECK(id_to_item_map_.find(id) == id_to_item_map_.end()); |
| 145 id_to_item_map_[id].item_type = TYPE_TABBED_BROWSER; | 157 id_to_item_map_[id].item_type = TYPE_TABBED_BROWSER; |
| (...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 491 NOTREACHED() << "Unexpected pref change for " << pref_name; | 503 NOTREACHED() << "Unexpected pref change for " << pref_name; |
| 492 } | 504 } |
| 493 break; | 505 break; |
| 494 } | 506 } |
| 495 default: | 507 default: |
| 496 NOTREACHED() << "Unexpected notification type=" << type; | 508 NOTREACHED() << "Unexpected notification type=" << type; |
| 497 } | 509 } |
| 498 } | 510 } |
| 499 | 511 |
| 500 void ChromeLauncherController::OnShellWindowAdded(ShellWindow* shell_window) { | 512 void ChromeLauncherController::OnShellWindowAdded(ShellWindow* shell_window) { |
| 513 aura::Window* window = shell_window->GetNativeWindow(); |
| 514 ash::LauncherItemStatus status = |
| 515 ash::wm::IsActiveWindow(window) ? |
| 516 ash::STATUS_ACTIVE : ash::STATUS_RUNNING; |
| 517 window->AddObserver(this); |
| 501 const std::string app_id = shell_window->extension()->id(); | 518 const std::string app_id = shell_window->extension()->id(); |
| 502 for (IDToItemMap::const_iterator i = id_to_item_map_.begin(); | 519 for (IDToItemMap::const_iterator i = id_to_item_map_.begin(); |
| 503 i != id_to_item_map_.end(); ++i) { | 520 i != id_to_item_map_.end(); ++i) { |
| 504 if (i->second.app_id == app_id) { | 521 if (i->second.app_id == app_id) { |
| 505 SetItemStatus(i->first, ash::STATUS_RUNNING); | 522 window_to_id_map_[window] = i->first; |
| 523 SetItemStatus(i->first, status); |
| 506 return; | 524 return; |
| 507 } | 525 } |
| 508 } | 526 } |
| 509 CreateAppLauncherItem(NULL, app_id, ash::STATUS_RUNNING); | 527 ash::LauncherID id = CreateAppLauncherItem(NULL, app_id, status); |
| 528 window_to_id_map_[window] = id; |
| 510 } | 529 } |
| 511 | 530 |
| 512 void ChromeLauncherController::OnShellWindowRemoved(ShellWindow* shell_window) { | 531 void ChromeLauncherController::OnShellWindowRemoved(ShellWindow* shell_window) { |
| 513 const std::string app_id = shell_window->extension()->id(); | 532 // Window removal is handled in OnWindowRemovingFromRootWindow() below. |
| 514 ShellWindowRegistry* registry = ShellWindowRegistry::Get(profile_); | 533 } |
| 515 if (registry->GetShellWindowsForApp(app_id).size() > 0) | |
| 516 return; | |
| 517 | 534 |
| 518 for (IDToItemMap::const_iterator i = id_to_item_map_.begin(); | 535 void ChromeLauncherController::OnWindowActivated(aura::Window* active, |
| 519 i != id_to_item_map_.end(); ++i) { | 536 aura::Window* old_active) { |
| 520 if (i->second.app_id == app_id) { | 537 if (window_to_id_map_.find(old_active) != window_to_id_map_.end()) { |
| 521 int index = model_->ItemIndexByID(i->first); | 538 if (window_to_id_map_.find(active) != window_to_id_map_.end() && |
| 522 DCHECK_GE(index, 0); | 539 window_to_id_map_[old_active] == window_to_id_map_[active]) { |
| 523 ash::LauncherItem item = model_->items()[index]; | 540 // Old and new windows are for the same item. Don't change the status. |
| 524 if (item.type == ash::TYPE_APP_SHORTCUT) | |
| 525 SetItemStatus(i->first, ash::STATUS_CLOSED); | |
| 526 else | |
| 527 LauncherItemClosed(i->first); | |
| 528 return; | 541 return; |
| 529 } | 542 } |
| 543 SetItemStatus(window_to_id_map_[old_active], ash::STATUS_RUNNING); |
| 530 } | 544 } |
| 545 if (window_to_id_map_.find(active) != window_to_id_map_.end()) |
| 546 SetItemStatus(window_to_id_map_[active], ash::STATUS_ACTIVE); |
| 547 } |
| 548 |
| 549 void ChromeLauncherController::OnWindowRemovingFromRootWindow( |
| 550 aura::Window* window) { |
| 551 window->RemoveObserver(this); |
| 552 DCHECK(window_to_id_map_.find(window) != window_to_id_map_.end()); |
| 553 ash::LauncherID id = window_to_id_map_[window]; |
| 554 window_to_id_map_.erase(window); |
| 555 |
| 556 DCHECK(id_to_item_map_.find(id) != id_to_item_map_.end()); |
| 557 ShellWindowRegistry::ShellWindowSet remaining_windows = |
| 558 ShellWindowRegistry::Get(profile_)->GetShellWindowsForApp( |
| 559 id_to_item_map_[id].app_id); |
| 560 |
| 561 // We can't count on getting called before or after the ShellWindowRegistry. |
| 562 if (remaining_windows.size() > 1 || |
| 563 (remaining_windows.size() == 1 && |
| 564 (*remaining_windows.begin())->GetNativeWindow() != window)) { |
| 565 return; |
| 566 } |
| 567 |
| 568 // Close or remove item. |
| 569 int index = model_->ItemIndexByID(id); |
| 570 DCHECK_GE(index, 0); |
| 571 ash::LauncherItem item = model_->items()[index]; |
| 572 if (item.type == ash::TYPE_APP_SHORTCUT) |
| 573 SetItemStatus(id, ash::STATUS_CLOSED); |
| 574 else |
| 575 LauncherItemClosed(id); |
| 531 } | 576 } |
| 532 | 577 |
| 533 void ChromeLauncherController::PersistPinnedState() { | 578 void ChromeLauncherController::PersistPinnedState() { |
| 534 // It is a coding error to call PersistPinnedState() if the pinned apps are | 579 // It is a coding error to call PersistPinnedState() if the pinned apps are |
| 535 // not user-editable. The code should check earlier and not perform any | 580 // not user-editable. The code should check earlier and not perform any |
| 536 // modification actions that trigger persisting the state. | 581 // modification actions that trigger persisting the state. |
| 537 if (!CanPin()) { | 582 if (!CanPin()) { |
| 538 NOTREACHED() << "Can't pin but pinned state being updated"; | 583 NOTREACHED() << "Can't pin but pinned state being updated"; |
| 539 return; | 584 return; |
| 540 } | 585 } |
| (...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 725 } | 770 } |
| 726 model_->AddAt(index, item); | 771 model_->AddAt(index, item); |
| 727 | 772 |
| 728 if (!controller || controller->type() != | 773 if (!controller || controller->type() != |
| 729 BrowserLauncherItemController::TYPE_EXTENSION_PANEL) { | 774 BrowserLauncherItemController::TYPE_EXTENSION_PANEL) { |
| 730 if (item.status != ash::STATUS_IS_PENDING) | 775 if (item.status != ash::STATUS_IS_PENDING) |
| 731 app_icon_loader_->FetchImage(app_id); | 776 app_icon_loader_->FetchImage(app_id); |
| 732 } | 777 } |
| 733 return id; | 778 return id; |
| 734 } | 779 } |
| OLD | NEW |