Home | History | Annotate | Download | only in blocked_content
      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