1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// Use of this source code is governed by a BSD-style license that can be 3513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// found in the LICENSE file. 4513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 5513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "chrome/browser/background_application_list_model.h" 6513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 7513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include <algorithm> 821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include <set> 9513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 10513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "base/stl_util-inl.h" 11513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "base/utf_string_conversions.h" 1221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/app/chrome_command_ids.h" 13513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "chrome/browser/background_mode_manager.h" 14513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "chrome/browser/browser_process.h" 15513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "chrome/browser/extensions/extension_prefs.h" 1621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/extensions/extension_service.h" 17513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "chrome/browser/extensions/image_loading_tracker.h" 1821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/profiles/profile.h" 19513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "chrome/common/extensions/extension.h" 20513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "chrome/common/extensions/extension_resource.h" 21ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/notification_details.h" 22ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/notification_source.h" 2372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/l10n/l10n_util_collator.h" 24513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 25513209b27ff55e2841eac0e4120199c23acce758Ben Murdochclass ExtensionNameComparator { 26513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch public: 27513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch explicit ExtensionNameComparator(icu::Collator* collator); 28513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch bool operator()(const Extension* x, const Extension* y); 29513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 30513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch private: 31513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch icu::Collator* collator_; 32513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}; 33513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 34513209b27ff55e2841eac0e4120199c23acce758Ben MurdochExtensionNameComparator::ExtensionNameComparator(icu::Collator* collator) 35513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch : collator_(collator) { 36513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 37513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 38513209b27ff55e2841eac0e4120199c23acce758Ben Murdochbool ExtensionNameComparator::operator()(const Extension* x, 39513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const Extension* y) { 40513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return l10n_util::StringComparator<string16>(collator_)( 41513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch UTF8ToUTF16(x->name()), 42513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch UTF8ToUTF16(y->name())); 43513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 44513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 45513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// Background application representation, private to the 46513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// BackgroundApplicationListModel class. 47513209b27ff55e2841eac0e4120199c23acce758Ben Murdochclass BackgroundApplicationListModel::Application 48513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch : public ImageLoadingTracker::Observer { 49513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch public: 50513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch Application(BackgroundApplicationListModel* model, 51513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const Extension* an_extension); 52513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 53513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch virtual ~Application(); 54513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 55513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Invoked when a request icon is available. 56513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch virtual void OnImageLoaded(SkBitmap* image, 57ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const ExtensionResource& resource, 58513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch int index); 59513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 60513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Uses the FILE thread to request this extension's icon, sized 61513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // appropriately. 62513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch void RequestIcon(Extension::Icons size); 63513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 64513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const Extension* extension_; 65513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch scoped_ptr<SkBitmap> icon_; 66513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch BackgroundApplicationListModel* model_; 67513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch ImageLoadingTracker tracker_; 68513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}; 69513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 70513209b27ff55e2841eac0e4120199c23acce758Ben Murdochnamespace { 7121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid GetServiceApplications(ExtensionService* service, 72513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch ExtensionList* applications_result) { 73513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const ExtensionList* extensions = service->extensions(); 74513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 75513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch for (ExtensionList::const_iterator cursor = extensions->begin(); 76513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch cursor != extensions->end(); 77513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch ++cursor) { 78513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const Extension* extension = *cursor; 79513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (BackgroundApplicationListModel::IsBackgroundApp(*extension)) 80513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch applications_result->push_back(extension); 81513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 82513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch std::string locale = g_browser_process->GetApplicationLocale(); 83513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch icu::Locale loc(locale.c_str()); 84513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch UErrorCode error = U_ZERO_ERROR; 85513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch scoped_ptr<icu::Collator> collator(icu::Collator::createInstance(loc, error)); 86513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch sort(applications_result->begin(), applications_result->end(), 87513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch ExtensionNameComparator(collator.get())); 88513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 89513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 90513209b27ff55e2841eac0e4120199c23acce758Ben Murdochbool HasBackgroundAppPermission( 91513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const std::set<std::string>& api_permissions) { 92513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return Extension::HasApiPermission( 93513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch api_permissions, Extension::kBackgroundPermission); 94513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 95513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} // namespace 96513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 97513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid 98513209b27ff55e2841eac0e4120199c23acce758Ben MurdochBackgroundApplicationListModel::Observer::OnApplicationDataChanged( 99513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const Extension* extension) { 100513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 101513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 102513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid 103513209b27ff55e2841eac0e4120199c23acce758Ben MurdochBackgroundApplicationListModel::Observer::OnApplicationListChanged() { 104513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 105513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 106513209b27ff55e2841eac0e4120199c23acce758Ben MurdochBackgroundApplicationListModel::Observer::~Observer() { 107513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 108513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 109513209b27ff55e2841eac0e4120199c23acce758Ben MurdochBackgroundApplicationListModel::Application::~Application() { 110513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 111513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 112513209b27ff55e2841eac0e4120199c23acce758Ben MurdochBackgroundApplicationListModel::Application::Application( 113513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch BackgroundApplicationListModel* model, 114513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const Extension* extension) 115513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch : extension_(extension), 116513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch icon_(NULL), 117513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch model_(model), 118513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch ALLOW_THIS_IN_INITIALIZER_LIST(tracker_(this)) { 119513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 120513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 121513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid BackgroundApplicationListModel::Application::OnImageLoaded( 122513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch SkBitmap* image, 123ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const ExtensionResource& resource, 124513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch int index) { 125513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (!image) 126513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return; 127513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch icon_.reset(new SkBitmap(*image)); 128513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch model_->OnApplicationDataChanged(extension_); 129513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 130513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 131513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid BackgroundApplicationListModel::Application::RequestIcon( 132513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch Extension::Icons size) { 133513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch ExtensionResource resource = extension_->GetIconResource( 134513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch size, ExtensionIconSet::MATCH_BIGGER); 135513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch tracker_.LoadImage(extension_, resource, gfx::Size(size, size), 136513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch ImageLoadingTracker::CACHE); 137513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 138513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 139513209b27ff55e2841eac0e4120199c23acce758Ben MurdochBackgroundApplicationListModel::~BackgroundApplicationListModel() { 140513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch STLDeleteContainerPairSecondPointers(applications_.begin(), 141513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch applications_.end()); 142513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 143513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 144513209b27ff55e2841eac0e4120199c23acce758Ben MurdochBackgroundApplicationListModel::BackgroundApplicationListModel(Profile* profile) 145513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch : profile_(profile) { 146513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch DCHECK(profile_); 147513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch registrar_.Add(this, 148513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch NotificationType::EXTENSION_LOADED, 149513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch Source<Profile>(profile)); 150513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch registrar_.Add(this, 151513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch NotificationType::EXTENSION_UNLOADED, 152513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch Source<Profile>(profile)); 153513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch registrar_.Add(this, 154513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch NotificationType::EXTENSIONS_READY, 155513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch Source<Profile>(profile)); 15621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen ExtensionService* service = profile->GetExtensionService(); 15721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (service && service->is_ready()) 15821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen Update(); 159513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 160513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 161513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid BackgroundApplicationListModel::AddObserver(Observer* observer) { 162513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch observers_.AddObserver(observer); 163513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 164513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 165513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid BackgroundApplicationListModel::AssociateApplicationData( 166513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const Extension* extension) { 167513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch DCHECK(IsBackgroundApp(*extension)); 168513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch Application* application = FindApplication(extension); 169513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (!application) { 17021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // App position is used as a dynamic command and so must be less than any 17121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // predefined command id. 17221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (applications_.size() >= IDC_MinimumLabelValue) { 17321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen LOG(ERROR) << "Background application limit of " << IDC_MinimumLabelValue 17421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen << " exceeded. Ignoring."; 17521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return; 17621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 177513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch application = new Application(this, extension); 178513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch applications_[extension->id()] = application; 179513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch application->RequestIcon(Extension::EXTENSION_ICON_BITTY); 180513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 181513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 182513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 183513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid BackgroundApplicationListModel::DissociateApplicationData( 184513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const Extension* extension) { 185513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch ApplicationMap::iterator found = applications_.find(extension->id()); 186513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (found != applications_.end()) { 187513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch delete found->second; 188513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch applications_.erase(found); 189513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 190513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 191513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 192513209b27ff55e2841eac0e4120199c23acce758Ben Murdochconst Extension* BackgroundApplicationListModel::GetExtension( 193513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch int position) const { 194513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch DCHECK(position >= 0 && static_cast<size_t>(position) < extensions_.size()); 195513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return extensions_[position]; 196513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 197513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 198513209b27ff55e2841eac0e4120199c23acce758Ben Murdochconst BackgroundApplicationListModel::Application* 199513209b27ff55e2841eac0e4120199c23acce758Ben MurdochBackgroundApplicationListModel::FindApplication( 200513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const Extension* extension) const { 201513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const std::string& id = extension->id(); 202513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch ApplicationMap::const_iterator found = applications_.find(id); 203513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return (found == applications_.end()) ? NULL : found->second; 204513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 205513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 206513209b27ff55e2841eac0e4120199c23acce758Ben MurdochBackgroundApplicationListModel::Application* 207513209b27ff55e2841eac0e4120199c23acce758Ben MurdochBackgroundApplicationListModel::FindApplication(const Extension* extension) { 208513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const std::string& id = extension->id(); 209513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch ApplicationMap::iterator found = applications_.find(id); 210513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return (found == applications_.end()) ? NULL : found->second; 211513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 212513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 213513209b27ff55e2841eac0e4120199c23acce758Ben Murdochconst SkBitmap* BackgroundApplicationListModel::GetIcon( 214513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const Extension* extension) { 215513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const Application* application = FindApplication(extension); 216513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (application) 217513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return application->icon_.get(); 218513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch AssociateApplicationData(extension); 219513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return NULL; 220513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 221513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 222513209b27ff55e2841eac0e4120199c23acce758Ben Murdochint BackgroundApplicationListModel::GetPosition( 223513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const Extension* extension) const { 224513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch int position = 0; 225513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const std::string& id = extension->id(); 226513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch for (ExtensionList::const_iterator cursor = extensions_.begin(); 227513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch cursor != extensions_.end(); 228513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch ++cursor, ++position) { 229513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (id == cursor->get()->id()) 230513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return position; 231513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 232513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch NOTREACHED(); 233513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return -1; 234513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 235513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 236513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// static 237513209b27ff55e2841eac0e4120199c23acce758Ben Murdochbool BackgroundApplicationListModel::IsBackgroundApp( 238513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const Extension& extension) { 239513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return HasBackgroundAppPermission(extension.api_permissions()); 240513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 241513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 242513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid BackgroundApplicationListModel::Observe( 243513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch NotificationType type, 244513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const NotificationSource& source, 245513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const NotificationDetails& details) { 246513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (type == NotificationType::EXTENSIONS_READY) { 247513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch Update(); 248513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return; 249513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 25021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen ExtensionService* service = profile_->GetExtensionService(); 251513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (!service || !service->is_ready()) 252513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return; 253201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 254513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch switch (type.value) { 255513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch case NotificationType::EXTENSION_LOADED: 256513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch OnExtensionLoaded(Details<Extension>(details).ptr()); 257513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch break; 258513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch case NotificationType::EXTENSION_UNLOADED: 25921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen OnExtensionUnloaded(Details<UnloadedExtensionInfo>(details)->extension); 260513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch break; 261513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch default: 262513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch NOTREACHED() << "Received unexpected notification"; 263513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 264513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 265513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 266513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid BackgroundApplicationListModel::OnApplicationDataChanged( 267513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const Extension* extension) { 268513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch FOR_EACH_OBSERVER(Observer, observers_, OnApplicationDataChanged(extension)); 269513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 270513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 271513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid BackgroundApplicationListModel::OnExtensionLoaded(Extension* extension) { 272513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // We only care about extensions that are background applications 273513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (!IsBackgroundApp(*extension)) 274513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return; 275513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch AssociateApplicationData(extension); 276513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch Update(); 277513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 278513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 27921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid BackgroundApplicationListModel::OnExtensionUnloaded( 28021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen const Extension* extension) { 281513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (!IsBackgroundApp(*extension)) 282513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return; 283513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch Update(); 284513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch DissociateApplicationData(extension); 285513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 286513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 287513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid BackgroundApplicationListModel::RemoveObserver(Observer* observer) { 288513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch observers_.RemoveObserver(observer); 289513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 290513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 291513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// Update queries the extensions service of the profile with which the model was 292513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// initialized to determine the current set of background applications. If that 293513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// differs from the old list, it generates OnApplicationListChanged events for 294513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// each observer. 295513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid BackgroundApplicationListModel::Update() { 29621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen ExtensionService* service = profile_->GetExtensionService(); 297513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 298513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Discover current background applications, compare with previous list, which 299513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // is consistently sorted, and notify observers if they differ. 300513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch ExtensionList extensions; 301513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch GetServiceApplications(service, &extensions); 302513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch ExtensionList::const_iterator old_cursor = extensions_.begin(); 303513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch ExtensionList::const_iterator new_cursor = extensions.begin(); 304513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch while (old_cursor != extensions_.end() && 305513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch new_cursor != extensions.end() && 306513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch (*old_cursor)->name() == (*new_cursor)->name() && 307513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch (*old_cursor)->id() == (*new_cursor)->id()) { 308513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch ++old_cursor; 309513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch ++new_cursor; 310513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 311513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (old_cursor != extensions_.end() || new_cursor != extensions.end()) { 312513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch extensions_ = extensions; 313513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch FOR_EACH_OBSERVER(Observer, observers_, OnApplicationListChanged()); 314513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 315513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 316