#include "chrome/browser/web_applications/web_app.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/extensions/manifest_handlers/app_launch_info.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 "extensions/browser/extension_system.h"
#include "extensions/common/extension.h"
#include "extensions/common/extension_resource.h"
+#include "extensions/common/manifest_handlers/icons_handler.h"
#include "extensions/common/url_pattern.h"
#include "grit/ash_resources.h"
#include "grit/chromium_strings.h"
#include "ui/aura/window.h"
#include "ui/aura/window_event_dispatcher.h"
#include "ui/base/l10n/l10n_util.h"
+#include "ui/keyboard/keyboard_util.h"
#include "ui/wm/core/window_animations.h"
#if defined(OS_CHROMEOS)
ash::Shell::GetInstance()->shelf_item_delegate_manager();
}
- notification_registrar_.Add(
- this,
- chrome::NOTIFICATION_EXTENSION_LOADED,
- content::Source<Profile>(profile_));
+ notification_registrar_.Add(this,
+ chrome::NOTIFICATION_EXTENSION_LOADED_DEPRECATED,
+ content::Source<Profile>(profile_));
notification_registrar_.Add(
this,
chrome::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED,
return;
}
-void ChromeLauncherController::RemoveTabFromRunningApp(
- WebContents* tab,
- const std::string& app_id) {
- web_contents_to_app_id_.erase(tab);
- // BrowserShortcutLauncherItemController::UpdateBrowserItemState() will update
- // the state when no application is associated with the tab.
- if (app_id.empty())
- return;
-
- 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);
- ash::ShelfItemStatus status = ash::STATUS_RUNNING;
- if (tab_list->empty()) {
- app_id_to_web_contents_list_.erase(i_app_id);
- status = ash::STATUS_CLOSED;
- }
- ash::ShelfID id = GetShelfIDForAppID(app_id);
- if (id)
- SetItemStatus(id, status);
- }
-}
-
void ChromeLauncherController::UpdateAppState(content::WebContents* contents,
AppState app_state) {
std::string app_id = app_tab_helper_->GetAppID(contents);
// 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);
- }
-
- web_contents_to_app_id_[contents] = app_id;
-
- if (app_state == APP_STATE_REMOVED) {
- // The tab has gone away.
- RemoveTabFromRunningApp(contents, app_id);
- } else if (!app_id.empty()) {
- WebContentsList& tab_list(app_id_to_web_contents_list_[app_id]);
- 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 (app_state == APP_STATE_INACTIVE || app_state == APP_STATE_ACTIVE) {
- if (i_tab != tab_list.begin()) {
- // Going to running state, but wasn't the front tab, indicating that a
- // new tab has already become active.
- return;
+ if (last_app_id != app_id) {
+ ash::ShelfID id = GetShelfIDForAppID(last_app_id);
+ if (id) {
+ // Since GetAppState() will use |web_contents_to_app_id_| we remove
+ // the connection before calling it.
+ web_contents_to_app_id_.erase(contents);
+ SetItemStatus(id, GetAppState(last_app_id));
}
}
+ }
- if (app_state == APP_STATE_ACTIVE || app_state == APP_STATE_WINDOW_ACTIVE) {
- tab_list.remove(contents);
- tab_list.push_front(contents);
- }
+ if (app_state == APP_STATE_REMOVED)
+ web_contents_to_app_id_.erase(contents);
+ else
+ web_contents_to_app_id_[contents] = app_id;
- ash::ShelfID id = GetShelfIDForAppID(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);
- }
+ ash::ShelfID id = GetShelfIDForAppID(app_id);
+ if (id) {
+ SetItemStatus(id, (app_state == APP_STATE_WINDOW_ACTIVE ||
+ app_state == APP_STATE_ACTIVE) ? ash::STATUS_ACTIVE :
+ GetAppState(app_id));
}
}
// The app list launcher can get added to the shelf after we applied the
// preferences. In that case the item might be at the wrong spot. As such we
// call the function again.
- if (model_->items()[index].type == ash::TYPE_APP_LIST &&
- ash::switches::UseAlternateShelfLayout())
+ if (model_->items()[index].type == ash::TYPE_APP_LIST)
UpdateAppLaunchersFromPref();
}
// We remember the moved item position if it is either pinnable or
// it is the app list with the alternate shelf layout.
if ((HasItemController(item.id) && IsPinned(item.id)) ||
- (ash::switches::UseAlternateShelfLayout() &&
- item.type == ash::TYPE_APP_LIST))
+ item.type == ash::TYPE_APP_LIST)
PersistPinnedState();
}
RestoreUnpinnedRunningApplicationOrder(user_email);
// Inform the system tray of the change.
ash::Shell::GetInstance()->system_tray_delegate()->ActiveUserWasChanged();
+ // Force on-screen keyboard to reset.
+ if (keyboard::IsKeyboardEnabled())
+ ash::Shell::GetInstance()->CreateKeyboard();
}
void ChromeLauncherController::AdditionalUserAddedToSession(Profile* profile) {
const content::NotificationSource& source,
const content::NotificationDetails& details) {
switch (type) {
- case chrome::NOTIFICATION_EXTENSION_LOADED: {
+ case chrome::NOTIFICATION_EXTENSION_LOADED_DEPRECATED: {
const Extension* extension =
content::Details<const Extension>(details).ptr();
if (IsAppPinned(extension->id())) {
gfx::Image ChromeLauncherController::GetAppListIcon(
content::WebContents* web_contents) const {
- ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+ ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
if (IsIncognito(web_contents))
- return rb.GetImageNamed(IDR_AURA_LAUNCHER_LIST_INCOGNITO_BROWSER);
+ return rb.GetImageNamed(IDR_ASH_SHELF_LIST_INCOGNITO_BROWSER);
FaviconTabHelper* favicon_tab_helper =
FaviconTabHelper::FromWebContents(web_contents);
gfx::Image result = favicon_tab_helper->GetFavicon();
SetShelfAlignmentFromPrefs();
}
-WebContents* ChromeLauncherController::GetLastActiveWebContents(
- const std::string& app_id) {
- AppIDToWebContentsListMap::iterator i =
- app_id_to_web_contents_list_.find(app_id);
- if (i == app_id_to_web_contents_list_.end())
- return NULL;
-
- // There are many crash records (crbug.com/341250) which indicate that the
- // app_id_to_web_contents_list_ contains deleted content entries - so there
- // must be a way that the content does not get properly updated. To fix
- // M33 and M34 we filter out the invalid items here, but this should be
- // addressed by a later patch correctly. Looking at the code however, the
- // real culprit is possibly BrowserStatusMonitor::UpdateAppItemState which
- // does not call "UpdateAppState(.., APP_STATE_REMOVED)" because due to a
- // Browser::SwapTabContent operation it isn't able to get the browser. I
- // think that the real patch is to call anyway when APP_STATE_REMOVED is
- // requested, but for a backport that seems risky.
- WebContentsList* list = &i->second;
- while (!list->empty()) {
- WebContents* contents = *list->begin();
- if (chrome::FindBrowserWithWebContents(contents))
- return contents;
- list->erase(list->begin());
- // This might not be necessary, but since we do not know why the lists
- // diverged we also erase it since it cannot be correct either.
- web_contents_to_app_id_.erase(contents);
+ash::ShelfItemStatus ChromeLauncherController::GetAppState(
+ const::std::string& app_id) {
+ ash::ShelfItemStatus status = ash::STATUS_CLOSED;
+ for (WebContentsToAppIDMap::iterator it = web_contents_to_app_id_.begin();
+ it != web_contents_to_app_id_.end();
+ ++it) {
+ if (it->second == app_id) {
+ Browser* browser = chrome::FindBrowserWithWebContents(it->first);
+ // Usually there should never be an item in our |web_contents_to_app_id_|
+ // list which got deleted already. However - in some situations e.g.
+ // Browser::SwapTabContent there is temporarily no associated browser.
+ if (!browser)
+ continue;
+ if (browser->window()->IsActive()) {
+ return browser->tab_strip_model()->GetActiveWebContents() == it->first ?
+ ash::STATUS_ACTIVE : ash::STATUS_RUNNING;
+ } else {
+ status = ash::STATUS_RUNNING;
+ }
+ }
}
- app_id_to_web_contents_list_.erase(app_id);
- return NULL;
+ return status;
}
ash::ShelfID ChromeLauncherController::InsertAppLauncherItem(
ash::ShelfItem item;
item.type = shelf_item_type;
- 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.image = extensions::util::GetDefaultAppIcon();
+
+ ash::ShelfItemStatus new_state = GetAppState(app_id);
+ if (new_state != ash::STATUS_CLOSED)
+ status = new_state;
+
item.status = status;
model_->AddAt(index, item);
}
int ChromeLauncherController::FindInsertionPoint(bool is_app_list) {
- bool alternate = ash::switches::UseAlternateShelfLayout();
// Keeping this change small to backport to M33&32 (see crbug.com/329597).
// TODO(skuhne): With the removal of the legacy shelf layout we should remove
// the ability to move the app list item since this was never used. We should
// instead ask the ShelfModel::ValidateInsertionIndex or similir for an index.
- if (is_app_list && alternate)
+ if (is_app_list)
return 0;
for (int i = model_->item_count() - 1; i > 0; --i) {
ash::ShelfItemType type = model_->items()[i].type;
if (type == ash::TYPE_APP_SHORTCUT ||
- ((is_app_list || alternate) && type == ash::TYPE_APP_LIST) ||
+ (is_app_list && type == ash::TYPE_APP_LIST) ||
type == ash::TYPE_BROWSER_SHORTCUT) {
return i;
}
// If not added yet, add the app list item either at the end or at the
// beginning - depending on the shelf layout.
if (!app_list_icon_added) {
- if (ash::switches::UseAlternateShelfLayout())
- pinned_apps.insert(pinned_apps.begin(), kAppShelfIdPlaceholder);
- else
- pinned_apps.push_back(kAppShelfIdPlaceholder);
+ pinned_apps.insert(pinned_apps.begin(), kAppShelfIdPlaceholder);
}
return pinned_apps;
}