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 3 // found in the LICENSE file. 4 5 #include "chrome/browser/ui/blocked_content/blocked_content_tab_helper.h" 6 7 #include "base/auto_reset.h" 8 #include "chrome/browser/chrome_notification_types.h" 9 #include "chrome/browser/content_settings/host_content_settings_map.h" 10 #include "chrome/browser/content_settings/tab_specific_content_settings.h" 11 #include "chrome/browser/profiles/profile.h" 12 #include "chrome/browser/ui/blocked_content/blocked_content_container.h" 13 #include "content/public/browser/navigation_controller.h" 14 #include "content/public/browser/navigation_details.h" 15 #include "content/public/browser/navigation_entry.h" 16 #include "content/public/browser/notification_details.h" 17 #include "content/public/browser/notification_service.h" 18 #include "content/public/browser/notification_source.h" 19 #include "content/public/browser/render_view_host.h" 20 #include "content/public/browser/web_contents.h" 21 #include "content/public/browser/web_contents_delegate.h" 22 23 using content::NavigationEntry; 24 25 DEFINE_WEB_CONTENTS_USER_DATA_KEY(BlockedContentTabHelper); 26 27 BlockedContentTabHelper::BlockedContentTabHelper( 28 content::WebContents* web_contents) 29 : content::WebContentsObserver(web_contents), 30 blocked_contents_(new BlockedContentContainer(web_contents)), 31 all_contents_blocked_(false), 32 delegate_(NULL) { 33 } 34 35 BlockedContentTabHelper::~BlockedContentTabHelper() { 36 } 37 38 void BlockedContentTabHelper::DidNavigateMainFrame( 39 const content::LoadCommittedDetails& details, 40 const content::FrameNavigateParams& params) { 41 // Clear all page actions, blocked content notifications and browser actions 42 // for this tab, unless this is an in-page navigation. 43 if (!details.is_in_page) { 44 // Close blocked popups. 45 if (blocked_contents_->GetBlockedContentsCount()) { 46 blocked_contents_->Clear(); 47 PopupNotificationVisibilityChanged(false); 48 } 49 } 50 } 51 52 void BlockedContentTabHelper::PopupNotificationVisibilityChanged( 53 bool visible) { 54 if (!web_contents()->IsBeingDestroyed()) { 55 TabSpecificContentSettings::FromWebContents(web_contents())-> 56 SetPopupsBlocked(visible); 57 } 58 } 59 60 void BlockedContentTabHelper::SendNotification(content::WebContents* contents, 61 bool blocked_state) { 62 content::NotificationService::current()->Notify( 63 chrome::NOTIFICATION_CONTENT_BLOCKED_STATE_CHANGED, 64 content::Source<content::WebContents>(contents), 65 content::Details<const bool>(&blocked_state)); 66 } 67 68 void BlockedContentTabHelper::SetAllContentsBlocked(bool value) { 69 if (all_contents_blocked_ == value) 70 return; 71 72 all_contents_blocked_ = value; 73 if (!all_contents_blocked_ && blocked_contents_->GetBlockedContentsCount()) { 74 std::vector<content::WebContents*> blocked; 75 blocked_contents_->GetBlockedContents(&blocked); 76 for (size_t i = 0; i < blocked.size(); ++i) { 77 SendNotification(blocked[i], false); 78 blocked_contents_->LaunchForContents(blocked[i]); 79 } 80 } 81 } 82 83 void BlockedContentTabHelper::AddWebContents(content::WebContents* new_contents, 84 WindowOpenDisposition disposition, 85 const gfx::Rect& initial_pos, 86 bool user_gesture) { 87 if (!blocked_contents_->GetBlockedContentsCount()) 88 PopupNotificationVisibilityChanged(true); 89 SendNotification(new_contents, true); 90 blocked_contents_->AddWebContents( 91 new_contents, disposition, initial_pos, user_gesture); 92 } 93 94 void BlockedContentTabHelper::AddPopup(content::WebContents* new_contents, 95 WindowOpenDisposition disposition, 96 const gfx::Rect& initial_pos, 97 bool user_gesture) { 98 // A page can't spawn popups (or do anything else, either) until its load 99 // commits, so when we reach here, the popup was spawned by the 100 // NavigationController's last committed entry, not the active entry. For 101 // example, if a page opens a popup in an onunload() handler, then the active 102 // entry is the page to be loaded as we navigate away from the unloading 103 // page. For this reason, we can't use GetURL() to get the opener URL, 104 // because it returns the active entry. 105 NavigationEntry* entry = 106 web_contents()->GetController().GetLastCommittedEntry(); 107 GURL creator = entry ? entry->GetVirtualURL() : GURL::EmptyGURL(); 108 Profile* profile = 109 Profile::FromBrowserContext(web_contents()->GetBrowserContext()); 110 111 if (creator.is_valid() && 112 profile->GetHostContentSettingsMap()->GetContentSetting( 113 creator, creator, CONTENT_SETTINGS_TYPE_POPUPS, std::string()) == 114 CONTENT_SETTING_ALLOW) { 115 content::WebContentsDelegate* delegate = web_contents()->GetDelegate(); 116 if (delegate) { 117 delegate->AddNewContents(web_contents(), 118 new_contents, 119 disposition, 120 initial_pos, 121 true, // user_gesture 122 NULL); 123 } 124 } else { 125 // Call blocked_contents_->AddWebContents with user_gesture == true 126 // so that the contents will not get blocked again. 127 SendNotification(new_contents, true); 128 blocked_contents_->AddWebContents(new_contents, 129 disposition, 130 initial_pos, 131 true); // user_gesture 132 TabSpecificContentSettings::FromWebContents(web_contents())-> 133 OnContentBlocked(CONTENT_SETTINGS_TYPE_POPUPS, std::string()); 134 } 135 } 136 137 void BlockedContentTabHelper::LaunchForContents( 138 content::WebContents* web_contents) { 139 SendNotification(web_contents, false); 140 blocked_contents_->LaunchForContents(web_contents); 141 if (!blocked_contents_->GetBlockedContentsCount()) 142 PopupNotificationVisibilityChanged(false); 143 } 144 145 size_t BlockedContentTabHelper::GetBlockedContentsCount() const { 146 return blocked_contents_->GetBlockedContentsCount(); 147 } 148 149 void BlockedContentTabHelper::GetBlockedContents( 150 std::vector<content::WebContents*>* blocked_contents) const { 151 blocked_contents_->GetBlockedContents(blocked_contents); 152 } 153