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 "apps/app_shim/app_shim_handler_mac.h" 6 7#include <map> 8 9#include "apps/shell_window_registry.h" 10#include "base/bind.h" 11#include "base/logging.h" 12#include "base/memory/singleton.h" 13#include "base/message_loop/message_loop.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 21namespace apps { 22 23namespace { 24 25void TerminateIfNoShellWindows() { 26 bool shell_windows_left = 27 apps::ShellWindowRegistry::IsShellWindowRegisteredInAnyProfile(0); 28 if (!shell_windows_left && !AppListService::Get( 29 chrome::HOST_DESKTOP_TYPE_NATIVE)->IsAppListVisible()) { 30 chrome::AttemptExit(); 31 } 32} 33 34class AppShimHandlerRegistry : public content::NotificationObserver { 35 public: 36 static AppShimHandlerRegistry* GetInstance() { 37 return Singleton<AppShimHandlerRegistry, 38 LeakySingletonTraits<AppShimHandlerRegistry> >::get(); 39 } 40 41 AppShimHandler* GetForAppMode(const std::string& app_mode_id) const { 42 HandlerMap::const_iterator it = handlers_.find(app_mode_id); 43 if (it != handlers_.end()) 44 return it->second; 45 46 return default_handler_; 47 } 48 49 bool SetForAppMode(const std::string& app_mode_id, AppShimHandler* handler) { 50 bool inserted_or_removed = handler ? 51 handlers_.insert(HandlerMap::value_type(app_mode_id, handler)).second : 52 handlers_.erase(app_mode_id) == 1; 53 DCHECK(inserted_or_removed); 54 return inserted_or_removed; 55 } 56 57 void SetDefaultHandler(AppShimHandler* handler) { 58 DCHECK_NE(default_handler_ == NULL, handler == NULL); 59 default_handler_ = handler; 60 } 61 62 void MaybeTerminate() { 63 if (!browser_opened_ever_) { 64 // Post this to give ShellWindows a chance to remove themselves from the 65 // registry. 66 base::MessageLoop::current()->PostTask( 67 FROM_HERE, 68 base::Bind(&TerminateIfNoShellWindows)); 69 } 70 } 71 72 private: 73 friend struct DefaultSingletonTraits<AppShimHandlerRegistry>; 74 typedef std::map<std::string, AppShimHandler*> HandlerMap; 75 76 AppShimHandlerRegistry() 77 : default_handler_(NULL), 78 browser_opened_ever_(false) { 79 registrar_.Add( 80 this, chrome::NOTIFICATION_BROWSER_OPENED, 81 content::NotificationService::AllBrowserContextsAndSources()); 82 } 83 84 virtual ~AppShimHandlerRegistry() {} 85 86 // content::NotificationObserver override: 87 virtual void Observe( 88 int type, 89 const content::NotificationSource& source, 90 const content::NotificationDetails& details) OVERRIDE { 91 DCHECK_EQ(chrome::NOTIFICATION_BROWSER_OPENED, type); 92 registrar_.Remove( 93 this, chrome::NOTIFICATION_BROWSER_OPENED, 94 content::NotificationService::AllBrowserContextsAndSources()); 95 browser_opened_ever_ = true; 96 } 97 98 HandlerMap handlers_; 99 AppShimHandler* default_handler_; 100 content::NotificationRegistrar registrar_; 101 bool browser_opened_ever_; 102 103 DISALLOW_COPY_AND_ASSIGN(AppShimHandlerRegistry); 104}; 105 106} // namespace 107 108// static 109void AppShimHandler::RegisterHandler(const std::string& app_mode_id, 110 AppShimHandler* handler) { 111 DCHECK(handler); 112 AppShimHandlerRegistry::GetInstance()->SetForAppMode(app_mode_id, handler); 113} 114 115// static 116void AppShimHandler::RemoveHandler(const std::string& app_mode_id) { 117 AppShimHandlerRegistry::GetInstance()->SetForAppMode(app_mode_id, NULL); 118} 119 120// static 121AppShimHandler* AppShimHandler::GetForAppMode(const std::string& app_mode_id) { 122 return AppShimHandlerRegistry::GetInstance()->GetForAppMode(app_mode_id); 123} 124 125// static 126void AppShimHandler::SetDefaultHandler(AppShimHandler* handler) { 127 AppShimHandlerRegistry::GetInstance()->SetDefaultHandler(handler); 128} 129 130// static 131void AppShimHandler::MaybeTerminate() { 132 AppShimHandlerRegistry::GetInstance()->MaybeTerminate(); 133} 134 135} // namespace apps 136