1// Copyright 2014 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/api/webstore/webstore_api.h"
6
7#include "base/lazy_instance.h"
8#include "base/values.h"
9#include "chrome/browser/extensions/install_tracker.h"
10#include "chrome/browser/extensions/install_tracker_factory.h"
11#include "chrome/common/extensions/chrome_extension_messages.h"
12#include "extensions/browser/extension_system.h"
13#include "ipc/ipc_sender.h"
14
15namespace extensions {
16
17namespace {
18
19base::LazyInstance<BrowserContextKeyedAPIFactory<WebstoreAPI> > g_factory =
20    LAZY_INSTANCE_INITIALIZER;
21
22}  // namespace
23
24struct WebstoreAPI::ObservedInstallInfo {
25  ObservedInstallInfo(int routing_id,
26                      const std::string& extension_id,
27                      IPC::Sender* ipc_sender);
28  ~ObservedInstallInfo();
29
30  int routing_id;
31  std::string extension_id;
32  IPC::Sender* ipc_sender;
33};
34
35WebstoreAPI::ObservedInstallInfo::ObservedInstallInfo(
36    int routing_id,
37    const std::string& extension_id,
38    IPC::Sender* ipc_sender)
39    : routing_id(routing_id),
40      extension_id(extension_id),
41      ipc_sender(ipc_sender) {}
42
43WebstoreAPI::ObservedInstallInfo::~ObservedInstallInfo() {}
44
45WebstoreAPI::WebstoreAPI(content::BrowserContext* browser_context)
46    : browser_context_(browser_context),
47      install_observer_(
48          new ScopedObserver<InstallTracker, InstallObserver>(this)) {
49  install_observer_->Add(
50      InstallTrackerFactory::GetForBrowserContext(browser_context));
51}
52
53WebstoreAPI::~WebstoreAPI() {}
54
55// static
56WebstoreAPI* WebstoreAPI::Get(content::BrowserContext* browser_context) {
57  return BrowserContextKeyedAPIFactory<WebstoreAPI>::Get(browser_context);
58}
59
60void WebstoreAPI::OnInlineInstallStart(int routing_id,
61                                       IPC::Sender* ipc_sender,
62                                       const std::string& extension_id,
63                                       int listeners_mask) {
64  if (listeners_mask & api::webstore::INSTALL_STAGE_LISTENER) {
65    install_stage_listeners_.push_back(
66        ObservedInstallInfo(routing_id, extension_id, ipc_sender));
67  }
68
69  if (listeners_mask & api::webstore::DOWNLOAD_PROGRESS_LISTENER) {
70    download_progress_listeners_.push_back(
71        ObservedInstallInfo(routing_id, extension_id, ipc_sender));
72  }
73}
74
75void WebstoreAPI::OnInlineInstallFinished(int routing_id,
76                                          const std::string& extension_id) {
77  RemoveListeners(routing_id, extension_id, &download_progress_listeners_);
78  RemoveListeners(routing_id, extension_id, &install_stage_listeners_);
79}
80
81void WebstoreAPI::OnBeginExtensionDownload(const std::string& extension_id) {
82  SendInstallMessageIfObserved(extension_id,
83                               api::webstore::INSTALL_STAGE_DOWNLOADING);
84}
85
86void WebstoreAPI::OnDownloadProgress(const std::string& extension_id,
87                                     int percent_downloaded) {
88  for (ObservedInstallInfoList::const_iterator iter =
89           download_progress_listeners_.begin();
90       iter != download_progress_listeners_.end();
91       ++iter) {
92    if (iter->extension_id == extension_id) {
93      iter->ipc_sender->Send(new ExtensionMsg_InlineInstallDownloadProgress(
94          iter->routing_id, percent_downloaded));
95    }
96  }
97}
98
99void WebstoreAPI::OnBeginCrxInstall(const std::string& extension_id) {
100  SendInstallMessageIfObserved(extension_id,
101                               api::webstore::INSTALL_STAGE_INSTALLING);
102}
103
104void WebstoreAPI::OnShutdown() {
105  install_observer_.reset();
106}
107
108void WebstoreAPI::Shutdown() {}
109
110// static
111BrowserContextKeyedAPIFactory<WebstoreAPI>* WebstoreAPI::GetFactoryInstance() {
112  return g_factory.Pointer();
113}
114
115void WebstoreAPI::SendInstallMessageIfObserved(
116    const std::string& extension_id,
117    api::webstore::InstallStage install_stage) {
118  for (ObservedInstallInfoList::const_iterator iter =
119           install_stage_listeners_.begin();
120       iter != install_stage_listeners_.end();
121       ++iter) {
122    if (iter->extension_id == extension_id) {
123      iter->ipc_sender->Send(new ExtensionMsg_InlineInstallStageChanged(
124          iter->routing_id, install_stage));
125    }
126  }
127}
128
129void WebstoreAPI::RemoveListeners(int routing_id,
130                                  const std::string& extension_id,
131                                  ObservedInstallInfoList* listeners) {
132  for (ObservedInstallInfoList::iterator iter = listeners->begin();
133       iter != listeners->end();) {
134    if (iter->extension_id == extension_id && iter->routing_id == routing_id)
135      iter = listeners->erase(iter);
136    else
137      ++iter;
138  }
139}
140
141}  // namespace extensions
142