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_lifetime_monitor.h"
6
7#include "apps/app_window.h"
8#include "chrome/browser/chrome_notification_types.h"
9#include "chrome/browser/profiles/profile.h"
10#include "content/public/browser/notification_details.h"
11#include "content/public/browser/notification_service.h"
12#include "extensions/browser/extension_host.h"
13#include "extensions/common/extension.h"
14
15namespace apps {
16
17using extensions::Extension;
18using extensions::ExtensionHost;
19
20AppLifetimeMonitor::AppLifetimeMonitor(Profile* profile)
21    : profile_(profile) {
22  registrar_.Add(
23      this, chrome::NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING,
24      content::NotificationService::AllSources());
25  registrar_.Add(
26      this, chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED,
27      content::NotificationService::AllSources());
28  registrar_.Add(
29      this, chrome::NOTIFICATION_APP_TERMINATING,
30      content::NotificationService::AllSources());
31
32  AppWindowRegistry* app_window_registry =
33      AppWindowRegistry::Factory::GetForBrowserContext(profile_,
34                                                       false /* create */);
35  DCHECK(app_window_registry);
36  app_window_registry->AddObserver(this);
37}
38
39AppLifetimeMonitor::~AppLifetimeMonitor() {}
40
41void AppLifetimeMonitor::AddObserver(Observer* observer) {
42  observers_.AddObserver(observer);
43}
44
45void AppLifetimeMonitor::RemoveObserver(Observer* observer) {
46  observers_.RemoveObserver(observer);
47}
48
49void AppLifetimeMonitor::Observe(int type,
50                                const content::NotificationSource& source,
51                                const content::NotificationDetails& details) {
52  switch (type) {
53    case chrome::NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING: {
54      ExtensionHost* host = content::Details<ExtensionHost>(details).ptr();
55      const Extension* extension = host->extension();
56      if (!extension || !extension->is_platform_app())
57        return;
58
59      NotifyAppStart(extension->id());
60      break;
61    }
62
63    case chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED: {
64      ExtensionHost* host = content::Details<ExtensionHost>(details).ptr();
65      const Extension* extension = host->extension();
66      if (!extension || !extension->is_platform_app())
67        return;
68
69      NotifyAppStop(extension->id());
70      break;
71    }
72
73    case chrome::NOTIFICATION_APP_TERMINATING: {
74      NotifyChromeTerminating();
75      break;
76    }
77  }
78}
79
80void AppLifetimeMonitor::OnAppWindowRemoved(AppWindow* app_window) {
81  if (!HasVisibleAppWindows(app_window))
82    NotifyAppDeactivated(app_window->extension_id());
83}
84
85void AppLifetimeMonitor::OnAppWindowHidden(AppWindow* app_window) {
86  if (!HasVisibleAppWindows(app_window))
87    NotifyAppDeactivated(app_window->extension_id());
88}
89
90void AppLifetimeMonitor::OnAppWindowShown(AppWindow* app_window) {
91  if (app_window->window_type() != AppWindow::WINDOW_TYPE_DEFAULT)
92    return;
93
94  if (HasVisibleAppWindows(app_window))
95    NotifyAppActivated(app_window->extension_id());
96}
97
98void AppLifetimeMonitor::Shutdown() {
99  AppWindowRegistry* app_window_registry =
100      AppWindowRegistry::Factory::GetForBrowserContext(profile_,
101                                                       false /* create */);
102  if (app_window_registry)
103    app_window_registry->RemoveObserver(this);
104}
105
106bool AppLifetimeMonitor::HasVisibleAppWindows(AppWindow* app_window) const {
107  AppWindowRegistry::AppWindowList windows =
108      AppWindowRegistry::Get(app_window->browser_context())
109          ->GetAppWindowsForApp(app_window->extension_id());
110
111  for (AppWindowRegistry::AppWindowList::const_iterator i = windows.begin();
112       i != windows.end();
113       ++i) {
114    if (!(*i)->is_hidden())
115      return true;
116  }
117  return false;
118}
119
120void AppLifetimeMonitor::NotifyAppStart(const std::string& app_id) {
121  FOR_EACH_OBSERVER(Observer, observers_, OnAppStart(profile_, app_id));
122}
123
124void AppLifetimeMonitor::NotifyAppActivated(const std::string& app_id) {
125  FOR_EACH_OBSERVER(Observer, observers_, OnAppActivated(profile_, app_id));
126}
127
128void AppLifetimeMonitor::NotifyAppDeactivated(const std::string& app_id) {
129  FOR_EACH_OBSERVER(Observer, observers_, OnAppDeactivated(profile_, app_id));
130}
131
132void AppLifetimeMonitor::NotifyAppStop(const std::string& app_id) {
133  FOR_EACH_OBSERVER(Observer, observers_, OnAppStop(profile_, app_id));
134}
135
136void AppLifetimeMonitor::NotifyChromeTerminating() {
137  FOR_EACH_OBSERVER(Observer, observers_, OnChromeTerminating());
138}
139
140}  // namespace apps
141