Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/background/background_application_list_model.h" | 5 #include "chrome/browser/background/background_application_list_model.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <set> | 8 #include <set> |
| 9 | 9 |
| 10 #include "base/stl_util.h" | 10 #include "base/stl_util.h" |
| 11 #include "base/utf_string_conversions.h" | 11 #include "base/utf_string_conversions.h" |
| 12 #include "chrome/app/chrome_command_ids.h" | 12 #include "chrome/app/chrome_command_ids.h" |
| 13 #include "chrome/browser/background/background_mode_manager.h" | 13 #include "chrome/browser/background/background_mode_manager.h" |
| 14 #include "chrome/browser/background/background_contents_service.h" | |
| 15 #include "chrome/browser/background/background_contents_service_factory.h" | |
| 14 #include "chrome/browser/browser_process.h" | 16 #include "chrome/browser/browser_process.h" |
| 15 #include "chrome/browser/extensions/extension_prefs.h" | 17 #include "chrome/browser/extensions/extension_prefs.h" |
| 16 #include "chrome/browser/extensions/extension_service.h" | 18 #include "chrome/browser/extensions/extension_service.h" |
| 17 #include "chrome/browser/extensions/image_loading_tracker.h" | 19 #include "chrome/browser/extensions/image_loading_tracker.h" |
| 18 #include "chrome/browser/profiles/profile.h" | 20 #include "chrome/browser/profiles/profile.h" |
| 19 #include "chrome/common/chrome_notification_types.h" | 21 #include "chrome/common/chrome_notification_types.h" |
| 20 #include "chrome/common/extensions/extension.h" | 22 #include "chrome/common/extensions/extension.h" |
| 21 #include "chrome/common/extensions/extension_icon_set.h" | 23 #include "chrome/common/extensions/extension_icon_set.h" |
| 22 #include "chrome/common/extensions/extension_resource.h" | 24 #include "chrome/common/extensions/extension_resource.h" |
| 23 #include "content/public/browser/notification_details.h" | 25 #include "content/public/browser/notification_details.h" |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 72 | 74 |
| 73 namespace { | 75 namespace { |
| 74 void GetServiceApplications(ExtensionService* service, | 76 void GetServiceApplications(ExtensionService* service, |
| 75 ExtensionList* applications_result) { | 77 ExtensionList* applications_result) { |
| 76 const ExtensionSet* extensions = service->extensions(); | 78 const ExtensionSet* extensions = service->extensions(); |
| 77 | 79 |
| 78 for (ExtensionSet::const_iterator cursor = extensions->begin(); | 80 for (ExtensionSet::const_iterator cursor = extensions->begin(); |
| 79 cursor != extensions->end(); | 81 cursor != extensions->end(); |
| 80 ++cursor) { | 82 ++cursor) { |
| 81 const Extension* extension = *cursor; | 83 const Extension* extension = *cursor; |
| 82 if (BackgroundApplicationListModel::IsBackgroundApp(*extension)) | 84 if (BackgroundApplicationListModel::IsBackgroundApp(*extension, |
| 85 service->profile())) { | |
| 83 applications_result->push_back(extension); | 86 applications_result->push_back(extension); |
| 87 } | |
| 84 } | 88 } |
| 85 | 89 |
| 86 // Walk the list of terminated extensions also (just because an extension | 90 // Walk the list of terminated extensions also (just because an extension |
| 87 // crashed doesn't mean we should ignore it). | 91 // crashed doesn't mean we should ignore it). |
| 88 extensions = service->terminated_extensions(); | 92 extensions = service->terminated_extensions(); |
| 89 for (ExtensionSet::const_iterator cursor = extensions->begin(); | 93 for (ExtensionSet::const_iterator cursor = extensions->begin(); |
| 90 cursor != extensions->end(); | 94 cursor != extensions->end(); |
| 91 ++cursor) { | 95 ++cursor) { |
| 92 const Extension* extension = *cursor; | 96 const Extension* extension = *cursor; |
| 93 if (BackgroundApplicationListModel::IsBackgroundApp(*extension)) | 97 if (BackgroundApplicationListModel::IsBackgroundApp(*extension, |
| 98 service->profile())) { | |
| 94 applications_result->push_back(extension); | 99 applications_result->push_back(extension); |
| 100 } | |
| 95 } | 101 } |
| 96 | 102 |
| 97 std::string locale = g_browser_process->GetApplicationLocale(); | 103 std::string locale = g_browser_process->GetApplicationLocale(); |
| 98 icu::Locale loc(locale.c_str()); | 104 icu::Locale loc(locale.c_str()); |
| 99 UErrorCode error = U_ZERO_ERROR; | 105 UErrorCode error = U_ZERO_ERROR; |
| 100 scoped_ptr<icu::Collator> collator(icu::Collator::createInstance(loc, error)); | 106 scoped_ptr<icu::Collator> collator(icu::Collator::createInstance(loc, error)); |
| 101 std::sort(applications_result->begin(), applications_result->end(), | 107 std::sort(applications_result->begin(), applications_result->end(), |
| 102 ExtensionNameComparator(collator.get())); | 108 ExtensionNameComparator(collator.get())); |
| 103 } | 109 } |
| 104 | 110 |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 160 content::Source<Profile>(profile)); | 166 content::Source<Profile>(profile)); |
| 161 registrar_.Add(this, | 167 registrar_.Add(this, |
| 162 chrome::NOTIFICATION_EXTENSION_UNLOADED, | 168 chrome::NOTIFICATION_EXTENSION_UNLOADED, |
| 163 content::Source<Profile>(profile)); | 169 content::Source<Profile>(profile)); |
| 164 registrar_.Add(this, | 170 registrar_.Add(this, |
| 165 chrome::NOTIFICATION_EXTENSIONS_READY, | 171 chrome::NOTIFICATION_EXTENSIONS_READY, |
| 166 content::Source<Profile>(profile)); | 172 content::Source<Profile>(profile)); |
| 167 registrar_.Add(this, | 173 registrar_.Add(this, |
| 168 chrome::NOTIFICATION_EXTENSION_PERMISSIONS_UPDATED, | 174 chrome::NOTIFICATION_EXTENSION_PERMISSIONS_UPDATED, |
| 169 content::Source<Profile>(profile)); | 175 content::Source<Profile>(profile)); |
| 176 registrar_.Add(this, | |
| 177 chrome::NOTIFICATION_BACKGROUND_CONTENTS_SERVICE_CHANGED, | |
| 178 content::Source<Profile>(profile)); | |
| 170 ExtensionService* service = profile->GetExtensionService(); | 179 ExtensionService* service = profile->GetExtensionService(); |
| 171 if (service && service->is_ready()) | 180 if (service && service->is_ready()) |
| 172 Update(); | 181 Update(); |
| 173 } | 182 } |
| 174 | 183 |
| 175 void BackgroundApplicationListModel::AddObserver(Observer* observer) { | 184 void BackgroundApplicationListModel::AddObserver(Observer* observer) { |
| 176 observers_.AddObserver(observer); | 185 observers_.AddObserver(observer); |
| 177 } | 186 } |
| 178 | 187 |
| 179 void BackgroundApplicationListModel::AssociateApplicationData( | 188 void BackgroundApplicationListModel::AssociateApplicationData( |
| 180 const Extension* extension) { | 189 const Extension* extension) { |
| 181 DCHECK(IsBackgroundApp(*extension)); | 190 DCHECK(IsBackgroundApp(*extension, profile_)); |
| 182 Application* application = FindApplication(extension); | 191 Application* application = FindApplication(extension); |
| 183 if (!application) { | 192 if (!application) { |
| 184 // App position is used as a dynamic command and so must be less than any | 193 // App position is used as a dynamic command and so must be less than any |
| 185 // predefined command id. | 194 // predefined command id. |
| 186 if (applications_.size() >= IDC_MinimumLabelValue) { | 195 if (applications_.size() >= IDC_MinimumLabelValue) { |
| 187 LOG(ERROR) << "Background application limit of " << IDC_MinimumLabelValue | 196 LOG(ERROR) << "Background application limit of " << IDC_MinimumLabelValue |
| 188 << " exceeded. Ignoring."; | 197 << " exceeded. Ignoring."; |
| 189 return; | 198 return; |
| 190 } | 199 } |
| 191 application = new Application(this, extension); | 200 application = new Application(this, extension); |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 243 ++cursor, ++position) { | 252 ++cursor, ++position) { |
| 244 if (id == cursor->get()->id()) | 253 if (id == cursor->get()->id()) |
| 245 return position; | 254 return position; |
| 246 } | 255 } |
| 247 NOTREACHED(); | 256 NOTREACHED(); |
| 248 return -1; | 257 return -1; |
| 249 } | 258 } |
| 250 | 259 |
| 251 // static | 260 // static |
| 252 bool BackgroundApplicationListModel::IsBackgroundApp( | 261 bool BackgroundApplicationListModel::IsBackgroundApp( |
| 253 const Extension& extension) { | 262 const Extension& extension, Profile* profile) { |
| 254 return extension.HasAPIPermission(ExtensionAPIPermission::kBackground); | 263 // An extension is a "background app" if it has the "background API" |
| 264 // permission, and meets one of the following criteria: | |
| 265 // 1) It is an extension (not a hosted app). | |
| 266 // 2) It is a hosted app, and has a background contents registered or in the | |
| 267 // manifest. | |
| 268 | |
| 269 // Not a background app if we don't have the background permission. | |
| 270 if (!extension.HasAPIPermission(ExtensionAPIPermission::kBackground)) | |
| 271 return false; | |
| 272 | |
| 273 // Extensions with background permission are always treated as background | |
|
Mihai Parparita -not on Chrome
2012/05/03 00:54:11
Nit: "Extensions and packaged apps"
Andrew T Wilson (Slow)
2012/05/03 07:42:56
Done.
| |
| 274 // apps. | |
| 275 if (!extension.is_hosted_app()) | |
| 276 return true; | |
| 277 | |
| 278 // Hosted apps with manifest-provided background pages are background apps. | |
| 279 if (extension.has_background_page()) | |
| 280 return true; | |
| 281 | |
| 282 BackgroundContentsService* service = | |
| 283 BackgroundContentsServiceFactory::GetForProfile(profile); | |
| 284 string16 app_id = ASCIIToUTF16(extension.id()); | |
| 285 // If we have an active or registered background contents for this app, then | |
| 286 // it's a background app. This covers the cases where the app has created its | |
| 287 // background contents, but it hasn't navigated yet, or the background | |
| 288 // contents crashed and hasn't yet been restarted - in both cases we still | |
| 289 // want to treat the app as a background app. | |
| 290 if (service->GetAppBackgroundContents(app_id) || | |
| 291 service->HasRegisteredBackgroundContents(app_id)) { | |
| 292 return true; | |
| 293 } | |
| 294 | |
| 295 // Doesn't meet our criteria, so it's not a background app. | |
| 296 return false; | |
| 255 } | 297 } |
| 256 | 298 |
| 257 void BackgroundApplicationListModel::Observe( | 299 void BackgroundApplicationListModel::Observe( |
| 258 int type, | 300 int type, |
| 259 const content::NotificationSource& source, | 301 const content::NotificationSource& source, |
| 260 const content::NotificationDetails& details) { | 302 const content::NotificationDetails& details) { |
| 261 if (type == chrome::NOTIFICATION_EXTENSIONS_READY) { | 303 if (type == chrome::NOTIFICATION_EXTENSIONS_READY) { |
| 262 Update(); | 304 Update(); |
| 263 return; | 305 return; |
| 264 } | 306 } |
| 265 ExtensionService* service = profile_->GetExtensionService(); | 307 ExtensionService* service = profile_->GetExtensionService(); |
| 266 if (!service || !service->is_ready()) | 308 if (!service || !service->is_ready()) |
| 267 return; | 309 return; |
| 268 | 310 |
| 269 switch (type) { | 311 switch (type) { |
| 270 case chrome::NOTIFICATION_EXTENSION_LOADED: | 312 case chrome::NOTIFICATION_EXTENSION_LOADED: |
| 271 OnExtensionLoaded(content::Details<Extension>(details).ptr()); | 313 OnExtensionLoaded(content::Details<Extension>(details).ptr()); |
| 272 break; | 314 break; |
| 273 case chrome::NOTIFICATION_EXTENSION_UNLOADED: | 315 case chrome::NOTIFICATION_EXTENSION_UNLOADED: |
| 274 OnExtensionUnloaded( | 316 OnExtensionUnloaded( |
| 275 content::Details<UnloadedExtensionInfo>(details)->extension); | 317 content::Details<UnloadedExtensionInfo>(details)->extension); |
| 276 break; | 318 break; |
| 277 case chrome::NOTIFICATION_EXTENSION_PERMISSIONS_UPDATED: | 319 case chrome::NOTIFICATION_EXTENSION_PERMISSIONS_UPDATED: |
| 278 OnExtensionPermissionsUpdated( | 320 OnExtensionPermissionsUpdated( |
| 279 content::Details<UpdatedExtensionPermissionsInfo>(details)->extension, | 321 content::Details<UpdatedExtensionPermissionsInfo>(details)->extension, |
| 280 content::Details<UpdatedExtensionPermissionsInfo>(details)->reason, | 322 content::Details<UpdatedExtensionPermissionsInfo>(details)->reason, |
| 281 content::Details<UpdatedExtensionPermissionsInfo>(details)-> | 323 content::Details<UpdatedExtensionPermissionsInfo>(details)-> |
| 282 permissions); | 324 permissions); |
| 283 break; | 325 break; |
| 326 case chrome::NOTIFICATION_BACKGROUND_CONTENTS_SERVICE_CHANGED: | |
| 327 Update(); | |
| 328 break; | |
| 284 default: | 329 default: |
| 285 NOTREACHED() << "Received unexpected notification"; | 330 NOTREACHED() << "Received unexpected notification"; |
| 286 } | 331 } |
| 287 } | 332 } |
| 288 | 333 |
| 289 void BackgroundApplicationListModel::SendApplicationDataChangedNotifications( | 334 void BackgroundApplicationListModel::SendApplicationDataChangedNotifications( |
| 290 const Extension* extension) { | 335 const Extension* extension) { |
| 291 FOR_EACH_OBSERVER(Observer, observers_, OnApplicationDataChanged(extension, | 336 FOR_EACH_OBSERVER(Observer, observers_, OnApplicationDataChanged(extension, |
| 292 profile_)); | 337 profile_)); |
| 293 } | 338 } |
| 294 | 339 |
| 295 void BackgroundApplicationListModel::OnExtensionLoaded( | 340 void BackgroundApplicationListModel::OnExtensionLoaded( |
| 296 const Extension* extension) { | 341 const Extension* extension) { |
| 297 // We only care about extensions that are background applications | 342 // We only care about extensions that are background applications |
| 298 if (!IsBackgroundApp(*extension)) | 343 if (!IsBackgroundApp(*extension, profile_)) |
| 299 return; | 344 return; |
| 300 AssociateApplicationData(extension); | 345 AssociateApplicationData(extension); |
| 301 } | 346 } |
| 302 | 347 |
| 303 void BackgroundApplicationListModel::OnExtensionUnloaded( | 348 void BackgroundApplicationListModel::OnExtensionUnloaded( |
| 304 const Extension* extension) { | 349 const Extension* extension) { |
| 305 if (!IsBackgroundApp(*extension)) | 350 if (!IsBackgroundApp(*extension, profile_)) |
| 306 return; | 351 return; |
| 307 Update(); | 352 Update(); |
| 308 DissociateApplicationData(extension); | 353 DissociateApplicationData(extension); |
| 309 } | 354 } |
| 310 | 355 |
| 311 void BackgroundApplicationListModel::OnExtensionPermissionsUpdated( | 356 void BackgroundApplicationListModel::OnExtensionPermissionsUpdated( |
| 312 const Extension* extension, | 357 const Extension* extension, |
| 313 UpdatedExtensionPermissionsInfo::Reason reason, | 358 UpdatedExtensionPermissionsInfo::Reason reason, |
| 314 const ExtensionPermissionSet* permissions) { | 359 const ExtensionPermissionSet* permissions) { |
| 315 if (permissions->HasAPIPermission(ExtensionAPIPermission::kBackground)) { | 360 if (permissions->HasAPIPermission(ExtensionAPIPermission::kBackground)) { |
| 316 switch (reason) { | 361 switch (reason) { |
| 317 case UpdatedExtensionPermissionsInfo::ADDED: | 362 case UpdatedExtensionPermissionsInfo::ADDED: |
| 318 DCHECK(IsBackgroundApp(*extension)); | 363 DCHECK(IsBackgroundApp(*extension, profile_)); |
| 319 OnExtensionLoaded(extension); | 364 OnExtensionLoaded(extension); |
| 320 break; | 365 break; |
| 321 case UpdatedExtensionPermissionsInfo::REMOVED: | 366 case UpdatedExtensionPermissionsInfo::REMOVED: |
| 322 DCHECK(!IsBackgroundApp(*extension)); | 367 DCHECK(!IsBackgroundApp(*extension, profile_)); |
| 323 Update(); | 368 Update(); |
| 324 DissociateApplicationData(extension); | 369 DissociateApplicationData(extension); |
| 325 break; | 370 break; |
| 326 default: | 371 default: |
| 327 NOTREACHED(); | 372 NOTREACHED(); |
| 328 } | 373 } |
| 329 } | 374 } |
| 330 } | 375 } |
| 331 | 376 |
| 332 void BackgroundApplicationListModel::RemoveObserver(Observer* observer) { | 377 void BackgroundApplicationListModel::RemoveObserver(Observer* observer) { |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 351 (*old_cursor)->name() == (*new_cursor)->name() && | 396 (*old_cursor)->name() == (*new_cursor)->name() && |
| 352 (*old_cursor)->id() == (*new_cursor)->id()) { | 397 (*old_cursor)->id() == (*new_cursor)->id()) { |
| 353 ++old_cursor; | 398 ++old_cursor; |
| 354 ++new_cursor; | 399 ++new_cursor; |
| 355 } | 400 } |
| 356 if (old_cursor != extensions_.end() || new_cursor != extensions.end()) { | 401 if (old_cursor != extensions_.end() || new_cursor != extensions.end()) { |
| 357 extensions_ = extensions; | 402 extensions_ = extensions; |
| 358 FOR_EACH_OBSERVER(Observer, observers_, OnApplicationListChanged(profile_)); | 403 FOR_EACH_OBSERVER(Observer, observers_, OnApplicationListChanged(profile_)); |
| 359 } | 404 } |
| 360 } | 405 } |
| OLD | NEW |