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) 51320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chrome/browser/apps/app_shim/extension_app_shim_handler_mac.h" 690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 7eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "apps/app_lifetime_monitor_factory.h" 858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "apps/launcher.h" 990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/files/file_path.h" 1090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/logging.h" 111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chrome/browser/apps/app_shim/app_shim_host_manager_mac.h" 12eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/browser/browser_process.h" 137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.h" 14eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/browser/profiles/profile.h" 15eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/browser/profiles/profile_manager.h" 165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/ui/extensions/extension_enable_flow.h" 175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/ui/extensions/extension_enable_flow_delegate.h" 183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "chrome/browser/ui/webui/ntp/core_app_launcher_handler.h" 19868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/web_applications/web_app_mac.h" 203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "chrome/common/extensions/extension_constants.h" 211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chrome/common/mac/app_shim_messages.h" 2203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "components/crx_file/id_util.h" 237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "content/public/browser/notification_details.h" 247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "content/public/browser/notification_service.h" 257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "content/public/browser/notification_source.h" 261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/browser/app_window/app_window.h" 271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/browser/app_window/app_window_registry.h" 2803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "extensions/browser/app_window/native_app_window.h" 2923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "extensions/browser/extension_host.h" 305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extension_registry.h" 3190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ui/base/cocoa/focus_window_set.h" 3290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciusing extensions::AppWindow; 341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciusing extensions::AppWindowRegistry; 355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using extensions::ExtensionRegistry; 365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochnamespace { 387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccitypedef AppWindowRegistry::AppWindowList AppWindowList; 40424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid ProfileLoadedCallback(base::Callback<void(Profile*)> callback, 427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch Profile* profile, 437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch Profile::CreateStatus status) { 447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (status == Profile::CREATE_STATUS_INITIALIZED) { 457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch callback.Run(profile); 467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return; 477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // This should never get an error since it only loads existing profiles. 507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch DCHECK_EQ(Profile::CREATE_STATUS_CREATED, status); 517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 53424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void SetAppHidden(Profile* profile, const std::string& app_id, bool hidden) { 545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) AppWindowList windows = 551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci AppWindowRegistry::Get(profile)->GetAppWindowsForApp(app_id); 565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (AppWindowList::const_reverse_iterator it = windows.rbegin(); 575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) it != windows.rend(); 585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ++it) { 59424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (hidden) 60424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) (*it)->GetBaseWindow()->HideWithApp(); 61424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) else 62424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) (*it)->GetBaseWindow()->ShowWithApp(); 63424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 64424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 65424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool FocusWindows(const AppWindowList& windows) { 67d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (windows.empty()) 68d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return false; 69d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 70d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) std::set<gfx::NativeWindow> native_windows; 715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (AppWindowList::const_iterator it = windows.begin(); it != windows.end(); 725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ++it) { 73d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) native_windows.insert((*it)->GetNativeWindow()); 74d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 75d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Allow workspace switching. For the browser process, we can reasonably rely 76d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // on OS X to switch spaces for us and honor relevant user settings. But shims 77d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // don't have windows, so we have to do it ourselves. 78cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ui::FocusWindowSet(native_windows); 79d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return true; 80d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 81d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Attempts to launch a packaged app, prompting the user to enable it if 835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// necessary. The prompt is shown in its own window. 845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// This class manages its own lifetime. 855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class EnableViaPrompt : public ExtensionEnableFlowDelegate { 865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public: 875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EnableViaPrompt(Profile* profile, 885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& extension_id, 895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::Callback<void()>& callback) 905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : profile_(profile), 915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) extension_id_(extension_id), 925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback_(callback) { 935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual ~EnableViaPrompt() { 965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void Run() { 995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) flow_.reset(new ExtensionEnableFlow(profile_, extension_id_, this)); 1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) flow_->StartForCurrentlyNonexistentWindow( 1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Callback<gfx::NativeWindow(void)>()); 1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private: 1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // ExtensionEnableFlowDelegate overrides. 1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual void ExtensionEnableFlowFinished() OVERRIDE { 1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback_.Run(); 1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) delete this; 1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual void ExtensionEnableFlowAborted(bool user_initiated) OVERRIDE { 1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback_.Run(); 1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) delete this; 1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Profile* profile_; 1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string extension_id_; 1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Callback<void()> callback_; 1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<ExtensionEnableFlow> flow_; 1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(EnableViaPrompt); 1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}; 1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} // namespace 1257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 12690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace apps { 12790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 128eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool ExtensionAppShimHandler::Delegate::ProfileExistsForPath( 129eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const base::FilePath& path) { 130eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ProfileManager* profile_manager = g_browser_process->profile_manager(); 131eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Check for the profile name in the profile info cache to ensure that we 132eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // never access any directory that isn't a known profile. 133eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::FilePath full_path = profile_manager->user_data_dir().Append(path); 134eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ProfileInfoCache& cache = profile_manager->GetProfileInfoCache(); 135eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return cache.GetIndexOfProfileWithPath(full_path) != std::string::npos; 136868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 13790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 138eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochProfile* ExtensionAppShimHandler::Delegate::ProfileForPath( 139eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const base::FilePath& path) { 140eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ProfileManager* profile_manager = g_browser_process->profile_manager(); 141eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::FilePath full_path = profile_manager->user_data_dir().Append(path); 1427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch Profile* profile = profile_manager->GetProfileByPath(full_path); 1437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // Use IsValidProfile to check if the profile has been created. 1457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return profile && profile_manager->IsValidProfile(profile) ? profile : NULL; 1467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 1477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid ExtensionAppShimHandler::Delegate::LoadProfileAsync( 1497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch const base::FilePath& path, 1507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch base::Callback<void(Profile*)> callback) { 1517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ProfileManager* profile_manager = g_browser_process->profile_manager(); 1527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch base::FilePath full_path = profile_manager->user_data_dir().Append(path); 1537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch profile_manager->CreateProfileAsync( 1547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch full_path, 1557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch base::Bind(&ProfileLoadedCallback, callback), 1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::string16(), base::string16(), std::string()); 157eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 158eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)AppWindowList ExtensionAppShimHandler::Delegate::GetWindows( 160eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch Profile* profile, 161eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const std::string& extension_id) { 1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return AppWindowRegistry::Get(profile)->GetAppWindowsForApp(extension_id); 163eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 164eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 165eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst extensions::Extension* 166eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochExtensionAppShimHandler::Delegate::GetAppExtension( 167eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch Profile* profile, 168eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const std::string& extension_id) { 1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ExtensionRegistry* registry = ExtensionRegistry::Get(profile); 170eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const extensions::Extension* extension = 1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) registry->GetExtensionById(extension_id, ExtensionRegistry::ENABLED); 172eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return extension && extension->is_platform_app() ? extension : NULL; 173eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 174eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ExtensionAppShimHandler::Delegate::EnableExtension( 1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Profile* profile, 1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& extension_id, 1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::Callback<void()>& callback) { 1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (new EnableViaPrompt(profile, extension_id, callback))->Run(); 1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 182eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid ExtensionAppShimHandler::Delegate::LaunchApp( 183eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch Profile* profile, 18458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const extensions::Extension* extension, 18558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const std::vector<base::FilePath>& files) { 1863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) CoreAppLauncherHandler::RecordAppLaunchType( 1873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) extension_misc::APP_LAUNCH_CMD_LINE_APP, extension->GetType()); 18868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (files.empty()) { 18968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) apps::LaunchPlatformApp(profile, extension); 19068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } else { 19168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) for (std::vector<base::FilePath>::const_iterator it = files.begin(); 19268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) it != files.end(); ++it) { 19368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) apps::LaunchPlatformAppWithPath(profile, extension, *it); 19468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 19558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 196eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 197eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 198eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid ExtensionAppShimHandler::Delegate::LaunchShim( 199eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch Profile* profile, 200eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const extensions::Extension* extension) { 201eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch web_app::MaybeLaunchShortcut( 202eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch web_app::ShortcutInfoForExtensionAndProfile(extension, profile)); 203eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 204eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 205eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid ExtensionAppShimHandler::Delegate::MaybeTerminate() { 2064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) AppShimHandler::MaybeTerminate(); 20790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 20890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 209eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochExtensionAppShimHandler::ExtensionAppShimHandler() 210eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch : delegate_(new Delegate), 2117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch weak_factory_(this) { 212eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // This is instantiated in BrowserProcessImpl::PreMainMessageLoopRun with 213eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // AppShimHostManager. Since PROFILE_CREATED is not fired until 214eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // ProfileManager::GetLastUsedProfile/GetLastOpenedProfiles, this should catch 215eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // notifications for all profiles. 216eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch registrar_.Add(this, chrome::NOTIFICATION_PROFILE_CREATED, 217eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch content::NotificationService::AllBrowserContextsAndSources()); 218eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED, 219eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch content::NotificationService::AllBrowserContextsAndSources()); 220eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 221eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 222eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochExtensionAppShimHandler::~ExtensionAppShimHandler() {} 223eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 224a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)AppShimHandler::Host* ExtensionAppShimHandler::FindHost( 225a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) Profile* profile, 226a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) const std::string& app_id) { 227a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) HostMap::iterator it = hosts_.find(make_pair(profile, app_id)); 228a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return it == hosts_.end() ? NULL : it->second; 229a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 230a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 231a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// static 2325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ExtensionAppShimHandler::QuitAppForWindow(AppWindow* app_window) { 2335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ExtensionAppShimHandler* handler = GetInstance(); 2345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Host* host = handler->FindHost( 2355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Profile::FromBrowserContext(app_window->browser_context()), 2365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) app_window->extension_id()); 237a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (host) { 238a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) handler->OnShimQuit(host); 239a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } else { 240a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // App shims might be disabled or the shim is still starting up. 2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) AppWindowRegistry::Get( 2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Profile::FromBrowserContext(app_window->browser_context())) 2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ->CloseAllAppWindowsForApp(app_window->extension_id()); 244a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 245a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 246a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ExtensionAppShimHandler::HideAppForWindow(AppWindow* app_window) { 2485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ExtensionAppShimHandler* handler = GetInstance(); 2495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Profile* profile = Profile::FromBrowserContext(app_window->browser_context()); 2505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Host* host = handler->FindHost(profile, app_window->extension_id()); 25158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (host) 25258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) host->OnAppHide(); 25358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) else 2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SetAppHidden(profile, app_window->extension_id(), true); 25558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 25658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ExtensionAppShimHandler::FocusAppForWindow(AppWindow* app_window) { 2585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ExtensionAppShimHandler* handler = GetInstance(); 2595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Profile* profile = Profile::FromBrowserContext(app_window->browser_context()); 2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& app_id = app_window->extension_id(); 261d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) Host* host = handler->FindHost(profile, app_id); 262d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (host) { 263d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) handler->OnShimFocus(host, 264d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) APP_SHIM_FOCUS_NORMAL, 265d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) std::vector<base::FilePath>()); 266d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } else { 2671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci FocusWindows(AppWindowRegistry::Get(profile)->GetAppWindowsForApp(app_id)); 268d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 269d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 270d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 271424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// static 27203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)bool ExtensionAppShimHandler::ActivateAndRequestUserAttentionForWindow( 2735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) AppWindow* app_window) { 2745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ExtensionAppShimHandler* handler = GetInstance(); 2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Profile* profile = Profile::FromBrowserContext(app_window->browser_context()); 2765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Host* host = handler->FindHost(profile, app_window->extension_id()); 277424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (host) { 278424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Bring the window to the front without showing it. 2795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) AppWindowRegistry::Get(profile)->AppWindowActivated(app_window); 28003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) host->OnAppRequestUserAttention(APP_SHIM_ATTENTION_INFORMATIONAL); 281424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return true; 282424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } else { 283424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Just show the app. 2845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SetAppHidden(profile, app_window->extension_id(), false); 285424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return false; 286424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 287424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 288424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 2895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// static 29003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void ExtensionAppShimHandler::RequestUserAttentionForWindow( 29103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) AppWindow* app_window, 29203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) AppShimAttentionType attention_type) { 29303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) ExtensionAppShimHandler* handler = GetInstance(); 29403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) Profile* profile = Profile::FromBrowserContext(app_window->browser_context()); 29503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) Host* host = handler->FindHost(profile, app_window->extension_id()); 29603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (host) 29703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) host->OnAppRequestUserAttention(attention_type); 29803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 29903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 30003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// static 3015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void ExtensionAppShimHandler::OnChromeWillHide() { 3025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Send OnAppHide to all the shims so that they go into the hidden state. 3035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // This is necessary so that when the shim is next focused, it will know to 3045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // unhide. 3055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ExtensionAppShimHandler* handler = GetInstance(); 3065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for (HostMap::iterator it = handler->hosts_.begin(); 3075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) it != handler->hosts_.end(); 3085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ++it) { 3095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) it->second->OnAppHide(); 3105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 3115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 3125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 31358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void ExtensionAppShimHandler::OnShimLaunch( 31458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) Host* host, 31558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) AppShimLaunchType launch_type, 31658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const std::vector<base::FilePath>& files) { 3177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch const std::string& app_id = host->GetAppId(); 31803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DCHECK(crx_file::id_util::IdIsValid(app_id)); 3197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 320eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const base::FilePath& profile_path = host->GetProfilePath(); 321eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK(!profile_path.empty()); 322eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 323eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (!delegate_->ProfileExistsForPath(profile_path)) { 324eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // User may have deleted the profile this shim was originally created for. 325eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // TODO(jackhou): Add some UI for this case and remove the LOG. 326eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch LOG(ERROR) << "Requested directory is not a known profile '" 327eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch << profile_path.value() << "'."; 3287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch host->OnAppLaunchComplete(APP_SHIM_LAUNCH_PROFILE_NOT_FOUND); 3297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return; 330eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 331eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 332eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch Profile* profile = delegate_->ProfileForPath(profile_path); 33390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 3347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (profile) { 33558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) OnProfileLoaded(host, launch_type, files, profile); 3367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return; 33790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 33890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 3397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // If the profile is not loaded, this must have been a launch by the shim. 3407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // Load the profile asynchronously, the host will be registered in 3417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // OnProfileLoaded. 3427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch DCHECK_EQ(APP_SHIM_LAUNCH_NORMAL, launch_type); 3437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch delegate_->LoadProfileAsync( 3447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch profile_path, 3457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch base::Bind(&ExtensionAppShimHandler::OnProfileLoaded, 3467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch weak_factory_.GetWeakPtr(), 34758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) host, launch_type, files)); 3487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 3497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // Return now. OnAppLaunchComplete will be called when the app is activated. 3507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 3517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 3525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// static 3535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)ExtensionAppShimHandler* ExtensionAppShimHandler::GetInstance() { 3545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return g_browser_process->platform_part() 3555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ->app_shim_host_manager() 3565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ->extension_app_shim_handler(); 3575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 3585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 35958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void ExtensionAppShimHandler::OnProfileLoaded( 36058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) Host* host, 36158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) AppShimLaunchType launch_type, 36258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const std::vector<base::FilePath>& files, 36358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) Profile* profile) { 3647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch const std::string& app_id = host->GetAppId(); 36590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 3667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // The first host to claim this (profile, app_id) becomes the main host. 3677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // For any others, focus or relaunch the app. 3687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!hosts_.insert(make_pair(make_pair(profile, app_id), host)).second) { 3697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch OnShimFocus(host, 3707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch launch_type == APP_SHIM_LAUNCH_NORMAL ? 37158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) APP_SHIM_FOCUS_REOPEN : APP_SHIM_FOCUS_NORMAL, 37258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) files); 3737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch host->OnAppLaunchComplete(APP_SHIM_LAUNCH_DUPLICATE_HOST); 3747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return; 375868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 37690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 3775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (launch_type != APP_SHIM_LAUNCH_NORMAL) { 3785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) host->OnAppLaunchComplete(APP_SHIM_LAUNCH_SUCCESS); 3795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 3805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 382eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // TODO(jeremya): Handle the case that launching the app fails. Probably we 383eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // need to watch for 'app successfully launched' or at least 'background page 384eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // exists/was created' and time out with failure if we don't see that sign of 385eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // life within a certain window. 3865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const extensions::Extension* extension = 3875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) delegate_->GetAppExtension(profile, app_id); 3885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (extension) { 38958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) delegate_->LaunchApp(profile, extension, files); 3905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 3915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) delegate_->EnableExtension( 3945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) profile, app_id, 3955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&ExtensionAppShimHandler::OnExtensionEnabled, 3965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) weak_factory_.GetWeakPtr(), 3975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) host->GetProfilePath(), app_id, files)); 39890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 39990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 4005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ExtensionAppShimHandler::OnExtensionEnabled( 4015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::FilePath& profile_path, 4025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& app_id, 4035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::vector<base::FilePath>& files) { 4045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Profile* profile = delegate_->ProfileForPath(profile_path); 4055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!profile) 4065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 4075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const extensions::Extension* extension = 4095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) delegate_->GetAppExtension(profile, app_id); 4105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!extension || !delegate_->ProfileExistsForPath(profile_path)) { 4115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // If !extension, the extension doesn't exist, or was not re-enabled. 4125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // If the profile doesn't exist, it may have been deleted during the enable 4135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // prompt. In this case, NOTIFICATION_PROFILE_DESTROYED may not be fired 4145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // until later, so respond to the host now. 4155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Host* host = FindHost(profile, app_id); 4165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (host) 4175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) host->OnAppLaunchComplete(APP_SHIM_LAUNCH_APP_NOT_FOUND); 4185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 4195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) delegate_->LaunchApp(profile, extension, files); 4225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 4235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 42590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void ExtensionAppShimHandler::OnShimClose(Host* host) { 4267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // This might be called when shutting down. Don't try to look up the profile 4277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // since profile_manager might not be around. 4287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch for (HostMap::iterator it = hosts_.begin(); it != hosts_.end(); ) { 4297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch HostMap::iterator current = it++; 4307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (current->second == host) 4317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch hosts_.erase(current); 4327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 43390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 43490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 43558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void ExtensionAppShimHandler::OnShimFocus( 43658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) Host* host, 43758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) AppShimFocusType focus_type, 43858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const std::vector<base::FilePath>& files) { 439eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK(delegate_->ProfileExistsForPath(host->GetProfilePath())); 440eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch Profile* profile = delegate_->ProfileForPath(host->GetProfilePath()); 44190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 4425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const AppWindowList windows = 443eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch delegate_->GetWindows(profile, host->GetAppId()); 444d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) bool windows_focused = FocusWindows(windows); 44558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 44658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (focus_type == APP_SHIM_FOCUS_NORMAL || 447d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) (focus_type == APP_SHIM_FOCUS_REOPEN && windows_focused)) { 448eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return; 449eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 450eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 45158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const extensions::Extension* extension = 45258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) delegate_->GetAppExtension(profile, host->GetAppId()); 45358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (extension) { 45458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) delegate_->LaunchApp(profile, extension, files); 45558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } else { 45658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Extensions may have been uninstalled or disabled since the shim 45758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // started. 45858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) host->OnAppClosed(); 459eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 460eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 461eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 462eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid ExtensionAppShimHandler::OnShimSetHidden(Host* host, bool hidden) { 463eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK(delegate_->ProfileExistsForPath(host->GetProfilePath())); 464eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch Profile* profile = delegate_->ProfileForPath(host->GetProfilePath()); 465eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 466424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) SetAppHidden(profile, host->GetAppId(), hidden); 46790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 46890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 469868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void ExtensionAppShimHandler::OnShimQuit(Host* host) { 470eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK(delegate_->ProfileExistsForPath(host->GetProfilePath())); 471eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch Profile* profile = delegate_->ProfileForPath(host->GetProfilePath()); 472868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 473a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) const std::string& app_id = host->GetAppId(); 4745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const AppWindowList windows = delegate_->GetWindows(profile, app_id); 4755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (AppWindowRegistry::const_iterator it = windows.begin(); 4765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) it != windows.end(); 4775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ++it) { 478868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) (*it)->GetBaseWindow()->Close(); 479868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 480424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Once the last window closes, flow will end up in OnAppDeactivated via 481424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // AppLifetimeMonitor. 482eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 483868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 484eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid ExtensionAppShimHandler::set_delegate(Delegate* delegate) { 485eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch delegate_.reset(delegate); 48690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 48790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 48890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void ExtensionAppShimHandler::Observe( 48990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int type, 49090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const content::NotificationSource& source, 49190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const content::NotificationDetails& details) { 49290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) Profile* profile = content::Source<Profile>(source).ptr(); 493eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (profile->IsOffTheRecord()) 494eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return; 495eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 49690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) switch (type) { 497eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch case chrome::NOTIFICATION_PROFILE_CREATED: { 498eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch AppLifetimeMonitorFactory::GetForProfile(profile)->AddObserver(this); 499eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch break; 500eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 501eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch case chrome::NOTIFICATION_PROFILE_DESTROYED: { 502eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch AppLifetimeMonitorFactory::GetForProfile(profile)->RemoveObserver(this); 503eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Shut down every shim associated with this profile. 504eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch for (HostMap::iterator it = hosts_.begin(); it != hosts_.end(); ) { 505eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Increment the iterator first as OnAppClosed may call back to 506eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // OnShimClose and invalidate the iterator. 507eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch HostMap::iterator current = it++; 5085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (profile->IsSameProfile(current->first.first)) { 5095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Host* host = current->second; 5105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) host->OnAppClosed(); 5115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 512eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 513868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) break; 514eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 515eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch default: { 51690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) NOTREACHED(); // Unexpected notification. 51790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) break; 518eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 51990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 52090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 52190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 522eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid ExtensionAppShimHandler::OnAppStart(Profile* profile, 523eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const std::string& app_id) {} 524eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 525eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid ExtensionAppShimHandler::OnAppActivated(Profile* profile, 526eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const std::string& app_id) { 527eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const extensions::Extension* extension = 528eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch delegate_->GetAppExtension(profile, app_id); 529eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (!extension) 530868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return; 531868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 532a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) Host* host = FindHost(profile, app_id); 533a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (host) { 534a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) host->OnAppLaunchComplete(APP_SHIM_LAUNCH_SUCCESS); 53558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) OnShimFocus(host, APP_SHIM_FOCUS_NORMAL, std::vector<base::FilePath>()); 536868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return; 5377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 538868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 539eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch delegate_->LaunchShim(profile, extension); 540868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 541868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 542eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid ExtensionAppShimHandler::OnAppDeactivated(Profile* profile, 543424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) const std::string& app_id) { 544424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) Host* host = FindHost(profile, app_id); 545424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (host) 546424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) host->OnAppClosed(); 547424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 5484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (hosts_.empty()) 549424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) delegate_->MaybeTerminate(); 550424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 551eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 552eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid ExtensionAppShimHandler::OnAppStop(Profile* profile, 553eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const std::string& app_id) {} 554eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 555eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid ExtensionAppShimHandler::OnChromeTerminating() {} 55690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 55790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} // namespace apps 558