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/ui/app_list/recommended_apps.h"
6
7#include <algorithm>
8#include <vector>
9
10#include "base/bind.h"
11#include "chrome/browser/extensions/extension_prefs.h"
12#include "chrome/browser/extensions/extension_service.h"
13#include "chrome/browser/extensions/extension_system_factory.h"
14#include "chrome/browser/extensions/install_tracker.h"
15#include "chrome/browser/extensions/install_tracker_factory.h"
16#include "chrome/browser/ui/app_list/recommended_apps_observer.h"
17#include "chrome/common/pref_names.h"
18#include "extensions/common/extension.h"
19
20namespace app_list {
21
22namespace {
23
24struct AppSortInfo {
25  AppSortInfo() : app(NULL) {}
26  AppSortInfo(const extensions::Extension* app,
27              const base::Time& last_launch_time)
28      : app(app), last_launch_time(last_launch_time) {}
29
30  const extensions::Extension* app;
31  base::Time last_launch_time;
32};
33
34bool AppLaunchedMoreRecent(const AppSortInfo& app1, const AppSortInfo& app2) {
35  return app1.last_launch_time > app2.last_launch_time;
36}
37
38}  // namespace
39
40RecommendedApps::RecommendedApps(Profile* profile) : profile_(profile) {
41  extensions::InstallTrackerFactory::GetForProfile(profile_)->AddObserver(this);
42
43  ExtensionService* service =
44      extensions::ExtensionSystem::Get(profile_)->extension_service();
45  extensions::ExtensionPrefs* prefs = service->extension_prefs();
46  pref_change_registrar_.Init(prefs->pref_service());
47  pref_change_registrar_.Add(prefs::kExtensionsPref,
48                             base::Bind(&RecommendedApps::Update,
49                                        base::Unretained(this)));
50
51  Update();
52}
53
54RecommendedApps::~RecommendedApps() {
55  extensions::InstallTrackerFactory::GetForProfile(profile_)
56      ->RemoveObserver(this);
57}
58
59void RecommendedApps::AddObserver(RecommendedAppsObserver* observer) {
60  observers_.AddObserver(observer);
61}
62
63void RecommendedApps::RemoveObserver(RecommendedAppsObserver* observer) {
64  observers_.RemoveObserver(observer);
65}
66
67void RecommendedApps::Update() {
68  ExtensionService* service =
69      extensions::ExtensionSystem::Get(profile_)->extension_service();
70  extensions::ExtensionPrefs* prefs = service->extension_prefs();
71
72  std::vector<AppSortInfo> sorted_apps;
73  const ExtensionSet* extensions = service->extensions();
74  for (ExtensionSet::const_iterator app = extensions->begin();
75       app != extensions->end(); ++app) {
76    if (!(*app)->ShouldDisplayInAppLauncher())
77      continue;
78
79    sorted_apps.push_back(
80        AppSortInfo(app->get(), prefs->GetLastLaunchTime((*app)->id())));
81  }
82
83  std::sort(sorted_apps.begin(), sorted_apps.end(), &AppLaunchedMoreRecent);
84
85  const size_t kMaxRecommendedApps = 4;
86  sorted_apps.resize(std::min(kMaxRecommendedApps, sorted_apps.size()));
87
88  Apps new_recommends;
89  for (size_t i = 0; i < sorted_apps.size(); ++i)
90    new_recommends.push_back(sorted_apps[i].app);
91
92  const bool changed = apps_.size() != new_recommends.size() ||
93      !std::equal(apps_.begin(), apps_.end(), new_recommends.begin());
94  if (changed) {
95    apps_.swap(new_recommends);
96    FOR_EACH_OBSERVER(
97        RecommendedAppsObserver, observers_, OnRecommendedAppsChanged());
98  }
99}
100
101void RecommendedApps::OnBeginExtensionInstall(
102    const ExtensionInstallParams& params) {}
103
104void RecommendedApps::OnDownloadProgress(const std::string& extension_id,
105                                int percent_downloaded) {}
106
107void RecommendedApps::OnInstallFailure(const std::string& extension_id) {}
108
109void RecommendedApps::OnExtensionInstalled(
110    const extensions::Extension* extension) {
111  Update();
112}
113
114void RecommendedApps::OnExtensionLoaded(
115    const extensions::Extension* extension) {
116  Update();
117}
118
119void RecommendedApps::OnExtensionUnloaded(
120    const extensions::Extension* extension) {
121  Update();
122}
123
124void RecommendedApps::OnExtensionUninstalled(
125    const extensions::Extension* extension) {
126  Update();
127}
128
129void RecommendedApps::OnAppsReordered() {}
130
131void RecommendedApps::OnAppInstalledToAppList(
132    const std::string& extension_id) {}
133
134void RecommendedApps::OnShutdown() {}
135
136}  // namespace app_list
137