• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/app_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 
TerminateIfNoAppWindows()25 void TerminateIfNoAppWindows() {
26   bool app_windows_left =
27       apps::AppWindowRegistry::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:
GetInstance()37   static AppShimHandlerRegistry* GetInstance() {
38     return Singleton<AppShimHandlerRegistry,
39                      LeakySingletonTraits<AppShimHandlerRegistry> >::get();
40   }
41 
GetForAppMode(const std::string & app_mode_id) const42   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 
SetForAppMode(const std::string & app_mode_id,AppShimHandler * handler)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 
SetDefaultHandler(AppShimHandler * handler)58   void SetDefaultHandler(AppShimHandler* handler) {
59     DCHECK_NE(default_handler_ == NULL, handler == NULL);
60     default_handler_ = handler;
61   }
62 
MaybeTerminate()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 
ShouldRestoreSession()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 
AppShimHandlerRegistry()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 
~AppShimHandlerRegistry()94   virtual ~AppShimHandlerRegistry() {}
95 
96   // content::NotificationObserver override:
Observe(int type,const content::NotificationSource & source,const content::NotificationDetails & details)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
RegisterHandler(const std::string & app_mode_id,AppShimHandler * handler)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
RemoveHandler(const std::string & app_mode_id)132 void AppShimHandler::RemoveHandler(const std::string& app_mode_id) {
133   AppShimHandlerRegistry::GetInstance()->SetForAppMode(app_mode_id, NULL);
134 }
135 
136 // static
GetForAppMode(const std::string & app_mode_id)137 AppShimHandler* AppShimHandler::GetForAppMode(const std::string& app_mode_id) {
138   return AppShimHandlerRegistry::GetInstance()->GetForAppMode(app_mode_id);
139 }
140 
141 // static
SetDefaultHandler(AppShimHandler * handler)142 void AppShimHandler::SetDefaultHandler(AppShimHandler* handler) {
143   AppShimHandlerRegistry::GetInstance()->SetDefaultHandler(handler);
144 }
145 
146 // static
MaybeTerminate()147 void AppShimHandler::MaybeTerminate() {
148   AppShimHandlerRegistry::GetInstance()->MaybeTerminate();
149 }
150 
151 // static
ShouldRestoreSession()152 bool AppShimHandler::ShouldRestoreSession() {
153   return AppShimHandlerRegistry::GetInstance()->ShouldRestoreSession();
154 }
155 
156 }  // namespace apps
157