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 |