| 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 "apps/app_load_service.h" | 7 #include "apps/app_load_service.h" |
| 8 #include "base/basictypes.h" | 8 #include "base/basictypes.h" |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 151 bool is_hosted_app_; | 151 bool is_hosted_app_; |
| 152 bool is_platform_app_; | 152 bool is_platform_app_; |
| 153 std::string extension_id_; | 153 std::string extension_id_; |
| 154 | 154 |
| 155 DISALLOW_COPY_AND_ASSIGN(CrashNotificationDelegate); | 155 DISALLOW_COPY_AND_ASSIGN(CrashNotificationDelegate); |
| 156 }; | 156 }; |
| 157 | 157 |
| 158 #if defined(ENABLE_NOTIFICATIONS) | 158 #if defined(ENABLE_NOTIFICATIONS) |
| 159 void NotificationImageReady( | 159 void NotificationImageReady( |
| 160 const std::string extension_name, | 160 const std::string extension_name, |
| 161 const string16 message, | 161 const base::string16 message, |
| 162 const GURL extension_url, | 162 const GURL extension_url, |
| 163 scoped_refptr<CrashNotificationDelegate> delegate, | 163 scoped_refptr<CrashNotificationDelegate> delegate, |
| 164 Profile* profile, | 164 Profile* profile, |
| 165 const gfx::Image& icon) { | 165 const gfx::Image& icon) { |
| 166 gfx::Image notification_icon(icon); | 166 gfx::Image notification_icon(icon); |
| 167 if (icon.IsEmpty()) { | 167 if (icon.IsEmpty()) { |
| 168 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | 168 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); |
| 169 notification_icon = rb.GetImageNamed(IDR_EXTENSION_DEFAULT_ICON); | 169 notification_icon = rb.GetImageNamed(IDR_EXTENSION_DEFAULT_ICON); |
| 170 } | 170 } |
| 171 string16 title; // no notification title | 171 base::string16 title; // no notification title |
| 172 DesktopNotificationService::AddIconNotification(extension_url, | 172 DesktopNotificationService::AddIconNotification(extension_url, |
| 173 title, | 173 title, |
| 174 message, | 174 message, |
| 175 notification_icon, | 175 notification_icon, |
| 176 string16(), | 176 base::string16(), |
| 177 delegate.get(), | 177 delegate.get(), |
| 178 profile); | 178 profile); |
| 179 } | 179 } |
| 180 #endif | 180 #endif |
| 181 | 181 |
| 182 // Show a popup notification balloon with a crash message for a given app/ | 182 // Show a popup notification balloon with a crash message for a given app/ |
| 183 // extension. | 183 // extension. |
| 184 void ShowBalloon(const Extension* extension, Profile* profile) { | 184 void ShowBalloon(const Extension* extension, Profile* profile) { |
| 185 #if defined(ENABLE_NOTIFICATIONS) | 185 #if defined(ENABLE_NOTIFICATIONS) |
| 186 const string16 message = l10n_util::GetStringFUTF16( | 186 const base::string16 message = l10n_util::GetStringFUTF16( |
| 187 extension->is_app() ? IDS_BACKGROUND_CRASHED_APP_BALLOON_MESSAGE : | 187 extension->is_app() ? IDS_BACKGROUND_CRASHED_APP_BALLOON_MESSAGE : |
| 188 IDS_BACKGROUND_CRASHED_EXTENSION_BALLOON_MESSAGE, | 188 IDS_BACKGROUND_CRASHED_EXTENSION_BALLOON_MESSAGE, |
| 189 UTF8ToUTF16(extension->name())); | 189 UTF8ToUTF16(extension->name())); |
| 190 extension_misc::ExtensionIcons size(extension_misc::EXTENSION_ICON_MEDIUM); | 190 extension_misc::ExtensionIcons size(extension_misc::EXTENSION_ICON_MEDIUM); |
| 191 extensions::ExtensionResource resource = | 191 extensions::ExtensionResource resource = |
| 192 extensions::IconsInfo::GetIconResource( | 192 extensions::IconsInfo::GetIconResource( |
| 193 extension, size, ExtensionIconSet::MATCH_SMALLER); | 193 extension, size, ExtensionIconSet::MATCH_SMALLER); |
| 194 // We can't just load the image in the Observe method below because, despite | 194 // We can't just load the image in the Observe method below because, despite |
| 195 // what this method is called, it may call the callback synchronously. | 195 // what this method is called, it may call the callback synchronously. |
| 196 // However, it's possible that the extension went away during the interim, | 196 // However, it's possible that the extension went away during the interim, |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 355 // change notification there. | 355 // change notification there. |
| 356 break; | 356 break; |
| 357 case chrome::NOTIFICATION_BACKGROUND_CONTENTS_NAVIGATED: { | 357 case chrome::NOTIFICATION_BACKGROUND_CONTENTS_NAVIGATED: { |
| 358 DCHECK(IsTracked(content::Details<BackgroundContents>(details).ptr())); | 358 DCHECK(IsTracked(content::Details<BackgroundContents>(details).ptr())); |
| 359 | 359 |
| 360 // Do not register in the pref if the extension has a manifest-specified | 360 // Do not register in the pref if the extension has a manifest-specified |
| 361 // background page. | 361 // background page. |
| 362 BackgroundContents* bgcontents = | 362 BackgroundContents* bgcontents = |
| 363 content::Details<BackgroundContents>(details).ptr(); | 363 content::Details<BackgroundContents>(details).ptr(); |
| 364 Profile* profile = content::Source<Profile>(source).ptr(); | 364 Profile* profile = content::Source<Profile>(source).ptr(); |
| 365 const string16& appid = GetParentApplicationId(bgcontents); | 365 const base::string16& appid = GetParentApplicationId(bgcontents); |
| 366 ExtensionService* extension_service = | 366 ExtensionService* extension_service = |
| 367 extensions::ExtensionSystem::Get(profile)->extension_service(); | 367 extensions::ExtensionSystem::Get(profile)->extension_service(); |
| 368 // extension_service can be NULL when running tests. | 368 // extension_service can be NULL when running tests. |
| 369 if (extension_service) { | 369 if (extension_service) { |
| 370 const Extension* extension = | 370 const Extension* extension = |
| 371 extension_service->GetExtensionById(UTF16ToUTF8(appid), false); | 371 extension_service->GetExtensionById(UTF16ToUTF8(appid), false); |
| 372 if (extension && BackgroundInfo::HasBackgroundPage(extension)) | 372 if (extension && BackgroundInfo::HasBackgroundPage(extension)) |
| 373 break; | 373 break; |
| 374 } | 374 } |
| 375 RegisterBackgroundContents(bgcontents); | 375 RegisterBackgroundContents(bgcontents); |
| (...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 566 const DictionaryValue* contents) { | 566 const DictionaryValue* contents) { |
| 567 ExtensionService* extensions_service = | 567 ExtensionService* extensions_service = |
| 568 extensions::ExtensionSystem::Get(profile)->extension_service(); | 568 extensions::ExtensionSystem::Get(profile)->extension_service(); |
| 569 DCHECK(extensions_service); | 569 DCHECK(extensions_service); |
| 570 | 570 |
| 571 const DictionaryValue* dict; | 571 const DictionaryValue* dict; |
| 572 if (!contents->GetDictionaryWithoutPathExpansion(extension_id, &dict) || | 572 if (!contents->GetDictionaryWithoutPathExpansion(extension_id, &dict) || |
| 573 dict == NULL) | 573 dict == NULL) |
| 574 return; | 574 return; |
| 575 | 575 |
| 576 string16 frame_name; | 576 base::string16 frame_name; |
| 577 std::string url; | 577 std::string url; |
| 578 dict->GetString(kUrlKey, &url); | 578 dict->GetString(kUrlKey, &url); |
| 579 dict->GetString(kFrameNameKey, &frame_name); | 579 dict->GetString(kFrameNameKey, &frame_name); |
| 580 LoadBackgroundContents(profile, | 580 LoadBackgroundContents(profile, |
| 581 GURL(url), | 581 GURL(url), |
| 582 frame_name, | 582 frame_name, |
| 583 UTF8ToUTF16(extension_id)); | 583 UTF8ToUTF16(extension_id)); |
| 584 } | 584 } |
| 585 | 585 |
| 586 void BackgroundContentsService::LoadBackgroundContentsFromManifests( | 586 void BackgroundContentsService::LoadBackgroundContentsFromManifests( |
| 587 Profile* profile) { | 587 Profile* profile) { |
| 588 const ExtensionSet* extensions = extensions::ExtensionSystem::Get(profile)-> | 588 const ExtensionSet* extensions = extensions::ExtensionSystem::Get(profile)-> |
| 589 extension_service()->extensions(); | 589 extension_service()->extensions(); |
| 590 ExtensionSet::const_iterator iter = extensions->begin(); | 590 ExtensionSet::const_iterator iter = extensions->begin(); |
| 591 for (; iter != extensions->end(); ++iter) { | 591 for (; iter != extensions->end(); ++iter) { |
| 592 const Extension* extension = iter->get(); | 592 const Extension* extension = iter->get(); |
| 593 if (extension->is_hosted_app() && | 593 if (extension->is_hosted_app() && |
| 594 BackgroundInfo::HasBackgroundPage(extension)) { | 594 BackgroundInfo::HasBackgroundPage(extension)) { |
| 595 LoadBackgroundContents(profile, | 595 LoadBackgroundContents(profile, |
| 596 BackgroundInfo::GetBackgroundURL(extension), | 596 BackgroundInfo::GetBackgroundURL(extension), |
| 597 ASCIIToUTF16("background"), | 597 ASCIIToUTF16("background"), |
| 598 UTF8ToUTF16(extension->id())); | 598 UTF8ToUTF16(extension->id())); |
| 599 } | 599 } |
| 600 } | 600 } |
| 601 } | 601 } |
| 602 | 602 |
| 603 void BackgroundContentsService::LoadBackgroundContents( | 603 void BackgroundContentsService::LoadBackgroundContents( |
| 604 Profile* profile, | 604 Profile* profile, |
| 605 const GURL& url, | 605 const GURL& url, |
| 606 const string16& frame_name, | 606 const base::string16& frame_name, |
| 607 const string16& application_id) { | 607 const base::string16& application_id) { |
| 608 // We are depending on the fact that we will initialize before any user | 608 // We are depending on the fact that we will initialize before any user |
| 609 // actions or session restore can take place, so no BackgroundContents should | 609 // actions or session restore can take place, so no BackgroundContents should |
| 610 // be running yet for the passed application_id. | 610 // be running yet for the passed application_id. |
| 611 DCHECK(!GetAppBackgroundContents(application_id)); | 611 DCHECK(!GetAppBackgroundContents(application_id)); |
| 612 DCHECK(!application_id.empty()); | 612 DCHECK(!application_id.empty()); |
| 613 DCHECK(url.is_valid()); | 613 DCHECK(url.is_valid()); |
| 614 DVLOG(1) << "Loading background content url: " << url; | 614 DVLOG(1) << "Loading background content url: " << url; |
| 615 | 615 |
| 616 BackgroundContents* contents = CreateBackgroundContents( | 616 BackgroundContents* contents = CreateBackgroundContents( |
| 617 SiteInstance::CreateForURL(profile, url), | 617 SiteInstance::CreateForURL(profile, url), |
| 618 MSG_ROUTING_NONE, | 618 MSG_ROUTING_NONE, |
| 619 profile, | 619 profile, |
| 620 frame_name, | 620 frame_name, |
| 621 application_id, | 621 application_id, |
| 622 std::string(), | 622 std::string(), |
| 623 NULL); | 623 NULL); |
| 624 | 624 |
| 625 // TODO(atwilson): Create RenderViews asynchronously to avoid increasing | 625 // TODO(atwilson): Create RenderViews asynchronously to avoid increasing |
| 626 // startup latency (http://crbug.com/47236). | 626 // startup latency (http://crbug.com/47236). |
| 627 contents->web_contents()->GetController().LoadURL( | 627 contents->web_contents()->GetController().LoadURL( |
| 628 url, content::Referrer(), content::PAGE_TRANSITION_LINK, std::string()); | 628 url, content::Referrer(), content::PAGE_TRANSITION_LINK, std::string()); |
| 629 } | 629 } |
| 630 | 630 |
| 631 BackgroundContents* BackgroundContentsService::CreateBackgroundContents( | 631 BackgroundContents* BackgroundContentsService::CreateBackgroundContents( |
| 632 SiteInstance* site, | 632 SiteInstance* site, |
| 633 int routing_id, | 633 int routing_id, |
| 634 Profile* profile, | 634 Profile* profile, |
| 635 const string16& frame_name, | 635 const base::string16& frame_name, |
| 636 const string16& application_id, | 636 const base::string16& application_id, |
| 637 const std::string& partition_id, | 637 const std::string& partition_id, |
| 638 content::SessionStorageNamespace* session_storage_namespace) { | 638 content::SessionStorageNamespace* session_storage_namespace) { |
| 639 BackgroundContents* contents = new BackgroundContents( | 639 BackgroundContents* contents = new BackgroundContents( |
| 640 site, routing_id, this, partition_id, session_storage_namespace); | 640 site, routing_id, this, partition_id, session_storage_namespace); |
| 641 | 641 |
| 642 // Register the BackgroundContents internally, then send out a notification | 642 // Register the BackgroundContents internally, then send out a notification |
| 643 // to external listeners. | 643 // to external listeners. |
| 644 BackgroundContentsOpenedDetails details = {contents, | 644 BackgroundContentsOpenedDetails details = {contents, |
| 645 frame_name, | 645 frame_name, |
| 646 application_id}; | 646 application_id}; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 660 DCHECK(IsTracked(background_contents)); | 660 DCHECK(IsTracked(background_contents)); |
| 661 if (!prefs_) | 661 if (!prefs_) |
| 662 return; | 662 return; |
| 663 | 663 |
| 664 // We store the first URL we receive for a given application. If there's | 664 // We store the first URL we receive for a given application. If there's |
| 665 // already an entry for this application, no need to do anything. | 665 // already an entry for this application, no need to do anything. |
| 666 // TODO(atwilson): Verify that this is the desired behavior based on developer | 666 // TODO(atwilson): Verify that this is the desired behavior based on developer |
| 667 // feedback (http://crbug.com/47118). | 667 // feedback (http://crbug.com/47118). |
| 668 DictionaryPrefUpdate update(prefs_, prefs::kRegisteredBackgroundContents); | 668 DictionaryPrefUpdate update(prefs_, prefs::kRegisteredBackgroundContents); |
| 669 DictionaryValue* pref = update.Get(); | 669 DictionaryValue* pref = update.Get(); |
| 670 const string16& appid = GetParentApplicationId(background_contents); | 670 const base::string16& appid = GetParentApplicationId(background_contents); |
| 671 DictionaryValue* current; | 671 DictionaryValue* current; |
| 672 if (pref->GetDictionaryWithoutPathExpansion(UTF16ToUTF8(appid), ¤t)) | 672 if (pref->GetDictionaryWithoutPathExpansion(UTF16ToUTF8(appid), ¤t)) |
| 673 return; | 673 return; |
| 674 | 674 |
| 675 // No entry for this application yet, so add one. | 675 // No entry for this application yet, so add one. |
| 676 DictionaryValue* dict = new DictionaryValue(); | 676 DictionaryValue* dict = new DictionaryValue(); |
| 677 dict->SetString(kUrlKey, background_contents->GetURL().spec()); | 677 dict->SetString(kUrlKey, background_contents->GetURL().spec()); |
| 678 dict->SetString(kFrameNameKey, contents_map_[appid].frame_name); | 678 dict->SetString(kFrameNameKey, contents_map_[appid].frame_name); |
| 679 pref->SetWithoutPathExpansion(UTF16ToUTF8(appid), dict); | 679 pref->SetWithoutPathExpansion(UTF16ToUTF8(appid), dict); |
| 680 } | 680 } |
| 681 | 681 |
| 682 bool BackgroundContentsService::HasRegisteredBackgroundContents( | 682 bool BackgroundContentsService::HasRegisteredBackgroundContents( |
| 683 const string16& app_id) { | 683 const base::string16& app_id) { |
| 684 if (!prefs_) | 684 if (!prefs_) |
| 685 return false; | 685 return false; |
| 686 std::string app = UTF16ToUTF8(app_id); | 686 std::string app = UTF16ToUTF8(app_id); |
| 687 const DictionaryValue* contents = | 687 const DictionaryValue* contents = |
| 688 prefs_->GetDictionary(prefs::kRegisteredBackgroundContents); | 688 prefs_->GetDictionary(prefs::kRegisteredBackgroundContents); |
| 689 return contents->HasKey(app); | 689 return contents->HasKey(app); |
| 690 } | 690 } |
| 691 | 691 |
| 692 void BackgroundContentsService::UnregisterBackgroundContents( | 692 void BackgroundContentsService::UnregisterBackgroundContents( |
| 693 BackgroundContents* background_contents) { | 693 BackgroundContents* background_contents) { |
| 694 if (!prefs_) | 694 if (!prefs_) |
| 695 return; | 695 return; |
| 696 DCHECK(IsTracked(background_contents)); | 696 DCHECK(IsTracked(background_contents)); |
| 697 const string16 appid = GetParentApplicationId(background_contents); | 697 const base::string16 appid = GetParentApplicationId(background_contents); |
| 698 DictionaryPrefUpdate update(prefs_, prefs::kRegisteredBackgroundContents); | 698 DictionaryPrefUpdate update(prefs_, prefs::kRegisteredBackgroundContents); |
| 699 update.Get()->RemoveWithoutPathExpansion(UTF16ToUTF8(appid), NULL); | 699 update.Get()->RemoveWithoutPathExpansion(UTF16ToUTF8(appid), NULL); |
| 700 } | 700 } |
| 701 | 701 |
| 702 void BackgroundContentsService::ShutdownAssociatedBackgroundContents( | 702 void BackgroundContentsService::ShutdownAssociatedBackgroundContents( |
| 703 const string16& appid) { | 703 const base::string16& appid) { |
| 704 BackgroundContents* contents = GetAppBackgroundContents(appid); | 704 BackgroundContents* contents = GetAppBackgroundContents(appid); |
| 705 if (contents) { | 705 if (contents) { |
| 706 UnregisterBackgroundContents(contents); | 706 UnregisterBackgroundContents(contents); |
| 707 // Background contents destructor shuts down the renderer. | 707 // Background contents destructor shuts down the renderer. |
| 708 delete contents; | 708 delete contents; |
| 709 } | 709 } |
| 710 } | 710 } |
| 711 | 711 |
| 712 void BackgroundContentsService::BackgroundContentsOpened( | 712 void BackgroundContentsService::BackgroundContentsOpened( |
| 713 BackgroundContentsOpenedDetails* details) { | 713 BackgroundContentsOpenedDetails* details) { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 724 // BackgroundContents is being tracked by this instance. | 724 // BackgroundContents is being tracked by this instance. |
| 725 bool BackgroundContentsService::IsTracked( | 725 bool BackgroundContentsService::IsTracked( |
| 726 BackgroundContents* background_contents) const { | 726 BackgroundContents* background_contents) const { |
| 727 return !GetParentApplicationId(background_contents).empty(); | 727 return !GetParentApplicationId(background_contents).empty(); |
| 728 } | 728 } |
| 729 | 729 |
| 730 void BackgroundContentsService::BackgroundContentsShutdown( | 730 void BackgroundContentsService::BackgroundContentsShutdown( |
| 731 BackgroundContents* background_contents) { | 731 BackgroundContents* background_contents) { |
| 732 // Remove the passed object from our list. | 732 // Remove the passed object from our list. |
| 733 DCHECK(IsTracked(background_contents)); | 733 DCHECK(IsTracked(background_contents)); |
| 734 string16 appid = GetParentApplicationId(background_contents); | 734 base::string16 appid = GetParentApplicationId(background_contents); |
| 735 contents_map_.erase(appid); | 735 contents_map_.erase(appid); |
| 736 } | 736 } |
| 737 | 737 |
| 738 BackgroundContents* BackgroundContentsService::GetAppBackgroundContents( | 738 BackgroundContents* BackgroundContentsService::GetAppBackgroundContents( |
| 739 const string16& application_id) { | 739 const base::string16& application_id) { |
| 740 BackgroundContentsMap::const_iterator it = contents_map_.find(application_id); | 740 BackgroundContentsMap::const_iterator it = contents_map_.find(application_id); |
| 741 return (it != contents_map_.end()) ? it->second.contents : NULL; | 741 return (it != contents_map_.end()) ? it->second.contents : NULL; |
| 742 } | 742 } |
| 743 | 743 |
| 744 const string16& BackgroundContentsService::GetParentApplicationId( | 744 const base::string16& BackgroundContentsService::GetParentApplicationId( |
| 745 BackgroundContents* contents) const { | 745 BackgroundContents* contents) const { |
| 746 for (BackgroundContentsMap::const_iterator it = contents_map_.begin(); | 746 for (BackgroundContentsMap::const_iterator it = contents_map_.begin(); |
| 747 it != contents_map_.end(); ++it) { | 747 it != contents_map_.end(); ++it) { |
| 748 if (contents == it->second.contents) | 748 if (contents == it->second.contents) |
| 749 return it->first; | 749 return it->first; |
| 750 } | 750 } |
| 751 return base::EmptyString16(); | 751 return base::EmptyString16(); |
| 752 } | 752 } |
| 753 | 753 |
| 754 void BackgroundContentsService::AddWebContents( | 754 void BackgroundContentsService::AddWebContents( |
| 755 WebContents* new_contents, | 755 WebContents* new_contents, |
| 756 WindowOpenDisposition disposition, | 756 WindowOpenDisposition disposition, |
| 757 const gfx::Rect& initial_pos, | 757 const gfx::Rect& initial_pos, |
| 758 bool user_gesture, | 758 bool user_gesture, |
| 759 bool* was_blocked) { | 759 bool* was_blocked) { |
| 760 Browser* browser = chrome::FindLastActiveWithProfile( | 760 Browser* browser = chrome::FindLastActiveWithProfile( |
| 761 Profile::FromBrowserContext(new_contents->GetBrowserContext()), | 761 Profile::FromBrowserContext(new_contents->GetBrowserContext()), |
| 762 chrome::GetActiveDesktop()); | 762 chrome::GetActiveDesktop()); |
| 763 if (browser) { | 763 if (browser) { |
| 764 chrome::AddWebContents(browser, NULL, new_contents, disposition, | 764 chrome::AddWebContents(browser, NULL, new_contents, disposition, |
| 765 initial_pos, user_gesture, was_blocked); | 765 initial_pos, user_gesture, was_blocked); |
| 766 } | 766 } |
| 767 } | 767 } |
| OLD | NEW |