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/extensions/install_tracker.h"
6
7#include "base/bind.h"
8#include "chrome/browser/chrome_notification_types.h"
9#include "chrome/browser/extensions/install_tracker_factory.h"
10#include "content/public/browser/notification_service.h"
11#include "extensions/browser/extension_prefs.h"
12#include "extensions/browser/extension_registry.h"
13#include "extensions/browser/pref_names.h"
14
15namespace extensions {
16
17InstallTracker::InstallTracker(content::BrowserContext* browser_context,
18                               extensions::ExtensionPrefs* prefs)
19    : extension_registry_observer_(this) {
20  registrar_.Add(this,
21                 extensions::NOTIFICATION_EXTENSION_UPDATE_DISABLED,
22                 content::Source<content::BrowserContext>(browser_context));
23  registrar_.Add(this,
24                 chrome::NOTIFICATION_APP_INSTALLED_TO_APPLIST,
25                 content::Source<content::BrowserContext>(browser_context));
26  extension_registry_observer_.Add(ExtensionRegistry::Get(browser_context));
27
28  // Prefs may be null in tests.
29  if (prefs) {
30    AppSorting* sorting = prefs->app_sorting();
31    registrar_.Add(this,
32                   chrome::NOTIFICATION_APP_LAUNCHER_REORDERED,
33                   content::Source<AppSorting>(sorting));
34    pref_change_registrar_.Init(prefs->pref_service());
35    pref_change_registrar_.Add(
36        pref_names::kExtensions,
37        base::Bind(&InstallTracker::OnAppsReordered, base::Unretained(this)));
38  }
39}
40
41InstallTracker::~InstallTracker() {
42}
43
44// static
45InstallTracker* InstallTracker::Get(content::BrowserContext* context) {
46  return InstallTrackerFactory::GetForBrowserContext(context);
47}
48
49void InstallTracker::AddObserver(InstallObserver* observer) {
50  observers_.AddObserver(observer);
51}
52
53void InstallTracker::RemoveObserver(InstallObserver* observer) {
54  observers_.RemoveObserver(observer);
55}
56
57const ActiveInstallData* InstallTracker::GetActiveInstall(
58    const std::string& extension_id) const {
59  ActiveInstallsMap::const_iterator install_data =
60      active_installs_.find(extension_id);
61  if (install_data == active_installs_.end())
62    return NULL;
63  else
64    return &(install_data->second);
65}
66
67void InstallTracker::AddActiveInstall(const ActiveInstallData& install_data) {
68  DCHECK(!install_data.extension_id.empty());
69  DCHECK(active_installs_.find(install_data.extension_id) ==
70         active_installs_.end());
71  active_installs_.insert(
72      std::make_pair(install_data.extension_id, install_data));
73}
74
75void InstallTracker::RemoveActiveInstall(const std::string& extension_id) {
76  active_installs_.erase(extension_id);
77}
78
79void InstallTracker::OnBeginExtensionInstall(
80    const InstallObserver::ExtensionInstallParams& params) {
81  ActiveInstallsMap::iterator install_data =
82      active_installs_.find(params.extension_id);
83  if (install_data == active_installs_.end()) {
84    ActiveInstallData install_data(params.extension_id);
85    install_data.is_ephemeral = params.is_ephemeral;
86    active_installs_.insert(std::make_pair(params.extension_id, install_data));
87  }
88
89  FOR_EACH_OBSERVER(InstallObserver, observers_,
90                    OnBeginExtensionInstall(params));
91}
92
93void InstallTracker::OnBeginExtensionDownload(const std::string& extension_id) {
94  FOR_EACH_OBSERVER(
95      InstallObserver, observers_, OnBeginExtensionDownload(extension_id));
96}
97
98void InstallTracker::OnDownloadProgress(const std::string& extension_id,
99                                        int percent_downloaded) {
100  ActiveInstallsMap::iterator install_data =
101      active_installs_.find(extension_id);
102  if (install_data != active_installs_.end()) {
103    install_data->second.percent_downloaded = percent_downloaded;
104  } else {
105    NOTREACHED();
106  }
107
108  FOR_EACH_OBSERVER(InstallObserver, observers_,
109                    OnDownloadProgress(extension_id, percent_downloaded));
110}
111
112void InstallTracker::OnBeginCrxInstall(const std::string& extension_id) {
113  FOR_EACH_OBSERVER(
114      InstallObserver, observers_, OnBeginCrxInstall(extension_id));
115}
116
117void InstallTracker::OnFinishCrxInstall(const std::string& extension_id,
118                                        bool success) {
119  FOR_EACH_OBSERVER(
120      InstallObserver, observers_, OnFinishCrxInstall(extension_id, success));
121}
122
123void InstallTracker::OnInstallFailure(
124    const std::string& extension_id) {
125  RemoveActiveInstall(extension_id);
126  FOR_EACH_OBSERVER(InstallObserver, observers_,
127                    OnInstallFailure(extension_id));
128}
129
130void InstallTracker::Shutdown() {
131  FOR_EACH_OBSERVER(InstallObserver, observers_, OnShutdown());
132}
133
134void InstallTracker::Observe(int type,
135                             const content::NotificationSource& source,
136                             const content::NotificationDetails& details) {
137  switch (type) {
138    case extensions::NOTIFICATION_EXTENSION_UPDATE_DISABLED: {
139      const Extension* extension =
140          content::Details<const Extension>(details).ptr();
141      FOR_EACH_OBSERVER(
142          InstallObserver, observers_, OnDisabledExtensionUpdated(extension));
143      break;
144    }
145    case chrome::NOTIFICATION_APP_LAUNCHER_REORDERED: {
146      FOR_EACH_OBSERVER(InstallObserver, observers_, OnAppsReordered());
147      break;
148    }
149    case chrome::NOTIFICATION_APP_INSTALLED_TO_APPLIST: {
150      const std::string& extension_id(
151          *content::Details<const std::string>(details).ptr());
152      FOR_EACH_OBSERVER(InstallObserver, observers_,
153                        OnAppInstalledToAppList(extension_id));
154      break;
155    }
156    default:
157      NOTREACHED();
158  }
159}
160
161void InstallTracker::OnExtensionInstalled(
162    content::BrowserContext* browser_context,
163    const Extension* extension,
164    bool is_update) {
165  RemoveActiveInstall(extension->id());
166}
167
168void InstallTracker::OnAppsReordered() {
169  FOR_EACH_OBSERVER(InstallObserver, observers_, OnAppsReordered());
170}
171
172}  // namespace extensions
173