190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// found in the LICENSE file. 490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "apps/app_shim/extension_app_shim_handler_mac.h" 690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 7eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "apps/app_lifetime_monitor_factory.h" 8a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "apps/app_shim/app_shim_host_manager_mac.h" 990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "apps/app_shim/app_shim_messages.h" 102385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch#include "apps/native_app_window.h" 11eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "apps/shell_window.h" 124311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch#include "apps/shell_window_registry.h" 1390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/files/file_path.h" 1490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/logging.h" 15eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/browser/browser_process.h" 167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.h" 1790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/browser/extensions/extension_host.h" 1890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/browser/extensions/extension_service.h" 1990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/browser/extensions/extension_system.h" 20eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/browser/lifetime/application_lifetime.h" 21eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/browser/profiles/profile.h" 22eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/browser/profiles/profile_manager.h" 2390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/browser/ui/extensions/application_launch.h" 24868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/ui/web_applications/web_app_ui.h" 25868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/web_applications/web_app_mac.h" 267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "content/public/browser/notification_details.h" 277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "content/public/browser/notification_service.h" 287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "content/public/browser/notification_source.h" 2990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ui/base/cocoa/focus_window_set.h" 3090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochnamespace { 327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid ProfileLoadedCallback(base::Callback<void(Profile*)> callback, 347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch Profile* profile, 357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch Profile::CreateStatus status) { 367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (status == Profile::CREATE_STATUS_INITIALIZED) { 377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch callback.Run(profile); 387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return; 397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // This should never get an error since it only loads existing profiles. 427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch DCHECK_EQ(Profile::CREATE_STATUS_CREATED, status); 437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 45a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void TerminateIfNoShellWindows() { 46a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) bool shell_windows_left = 474311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch apps::ShellWindowRegistry::IsShellWindowRegisteredInAnyProfile(0); 48a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (!shell_windows_left) 49a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) chrome::AttemptExit(); 50a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 51a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} // namespace 537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 5490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace apps { 5590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 564311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdochtypedef ShellWindowRegistry::ShellWindowList ShellWindowList; 57eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 58eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool ExtensionAppShimHandler::Delegate::ProfileExistsForPath( 59eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const base::FilePath& path) { 60eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ProfileManager* profile_manager = g_browser_process->profile_manager(); 61eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Check for the profile name in the profile info cache to ensure that we 62eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // never access any directory that isn't a known profile. 63eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::FilePath full_path = profile_manager->user_data_dir().Append(path); 64eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ProfileInfoCache& cache = profile_manager->GetProfileInfoCache(); 65eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return cache.GetIndexOfProfileWithPath(full_path) != std::string::npos; 66868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 6790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 68eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochProfile* ExtensionAppShimHandler::Delegate::ProfileForPath( 69eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const base::FilePath& path) { 70eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ProfileManager* profile_manager = g_browser_process->profile_manager(); 71eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::FilePath full_path = profile_manager->user_data_dir().Append(path); 727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch Profile* profile = profile_manager->GetProfileByPath(full_path); 737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // Use IsValidProfile to check if the profile has been created. 757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return profile && profile_manager->IsValidProfile(profile) ? profile : NULL; 767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid ExtensionAppShimHandler::Delegate::LoadProfileAsync( 797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch const base::FilePath& path, 807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch base::Callback<void(Profile*)> callback) { 817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ProfileManager* profile_manager = g_browser_process->profile_manager(); 827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch base::FilePath full_path = profile_manager->user_data_dir().Append(path); 837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch profile_manager->CreateProfileAsync( 847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch full_path, 857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch base::Bind(&ProfileLoadedCallback, callback), 862385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch string16(), string16(), std::string()); 87eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 88eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 89eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochShellWindowList ExtensionAppShimHandler::Delegate::GetWindows( 90eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch Profile* profile, 91eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const std::string& extension_id) { 924311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch return ShellWindowRegistry::Get(profile)->GetShellWindowsForApp(extension_id); 93eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 94eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 95eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst extensions::Extension* 96eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochExtensionAppShimHandler::Delegate::GetAppExtension( 97eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch Profile* profile, 98eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const std::string& extension_id) { 99eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ExtensionService* extension_service = 100eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch extensions::ExtensionSystem::Get(profile)->extension_service(); 101eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK(extension_service); 102eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const extensions::Extension* extension = 103eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch extension_service->GetExtensionById(extension_id, false); 104eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return extension && extension->is_platform_app() ? extension : NULL; 105eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 106eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 107eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid ExtensionAppShimHandler::Delegate::LaunchApp( 108eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch Profile* profile, 109eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const extensions::Extension* extension) { 110eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch chrome::OpenApplication( 111eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch chrome::AppLaunchParams(profile, extension, NEW_FOREGROUND_TAB)); 112eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 113eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 114eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid ExtensionAppShimHandler::Delegate::LaunchShim( 115eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch Profile* profile, 116eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const extensions::Extension* extension) { 117eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch web_app::MaybeLaunchShortcut( 118eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch web_app::ShortcutInfoForExtensionAndProfile(extension, profile)); 119eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 120eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 121eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid ExtensionAppShimHandler::Delegate::MaybeTerminate() { 122a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // Post this to give ShellWindows a chance to remove themselves from the 123a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // registry. 124a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) base::MessageLoop::current()->PostTask( 125a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) FROM_HERE, 126a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) base::Bind(&TerminateIfNoShellWindows)); 12790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 12890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 129eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochExtensionAppShimHandler::ExtensionAppShimHandler() 130eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch : delegate_(new Delegate), 1317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch browser_opened_ever_(false), 1327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch weak_factory_(this) { 133eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // This is instantiated in BrowserProcessImpl::PreMainMessageLoopRun with 134eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // AppShimHostManager. Since PROFILE_CREATED is not fired until 135eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // ProfileManager::GetLastUsedProfile/GetLastOpenedProfiles, this should catch 136eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // notifications for all profiles. 137eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch registrar_.Add(this, chrome::NOTIFICATION_PROFILE_CREATED, 138eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch content::NotificationService::AllBrowserContextsAndSources()); 139eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED, 140eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch content::NotificationService::AllBrowserContextsAndSources()); 141eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNINSTALLED, 142eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch content::NotificationService::AllBrowserContextsAndSources()); 1433240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_PROCESS_TERMINATED, 1443240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch content::NotificationService::AllBrowserContextsAndSources()); 145eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch registrar_.Add(this, chrome::NOTIFICATION_BROWSER_OPENED, 146eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch content::NotificationService::AllBrowserContextsAndSources()); 147eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 148eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 149eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochExtensionAppShimHandler::~ExtensionAppShimHandler() {} 150eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 151a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)AppShimHandler::Host* ExtensionAppShimHandler::FindHost( 152a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) Profile* profile, 153a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) const std::string& app_id) { 154a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) HostMap::iterator it = hosts_.find(make_pair(profile, app_id)); 155a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return it == hosts_.end() ? NULL : it->second; 156a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 157a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 158a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// static 159a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void ExtensionAppShimHandler::QuitAppForWindow(ShellWindow* shell_window) { 160a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) ExtensionAppShimHandler* handler = 161a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) g_browser_process->platform_part()->app_shim_host_manager()-> 162a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) extension_app_shim_handler(); 163a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) Host* host = handler->FindHost(shell_window->profile(), 164a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) shell_window->extension_id()); 165a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (host) { 166a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) handler->OnShimQuit(host); 167a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } else { 168a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // App shims might be disabled or the shim is still starting up. 1694311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch ShellWindowRegistry::Get(shell_window->profile())-> 170a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) CloseAllShellWindowsForApp(shell_window->extension_id()); 171a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 172a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 173a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 1747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid ExtensionAppShimHandler::OnShimLaunch(Host* host, 175868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) AppShimLaunchType launch_type) { 1767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch const std::string& app_id = host->GetAppId(); 1777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch DCHECK(extensions::Extension::IdIsValid(app_id)); 1787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 179eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const base::FilePath& profile_path = host->GetProfilePath(); 180eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK(!profile_path.empty()); 181eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 182eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (!delegate_->ProfileExistsForPath(profile_path)) { 183eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // User may have deleted the profile this shim was originally created for. 184eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // TODO(jackhou): Add some UI for this case and remove the LOG. 185eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch LOG(ERROR) << "Requested directory is not a known profile '" 186eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch << profile_path.value() << "'."; 1877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch host->OnAppLaunchComplete(APP_SHIM_LAUNCH_PROFILE_NOT_FOUND); 1887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return; 189eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 190eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 191eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch Profile* profile = delegate_->ProfileForPath(profile_path); 19290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (profile) { 1947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch OnProfileLoaded(host, launch_type, profile); 1957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return; 19690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 19790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // If the profile is not loaded, this must have been a launch by the shim. 1997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // Load the profile asynchronously, the host will be registered in 2007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // OnProfileLoaded. 2017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch DCHECK_EQ(APP_SHIM_LAUNCH_NORMAL, launch_type); 2027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch delegate_->LoadProfileAsync( 2037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch profile_path, 2047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch base::Bind(&ExtensionAppShimHandler::OnProfileLoaded, 2057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch weak_factory_.GetWeakPtr(), 2067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch host, launch_type)); 2077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 2087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // Return now. OnAppLaunchComplete will be called when the app is activated. 2097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 2107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 2117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid ExtensionAppShimHandler::OnProfileLoaded(Host* host, 2127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch AppShimLaunchType launch_type, 2137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch Profile* profile) { 2147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch const std::string& app_id = host->GetAppId(); 215eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // TODO(jackhou): Add some UI for this case and remove the LOG. 216eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const extensions::Extension* extension = 217eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch delegate_->GetAppExtension(profile, app_id); 218eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (!extension) { 219eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch LOG(ERROR) << "Attempted to launch nonexistent app with id '" 220eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch << app_id << "'."; 2217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch host->OnAppLaunchComplete(APP_SHIM_LAUNCH_APP_NOT_FOUND); 2227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return; 223eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 22490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 2257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // The first host to claim this (profile, app_id) becomes the main host. 2267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // For any others, focus or relaunch the app. 2277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!hosts_.insert(make_pair(make_pair(profile, app_id), host)).second) { 2287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch OnShimFocus(host, 2297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch launch_type == APP_SHIM_LAUNCH_NORMAL ? 2307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch APP_SHIM_FOCUS_REOPEN : APP_SHIM_FOCUS_NORMAL); 2317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch host->OnAppLaunchComplete(APP_SHIM_LAUNCH_DUPLICATE_HOST); 2327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return; 233868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 23490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 235eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // TODO(jeremya): Handle the case that launching the app fails. Probably we 236eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // need to watch for 'app successfully launched' or at least 'background page 237eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // exists/was created' and time out with failure if we don't see that sign of 238eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // life within a certain window. 239eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (launch_type == APP_SHIM_LAUNCH_NORMAL) 240eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch delegate_->LaunchApp(profile, extension); 2417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch else 2427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch host->OnAppLaunchComplete(APP_SHIM_LAUNCH_SUCCESS); 24390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 24490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 24590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void ExtensionAppShimHandler::OnShimClose(Host* host) { 2467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // This might be called when shutting down. Don't try to look up the profile 2477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // since profile_manager might not be around. 2487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch for (HostMap::iterator it = hosts_.begin(); it != hosts_.end(); ) { 2497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch HostMap::iterator current = it++; 2507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (current->second == host) 2517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch hosts_.erase(current); 2527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 25390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 25490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 255eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid ExtensionAppShimHandler::OnShimFocus(Host* host, 256eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch AppShimFocusType focus_type) { 257eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK(delegate_->ProfileExistsForPath(host->GetProfilePath())); 258eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch Profile* profile = delegate_->ProfileForPath(host->GetProfilePath()); 25990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 260eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const ShellWindowList windows = 261eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch delegate_->GetWindows(profile, host->GetAppId()); 26290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::set<gfx::NativeWindow> native_windows; 263eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch for (ShellWindowList::const_iterator it = windows.begin(); 264868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) it != windows.end(); ++it) { 265868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) native_windows.insert((*it)->GetNativeWindow()); 26690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 267eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (!native_windows.empty()) { 268eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ui::FocusWindowSet(native_windows); 269eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return; 270eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 271eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 272eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (focus_type == APP_SHIM_FOCUS_REOPEN) { 273eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const extensions::Extension* extension = 274eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch delegate_->GetAppExtension(profile, host->GetAppId()); 275eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (extension) { 276eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch delegate_->LaunchApp(profile, extension); 277eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } else { 278eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Extensions may have been uninstalled or disabled since the shim 279eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // started. 280eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch host->OnAppClosed(); 281eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 282eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 283eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 284eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 285eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid ExtensionAppShimHandler::OnShimSetHidden(Host* host, bool hidden) { 286eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK(delegate_->ProfileExistsForPath(host->GetProfilePath())); 287eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch Profile* profile = delegate_->ProfileForPath(host->GetProfilePath()); 288eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 289eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const ShellWindowList windows = 290eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch delegate_->GetWindows(profile, host->GetAppId()); 291eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch for (ShellWindowList::const_reverse_iterator it = windows.rbegin(); 292eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch it != windows.rend(); ++it) { 293eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (hidden) 294eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch (*it)->GetBaseWindow()->Hide(); 295eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch else 296eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch (*it)->GetBaseWindow()->ShowInactive(); 297eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 29890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 29990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 300868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void ExtensionAppShimHandler::OnShimQuit(Host* host) { 301eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK(delegate_->ProfileExistsForPath(host->GetProfilePath())); 302eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch Profile* profile = delegate_->ProfileForPath(host->GetProfilePath()); 303868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 304a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) const std::string& app_id = host->GetAppId(); 305eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const ShellWindowList windows = 306a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) delegate_->GetWindows(profile, app_id); 3074311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch for (ShellWindowRegistry::const_iterator it = windows.begin(); 308868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) it != windows.end(); ++it) { 309868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) (*it)->GetBaseWindow()->Close(); 310868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 311868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 312a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) DCHECK_NE(0u, hosts_.count(make_pair(profile, app_id))); 313a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) host->OnAppClosed(); 314868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 315eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (!browser_opened_ever_ && hosts_.empty()) 316eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch delegate_->MaybeTerminate(); 317eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 318868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 319eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid ExtensionAppShimHandler::set_delegate(Delegate* delegate) { 320eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch delegate_.reset(delegate); 32190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 32290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 32390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void ExtensionAppShimHandler::Observe( 32490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int type, 32590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const content::NotificationSource& source, 32690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const content::NotificationDetails& details) { 327eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (type == chrome::NOTIFICATION_BROWSER_OPENED) { 328eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch registrar_.Remove( 329eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch this, chrome::NOTIFICATION_BROWSER_OPENED, 330eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch content::NotificationService::AllBrowserContextsAndSources()); 331eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch browser_opened_ever_ = true; 332eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return; 333eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 334eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 33590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) Profile* profile = content::Source<Profile>(source).ptr(); 336eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (profile->IsOffTheRecord()) 337eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return; 338eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 33990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) switch (type) { 340eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch case chrome::NOTIFICATION_PROFILE_CREATED: { 341eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch AppLifetimeMonitorFactory::GetForProfile(profile)->AddObserver(this); 342eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch break; 343eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 344eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch case chrome::NOTIFICATION_PROFILE_DESTROYED: { 345eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch AppLifetimeMonitorFactory::GetForProfile(profile)->RemoveObserver(this); 346eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Shut down every shim associated with this profile. 347eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch for (HostMap::iterator it = hosts_.begin(); it != hosts_.end(); ) { 348eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Increment the iterator first as OnAppClosed may call back to 349eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // OnShimClose and invalidate the iterator. 350eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch HostMap::iterator current = it++; 351eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (profile->IsSameProfile(current->first.first)) 352eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch current->second->OnAppClosed(); 353eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 354868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) break; 355eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 3563240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch case chrome::NOTIFICATION_EXTENSION_PROCESS_TERMINATED: 357eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch case chrome::NOTIFICATION_EXTENSION_UNINSTALLED: { 3583240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch std::string app_id; 3593240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch if (type == chrome::NOTIFICATION_EXTENSION_PROCESS_TERMINATED) { 3603240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch app_id = content::Details<extensions::ExtensionHost>(details).ptr() 3613240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch ->extension_id(); 3623240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch } else { 3633240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch app_id = content::Details<extensions::Extension>(details).ptr()->id(); 3643240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch } 365a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) Host* host = FindHost(profile, app_id); 366a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (host) 367a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) host->OnAppClosed(); 36890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) break; 369eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 370eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch default: { 37190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) NOTREACHED(); // Unexpected notification. 37290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) break; 373eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 37490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 37590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 37690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 377eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid ExtensionAppShimHandler::OnAppStart(Profile* profile, 378eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const std::string& app_id) {} 379eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 380eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid ExtensionAppShimHandler::OnAppActivated(Profile* profile, 381eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const std::string& app_id) { 382eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const extensions::Extension* extension = 383eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch delegate_->GetAppExtension(profile, app_id); 384eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (!extension) 385868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return; 386868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 387a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) Host* host = FindHost(profile, app_id); 388a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (host) { 389a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) host->OnAppLaunchComplete(APP_SHIM_LAUNCH_SUCCESS); 390a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) OnShimFocus(host, APP_SHIM_FOCUS_NORMAL); 391868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return; 3927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 393868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 394eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch delegate_->LaunchShim(profile, extension); 395868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 396868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 397eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid ExtensionAppShimHandler::OnAppDeactivated(Profile* profile, 398eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const std::string& app_id) {} 399eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 400eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid ExtensionAppShimHandler::OnAppStop(Profile* profile, 401eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const std::string& app_id) {} 402eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 403eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid ExtensionAppShimHandler::OnChromeTerminating() {} 40490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 40590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} // namespace apps 406