1 // Copyright 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "chrome/browser/apps/app_shim/app_shim_handler_mac.h" 6 7 #include <map> 8 9 #include "base/bind.h" 10 #include "base/logging.h" 11 #include "base/memory/singleton.h" 12 #include "base/message_loop/message_loop.h" 13 #include "chrome/browser/apps/app_window_registry_util.h" 14 #include "chrome/browser/chrome_notification_types.h" 15 #include "chrome/browser/lifetime/application_lifetime.h" 16 #include "chrome/browser/ui/app_list/app_list_service.h" 17 #include "content/public/browser/notification_observer.h" 18 #include "content/public/browser/notification_registrar.h" 19 #include "content/public/browser/notification_service.h" 20 21 namespace apps { 22 23 namespace { 24 25 void TerminateIfNoAppWindows() { 26 bool app_windows_left = 27 AppWindowRegistryUtil::IsAppWindowRegisteredInAnyProfile(0); 28 if (!app_windows_left && 29 !AppListService::Get(chrome::HOST_DESKTOP_TYPE_NATIVE) 30 ->IsAppListVisible()) { 31 chrome::AttemptExit(); 32 } 33 } 34 35 class AppShimHandlerRegistry : public content::NotificationObserver { 36 public: 37 static AppShimHandlerRegistry* GetInstance() { 38 return Singleton<AppShimHandlerRegistry, 39 LeakySingletonTraits<AppShimHandlerRegistry> >::get(); 40 } 41 42 AppShimHandler* GetForAppMode(const std::string& app_mode_id) const { 43 HandlerMap::const_iterator it = handlers_.find(app_mode_id); 44 if (it != handlers_.end()) 45 return it->second; 46 47 return default_handler_; 48 } 49 50 bool SetForAppMode(const std::string& app_mode_id, AppShimHandler* handler) { 51 bool inserted_or_removed = handler ? 52 handlers_.insert(HandlerMap::value_type(app_mode_id, handler)).second : 53 handlers_.erase(app_mode_id) == 1; 54 DCHECK(inserted_or_removed); 55 return inserted_or_removed; 56 } 57 58 void SetDefaultHandler(AppShimHandler* handler) { 59 DCHECK_NE(default_handler_ == NULL, handler == NULL); 60 default_handler_ = handler; 61 } 62 63 void MaybeTerminate() { 64 if (!browser_session_running_) { 65 // Post this to give AppWindows a chance to remove themselves from the 66 // registry. 67 base::MessageLoop::current()->PostTask( 68 FROM_HERE, base::Bind(&TerminateIfNoAppWindows)); 69 } 70 } 71 72 bool ShouldRestoreSession() { 73 return !browser_session_running_; 74 } 75 76 private: 77 friend struct DefaultSingletonTraits<AppShimHandlerRegistry>; 78 typedef std::map<std::string, AppShimHandler*> HandlerMap; 79 80 AppShimHandlerRegistry() 81 : default_handler_(NULL), 82 browser_session_running_(false) { 83 registrar_.Add( 84 this, chrome::NOTIFICATION_BROWSER_OPENED, 85 content::NotificationService::AllBrowserContextsAndSources()); 86 registrar_.Add( 87 this, chrome::NOTIFICATION_CLOSE_ALL_BROWSERS_REQUEST, 88 content::NotificationService::AllBrowserContextsAndSources()); 89 registrar_.Add( 90 this, chrome::NOTIFICATION_BROWSER_CLOSE_CANCELLED, 91 content::NotificationService::AllBrowserContextsAndSources()); 92 } 93 94 virtual ~AppShimHandlerRegistry() {} 95 96 // content::NotificationObserver override: 97 virtual void Observe( 98 int type, 99 const content::NotificationSource& source, 100 const content::NotificationDetails& details) OVERRIDE { 101 switch (type) { 102 case chrome::NOTIFICATION_BROWSER_OPENED: 103 case chrome::NOTIFICATION_BROWSER_CLOSE_CANCELLED: 104 browser_session_running_ = true; 105 break; 106 case chrome::NOTIFICATION_CLOSE_ALL_BROWSERS_REQUEST: 107 browser_session_running_ = false; 108 break; 109 default: 110 NOTREACHED(); 111 } 112 } 113 114 HandlerMap handlers_; 115 AppShimHandler* default_handler_; 116 content::NotificationRegistrar registrar_; 117 bool browser_session_running_; 118 119 DISALLOW_COPY_AND_ASSIGN(AppShimHandlerRegistry); 120 }; 121 122 } // namespace 123 124 // static 125 void AppShimHandler::RegisterHandler(const std::string& app_mode_id, 126 AppShimHandler* handler) { 127 DCHECK(handler); 128 AppShimHandlerRegistry::GetInstance()->SetForAppMode(app_mode_id, handler); 129 } 130 131 // static 132 void AppShimHandler::RemoveHandler(const std::string& app_mode_id) { 133 AppShimHandlerRegistry::GetInstance()->SetForAppMode(app_mode_id, NULL); 134 } 135 136 // static 137 AppShimHandler* AppShimHandler::GetForAppMode(const std::string& app_mode_id) { 138 return AppShimHandlerRegistry::GetInstance()->GetForAppMode(app_mode_id); 139 } 140 141 // static 142 void AppShimHandler::SetDefaultHandler(AppShimHandler* handler) { 143 AppShimHandlerRegistry::GetInstance()->SetDefaultHandler(handler); 144 } 145 146 // static 147 void AppShimHandler::MaybeTerminate() { 148 AppShimHandlerRegistry::GetInstance()->MaybeTerminate(); 149 } 150 151 // static 152 bool AppShimHandler::ShouldRestoreSession() { 153 return AppShimHandlerRegistry::GetInstance()->ShouldRestoreSession(); 154 } 155 156 } // namespace apps 157