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

Unified Diff: chrome/browser/ui/ash/launcher/chrome_launcher_controller_per_app.cc

Issue 22887015: Remove PerBrowser launcher (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix nit Created 7 years, 4 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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/ui/ash/launcher/chrome_launcher_controller_per_app.cc
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_per_app.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_per_app.cc
deleted file mode 100644
index 3137581a8ca5aba5c2b41e2a2de9ce09bbfdfe7d..0000000000000000000000000000000000000000
--- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_per_app.cc
+++ /dev/null
@@ -1,1678 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ui/ash/launcher/chrome_launcher_controller_per_app.h"
-
-#include <vector>
-
-#include "ash/ash_switches.h"
-#include "ash/launcher/launcher.h"
-#include "ash/launcher/launcher_model.h"
-#include "ash/launcher/launcher_util.h"
-#include "ash/root_window_controller.h"
-#include "ash/shelf/shelf_layout_manager.h"
-#include "ash/shelf/shelf_widget.h"
-#include "ash/shell.h"
-#include "ash/wm/window_util.h"
-#include "base/command_line.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/values.h"
-#include "chrome/browser/app_mode/app_mode_utils.h"
-#include "chrome/browser/chrome_notification_types.h"
-#include "chrome/browser/defaults.h"
-#include "chrome/browser/extensions/app_icon_loader_impl.h"
-#include "chrome/browser/extensions/extension_service.h"
-#include "chrome/browser/extensions/extension_system.h"
-#include "chrome/browser/favicon/favicon_tab_helper.h"
-#include "chrome/browser/prefs/incognito_mode_prefs.h"
-#include "chrome/browser/prefs/pref_service_syncable.h"
-#include "chrome/browser/prefs/scoped_user_pref_update.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/profiles/profile_manager.h"
-#include "chrome/browser/ui/ash/app_sync_ui_state.h"
-#include "chrome/browser/ui/ash/chrome_launcher_prefs.h"
-#include "chrome/browser/ui/ash/launcher/app_shortcut_launcher_item_controller.h"
-#include "chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.h"
-#include "chrome/browser/ui/ash/launcher/chrome_launcher_app_menu_item.h"
-#include "chrome/browser/ui/ash/launcher/chrome_launcher_app_menu_item_browser.h"
-#include "chrome/browser/ui/ash/launcher/chrome_launcher_app_menu_item_tab.h"
-#include "chrome/browser/ui/ash/launcher/launcher_app_tab_helper.h"
-#include "chrome/browser/ui/ash/launcher/launcher_application_menu_item_model.h"
-#include "chrome/browser/ui/ash/launcher/launcher_context_menu.h"
-#include "chrome/browser/ui/ash/launcher/launcher_item_controller.h"
-#include "chrome/browser/ui/ash/launcher/shell_window_launcher_controller.h"
-#include "chrome/browser/ui/ash/launcher/shell_window_launcher_item_controller.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/browser_commands.h"
-#include "chrome/browser/ui/browser_finder.h"
-#include "chrome/browser/ui/browser_list.h"
-#include "chrome/browser/ui/browser_tabstrip.h"
-#include "chrome/browser/ui/browser_window.h"
-#include "chrome/browser/ui/extensions/application_launch.h"
-#include "chrome/browser/ui/extensions/extension_enable_flow.h"
-#include "chrome/browser/ui/host_desktop.h"
-#include "chrome/browser/ui/tabs/tab_strip_model.h"
-#include "chrome/browser/web_applications/web_app.h"
-#include "chrome/common/chrome_switches.h"
-#include "chrome/common/extensions/extension.h"
-#include "chrome/common/extensions/manifest_handlers/icons_handler.h"
-#include "chrome/common/pref_names.h"
-#include "chrome/common/url_constants.h"
-#include "content/public/browser/navigation_entry.h"
-#include "content/public/browser/notification_service.h"
-#include "content/public/browser/web_contents.h"
-#include "extensions/common/extension_resource.h"
-#include "extensions/common/url_pattern.h"
-#include "grit/ash_resources.h"
-#include "grit/chromium_strings.h"
-#include "grit/generated_resources.h"
-#include "grit/theme_resources.h"
-#include "grit/ui_resources.h"
-#include "ui/aura/root_window.h"
-#include "ui/aura/window.h"
-#include "ui/base/l10n/l10n_util.h"
-#include "ui/views/corewm/window_animations.h"
-
-#if defined(OS_CHROMEOS)
-#include "chrome/browser/chromeos/login/default_pinned_apps_field_trial.h"
-#endif
-
-using extensions::Extension;
-using extension_misc::kGmailAppId;
-using content::WebContents;
-
-namespace {
-
-std::string GetPrefKeyForRootWindow(aura::RootWindow* root_window) {
- gfx::Display display = gfx::Screen::GetScreenFor(
- root_window)->GetDisplayNearestWindow(root_window);
- DCHECK(display.is_valid());
-
- return base::Int64ToString(display.id());
-}
-
-void UpdatePerDisplayPref(PrefService* pref_service,
- aura::RootWindow* root_window,
- const char* pref_key,
- const std::string& value) {
- std::string key = GetPrefKeyForRootWindow(root_window);
- if (key.empty())
- return;
-
- DictionaryPrefUpdate update(pref_service, prefs::kShelfPreferences);
- base::DictionaryValue* shelf_prefs = update.Get();
- base::DictionaryValue* prefs = NULL;
- if (!shelf_prefs->GetDictionary(key, &prefs)) {
- prefs = new base::DictionaryValue();
- shelf_prefs->Set(key, prefs);
- }
- prefs->SetStringWithoutPathExpansion(pref_key, value);
-}
-
-// Returns a pref value in |pref_service| for the display of |root_window|. The
-// pref value is stored in |local_path| and |path|, but |pref_service| may have
-// per-display preferences and the value can be specified by policy. Here is
-// the priority:
-// * A value managed by policy. This is a single value that applies to all
-// displays.
-// * A user-set value for the specified display.
-// * A user-set value in |local_path| or |path|, if no per-display settings are
-// ever specified (see http://crbug.com/173719 for why). |local_path| is
-// preferred. See comment in |kShelfAlignment| as to why we consider two
-// prefs and why |local_path| is preferred.
-// * A value recommended by policy. This is a single value that applies to all
-// root windows.
-// * The default value for |local_path| if the value is not recommended by
-// policy.
-std::string GetPrefForRootWindow(PrefService* pref_service,
- aura::RootWindow* root_window,
- const char* local_path,
- const char* path) {
- const PrefService::Preference* local_pref =
- pref_service->FindPreference(local_path);
- const std::string value(pref_service->GetString(local_path));
- if (local_pref->IsManaged())
- return value;
-
- std::string pref_key = GetPrefKeyForRootWindow(root_window);
- bool has_per_display_prefs = false;
- if (!pref_key.empty()) {
- const base::DictionaryValue* shelf_prefs = pref_service->GetDictionary(
- prefs::kShelfPreferences);
- const base::DictionaryValue* display_pref = NULL;
- std::string per_display_value;
- if (shelf_prefs->GetDictionary(pref_key, &display_pref) &&
- display_pref->GetString(path, &per_display_value))
- return per_display_value;
-
- // If the pref for the specified display is not found, scan the whole prefs
- // and check if the prefs for other display is already specified.
- std::string unused_value;
- for (base::DictionaryValue::Iterator iter(*shelf_prefs);
- !iter.IsAtEnd(); iter.Advance()) {
- const base::DictionaryValue* display_pref = NULL;
- if (iter.value().GetAsDictionary(&display_pref) &&
- display_pref->GetString(path, &unused_value)) {
- has_per_display_prefs = true;
- break;
- }
- }
- }
-
- if (local_pref->IsRecommended() || !has_per_display_prefs)
- return value;
-
- const base::Value* default_value =
- pref_service->GetDefaultPrefValue(local_path);
- std::string default_string;
- default_value->GetAsString(&default_string);
- return default_string;
-}
-
-// If prefs have synced and no user-set value exists at |local_path|, the value
-// from |synced_path| is copied to |local_path|.
-void MaybePropagatePrefToLocal(PrefServiceSyncable* pref_service,
- const char* local_path,
- const char* synced_path) {
- if (!pref_service->FindPreference(local_path)->HasUserSetting() &&
- pref_service->IsSyncing()) {
- // First time the user is using this machine, propagate from remote to
- // local.
- pref_service->SetString(local_path, pref_service->GetString(synced_path));
- }
-}
-
-} // namespace
-
-ChromeLauncherControllerPerApp::ChromeLauncherControllerPerApp(
- Profile* profile,
- ash::LauncherModel* model)
- : model_(model),
- profile_(profile),
- app_sync_ui_state_(NULL),
- ignore_persist_pinned_state_change_(false) {
- if (!profile_) {
- // Use the original profile as on chromeos we may get a temporary off the
- // record profile.
- profile_ = ProfileManager::GetDefaultProfile()->GetOriginalProfile();
-
- app_sync_ui_state_ = AppSyncUIState::Get(profile_);
- if (app_sync_ui_state_)
- app_sync_ui_state_->AddObserver(this);
- }
-
- model_->AddObserver(this);
- BrowserList::AddObserver(this);
- // Right now ash::Shell isn't created for tests.
- // TODO(mukai): Allows it to observe display change and write tests.
- if (ash::Shell::HasInstance())
- ash::Shell::GetInstance()->display_controller()->AddObserver(this);
- // TODO(stevenjb): Find a better owner for shell_window_controller_?
- shell_window_controller_.reset(new ShellWindowLauncherController(this));
- app_tab_helper_.reset(new LauncherAppTabHelper(profile_));
- app_icon_loader_.reset(new extensions::AppIconLoaderImpl(
- profile_, extension_misc::EXTENSION_ICON_SMALL, this));
-
- notification_registrar_.Add(this,
- chrome::NOTIFICATION_EXTENSION_LOADED,
- content::Source<Profile>(profile_));
- notification_registrar_.Add(this,
- chrome::NOTIFICATION_EXTENSION_UNLOADED,
- content::Source<Profile>(profile_));
- pref_change_registrar_.Init(profile_->GetPrefs());
- pref_change_registrar_.Add(
- prefs::kPinnedLauncherApps,
- base::Bind(&ChromeLauncherControllerPerApp::UpdateAppLaunchersFromPref,
- base::Unretained(this)));
- pref_change_registrar_.Add(
- prefs::kShelfAlignmentLocal,
- base::Bind(&ChromeLauncherControllerPerApp::SetShelfAlignmentFromPrefs,
- base::Unretained(this)));
- pref_change_registrar_.Add(
- prefs::kShelfAutoHideBehaviorLocal,
- base::Bind(&ChromeLauncherControllerPerApp::
- SetShelfAutoHideBehaviorFromPrefs,
- base::Unretained(this)));
- pref_change_registrar_.Add(
- prefs::kShelfPreferences,
- base::Bind(&ChromeLauncherControllerPerApp::SetShelfBehaviorsFromPrefs,
- base::Unretained(this)));
-}
-
-ChromeLauncherControllerPerApp::~ChromeLauncherControllerPerApp() {
- // Reset the shell window controller here since it has a weak pointer to this.
- shell_window_controller_.reset();
-
- for (std::set<ash::Launcher*>::iterator iter = launchers_.begin();
- iter != launchers_.end();
- ++iter)
- (*iter)->shelf_widget()->shelf_layout_manager()->RemoveObserver(this);
-
- model_->RemoveObserver(this);
- BrowserList::RemoveObserver(this);
- if (ash::Shell::HasInstance())
- ash::Shell::GetInstance()->display_controller()->RemoveObserver(this);
- for (IDToItemControllerMap::iterator i = id_to_item_controller_map_.begin();
- i != id_to_item_controller_map_.end(); ++i) {
- i->second->OnRemoved();
- // TODO(skuhne): After getting rid of the old launcher, get also rid of the
- // BrowserLauncherItemController (since it is only used for activation
- // tracking at that point.
- int index = model_->ItemIndexByID(i->first);
- // A "browser proxy" is not known to the model and this removal does
- // therefore not need to be propagated to the model.
- if (index != -1 &&
- model_->items()[index].type != ash::TYPE_BROWSER_SHORTCUT)
- model_->RemoveItemAt(index);
- }
-
- if (ash::Shell::HasInstance())
- ash::Shell::GetInstance()->RemoveShellObserver(this);
-
- if (app_sync_ui_state_)
- app_sync_ui_state_->RemoveObserver(this);
-
- PrefServiceSyncable::FromProfile(profile_)->RemoveObserver(this);
-}
-
-void ChromeLauncherControllerPerApp::Init() {
- UpdateAppLaunchersFromPref();
- CreateBrowserShortcutLauncherItem();
-
- // TODO(sky): update unit test so that this test isn't necessary.
- if (ash::Shell::HasInstance()) {
- SetShelfAutoHideBehaviorFromPrefs();
- SetShelfAlignmentFromPrefs();
- PrefServiceSyncable* prefs = PrefServiceSyncable::FromProfile(profile_);
- if (!prefs->FindPreference(prefs::kShelfAlignmentLocal)->HasUserSetting() ||
- !prefs->FindPreference(prefs::kShelfAutoHideBehaviorLocal)->
- HasUserSetting()) {
- // This causes OnIsSyncingChanged to be called when the value of
- // PrefService::IsSyncing() changes.
- prefs->AddObserver(this);
- }
- ash::Shell::GetInstance()->AddShellObserver(this);
- }
-}
-
-ChromeLauncherControllerPerApp*
-ChromeLauncherControllerPerApp::GetPerAppInterface() {
- return this;
-}
-
-ash::LauncherID ChromeLauncherControllerPerApp::CreateTabbedLauncherItem(
- LauncherItemController* controller,
- IncognitoState is_incognito,
- ash::LauncherItemStatus status) {
- // The PerAppLauncher doesn't need an empty slot for TabbedLauncherItem and
- // its LauncherItemController.
- // TODO(skuhne): Remove function when PerBrowser launcher gets removed.
- return 0;
-}
-
-ash::LauncherID ChromeLauncherControllerPerApp::CreateAppLauncherItem(
- LauncherItemController* controller,
- const std::string& app_id,
- ash::LauncherItemStatus status) {
- CHECK(controller);
- int index = 0;
- // Panels are inserted on the left so as not to push all existing panels over.
- if (controller->GetLauncherItemType() != ash::TYPE_APP_PANEL) {
- index = model_->item_count();
- // For the alternate shelf layout increment the index (after the app icon)
- if (ash::switches::UseAlternateShelfLayout())
- ++index;
- }
- return InsertAppLauncherItem(controller,
- app_id,
- status,
- index,
- controller->GetLauncherItemType());
-}
-
-void ChromeLauncherControllerPerApp::SetItemStatus(
- ash::LauncherID id,
- ash::LauncherItemStatus status) {
- int index = model_->ItemIndexByID(id);
- // Since ordinary browser windows are not registered, we might get a negative
- // index here.
- if (index >= 0) {
- ash::LauncherItem item = model_->items()[index];
- item.status = status;
- model_->Set(index, item);
-
- if (model_->items()[index].type == ash::TYPE_BROWSER_SHORTCUT)
- return;
- }
- UpdateBrowserItemStatus();
-}
-
-void ChromeLauncherControllerPerApp::SetItemController(
- ash::LauncherID id,
- LauncherItemController* controller) {
- CHECK(controller);
- IDToItemControllerMap::iterator iter = id_to_item_controller_map_.find(id);
- CHECK(iter != id_to_item_controller_map_.end());
- iter->second->OnRemoved();
- iter->second = controller;
- controller->set_launcher_id(id);
-}
-
-void ChromeLauncherControllerPerApp::CloseLauncherItem(ash::LauncherID id) {
- CHECK(id);
- if (IsPinned(id)) {
- // Create a new shortcut controller.
- IDToItemControllerMap::iterator iter = id_to_item_controller_map_.find(id);
- CHECK(iter != id_to_item_controller_map_.end());
- SetItemStatus(id, ash::STATUS_CLOSED);
- std::string app_id = iter->second->app_id();
- iter->second->OnRemoved();
- iter->second = new AppShortcutLauncherItemController(app_id, this);
- iter->second->set_launcher_id(id);
- } else {
- LauncherItemClosed(id);
- }
-}
-
-void ChromeLauncherControllerPerApp::Pin(ash::LauncherID id) {
- DCHECK(HasItemController(id));
-
- int index = model_->ItemIndexByID(id);
- DCHECK_GE(index, 0);
-
- ash::LauncherItem item = model_->items()[index];
-
- if (item.type == ash::TYPE_PLATFORM_APP ||
- item.type == ash::TYPE_WINDOWED_APP) {
- item.type = ash::TYPE_APP_SHORTCUT;
- model_->Set(index, item);
- } else if (item.type != ash::TYPE_APP_SHORTCUT) {
- return;
- }
-
- if (CanPin())
- PersistPinnedState();
-}
-
-void ChromeLauncherControllerPerApp::Unpin(ash::LauncherID id) {
- DCHECK(HasItemController(id));
-
- LauncherItemController* controller = id_to_item_controller_map_[id];
- if (controller->type() == LauncherItemController::TYPE_APP) {
- int index = model_->ItemIndexByID(id);
- DCHECK_GE(index, 0);
- ash::LauncherItem item = model_->items()[index];
- item.type = ash::TYPE_PLATFORM_APP;
- model_->Set(index, item);
- } else {
- // Prevent the removal of items upon unpin if it is locked by a running
- // windowed V1 app.
- if (!controller->locked()) {
- LauncherItemClosed(id);
- } else {
- int index = model_->ItemIndexByID(id);
- DCHECK_GE(index, 0);
- ash::LauncherItem item = model_->items()[index];
- item.type = ash::TYPE_WINDOWED_APP;
- model_->Set(index, item);
- }
- }
- if (CanPin())
- PersistPinnedState();
-}
-
-bool ChromeLauncherControllerPerApp::IsPinned(ash::LauncherID id) {
- int index = model_->ItemIndexByID(id);
- if (index < 0)
- return false;
- ash::LauncherItemType type = model_->items()[index].type;
- return (type == ash::TYPE_APP_SHORTCUT || type == ash::TYPE_BROWSER_SHORTCUT);
-}
-
-void ChromeLauncherControllerPerApp::TogglePinned(ash::LauncherID id) {
- if (!HasItemController(id))
- return; // May happen if item closed with menu open.
-
- if (IsPinned(id))
- Unpin(id);
- else
- Pin(id);
-}
-
-bool ChromeLauncherControllerPerApp::IsPinnable(ash::LauncherID id) const {
- int index = model_->ItemIndexByID(id);
- if (index == -1)
- return false;
-
- ash::LauncherItemType type = model_->items()[index].type;
- return ((type == ash::TYPE_APP_SHORTCUT ||
- type == ash::TYPE_PLATFORM_APP ||
- type == ash::TYPE_WINDOWED_APP) &&
- CanPin());
-}
-
-void ChromeLauncherControllerPerApp::LockV1AppWithID(
- const std::string& app_id) {
- ash::LauncherID id = GetLauncherIDForAppID(app_id);
- if (!IsPinned(id) && !IsWindowedAppInLauncher(app_id)) {
- CreateAppShortcutLauncherItemWithType(app_id,
- model_->item_count(),
- ash::TYPE_WINDOWED_APP);
- id = GetLauncherIDForAppID(app_id);
- }
- CHECK(id);
- id_to_item_controller_map_[id]->lock();
-}
-
-void ChromeLauncherControllerPerApp::UnlockV1AppWithID(
- const std::string& app_id) {
- ash::LauncherID id = GetLauncherIDForAppID(app_id);
- CHECK(IsPinned(id) || IsWindowedAppInLauncher(app_id));
- CHECK(id);
- LauncherItemController* controller = id_to_item_controller_map_[id];
- controller->unlock();
- if (!controller->locked() && !IsPinned(id))
- CloseLauncherItem(id);
-}
-
-void ChromeLauncherControllerPerApp::Launch(ash::LauncherID id,
- int event_flags) {
- if (!HasItemController(id))
- return; // In case invoked from menu and item closed while menu up.
- id_to_item_controller_map_[id]->Launch(event_flags);
-}
-
-void ChromeLauncherControllerPerApp::Close(ash::LauncherID id) {
- if (!HasItemController(id))
- return; // May happen if menu closed.
- id_to_item_controller_map_[id]->Close();
-}
-
-bool ChromeLauncherControllerPerApp::IsOpen(ash::LauncherID id) {
- if (!HasItemController(id))
- return false;
- return id_to_item_controller_map_[id]->IsOpen();
-}
-
-bool ChromeLauncherControllerPerApp::IsPlatformApp(ash::LauncherID id) {
- if (!HasItemController(id))
- return false;
-
- std::string app_id = GetAppIDForLauncherID(id);
- const Extension* extension = GetExtensionForAppID(app_id);
- // An extension can be synced / updated at any time and therefore not be
- // available.
- return extension ? extension->is_platform_app() : false;
-}
-
-void ChromeLauncherControllerPerApp::LaunchApp(const std::string& app_id,
- int event_flags) {
- // |extension| could be NULL when it is being unloaded for updating.
- const Extension* extension = GetExtensionForAppID(app_id);
- if (!extension)
- return;
-
- const ExtensionService* service =
- extensions::ExtensionSystem::Get(profile_)->extension_service();
- if (!service->IsExtensionEnabledForLauncher(app_id)) {
- // Do nothing if there is already a running enable flow.
- if (extension_enable_flow_)
- return;
-
- extension_enable_flow_.reset(
- new ExtensionEnableFlow(profile_, app_id, this));
- extension_enable_flow_->StartForNativeWindow(NULL);
- return;
- }
-
- chrome::OpenApplication(chrome::AppLaunchParams(GetProfileForNewWindows(),
- extension,
- event_flags));
-}
-
-void ChromeLauncherControllerPerApp::ActivateApp(const std::string& app_id,
- int event_flags) {
- // If there is an existing non-shortcut controller for this app, open it.
- ash::LauncherID id = GetLauncherIDForAppID(app_id);
- if (id) {
- LauncherItemController* controller = id_to_item_controller_map_[id];
- controller->Activate();
- return;
- }
-
- // Create a temporary application launcher item and use it to see if there are
- // running instances.
- scoped_ptr<AppShortcutLauncherItemController> app_controller(
- new AppShortcutLauncherItemController(app_id, this));
- if (!app_controller->GetRunningApplications().empty())
- app_controller->Activate();
- else
- LaunchApp(app_id, event_flags);
-}
-
-extensions::ExtensionPrefs::LaunchType
- ChromeLauncherControllerPerApp::GetLaunchType(ash::LauncherID id) {
- DCHECK(HasItemController(id));
-
- const Extension* extension = GetExtensionForAppID(
- id_to_item_controller_map_[id]->app_id());
-
- // An extension can be unloaded/updated/unavailable at any time.
- if (!extension)
- return extensions::ExtensionPrefs::LAUNCH_DEFAULT;
-
- return profile_->GetExtensionService()->extension_prefs()->GetLaunchType(
- extension,
- extensions::ExtensionPrefs::LAUNCH_DEFAULT);
-}
-
-std::string ChromeLauncherControllerPerApp::GetAppID(
- content::WebContents* tab) {
- return app_tab_helper_->GetAppID(tab);
-}
-
-ash::LauncherID ChromeLauncherControllerPerApp::GetLauncherIDForAppID(
- const std::string& app_id) {
- for (IDToItemControllerMap::const_iterator i =
- id_to_item_controller_map_.begin();
- i != id_to_item_controller_map_.end(); ++i) {
- if (i->second->type() == LauncherItemController::TYPE_APP_PANEL)
- continue; // Don't include panels
- if (i->second->app_id() == app_id)
- return i->first;
- }
- return 0;
-}
-
-std::string ChromeLauncherControllerPerApp::GetAppIDForLauncherID(
- ash::LauncherID id) {
- CHECK(HasItemController(id));
- return id_to_item_controller_map_[id]->app_id();
-}
-
-void ChromeLauncherControllerPerApp::SetAppImage(
- const std::string& id,
- const gfx::ImageSkia& image) {
- // TODO: need to get this working for shortcuts.
-
- for (IDToItemControllerMap::const_iterator i =
- id_to_item_controller_map_.begin();
- i != id_to_item_controller_map_.end(); ++i) {
- LauncherItemController* controller = i->second;
- if (controller->app_id() != id)
- continue;
- if (controller->image_set_by_controller())
- continue;
- int index = model_->ItemIndexByID(i->first);
- if (index == -1)
- continue;
- ash::LauncherItem item = model_->items()[index];
- item.image = image;
- model_->Set(index, item);
- // It's possible we're waiting on more than one item, so don't break.
- }
-}
-
-void ChromeLauncherControllerPerApp::OnAutoHideBehaviorChanged(
- aura::RootWindow* root_window,
- ash::ShelfAutoHideBehavior new_behavior) {
- SetShelfAutoHideBehaviorPrefs(new_behavior, root_window);
-}
-
-void ChromeLauncherControllerPerApp::SetLauncherItemImage(
- ash::LauncherID launcher_id,
- const gfx::ImageSkia& image) {
- int index = model_->ItemIndexByID(launcher_id);
- if (index == -1)
- return;
- ash::LauncherItem item = model_->items()[index];
- item.image = image;
- model_->Set(index, item);
-}
-
-bool ChromeLauncherControllerPerApp::IsAppPinned(const std::string& app_id) {
- for (IDToItemControllerMap::const_iterator i =
- id_to_item_controller_map_.begin();
- i != id_to_item_controller_map_.end(); ++i) {
- if (IsPinned(i->first) && i->second->app_id() == app_id)
- return true;
- }
- return false;
-}
-
-bool ChromeLauncherControllerPerApp::IsWindowedAppInLauncher(
- const std::string& app_id) {
- int index = model_->ItemIndexByID(GetLauncherIDForAppID(app_id));
- if (index < 0)
- return false;
-
- ash::LauncherItemType type = model_->items()[index].type;
- return type == ash::TYPE_WINDOWED_APP;
-}
-
-void ChromeLauncherControllerPerApp::PinAppWithID(const std::string& app_id) {
- if (CanPin())
- DoPinAppWithID(app_id);
- else
- NOTREACHED();
-}
-
-void ChromeLauncherControllerPerApp::SetLaunchType(
- ash::LauncherID id,
- extensions::ExtensionPrefs::LaunchType launch_type) {
- if (!HasItemController(id))
- return;
-
- profile_->GetExtensionService()->extension_prefs()->SetLaunchType(
- id_to_item_controller_map_[id]->app_id(), launch_type);
-}
-
-void ChromeLauncherControllerPerApp::UnpinAppsWithID(
- const std::string& app_id) {
- if (CanPin())
- DoUnpinAppsWithID(app_id);
- else
- NOTREACHED();
-}
-
-bool ChromeLauncherControllerPerApp::IsLoggedInAsGuest() {
- return ProfileManager::GetDefaultProfileOrOffTheRecord()->IsOffTheRecord();
-}
-
-void ChromeLauncherControllerPerApp::CreateNewWindow() {
- chrome::NewEmptyWindow(
- GetProfileForNewWindows(), chrome::HOST_DESKTOP_TYPE_ASH);
-}
-
-void ChromeLauncherControllerPerApp::CreateNewIncognitoWindow() {
- chrome::NewEmptyWindow(GetProfileForNewWindows()->GetOffTheRecordProfile(),
- chrome::HOST_DESKTOP_TYPE_ASH);
-}
-
-bool ChromeLauncherControllerPerApp::CanPin() const {
- const PrefService::Preference* pref =
- profile_->GetPrefs()->FindPreference(prefs::kPinnedLauncherApps);
- return pref && pref->IsUserModifiable();
-}
-
-void ChromeLauncherControllerPerApp::PersistPinnedState() {
- if (ignore_persist_pinned_state_change_)
- return;
- // It is a coding error to call PersistPinnedState() if the pinned apps are
- // not user-editable. The code should check earlier and not perform any
- // modification actions that trigger persisting the state.
- if (!CanPin()) {
- NOTREACHED() << "Can't pin but pinned state being updated";
- return;
- }
-
- // Mutating kPinnedLauncherApps is going to notify us and trigger us to
- // process the change. We don't want that to happen so remove ourselves as a
- // listener.
- pref_change_registrar_.Remove(prefs::kPinnedLauncherApps);
- {
- ListPrefUpdate updater(profile_->GetPrefs(), prefs::kPinnedLauncherApps);
- updater->Clear();
- for (size_t i = 0; i < model_->items().size(); ++i) {
- if (model_->items()[i].type == ash::TYPE_APP_SHORTCUT) {
- ash::LauncherID id = model_->items()[i].id;
- if (HasItemController(id) && IsPinned(id)) {
- base::DictionaryValue* app_value = ash::CreateAppDict(
- id_to_item_controller_map_[id]->app_id());
- if (app_value)
- updater->Append(app_value);
- }
- } else if (model_->items()[i].type == ash::TYPE_BROWSER_SHORTCUT) {
- PersistChromeItemIndex(i);
- }
- }
- }
- pref_change_registrar_.Add(
- prefs::kPinnedLauncherApps,
- base::Bind(&ChromeLauncherControllerPerApp::UpdateAppLaunchersFromPref,
- base::Unretained(this)));
-}
-
-ash::LauncherModel* ChromeLauncherControllerPerApp::model() {
- return model_;
-}
-
-Profile* ChromeLauncherControllerPerApp::profile() {
- return profile_;
-}
-
-ash::ShelfAutoHideBehavior
- ChromeLauncherControllerPerApp::GetShelfAutoHideBehavior(
- aura::RootWindow* root_window) const {
- // Don't show the shelf in app mode.
- if (chrome::IsRunningInAppMode())
- return ash::SHELF_AUTO_HIDE_ALWAYS_HIDDEN;
-
- // See comment in |kShelfAlignment| as to why we consider two prefs.
- const std::string behavior_value(
- GetPrefForRootWindow(profile_->GetPrefs(),
- root_window,
- prefs::kShelfAutoHideBehaviorLocal,
- prefs::kShelfAutoHideBehavior));
-
- // Note: To maintain sync compatibility with old images of chrome/chromeos
- // the set of values that may be encountered includes the now-extinct
- // "Default" as well as "Never" and "Always", "Default" should now
- // be treated as "Never" (http://crbug.com/146773).
- if (behavior_value == ash::kShelfAutoHideBehaviorAlways)
- return ash::SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS;
- return ash::SHELF_AUTO_HIDE_BEHAVIOR_NEVER;
-}
-
-bool ChromeLauncherControllerPerApp::CanUserModifyShelfAutoHideBehavior(
- aura::RootWindow* root_window) const {
- return profile_->GetPrefs()->
- FindPreference(prefs::kShelfAutoHideBehaviorLocal)->IsUserModifiable();
-}
-
-void ChromeLauncherControllerPerApp::ToggleShelfAutoHideBehavior(
- aura::RootWindow* root_window) {
- ash::ShelfAutoHideBehavior behavior = GetShelfAutoHideBehavior(root_window) ==
- ash::SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS ?
- ash::SHELF_AUTO_HIDE_BEHAVIOR_NEVER :
- ash::SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS;
- SetShelfAutoHideBehaviorPrefs(behavior, root_window);
- return;
-}
-
-void ChromeLauncherControllerPerApp::RemoveTabFromRunningApp(
- WebContents* tab,
- const std::string& app_id) {
- web_contents_to_app_id_.erase(tab);
- AppIDToWebContentsListMap::iterator i_app_id =
- app_id_to_web_contents_list_.find(app_id);
- if (i_app_id != app_id_to_web_contents_list_.end()) {
- WebContentsList* tab_list = &i_app_id->second;
- tab_list->remove(tab);
- if (tab_list->empty()) {
- app_id_to_web_contents_list_.erase(i_app_id);
- i_app_id = app_id_to_web_contents_list_.end();
- ash::LauncherID id = GetLauncherIDForAppID(app_id);
- if (id)
- SetItemStatus(id, ash::STATUS_CLOSED);
- }
- }
-}
-
-void ChromeLauncherControllerPerApp::UpdateAppState(
- content::WebContents* contents,
- AppState app_state) {
- std::string app_id = GetAppID(contents);
-
- // Check if the gMail app is loaded and it matches the given content.
- // This special treatment is needed to address crbug.com/234268.
- if (app_id.empty() && ContentCanBeHandledByGmailApp(contents))
- app_id = kGmailAppId;
-
- // Check the old |app_id| for a tab. If the contents has changed we need to
- // remove it from the previous app.
- if (web_contents_to_app_id_.find(contents) != web_contents_to_app_id_.end()) {
- std::string last_app_id = web_contents_to_app_id_[contents];
- if (last_app_id != app_id)
- RemoveTabFromRunningApp(contents, last_app_id);
- }
-
- if (app_id.empty()) {
- // Even if there is no application running, we should update the activation
- // state of the associated browser.
- UpdateBrowserItemStatus();
- return;
- }
-
- web_contents_to_app_id_[contents] = app_id;
-
- if (app_state == APP_STATE_REMOVED) {
- // The tab has gone away.
- RemoveTabFromRunningApp(contents, app_id);
- } else {
- WebContentsList& tab_list(app_id_to_web_contents_list_[app_id]);
-
- if (app_state == APP_STATE_INACTIVE) {
- WebContentsList::const_iterator i_tab =
- std::find(tab_list.begin(), tab_list.end(), contents);
- if (i_tab == tab_list.end())
- tab_list.push_back(contents);
- if (i_tab != tab_list.begin()) {
- // Going inactive, but wasn't the front tab, indicating that a new
- // tab has already become active.
- return;
- }
- } else {
- tab_list.remove(contents);
- tab_list.push_front(contents);
- }
- ash::LauncherID id = GetLauncherIDForAppID(app_id);
- if (id) {
- // If the window is active, mark the app as active.
- SetItemStatus(id, app_state == APP_STATE_WINDOW_ACTIVE ?
- ash::STATUS_ACTIVE : ash::STATUS_RUNNING);
- }
- }
- UpdateBrowserItemStatus();
-}
-
-void ChromeLauncherControllerPerApp::SetRefocusURLPatternForTest(
- ash::LauncherID id,
- const GURL& url) {
- DCHECK(HasItemController(id));
- LauncherItemController* controller = id_to_item_controller_map_[id];
-
- int index = model_->ItemIndexByID(id);
- if (index == -1) {
- NOTREACHED() << "Invalid launcher id";
- return;
- }
-
- ash::LauncherItemType type = model_->items()[index].type;
- if (type == ash::TYPE_APP_SHORTCUT || type == ash::TYPE_WINDOWED_APP) {
- AppShortcutLauncherItemController* app_controller =
- static_cast<AppShortcutLauncherItemController*>(controller);
- app_controller->set_refocus_url(url);
- } else {
- NOTREACHED() << "Invalid launcher type";
- }
-}
-
-const Extension* ChromeLauncherControllerPerApp::GetExtensionForAppID(
- const std::string& app_id) const {
- // Some unit tests do not have a real extension.
- return (profile_->GetExtensionService()) ?
- profile_->GetExtensionService()->GetInstalledExtension(app_id) : NULL;
-}
-
-void ChromeLauncherControllerPerApp::ActivateWindowOrMinimizeIfActive(
- ui::BaseWindow* window,
- bool allow_minimize) {
- if (window->IsActive() && allow_minimize) {
- if (CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kDisableMinimizeOnSecondLauncherItemClick)) {
- AnimateWindow(window->GetNativeWindow(),
- views::corewm::WINDOW_ANIMATION_TYPE_BOUNCE);
- } else {
- window->Minimize();
- }
- } else {
- window->Show();
- window->Activate();
- }
-}
-
-void ChromeLauncherControllerPerApp::ItemSelected(const ash::LauncherItem& item,
- const ui::Event& event) {
- DCHECK(HasItemController(item.id));
- LauncherItemController* item_controller = id_to_item_controller_map_[item.id];
-#if defined(OS_CHROMEOS)
- if (!item_controller->app_id().empty()) {
- chromeos::default_pinned_apps_field_trial::RecordShelfAppClick(
- item_controller->app_id());
- }
-#endif
- item_controller->Clicked(event);
-}
-
-string16 ChromeLauncherControllerPerApp::GetTitle(
- const ash::LauncherItem& item) {
- DCHECK(HasItemController(item.id));
- return id_to_item_controller_map_[item.id]->GetTitle();
-}
-
-ui::MenuModel* ChromeLauncherControllerPerApp::CreateContextMenu(
- const ash::LauncherItem& item,
- aura::RootWindow* root_window) {
- return new LauncherContextMenu(this, &item, root_window);
-}
-
-ash::LauncherMenuModel* ChromeLauncherControllerPerApp::CreateApplicationMenu(
- const ash::LauncherItem& item,
- int event_flags) {
- return new LauncherApplicationMenuItemModel(GetApplicationList(item,
- event_flags));
-}
-
-ash::LauncherID ChromeLauncherControllerPerApp::GetIDByWindow(
- aura::Window* window) {
- int browser_index = ash::launcher::GetBrowserItemIndex(*model_);
- DCHECK_GE(browser_index, 0);
- ash::LauncherID browser_id = model_->items()[browser_index].id;
-
- IDToItemControllerMap::const_iterator i = id_to_item_controller_map_.begin();
- for (; i != id_to_item_controller_map_.end(); ++i) {
- // Since a |window| can be used by multiple applications, an explicit
- // application always gets chosen over the generic browser.
- if (i->first != browser_id && i->second->IsCurrentlyShownInWindow(window))
- return i->first;
- }
-
- if (i == id_to_item_controller_map_.end() &&
- GetBrowserShortcutLauncherItemController()->
- IsCurrentlyShownInWindow(window))
- return browser_id;
-
- return 0;
-}
-
-bool ChromeLauncherControllerPerApp::IsDraggable(
- const ash::LauncherItem& item) {
- return (item.type == ash::TYPE_APP_SHORTCUT ||
- item.type == ash::TYPE_WINDOWED_APP) ? CanPin() : true;
-}
-
-bool ChromeLauncherControllerPerApp::ShouldShowTooltip(
- const ash::LauncherItem& item) {
- if (item.type == ash::TYPE_APP_PANEL &&
- id_to_item_controller_map_[item.id]->IsVisible())
- return false;
- return true;
-}
-
-void ChromeLauncherControllerPerApp::OnLauncherCreated(
- ash::Launcher* launcher) {
- launchers_.insert(launcher);
- launcher->shelf_widget()->shelf_layout_manager()->AddObserver(this);
-}
-
-void ChromeLauncherControllerPerApp::OnLauncherDestroyed(
- ash::Launcher* launcher) {
- launchers_.erase(launcher);
- // RemoveObserver is not called here, since by the time this method is called
- // Launcher is already in its destructor.
-}
-
-void ChromeLauncherControllerPerApp::LauncherItemAdded(int index) {
-}
-
-void ChromeLauncherControllerPerApp::LauncherItemRemoved(
- int index,
- ash::LauncherID id) {
-}
-
-void ChromeLauncherControllerPerApp::LauncherItemMoved(
- int start_index,
- int target_index) {
- ash::LauncherID id = model_->items()[target_index].id;
- if (HasItemController(id) && IsPinned(id))
- PersistPinnedState();
-}
-
-void ChromeLauncherControllerPerApp::LauncherItemChanged(
- int index,
- const ash::LauncherItem& old_item) {
- ash::LauncherID id = model_->items()[index].id;
- DCHECK(HasItemController(id));
- id_to_item_controller_map_[id]->LauncherItemChanged(index, old_item);
-}
-
-void ChromeLauncherControllerPerApp::LauncherStatusChanged() {
-}
-
-void ChromeLauncherControllerPerApp::Observe(
- int type,
- const content::NotificationSource& source,
- const content::NotificationDetails& details) {
- switch (type) {
- case chrome::NOTIFICATION_EXTENSION_LOADED: {
- const Extension* extension =
- content::Details<const Extension>(details).ptr();
- if (IsAppPinned(extension->id())) {
- // Clear and re-fetch to ensure icon is up-to-date.
- app_icon_loader_->ClearImage(extension->id());
- app_icon_loader_->FetchImage(extension->id());
- }
-
- UpdateAppLaunchersFromPref();
- break;
- }
- case chrome::NOTIFICATION_EXTENSION_UNLOADED: {
- const content::Details<extensions::UnloadedExtensionInfo>& unload_info(
- details);
- const Extension* extension = unload_info->extension;
- const std::string& id = extension->id();
- // Since we might have windowed apps of this type which might have
- // outstanding locks which needs to be removed.
- if (GetLauncherIDForAppID(id) &&
- unload_info->reason == extension_misc::UNLOAD_REASON_UNINSTALL) {
- CloseWindowedAppsFromRemovedExtension(id);
- }
-
- if (IsAppPinned(id)) {
- if (unload_info->reason == extension_misc::UNLOAD_REASON_UNINSTALL) {
- DoUnpinAppsWithID(id);
- app_icon_loader_->ClearImage(id);
- } else {
- app_icon_loader_->UpdateImage(id);
- }
- }
- break;
- }
- default:
- NOTREACHED() << "Unexpected notification type=" << type;
- }
-}
-
-void ChromeLauncherControllerPerApp::OnShelfAlignmentChanged(
- aura::RootWindow* root_window) {
- const char* pref_value = NULL;
- switch (ash::Shell::GetInstance()->GetShelfAlignment(root_window)) {
- case ash::SHELF_ALIGNMENT_BOTTOM:
- pref_value = ash::kShelfAlignmentBottom;
- break;
- case ash::SHELF_ALIGNMENT_LEFT:
- pref_value = ash::kShelfAlignmentLeft;
- break;
- case ash::SHELF_ALIGNMENT_RIGHT:
- pref_value = ash::kShelfAlignmentRight;
- break;
- case ash::SHELF_ALIGNMENT_TOP:
- pref_value = ash::kShelfAlignmentTop;
- }
-
- UpdatePerDisplayPref(
- profile_->GetPrefs(), root_window, prefs::kShelfAlignment, pref_value);
-
- if (root_window == ash::Shell::GetPrimaryRootWindow()) {
- // See comment in |kShelfAlignment| about why we have two prefs here.
- profile_->GetPrefs()->SetString(prefs::kShelfAlignmentLocal, pref_value);
- profile_->GetPrefs()->SetString(prefs::kShelfAlignment, pref_value);
- }
-}
-
-void ChromeLauncherControllerPerApp::OnDisplayConfigurationChanging() {
-}
-
-void ChromeLauncherControllerPerApp::OnDisplayConfigurationChanged() {
- SetShelfBehaviorsFromPrefs();
-}
-
-void ChromeLauncherControllerPerApp::OnIsSyncingChanged() {
- PrefServiceSyncable* prefs = PrefServiceSyncable::FromProfile(profile_);
- MaybePropagatePrefToLocal(prefs,
- prefs::kShelfAlignmentLocal,
- prefs::kShelfAlignment);
- MaybePropagatePrefToLocal(prefs,
- prefs::kShelfAutoHideBehaviorLocal,
- prefs::kShelfAutoHideBehavior);
-}
-
-void ChromeLauncherControllerPerApp::OnAppSyncUIStatusChanged() {
- if (app_sync_ui_state_->status() == AppSyncUIState::STATUS_SYNCING)
- model_->SetStatus(ash::LauncherModel::STATUS_LOADING);
- else
- model_->SetStatus(ash::LauncherModel::STATUS_NORMAL);
-}
-
-void ChromeLauncherControllerPerApp::ExtensionEnableFlowFinished() {
- LaunchApp(extension_enable_flow_->extension_id(), ui::EF_NONE);
- extension_enable_flow_.reset();
-}
-
-void ChromeLauncherControllerPerApp::ExtensionEnableFlowAborted(
- bool user_initiated) {
- extension_enable_flow_.reset();
-}
-
-ChromeLauncherAppMenuItems ChromeLauncherControllerPerApp::GetApplicationList(
- const ash::LauncherItem& item,
- int event_flags) {
- // Make sure that there is a controller associated with the id and that the
- // extension itself is a valid application and not a panel.
- if (!HasItemController(item.id) ||
- !GetLauncherIDForAppID(id_to_item_controller_map_[item.id]->app_id()))
- return ChromeLauncherAppMenuItems().Pass();
-
- return id_to_item_controller_map_[item.id]->GetApplicationList(event_flags);
-}
-
-std::vector<content::WebContents*>
-ChromeLauncherControllerPerApp::GetV1ApplicationsFromAppId(
- std::string app_id) {
- ash::LauncherID id = GetLauncherIDForAppID(app_id);
-
- // If there is no such an item pinned to the launcher, no menu gets created.
- if (id) {
- LauncherItemController* controller = id_to_item_controller_map_[id];
- DCHECK(controller);
- if (controller->type() == LauncherItemController::TYPE_SHORTCUT)
- return GetV1ApplicationsFromController(controller);
- }
- return std::vector<content::WebContents*>();
-}
-
-void ChromeLauncherControllerPerApp::ActivateShellApp(
- const std::string& app_id,
- int index) {
- ash::LauncherID id = GetLauncherIDForAppID(app_id);
- if (id) {
- LauncherItemController* controller = id_to_item_controller_map_[id];
- if (controller->type() == LauncherItemController::TYPE_APP) {
- ShellWindowLauncherItemController* shell_window_controller =
- static_cast<ShellWindowLauncherItemController*>(controller);
- shell_window_controller->ActivateIndexedApp(index);
- }
- }
-}
-
-bool ChromeLauncherControllerPerApp::IsWebContentHandledByApplication(
- content::WebContents* web_contents,
- const std::string& app_id) {
- if ((web_contents_to_app_id_.find(web_contents) !=
- web_contents_to_app_id_.end()) &&
- (web_contents_to_app_id_[web_contents] == app_id))
- return true;
- return (app_id == kGmailAppId && ContentCanBeHandledByGmailApp(web_contents));
-}
-
-bool ChromeLauncherControllerPerApp::ContentCanBeHandledByGmailApp(
- content::WebContents* web_contents) {
- ash::LauncherID id = GetLauncherIDForAppID(kGmailAppId);
- if (id) {
- const GURL url = web_contents->GetURL();
- // We need to extend the application matching for the gMail app beyond the
- // manifest file's specification. This is required because of the namespace
- // overlap with the offline app ("/mail/mu/").
- if (!MatchPattern(url.path(), "/mail/mu/*") &&
- MatchPattern(url.path(), "/mail/*") &&
- GetExtensionForAppID(kGmailAppId) &&
- GetExtensionForAppID(kGmailAppId)->OverlapsWithOrigin(url))
- return true;
- }
- return false;
-}
-
-gfx::Image ChromeLauncherControllerPerApp::GetAppListIcon(
- content::WebContents* web_contents) const {
- ResourceBundle& rb = ResourceBundle::GetSharedInstance();
- if (IsIncognito(web_contents))
- return rb.GetImageNamed(IDR_AURA_LAUNCHER_LIST_INCOGNITO_BROWSER);
- FaviconTabHelper* favicon_tab_helper =
- FaviconTabHelper::FromWebContents(web_contents);
- gfx::Image result = favicon_tab_helper->GetFavicon();
- if (result.IsEmpty())
- return rb.GetImageNamed(IDR_DEFAULT_FAVICON);
- return result;
-}
-
-string16 ChromeLauncherControllerPerApp::GetAppListTitle(
- content::WebContents* web_contents) const {
- string16 title = web_contents->GetTitle();
- if (!title.empty())
- return title;
- WebContentsToAppIDMap::const_iterator iter =
- web_contents_to_app_id_.find(web_contents);
- if (iter != web_contents_to_app_id_.end()) {
- std::string app_id = iter->second;
- const extensions::Extension* extension = GetExtensionForAppID(app_id);
- if (extension)
- return UTF8ToUTF16(extension->name());
- }
- return l10n_util::GetStringUTF16(IDS_NEW_TAB_TITLE);
-}
-
-void ChromeLauncherControllerPerApp::OnBrowserRemoved(Browser* browser) {
- // When called by a unit test it is possible that there is no shell.
- // In that case, the following function should not get called.
- if (ash::Shell::HasInstance())
- UpdateBrowserItemStatus();
-}
-
-ash::LauncherID ChromeLauncherControllerPerApp::CreateAppShortcutLauncherItem(
- const std::string& app_id,
- int index) {
- return CreateAppShortcutLauncherItemWithType(app_id,
- index,
- ash::TYPE_APP_SHORTCUT);
-}
-
-void ChromeLauncherControllerPerApp::SetAppTabHelperForTest(
- AppTabHelper* helper) {
- app_tab_helper_.reset(helper);
-}
-
-void ChromeLauncherControllerPerApp::SetAppIconLoaderForTest(
- extensions::AppIconLoader* loader) {
- app_icon_loader_.reset(loader);
-}
-
-const std::string&
-ChromeLauncherControllerPerApp::GetAppIdFromLauncherIdForTest(
- ash::LauncherID id) {
- return id_to_item_controller_map_[id]->app_id();
-}
-
-ash::LauncherID
-ChromeLauncherControllerPerApp::CreateAppShortcutLauncherItemWithType(
- const std::string& app_id,
- int index,
- ash::LauncherItemType launcher_item_type) {
- AppShortcutLauncherItemController* controller =
- new AppShortcutLauncherItemController(app_id, this);
- ash::LauncherID launcher_id = InsertAppLauncherItem(
- controller, app_id, ash::STATUS_CLOSED, index, launcher_item_type);
- return launcher_id;
-}
-
-void ChromeLauncherControllerPerApp::UpdateBrowserItemStatus() {
- // Determine the new browser's active state and change if necessary.
- size_t browser_index = ash::launcher::GetBrowserItemIndex(*model_);
- DCHECK_GE(browser_index, 0u);
- ash::LauncherItem browser_item = model_->items()[browser_index];
- ash::LauncherItemStatus browser_status = ash::STATUS_CLOSED;
-
- aura::Window* window = ash::wm::GetActiveWindow();
- if (window) {
- // Check if the active browser / tab is a browser which is not an app,
- // a windowed app, a popup or any other item which is not a browser of
- // interest.
- Browser* browser = chrome::FindBrowserWithWindow(window);
- if (IsBrowserRepresentedInBrowserList(browser)) {
- browser_status = ash::STATUS_ACTIVE;
- const ash::LauncherItems& items = model_->items();
- // If another launcher item has claimed to be active, we don't.
- for (size_t i = 0;
- i < items.size() && browser_status == ash::STATUS_ACTIVE; ++i) {
- if (i != browser_index && items[i].status == ash::STATUS_ACTIVE)
- browser_status = ash::STATUS_RUNNING;
- }
- }
- }
-
- if (browser_status == ash::STATUS_CLOSED) {
- const BrowserList* ash_browser_list =
- BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_ASH);
- for (BrowserList::const_reverse_iterator it =
- ash_browser_list->begin_last_active();
- it != ash_browser_list->end_last_active() &&
- browser_status == ash::STATUS_CLOSED; ++it) {
- if (IsBrowserRepresentedInBrowserList(*it))
- browser_status = ash::STATUS_RUNNING;
- }
- }
-
- if (browser_status != browser_item.status) {
- browser_item.status = browser_status;
- model_->Set(browser_index, browser_item);
- }
-}
-
-Profile* ChromeLauncherControllerPerApp::GetProfileForNewWindows() {
- return ProfileManager::GetDefaultProfileOrOffTheRecord();
-}
-
-void ChromeLauncherControllerPerApp::LauncherItemClosed(ash::LauncherID id) {
- IDToItemControllerMap::iterator iter = id_to_item_controller_map_.find(id);
- CHECK(iter != id_to_item_controller_map_.end());
- CHECK(iter->second);
- app_icon_loader_->ClearImage(iter->second->app_id());
- iter->second->OnRemoved();
- id_to_item_controller_map_.erase(iter);
- int index = model_->ItemIndexByID(id);
- // A "browser proxy" is not known to the model and this removal does
- // therefore not need to be propagated to the model.
- if (index != -1)
- model_->RemoveItemAt(index);
-}
-
-void ChromeLauncherControllerPerApp::DoPinAppWithID(
- const std::string& app_id) {
- // If there is an item, do nothing and return.
- if (IsAppPinned(app_id))
- return;
-
- ash::LauncherID launcher_id = GetLauncherIDForAppID(app_id);
- if (launcher_id) {
- // App item exists, pin it
- Pin(launcher_id);
- } else {
- // Otherwise, create a shortcut item for it.
- CreateAppShortcutLauncherItem(app_id, model_->item_count());
- if (CanPin())
- PersistPinnedState();
- }
-}
-
-void ChromeLauncherControllerPerApp::DoUnpinAppsWithID(
- const std::string& app_id) {
- for (IDToItemControllerMap::iterator i = id_to_item_controller_map_.begin();
- i != id_to_item_controller_map_.end(); ) {
- IDToItemControllerMap::iterator current(i);
- ++i;
- if (current->second->app_id() == app_id && IsPinned(current->first))
- Unpin(current->first);
- }
-}
-
-void ChromeLauncherControllerPerApp::UpdateAppLaunchersFromPref() {
- // Construct a vector representation of to-be-pinned apps from the pref.
- std::vector<std::string> pinned_apps;
- int chrome_icon_index = GetChromeIconIndexFromPref();
- int index = 0;
- int max_index = model_->item_count();
- // Using the alternate shelf layout the App Icon should be the first item in
- // the list thus start adding items at slot 1 (instead of slot 0).
- if (ash::switches::UseAlternateShelfLayout()) {
- ++index;
- ++max_index;
- // The alternate shelf layout's icon position will always include the
- // AppLauncher which needs to be subtracted here.
- if (chrome_icon_index > 0)
- --chrome_icon_index;
- }
- const base::ListValue* pinned_apps_pref =
- profile_->GetPrefs()->GetList(prefs::kPinnedLauncherApps);
- for (base::ListValue::const_iterator it(pinned_apps_pref->begin());
- it != pinned_apps_pref->end(); ++it) {
- // To preserve the Chrome icon position, we insert a dummy slot for it - if
- // the model has a Chrome item. While initializing we can come here with no
- // item in which case the count would be 1 or below.
- if (it - pinned_apps_pref->begin() == chrome_icon_index &&
- model_->item_count() > 1) {
- pinned_apps.push_back(extension_misc::kChromeAppId);
- }
-
- DictionaryValue* app = NULL;
- std::string app_id;
- if ((*it)->GetAsDictionary(&app) &&
- app->GetString(ash::kPinnedAppsPrefAppIDPath, &app_id) &&
- std::find(pinned_apps.begin(), pinned_apps.end(), app_id) ==
- pinned_apps.end() &&
- app_tab_helper_->IsValidID(app_id)) {
- pinned_apps.push_back(app_id);
- }
- }
-
- // Walk the model and |pinned_apps| from the pref lockstep, adding and
- // removing items as necessary. NB: This code uses plain old indexing instead
- // of iterators because of model mutations as part of the loop.
- std::vector<std::string>::const_iterator pref_app_id(pinned_apps.begin());
- for (; index < max_index && pref_app_id != pinned_apps.end(); ++index) {
- // If the next app launcher according to the pref is present in the model,
- // delete all app launcher entries in between.
- if (*pref_app_id == extension_misc::kChromeAppId ||
- IsAppPinned(*pref_app_id)) {
- for (; index < max_index; ++index) {
- const ash::LauncherItem& item(model_->items()[index]);
- if (item.type != ash::TYPE_APP_SHORTCUT &&
- item.type != ash::TYPE_BROWSER_SHORTCUT)
- continue;
-
- IDToItemControllerMap::const_iterator entry =
- id_to_item_controller_map_.find(item.id);
- if ((extension_misc::kChromeAppId == *pref_app_id &&
- item.type == ash::TYPE_BROWSER_SHORTCUT) ||
- (entry != id_to_item_controller_map_.end() &&
- entry->second->app_id() == *pref_app_id)) {
- ++pref_app_id;
- break;
- } else {
- if (item.type == ash::TYPE_BROWSER_SHORTCUT) {
- // We cannot delete the browser shortcut. As such we move it up by
- // one. To avoid any side effects from our pinned state observer, we
- // do not call the model directly.
- MoveItemWithoutPinnedStateChangeNotification(index, index + 1);
- } else {
- LauncherItemClosed(item.id);
- --max_index;
- }
- --index;
- }
- }
- // If the item wasn't found, that means id_to_item_controller_map_
- // is out of sync.
- DCHECK(index < max_index);
- } else {
- // This app wasn't pinned before, insert a new entry.
- ash::LauncherID id = CreateAppShortcutLauncherItem(*pref_app_id, index);
- index = model_->ItemIndexByID(id);
- ++pref_app_id;
- }
- }
-
- // Remove any trailing existing items.
- while (index < model_->item_count()) {
- const ash::LauncherItem& item(model_->items()[index]);
- if (item.type == ash::TYPE_APP_SHORTCUT)
- LauncherItemClosed(item.id);
- else
- ++index;
- }
-
- // Append unprocessed items from the pref to the end of the model.
- for (; pref_app_id != pinned_apps.end(); ++pref_app_id) {
- // Ignore the chrome icon.
- if (*pref_app_id != extension_misc::kChromeAppId)
- DoPinAppWithID(*pref_app_id);
- }
-
-}
-
-void ChromeLauncherControllerPerApp::SetShelfAutoHideBehaviorPrefs(
- ash::ShelfAutoHideBehavior behavior,
- aura::RootWindow* root_window) {
- const char* value = NULL;
- switch (behavior) {
- case ash::SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS:
- value = ash::kShelfAutoHideBehaviorAlways;
- break;
- case ash::SHELF_AUTO_HIDE_BEHAVIOR_NEVER:
- value = ash::kShelfAutoHideBehaviorNever;
- break;
- case ash::SHELF_AUTO_HIDE_ALWAYS_HIDDEN:
- // This one should not be a valid preference option for now. We only want
- // to completely hide it when we run app mode.
- NOTREACHED();
- return;
- }
-
- UpdatePerDisplayPref(
- profile_->GetPrefs(), root_window, prefs::kShelfAutoHideBehavior, value);
-
- if (root_window == ash::Shell::GetPrimaryRootWindow()) {
- // See comment in |kShelfAlignment| about why we have two prefs here.
- profile_->GetPrefs()->SetString(prefs::kShelfAutoHideBehaviorLocal, value);
- profile_->GetPrefs()->SetString(prefs::kShelfAutoHideBehavior, value);
- }
-}
-
-void ChromeLauncherControllerPerApp::SetShelfAutoHideBehaviorFromPrefs() {
- ash::Shell::RootWindowList root_windows = ash::Shell::GetAllRootWindows();
-
- for (ash::Shell::RootWindowList::const_iterator iter = root_windows.begin();
- iter != root_windows.end(); ++iter) {
- ash::Shell::GetInstance()->SetShelfAutoHideBehavior(
- GetShelfAutoHideBehavior(*iter), *iter);
- }
-}
-
-void ChromeLauncherControllerPerApp::SetShelfAlignmentFromPrefs() {
- if (!ash::ShelfWidget::ShelfAlignmentAllowed())
- return;
-
- ash::Shell::RootWindowList root_windows = ash::Shell::GetAllRootWindows();
-
- for (ash::Shell::RootWindowList::const_iterator iter = root_windows.begin();
- iter != root_windows.end(); ++iter) {
- // See comment in |kShelfAlignment| as to why we consider two prefs.
- const std::string alignment_value(
- GetPrefForRootWindow(profile_->GetPrefs(),
- *iter,
- prefs::kShelfAlignmentLocal,
- prefs::kShelfAlignment));
- ash::ShelfAlignment alignment = ash::SHELF_ALIGNMENT_BOTTOM;
- if (alignment_value == ash::kShelfAlignmentLeft)
- alignment = ash::SHELF_ALIGNMENT_LEFT;
- else if (alignment_value == ash::kShelfAlignmentRight)
- alignment = ash::SHELF_ALIGNMENT_RIGHT;
- else if (alignment_value == ash::kShelfAlignmentTop)
- alignment = ash::SHELF_ALIGNMENT_TOP;
- ash::Shell::GetInstance()->SetShelfAlignment(alignment, *iter);
- }
-}
-
-void ChromeLauncherControllerPerApp::SetShelfBehaviorsFromPrefs() {
- SetShelfAutoHideBehaviorFromPrefs();
- SetShelfAlignmentFromPrefs();
-}
-
-WebContents* ChromeLauncherControllerPerApp::GetLastActiveWebContents(
- const std::string& app_id) {
- AppIDToWebContentsListMap::const_iterator i =
- app_id_to_web_contents_list_.find(app_id);
- if (i == app_id_to_web_contents_list_.end())
- return NULL;
- DCHECK_GT(i->second.size(), 0u);
- return *i->second.begin();
-}
-
-ash::LauncherID ChromeLauncherControllerPerApp::InsertAppLauncherItem(
- LauncherItemController* controller,
- const std::string& app_id,
- ash::LauncherItemStatus status,
- int index,
- ash::LauncherItemType launcher_item_type) {
- ash::LauncherID id = model_->next_id();
- CHECK(!HasItemController(id));
- CHECK(controller);
- id_to_item_controller_map_[id] = controller;
- controller->set_launcher_id(id);
-
- ash::LauncherItem item;
- item.type = launcher_item_type;
- item.is_incognito = false;
- item.image = extensions::IconsInfo::GetDefaultAppIcon();
-
- WebContents* active_tab = GetLastActiveWebContents(app_id);
- if (active_tab) {
- Browser* browser = chrome::FindBrowserWithWebContents(active_tab);
- DCHECK(browser);
- if (browser->window()->IsActive())
- status = ash::STATUS_ACTIVE;
- else
- status = ash::STATUS_RUNNING;
- }
- item.status = status;
-
- model_->AddAt(index, item);
-
- app_icon_loader_->FetchImage(app_id);
-
- return id;
-}
-
-bool ChromeLauncherControllerPerApp::HasItemController(
- ash::LauncherID id) const {
- return id_to_item_controller_map_.find(id) !=
- id_to_item_controller_map_.end();
-}
-
-std::vector<content::WebContents*>
-ChromeLauncherControllerPerApp::GetV1ApplicationsFromController(
- LauncherItemController* controller) {
- DCHECK(controller->type() == LauncherItemController::TYPE_SHORTCUT);
- AppShortcutLauncherItemController* app_controller =
- static_cast<AppShortcutLauncherItemController*>(controller);
- return app_controller->GetRunningApplications();
-}
-
-bool ChromeLauncherControllerPerApp::IsBrowserRepresentedInBrowserList(
- Browser* browser) {
- return (browser &&
- (browser->is_type_tabbed() ||
- !browser->is_app() ||
- !browser->is_type_popup() ||
- GetLauncherIDForAppID(web_app::GetExtensionIdFromApplicationName(
- browser->app_name())) <= 0));
-}
-
-LauncherItemController*
-ChromeLauncherControllerPerApp::GetBrowserShortcutLauncherItemController() {
- for (IDToItemControllerMap::iterator i = id_to_item_controller_map_.begin();
- i != id_to_item_controller_map_.end(); ++i) {
- int index = model_->ItemIndexByID(i->first);
- const ash::LauncherItem& item = model_->items()[index];
- if (item.type == ash::TYPE_BROWSER_SHORTCUT)
- return i->second;
- }
- // LauncerItemController For Browser Shortcut must be existed. If it does not
- // existe create it.
- ash::LauncherID id = CreateBrowserShortcutLauncherItem();
- DCHECK(id_to_item_controller_map_[id]);
- return id_to_item_controller_map_[id];
-}
-
-ash::LauncherID
-ChromeLauncherControllerPerApp::CreateBrowserShortcutLauncherItem() {
- ash::LauncherItem browser_shortcut;
- browser_shortcut.type = ash::TYPE_BROWSER_SHORTCUT;
- browser_shortcut.is_incognito = false;
- ResourceBundle& rb = ResourceBundle::GetSharedInstance();
- browser_shortcut.image = *rb.GetImageSkiaNamed(IDR_PRODUCT_LOGO_32);
- ash::LauncherID id = model_->next_id();
- size_t index = GetChromeIconIndexFromPref();
- model_->AddAt(index, browser_shortcut);
- browser_item_controller_.reset(
- new BrowserShortcutLauncherItemController(this, profile_));
- id_to_item_controller_map_[id] = browser_item_controller_.get();
- id_to_item_controller_map_[id]->set_launcher_id(id);
- return id;
-}
-
-void ChromeLauncherControllerPerApp::PersistChromeItemIndex(int index) {
- profile_->GetPrefs()->SetInteger(prefs::kShelfChromeIconIndex, index);
-}
-
-int ChromeLauncherControllerPerApp::GetChromeIconIndexFromPref() const {
- size_t index = profile_->GetPrefs()->GetInteger(prefs::kShelfChromeIconIndex);
- const base::ListValue* pinned_apps_pref =
- profile_->GetPrefs()->GetList(prefs::kPinnedLauncherApps);
- if (ash::switches::UseAlternateShelfLayout())
- return std::max(static_cast<size_t>(1),
- std::min(pinned_apps_pref->GetSize() + 1, index));
- return std::max(static_cast<size_t>(0),
- std::min(pinned_apps_pref->GetSize(), index));
-}
-
-bool ChromeLauncherControllerPerApp::IsIncognito(
- content::WebContents* web_contents) const {
- const Profile* profile =
- Profile::FromBrowserContext(web_contents->GetBrowserContext());
- return profile->IsOffTheRecord() && !profile->IsGuestSession();
-}
-
-void ChromeLauncherControllerPerApp::CloseWindowedAppsFromRemovedExtension(
- const std::string& app_id) {
- // This function cannot rely on the controller's enumeration functionality
- // since the extension has already be unloaded.
- const BrowserList* ash_browser_list =
- BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_ASH);
- std::vector<Browser*> browser_to_close;
- for (BrowserList::const_reverse_iterator
- it = ash_browser_list->begin_last_active();
- it != ash_browser_list->end_last_active(); ++it) {
- Browser* browser = *it;
- if (!browser->is_type_tabbed() &&
- browser->is_type_popup() &&
- browser->is_app() &&
- app_id == web_app::GetExtensionIdFromApplicationName(
- browser->app_name())) {
- browser_to_close.push_back(browser);
- }
- }
- while (!browser_to_close.empty()) {
- TabStripModel* tab_strip = browser_to_close.back()->tab_strip_model();
- tab_strip->CloseWebContentsAt(0, TabStripModel::CLOSE_NONE);
- browser_to_close.pop_back();
- }
-}
-
-void
-ChromeLauncherControllerPerApp::MoveItemWithoutPinnedStateChangeNotification(
- int source_index, int target_index) {
- base::AutoReset<bool> auto_reset(&ignore_persist_pinned_state_change_, true);
- model_->Move(source_index, target_index);
-}

Powered by Google App Engine
This is Rietveld 408576698