Home | History | Annotate | Download | only in app_shim
      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 
     21 namespace apps {
     22 
     23 namespace {
     24 
     25 void 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 
     34 class 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
    109 void 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
    116 void AppShimHandler::RemoveHandler(const std::string& app_mode_id) {
    117   AppShimHandlerRegistry::GetInstance()->SetForAppMode(app_mode_id, NULL);
    118 }
    119 
    120 // static
    121 AppShimHandler* AppShimHandler::GetForAppMode(const std::string& app_mode_id) {
    122   return AppShimHandlerRegistry::GetInstance()->GetForAppMode(app_mode_id);
    123 }
    124 
    125 // static
    126 void AppShimHandler::SetDefaultHandler(AppShimHandler* handler) {
    127   AppShimHandlerRegistry::GetInstance()->SetDefaultHandler(handler);
    128 }
    129 
    130 // static
    131 void AppShimHandler::MaybeTerminate() {
    132   AppShimHandlerRegistry::GetInstance()->MaybeTerminate();
    133 }
    134 
    135 }  // namespace apps
    136