1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "chrome/browser/infobars/infobar_service.h" 6 7 #include "base/command_line.h" 8 #include "chrome/browser/chrome_notification_types.h" 9 #include "chrome/browser/infobars/insecure_content_infobar_delegate.h" 10 #include "chrome/common/render_messages.h" 11 #include "components/infobars/core/infobar.h" 12 #include "content/public/browser/navigation_details.h" 13 #include "content/public/browser/navigation_entry.h" 14 #include "content/public/browser/notification_service.h" 15 #include "content/public/browser/web_contents.h" 16 17 DEFINE_WEB_CONTENTS_USER_DATA_KEY(InfoBarService); 18 19 using infobars::InfoBar; 20 using infobars::InfoBarDelegate; 21 using infobars::InfoBarManager; 22 23 // static 24 InfoBarDelegate::NavigationDetails 25 InfoBarService::NavigationDetailsFromLoadCommittedDetails( 26 const content::LoadCommittedDetails& details) { 27 InfoBarDelegate::NavigationDetails navigation_details; 28 navigation_details.entry_id = details.entry->GetUniqueID(); 29 navigation_details.is_navigation_to_different_page = 30 details.is_navigation_to_different_page(); 31 navigation_details.did_replace_entry = details.did_replace_entry; 32 navigation_details.is_main_frame = details.is_main_frame; 33 34 const content::PageTransition transition = details.entry->GetTransitionType(); 35 navigation_details.is_reload = 36 content::PageTransitionStripQualifier(transition) == 37 content::PAGE_TRANSITION_RELOAD; 38 navigation_details.is_redirect = 39 (transition & content::PAGE_TRANSITION_IS_REDIRECT_MASK) != 0; 40 41 return navigation_details; 42 } 43 44 // static 45 content::WebContents* InfoBarService::WebContentsFromInfoBar(InfoBar* infobar) { 46 if (!infobar || !infobar->owner()) 47 return NULL; 48 InfoBarService* infobar_service = 49 static_cast<InfoBarService*>(infobar->owner()); 50 return infobar_service->web_contents(); 51 } 52 53 InfoBarService::InfoBarService(content::WebContents* web_contents) 54 : content::WebContentsObserver(web_contents) { 55 DCHECK(web_contents); 56 } 57 58 InfoBarService::~InfoBarService() { 59 ShutDown(); 60 } 61 62 int InfoBarService::GetActiveEntryID() { 63 content::NavigationEntry* active_entry = 64 web_contents()->GetController().GetActiveEntry(); 65 return active_entry ? active_entry->GetUniqueID() : 0; 66 } 67 68 void InfoBarService::NotifyInfoBarAdded(InfoBar* infobar) { 69 InfoBarManager::NotifyInfoBarAdded(infobar); 70 // TODO(droger): Remove the notifications and have listeners change to be 71 // InfoBarManager::Observers instead. See http://crbug.com/354380 72 content::NotificationService::current()->Notify( 73 chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_ADDED, 74 content::Source<InfoBarService>(this), 75 content::Details<InfoBar::AddedDetails>(infobar)); 76 } 77 78 void InfoBarService::NotifyInfoBarRemoved(InfoBar* infobar, bool animate) { 79 InfoBarManager::NotifyInfoBarRemoved(infobar, animate); 80 // TODO(droger): Remove the notifications and have listeners change to be 81 // InfoBarManager::Observers instead. See http://crbug.com/354380 82 InfoBar::RemovedDetails removed_details(infobar, animate); 83 content::NotificationService::current()->Notify( 84 chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED, 85 content::Source<InfoBarService>(this), 86 content::Details<InfoBar::RemovedDetails>(&removed_details)); 87 } 88 89 void InfoBarService::RenderProcessGone(base::TerminationStatus status) { 90 RemoveAllInfoBars(true); 91 } 92 93 void InfoBarService::NavigationEntryCommitted( 94 const content::LoadCommittedDetails& load_details) { 95 OnNavigation(NavigationDetailsFromLoadCommittedDetails(load_details)); 96 } 97 98 void InfoBarService::WebContentsDestroyed() { 99 // The WebContents is going away; be aggressively paranoid and delete 100 // ourselves lest other parts of the system attempt to add infobars or use 101 // us otherwise during the destruction. 102 web_contents()->RemoveUserData(UserDataKey()); 103 // That was the equivalent of "delete this". This object is now destroyed; 104 // returning from this function is the only safe thing to do. 105 } 106 107 bool InfoBarService::OnMessageReceived(const IPC::Message& message) { 108 bool handled = true; 109 IPC_BEGIN_MESSAGE_MAP(InfoBarService, message) 110 IPC_MESSAGE_HANDLER(ChromeViewHostMsg_DidBlockDisplayingInsecureContent, 111 OnDidBlockDisplayingInsecureContent) 112 IPC_MESSAGE_HANDLER(ChromeViewHostMsg_DidBlockRunningInsecureContent, 113 OnDidBlockRunningInsecureContent) 114 IPC_MESSAGE_UNHANDLED(handled = false) 115 IPC_END_MESSAGE_MAP() 116 return handled; 117 } 118 119 void InfoBarService::OnDidBlockDisplayingInsecureContent() { 120 InsecureContentInfoBarDelegate::Create( 121 this, InsecureContentInfoBarDelegate::DISPLAY); 122 } 123 124 void InfoBarService::OnDidBlockRunningInsecureContent() { 125 InsecureContentInfoBarDelegate::Create(this, 126 InsecureContentInfoBarDelegate::RUN); 127 } 128