15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/blocked_content/blocked_content_tab_helper.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/auto_reset.h"
87dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/content_settings/host_content_settings_map.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/content_settings/tab_specific_content_settings.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/blocked_content/blocked_content_container.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/navigation_controller.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/navigation_details.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/navigation_entry.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_details.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_service.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_source.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/render_view_host.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents_delegate.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::NavigationEntry;
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DEFINE_WEB_CONTENTS_USER_DATA_KEY(BlockedContentTabHelper);
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BlockedContentTabHelper::BlockedContentTabHelper(
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    content::WebContents* web_contents)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : content::WebContentsObserver(web_contents),
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      blocked_contents_(new BlockedContentContainer(web_contents)),
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      all_contents_blocked_(false),
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delegate_(NULL) {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BlockedContentTabHelper::~BlockedContentTabHelper() {
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BlockedContentTabHelper::DidNavigateMainFrame(
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const content::LoadCommittedDetails& details,
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const content::FrameNavigateParams& params) {
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Clear all page actions, blocked content notifications and browser actions
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // for this tab, unless this is an in-page navigation.
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!details.is_in_page) {
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Close blocked popups.
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (blocked_contents_->GetBlockedContentsCount()) {
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      blocked_contents_->Clear();
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PopupNotificationVisibilityChanged(false);
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BlockedContentTabHelper::PopupNotificationVisibilityChanged(
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool visible) {
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!web_contents()->IsBeingDestroyed()) {
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TabSpecificContentSettings::FromWebContents(web_contents())->
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SetPopupsBlocked(visible);
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BlockedContentTabHelper::SendNotification(content::WebContents* contents,
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               bool blocked_state) {
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::NotificationService::current()->Notify(
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      chrome::NOTIFICATION_CONTENT_BLOCKED_STATE_CHANGED,
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::Source<content::WebContents>(contents),
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::Details<const bool>(&blocked_state));
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BlockedContentTabHelper::SetAllContentsBlocked(bool value) {
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (all_contents_blocked_ == value)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  all_contents_blocked_ = value;
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!all_contents_blocked_ && blocked_contents_->GetBlockedContentsCount()) {
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<content::WebContents*> blocked;
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    blocked_contents_->GetBlockedContents(&blocked);
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < blocked.size(); ++i) {
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SendNotification(blocked[i], false);
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      blocked_contents_->LaunchForContents(blocked[i]);
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BlockedContentTabHelper::AddWebContents(content::WebContents* new_contents,
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             WindowOpenDisposition disposition,
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             const gfx::Rect& initial_pos,
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             bool user_gesture) {
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!blocked_contents_->GetBlockedContentsCount())
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PopupNotificationVisibilityChanged(true);
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SendNotification(new_contents, true);
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  blocked_contents_->AddWebContents(
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new_contents, disposition, initial_pos, user_gesture);
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BlockedContentTabHelper::AddPopup(content::WebContents* new_contents,
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       WindowOpenDisposition disposition,
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       const gfx::Rect& initial_pos,
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       bool user_gesture) {
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A page can't spawn popups (or do anything else, either) until its load
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // commits, so when we reach here, the popup was spawned by the
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // NavigationController's last committed entry, not the active entry.  For
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // example, if a page opens a popup in an onunload() handler, then the active
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // entry is the page to be loaded as we navigate away from the unloading
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // page.  For this reason, we can't use GetURL() to get the opener URL,
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // because it returns the active entry.
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NavigationEntry* entry =
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      web_contents()->GetController().GetLastCommittedEntry();
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL creator = entry ? entry->GetVirtualURL() : GURL::EmptyGURL();
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Profile* profile =
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Profile::FromBrowserContext(web_contents()->GetBrowserContext());
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (creator.is_valid() &&
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      profile->GetHostContentSettingsMap()->GetContentSetting(
113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          creator, creator, CONTENT_SETTINGS_TYPE_POPUPS, std::string()) ==
114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          CONTENT_SETTING_ALLOW) {
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    content::WebContentsDelegate* delegate = web_contents()->GetDelegate();
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (delegate) {
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delegate->AddNewContents(web_contents(),
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               new_contents,
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               disposition,
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               initial_pos,
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               true,  // user_gesture
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               NULL);
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Call blocked_contents_->AddWebContents with user_gesture == true
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // so that the contents will not get blocked again.
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SendNotification(new_contents, true);
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    blocked_contents_->AddWebContents(new_contents,
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      disposition,
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      initial_pos,
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      true);  // user_gesture
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TabSpecificContentSettings::FromWebContents(web_contents())->
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        OnContentBlocked(CONTENT_SETTINGS_TYPE_POPUPS, std::string());
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BlockedContentTabHelper::LaunchForContents(
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    content::WebContents* web_contents) {
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SendNotification(web_contents, false);
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  blocked_contents_->LaunchForContents(web_contents);
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!blocked_contents_->GetBlockedContentsCount())
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PopupNotificationVisibilityChanged(false);
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t BlockedContentTabHelper::GetBlockedContentsCount() const {
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return blocked_contents_->GetBlockedContentsCount();
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BlockedContentTabHelper::GetBlockedContents(
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<content::WebContents*>* blocked_contents) const {
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  blocked_contents_->GetBlockedContents(blocked_contents);
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
153