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_contents_service.h" | 5 #include "chrome/browser/background/background_contents_service.h" |
| 6 | 6 |
| 7 #include "base/basictypes.h" | 7 #include "base/basictypes.h" |
| 8 #include "base/bind.h" | 8 #include "base/bind.h" |
| 9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
| 10 #include "base/message_loop.h" | 10 #include "base/message_loop.h" |
| (...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 209 // uninstalls the extension. | 209 // uninstalls the extension. |
| 210 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNINSTALLED, | 210 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNINSTALLED, |
| 211 content::Source<Profile>(profile)); | 211 content::Source<Profile>(profile)); |
| 212 } | 212 } |
| 213 | 213 |
| 214 void BackgroundContentsService::Observe( | 214 void BackgroundContentsService::Observe( |
| 215 int type, | 215 int type, |
| 216 const content::NotificationSource& source, | 216 const content::NotificationSource& source, |
| 217 const content::NotificationDetails& details) { | 217 const content::NotificationDetails& details) { |
| 218 switch (type) { | 218 switch (type) { |
| 219 case chrome::NOTIFICATION_EXTENSIONS_READY: | 219 case chrome::NOTIFICATION_EXTENSIONS_READY: { |
| 220 LoadBackgroundContentsFromManifests( | 220 Profile* profile = content::Source<Profile>(source).ptr(); |
| 221 content::Source<Profile>(source).ptr()); | 221 LoadBackgroundContentsFromManifests(profile); |
| 222 LoadBackgroundContentsFromPrefs(content::Source<Profile>(source).ptr()); | 222 LoadBackgroundContentsFromPrefs(profile); |
| 223 SendChangeNotification(profile); | |
| 223 break; | 224 break; |
| 225 } | |
| 224 case chrome::NOTIFICATION_BACKGROUND_CONTENTS_DELETED: | 226 case chrome::NOTIFICATION_BACKGROUND_CONTENTS_DELETED: |
| 225 BackgroundContentsShutdown( | 227 BackgroundContentsShutdown( |
| 226 content::Details<BackgroundContents>(details).ptr()); | 228 content::Details<BackgroundContents>(details).ptr()); |
| 229 SendChangeNotification(content::Source<Profile>(source).ptr()); | |
| 227 break; | 230 break; |
| 228 case chrome::NOTIFICATION_BACKGROUND_CONTENTS_CLOSED: | 231 case chrome::NOTIFICATION_BACKGROUND_CONTENTS_CLOSED: |
| 229 DCHECK(IsTracked(content::Details<BackgroundContents>(details).ptr())); | 232 DCHECK(IsTracked(content::Details<BackgroundContents>(details).ptr())); |
| 230 UnregisterBackgroundContents( | 233 UnregisterBackgroundContents( |
| 231 content::Details<BackgroundContents>(details).ptr()); | 234 content::Details<BackgroundContents>(details).ptr()); |
| 235 // CLOSED is always followed by a DELETED notification so we'll send our | |
| 236 // change notification there. | |
| 232 break; | 237 break; |
| 233 case chrome::NOTIFICATION_BACKGROUND_CONTENTS_NAVIGATED: { | 238 case chrome::NOTIFICATION_BACKGROUND_CONTENTS_NAVIGATED: { |
| 234 DCHECK(IsTracked(content::Details<BackgroundContents>(details).ptr())); | 239 DCHECK(IsTracked(content::Details<BackgroundContents>(details).ptr())); |
| 235 | 240 |
| 236 // Do not register in the pref if the extension has a manifest-specified | 241 // Do not register in the pref if the extension has a manifest-specified |
| 237 // background page. | 242 // background page. |
| 238 BackgroundContents* bgcontents = | 243 BackgroundContents* bgcontents = |
| 239 content::Details<BackgroundContents>(details).ptr(); | 244 content::Details<BackgroundContents>(details).ptr(); |
| 240 Profile* profile = content::Source<Profile>(source).ptr(); | 245 Profile* profile = content::Source<Profile>(source).ptr(); |
| 241 const string16& appid = GetParentApplicationId(bgcontents); | 246 const string16& appid = GetParentApplicationId(bgcontents); |
| 242 ExtensionService* extension_service = profile->GetExtensionService(); | 247 ExtensionService* extension_service = profile->GetExtensionService(); |
| 243 // extension_service can be NULL when running tests. | 248 // extension_service can be NULL when running tests. |
| 244 if (extension_service) { | 249 if (extension_service) { |
| 245 const Extension* extension = | 250 const Extension* extension = |
| 246 extension_service->GetExtensionById(UTF16ToUTF8(appid), false); | 251 extension_service->GetExtensionById(UTF16ToUTF8(appid), false); |
| 247 if (extension && extension->has_background_page()) | 252 if (extension && extension->has_background_page()) |
| 248 break; | 253 break; |
| 249 } | 254 } |
| 250 RegisterBackgroundContents(bgcontents); | 255 RegisterBackgroundContents(bgcontents); |
| 256 SendChangeNotification(profile); | |
|
Mihai Parparita -not on Chrome
2012/05/03 00:54:11
Why would a navigation cause the list of backgroun
Andrew T Wilson (Slow)
2012/05/03 07:42:56
It doesn't change the list of background content *
| |
| 251 break; | 257 break; |
| 252 } | 258 } |
| 253 case chrome::NOTIFICATION_EXTENSION_LOADED: { | 259 case chrome::NOTIFICATION_EXTENSION_LOADED: { |
| 254 const Extension* extension = | 260 const Extension* extension = |
| 255 content::Details<const Extension>(details).ptr(); | 261 content::Details<const Extension>(details).ptr(); |
| 256 Profile* profile = content::Source<Profile>(source).ptr(); | 262 Profile* profile = content::Source<Profile>(source).ptr(); |
| 257 if (extension->is_hosted_app() && | 263 if (extension->is_hosted_app() && |
| 258 extension->has_background_page()) { | 264 extension->has_background_page()) { |
| 259 // If there is a background page specified in the manifest for a hosted | 265 // If there is a background page specified in the manifest for a hosted |
| 260 // app, then blow away registered urls in the pref. | 266 // app, then blow away registered urls in the pref. |
| 261 ShutdownAssociatedBackgroundContents(ASCIIToUTF16(extension->id())); | 267 ShutdownAssociatedBackgroundContents(ASCIIToUTF16(extension->id())); |
| 262 | 268 |
| 263 ExtensionService* service = profile->GetExtensionService(); | 269 ExtensionService* service = profile->GetExtensionService(); |
| 264 if (service && service->is_ready()) { | 270 if (service && service->is_ready()) { |
| 265 // Now load the manifest-specified background page. If service isn't | 271 // Now load the manifest-specified background page. If service isn't |
| 266 // ready, then the background page will be loaded from the | 272 // ready, then the background page will be loaded from the |
| 267 // EXTENSIONS_READY callback. | 273 // EXTENSIONS_READY callback. |
| 268 LoadBackgroundContents(profile, extension->GetBackgroundURL(), | 274 LoadBackgroundContents(profile, extension->GetBackgroundURL(), |
| 269 ASCIIToUTF16("background"), UTF8ToUTF16(extension->id())); | 275 ASCIIToUTF16("background"), UTF8ToUTF16(extension->id())); |
| 270 } | 276 } |
| 271 } | 277 } |
| 272 | 278 |
| 273 // Remove any "This extension has crashed" balloons. | 279 // Remove any "This extension has crashed" balloons. |
| 274 ScheduleCloseBalloon(extension->id()); | 280 ScheduleCloseBalloon(extension->id()); |
| 281 SendChangeNotification(profile); | |
| 275 break; | 282 break; |
| 276 } | 283 } |
| 277 case chrome::NOTIFICATION_EXTENSION_PROCESS_TERMINATED: | 284 case chrome::NOTIFICATION_EXTENSION_PROCESS_TERMINATED: |
| 278 case chrome::NOTIFICATION_BACKGROUND_CONTENTS_TERMINATED: { | 285 case chrome::NOTIFICATION_BACKGROUND_CONTENTS_TERMINATED: { |
| 279 Profile* profile = content::Source<Profile>(source).ptr(); | 286 Profile* profile = content::Source<Profile>(source).ptr(); |
| 280 const Extension* extension = NULL; | 287 const Extension* extension = NULL; |
| 281 if (type == chrome::NOTIFICATION_BACKGROUND_CONTENTS_TERMINATED) { | 288 if (type == chrome::NOTIFICATION_BACKGROUND_CONTENTS_TERMINATED) { |
| 282 BackgroundContents* bg = | 289 BackgroundContents* bg = |
| 283 content::Details<BackgroundContents>(details).ptr(); | 290 content::Details<BackgroundContents>(details).ptr(); |
| 284 std::string extension_id = UTF16ToASCII( | 291 std::string extension_id = UTF16ToASCII( |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 304 break; | 311 break; |
| 305 } | 312 } |
| 306 case chrome::NOTIFICATION_EXTENSION_UNLOADED: | 313 case chrome::NOTIFICATION_EXTENSION_UNLOADED: |
| 307 switch (content::Details<UnloadedExtensionInfo>(details)->reason) { | 314 switch (content::Details<UnloadedExtensionInfo>(details)->reason) { |
| 308 case extension_misc::UNLOAD_REASON_DISABLE: // Fall through. | 315 case extension_misc::UNLOAD_REASON_DISABLE: // Fall through. |
| 309 case extension_misc::UNLOAD_REASON_TERMINATE: // Fall through. | 316 case extension_misc::UNLOAD_REASON_TERMINATE: // Fall through. |
| 310 case extension_misc::UNLOAD_REASON_UNINSTALL: | 317 case extension_misc::UNLOAD_REASON_UNINSTALL: |
| 311 ShutdownAssociatedBackgroundContents( | 318 ShutdownAssociatedBackgroundContents( |
| 312 ASCIIToUTF16(content::Details<UnloadedExtensionInfo>(details)-> | 319 ASCIIToUTF16(content::Details<UnloadedExtensionInfo>(details)-> |
| 313 extension->id())); | 320 extension->id())); |
| 321 SendChangeNotification(content::Source<Profile>(source).ptr()); | |
| 314 break; | 322 break; |
| 315 case extension_misc::UNLOAD_REASON_UPDATE: { | 323 case extension_misc::UNLOAD_REASON_UPDATE: { |
| 316 // If there is a manifest specified background page, then shut it down | 324 // If there is a manifest specified background page, then shut it down |
| 317 // here, since if the updated extension still has the background page, | 325 // here, since if the updated extension still has the background page, |
| 318 // then it will be loaded from LOADED callback. Otherwise, leave | 326 // then it will be loaded from LOADED callback. Otherwise, leave |
| 319 // BackgroundContents in place. | 327 // BackgroundContents in place. |
| 328 // We don't call SendChangeNotification here - it will be generated | |
| 329 // from the LOADED callback. | |
| 320 const Extension* extension = | 330 const Extension* extension = |
| 321 content::Details<UnloadedExtensionInfo>(details)->extension; | 331 content::Details<UnloadedExtensionInfo>(details)->extension; |
| 322 if (extension->has_background_page()) | 332 if (extension->has_background_page()) |
| 323 ShutdownAssociatedBackgroundContents(ASCIIToUTF16(extension->id())); | 333 ShutdownAssociatedBackgroundContents(ASCIIToUTF16(extension->id())); |
| 324 break; | 334 break; |
| 325 } | 335 } |
| 326 default: | 336 default: |
| 327 NOTREACHED(); | 337 NOTREACHED(); |
| 328 ShutdownAssociatedBackgroundContents( | 338 ShutdownAssociatedBackgroundContents( |
| 329 ASCIIToUTF16(content::Details<UnloadedExtensionInfo>(details)-> | 339 ASCIIToUTF16(content::Details<UnloadedExtensionInfo>(details)-> |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 369 NOTREACHED() << "No extension found for BackgroundContents - id = " | 379 NOTREACHED() << "No extension found for BackgroundContents - id = " |
| 370 << *it; | 380 << *it; |
| 371 // Don't cancel out of our loop, just ignore this BackgroundContents and | 381 // Don't cancel out of our loop, just ignore this BackgroundContents and |
| 372 // load the next one. | 382 // load the next one. |
| 373 continue; | 383 continue; |
| 374 } | 384 } |
| 375 LoadBackgroundContentsFromDictionary(profile, *it, contents); | 385 LoadBackgroundContentsFromDictionary(profile, *it, contents); |
| 376 } | 386 } |
| 377 } | 387 } |
| 378 | 388 |
| 389 void BackgroundContentsService::SendChangeNotification(Profile* profile) { | |
| 390 content::NotificationService::current()->Notify( | |
| 391 chrome::NOTIFICATION_BACKGROUND_CONTENTS_SERVICE_CHANGED, | |
| 392 content::Source<Profile>(profile), | |
| 393 content::Details<BackgroundContentsService>(this)); | |
| 394 } | |
| 395 | |
| 379 void BackgroundContentsService::LoadBackgroundContentsForExtension( | 396 void BackgroundContentsService::LoadBackgroundContentsForExtension( |
| 380 Profile* profile, | 397 Profile* profile, |
| 381 const std::string& extension_id) { | 398 const std::string& extension_id) { |
| 382 // First look if the manifest specifies a background page. | 399 // First look if the manifest specifies a background page. |
| 383 const Extension* extension = | 400 const Extension* extension = |
| 384 profile->GetExtensionService()->GetExtensionById(extension_id, false); | 401 profile->GetExtensionService()->GetExtensionById(extension_id, false); |
| 385 DCHECK(!extension || extension->is_hosted_app()); | 402 DCHECK(!extension || extension->is_hosted_app()); |
| 386 if (extension && extension->has_background_page()) { | 403 if (extension && extension->has_background_page()) { |
| 387 LoadBackgroundContents(profile, | 404 LoadBackgroundContents(profile, |
| 388 extension->GetBackgroundURL(), | 405 extension->GetBackgroundURL(), |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 503 if (pref->GetDictionaryWithoutPathExpansion(UTF16ToUTF8(appid), ¤t)) | 520 if (pref->GetDictionaryWithoutPathExpansion(UTF16ToUTF8(appid), ¤t)) |
| 504 return; | 521 return; |
| 505 | 522 |
| 506 // No entry for this application yet, so add one. | 523 // No entry for this application yet, so add one. |
| 507 DictionaryValue* dict = new DictionaryValue(); | 524 DictionaryValue* dict = new DictionaryValue(); |
| 508 dict->SetString(kUrlKey, background_contents->GetURL().spec()); | 525 dict->SetString(kUrlKey, background_contents->GetURL().spec()); |
| 509 dict->SetString(kFrameNameKey, contents_map_[appid].frame_name); | 526 dict->SetString(kFrameNameKey, contents_map_[appid].frame_name); |
| 510 pref->SetWithoutPathExpansion(UTF16ToUTF8(appid), dict); | 527 pref->SetWithoutPathExpansion(UTF16ToUTF8(appid), dict); |
| 511 } | 528 } |
| 512 | 529 |
| 530 bool BackgroundContentsService::HasRegisteredBackgroundContents( | |
| 531 const string16& app_id) { | |
| 532 if (!prefs_) | |
| 533 return false; | |
| 534 std::string app = UTF16ToUTF8(app_id); | |
| 535 const DictionaryValue* contents = | |
| 536 prefs_->GetDictionary(prefs::kRegisteredBackgroundContents); | |
| 537 // Walk our dictionary looking for any entries with this key. | |
|
Mihai Parparita -not on Chrome
2012/05/03 00:54:11
Why not use contents->HasKey(app)?
Andrew T Wilson (Slow)
2012/05/03 07:42:56
Ah, good idea. I should've checked DictionaryValue
| |
| 538 for (DictionaryValue::key_iterator it = contents->begin_keys(); | |
| 539 it != contents->end_keys(); ++it) { | |
| 540 if (*it == app) | |
| 541 return true; | |
| 542 } | |
| 543 return false; | |
| 544 } | |
| 545 | |
| 513 void BackgroundContentsService::UnregisterBackgroundContents( | 546 void BackgroundContentsService::UnregisterBackgroundContents( |
| 514 BackgroundContents* background_contents) { | 547 BackgroundContents* background_contents) { |
| 515 if (!prefs_) | 548 if (!prefs_) |
| 516 return; | 549 return; |
| 517 DCHECK(IsTracked(background_contents)); | 550 DCHECK(IsTracked(background_contents)); |
| 518 const string16 appid = GetParentApplicationId(background_contents); | 551 const string16 appid = GetParentApplicationId(background_contents); |
| 519 DictionaryPrefUpdate update(prefs_, prefs::kRegisteredBackgroundContents); | 552 DictionaryPrefUpdate update(prefs_, prefs::kRegisteredBackgroundContents); |
| 520 update.Get()->RemoveWithoutPathExpansion(UTF16ToUTF8(appid), NULL); | 553 update.Get()->RemoveWithoutPathExpansion(UTF16ToUTF8(appid), NULL); |
| 521 } | 554 } |
| 522 | 555 |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 576 WebContents* new_contents, | 609 WebContents* new_contents, |
| 577 WindowOpenDisposition disposition, | 610 WindowOpenDisposition disposition, |
| 578 const gfx::Rect& initial_pos, | 611 const gfx::Rect& initial_pos, |
| 579 bool user_gesture) { | 612 bool user_gesture) { |
| 580 Browser* browser = BrowserList::GetLastActiveWithProfile( | 613 Browser* browser = BrowserList::GetLastActiveWithProfile( |
| 581 Profile::FromBrowserContext(new_contents->GetBrowserContext())); | 614 Profile::FromBrowserContext(new_contents->GetBrowserContext())); |
| 582 if (!browser) | 615 if (!browser) |
| 583 return; | 616 return; |
| 584 browser->AddWebContents(new_contents, disposition, initial_pos, user_gesture); | 617 browser->AddWebContents(new_contents, disposition, initial_pos, user_gesture); |
| 585 } | 618 } |
| OLD | NEW |