1868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 2868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// found in the LICENSE file. 4868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 5868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "apps/app_load_service.h" 6868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 7868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "apps/app_load_service_factory.h" 85f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "apps/app_restore_service.h" 9bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch#include "apps/launcher.h" 10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/extensions/extension_service.h" 115e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "chrome/browser/extensions/unpacked_installer.h" 125e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "chrome/browser/profiles/profile.h" 13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/public/browser/notification_details.h" 14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/public/browser/notification_service.h" 15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/public/browser/notification_types.h" 161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/browser/app_window/app_window_registry.h" 1723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "extensions/browser/extension_host.h" 185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extension_prefs.h" 191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/browser/extension_registry.h" 205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extension_system.h" 215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "extensions/browser/notification_types.h" 22f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/extension.h" 23868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 24868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)using extensions::Extension; 25868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)using extensions::ExtensionPrefs; 26a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)using extensions::ExtensionSystem; 27868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 28868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)namespace apps { 29868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 305e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)AppLoadService::PostReloadAction::PostReloadAction() 311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) : action_type(LAUNCH), 321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) command_line(CommandLine::NO_PROGRAM) { 335e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)} 345e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) 35868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)AppLoadService::AppLoadService(Profile* profile) 36868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) : profile_(profile) { 375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) registrar_.Add(this, 385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) extensions::NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING, 395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) content::NotificationService::AllSources()); 401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci extensions::ExtensionRegistry::Get(profile_)->AddObserver(this); 41868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 42868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciAppLoadService::~AppLoadService() { 441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci extensions::ExtensionRegistry::Get(profile_)->RemoveObserver(this); 451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 46868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 47868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void AppLoadService::RestartApplication(const std::string& extension_id) { 485e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) post_reload_actions_[extension_id].action_type = RESTART; 49868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ExtensionService* service = extensions::ExtensionSystem::Get(profile_)-> 50868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) extension_service(); 51868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(service); 52868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) service->ReloadExtension(extension_id); 53868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 54868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void AppLoadService::RestartApplicationIfRunning( 565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const std::string& extension_id) { 575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (apps::AppRestoreService::Get(profile_)->IsAppRestorable(extension_id)) 585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) RestartApplication(extension_id); 595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 615e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)bool AppLoadService::LoadAndLaunch(const base::FilePath& extension_path, 625e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) const CommandLine& command_line, 635e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) const base::FilePath& current_dir) { 64a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ExtensionService* extension_service = 655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ExtensionSystem::Get(profile_)->extension_service(); 665e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) std::string extension_id; 67a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!extensions::UnpackedInstaller::Create(extension_service)-> 685e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) LoadFromCommandLine(base::FilePath(extension_path), &extension_id)) { 695e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) return false; 705e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) } 715e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) 725e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) // Schedule the app to be launched once loaded. 735e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) PostReloadAction& action = post_reload_actions_[extension_id]; 745e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) action.action_type = LAUNCH_WITH_COMMAND_LINE; 755e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) action.command_line = command_line; 765e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) action.current_dir = current_dir; 775e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) return true; 78868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 79868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 80868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// static 81868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)AppLoadService* AppLoadService::Get(Profile* profile) { 82868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return apps::AppLoadServiceFactory::GetForProfile(profile); 83868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 84868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 85868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void AppLoadService::Observe(int type, 86868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const content::NotificationSource& source, 87868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const content::NotificationDetails& details) { 881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK_EQ(type, extensions::NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING); 891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci extensions::ExtensionHost* host = 901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci content::Details<extensions::ExtensionHost>(details).ptr(); 911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const Extension* extension = host->extension(); 921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // It is possible for an extension to be unloaded before it stops loading. 931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!extension) 941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci std::map<std::string, PostReloadAction>::iterator it = 961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci post_reload_actions_.find(extension->id()); 971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (it == post_reload_actions_.end()) 981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci switch (it->second.action_type) { 1011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci case LAUNCH: 1021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci LaunchPlatformApp(profile_, extension); 1031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci break; 1041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci case RESTART: 1051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci RestartPlatformApp(profile_, extension); 106868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) break; 1071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci case LAUNCH_WITH_COMMAND_LINE: 1081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci LaunchPlatformAppWithCommandLine( 1091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci profile_, extension, it->second.command_line, it->second.current_dir); 110868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) break; 111868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) default: 112868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) NOTREACHED(); 113868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 1141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci post_reload_actions_.erase(it); 1161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid AppLoadService::OnExtensionUnloaded( 1191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci content::BrowserContext* browser_context, 1201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const Extension* extension, 1211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci extensions::UnloadedExtensionInfo::Reason reason) { 1221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!extension->is_platform_app()) 1231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 1241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci extensions::ExtensionPrefs* extension_prefs = 1261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci extensions::ExtensionPrefs::Get(browser_context); 1271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (WasUnloadedForReload(extension->id(), reason) && 1281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci extension_prefs->IsActive(extension->id()) && 1291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci !HasPostReloadAction(extension->id())) { 1301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci post_reload_actions_[extension->id()].action_type = LAUNCH; 1311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 132868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 133868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 1347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool AppLoadService::WasUnloadedForReload( 1351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const extensions::ExtensionId& extension_id, 1361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const extensions::UnloadedExtensionInfo::Reason reason) { 1371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (reason == extensions::UnloadedExtensionInfo::REASON_DISABLE) { 1387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ExtensionPrefs* prefs = ExtensionPrefs::Get(profile_); 1391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return (prefs->GetDisableReasons(extension_id) & 1401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Extension::DISABLE_RELOAD) != 0; 1417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 1427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return false; 1437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 1447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochbool AppLoadService::HasPostReloadAction(const std::string& extension_id) { 1467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return post_reload_actions_.find(extension_id) != post_reload_actions_.end(); 1477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 1487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 149868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} // namespace apps 150