root/chrome/browser/ui/blocked_content/popup_blocker_tab_helper.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. DidNavigateMainFrame
  2. PopupNotificationVisibilityChanged
  3. MaybeBlockPopup
  4. AddBlockedPopup
  5. ShowBlockedPopup
  6. GetBlockedPopupsCount
  7. GetBlockedPopupRequests

// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ui/blocked_content/popup_blocker_tab_helper.h"

#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/content_settings/host_content_settings_map.h"
#include "chrome/browser/content_settings/tab_specific_content_settings.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/blocked_content/blocked_window_params.h"
#include "chrome/browser/ui/browser_navigator.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/common/render_messages.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/navigation_details.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/browser/web_contents_view.h"
#include "third_party/WebKit/public/web/WebWindowFeatures.h"

#if defined(OS_ANDROID)
#include "chrome/browser/ui/android/tab_model/tab_model_list.h"
#endif

using blink::WebWindowFeatures;

const size_t kMaximumNumberOfPopups = 25;

DEFINE_WEB_CONTENTS_USER_DATA_KEY(PopupBlockerTabHelper);

struct PopupBlockerTabHelper::BlockedRequest {
  BlockedRequest(const chrome::NavigateParams& params,
                 const WebWindowFeatures& window_features)
      : params(params), window_features(window_features) {}

  chrome::NavigateParams params;
  WebWindowFeatures window_features;
};

PopupBlockerTabHelper::PopupBlockerTabHelper(
    content::WebContents* web_contents)
    : content::WebContentsObserver(web_contents) {
}

PopupBlockerTabHelper::~PopupBlockerTabHelper() {
}

void PopupBlockerTabHelper::DidNavigateMainFrame(
    const content::LoadCommittedDetails& details,
    const content::FrameNavigateParams& params) {
  // Clear all page actions, blocked content notifications and browser actions
  // for this tab, unless this is an in-page navigation.
  if (details.is_in_page)
    return;

  // Close blocked popups.
  if (!blocked_popups_.IsEmpty()) {
    blocked_popups_.Clear();
    PopupNotificationVisibilityChanged(false);
  }
}

void PopupBlockerTabHelper::PopupNotificationVisibilityChanged(
    bool visible) {
  if (!web_contents()->IsBeingDestroyed()) {
    TabSpecificContentSettings::FromWebContents(web_contents())->
        SetPopupsBlocked(visible);
  }
}

bool PopupBlockerTabHelper::MaybeBlockPopup(
    const chrome::NavigateParams& params,
    const WebWindowFeatures& window_features) {
  // A page can't spawn popups (or do anything else, either) until its load
  // commits, so when we reach here, the popup was spawned by the
  // NavigationController's last committed entry, not the active entry.  For
  // example, if a page opens a popup in an onunload() handler, then the active
  // entry is the page to be loaded as we navigate away from the unloading
  // page.  For this reason, we can't use GetURL() to get the opener URL,
  // because it returns the active entry.
  content::NavigationEntry* entry =
      web_contents()->GetController().GetLastCommittedEntry();
  GURL creator = entry ? entry->GetVirtualURL() : GURL();
  Profile* profile =
      Profile::FromBrowserContext(web_contents()->GetBrowserContext());

  if (creator.is_valid() &&
      profile->GetHostContentSettingsMap()->GetContentSetting(
          creator, creator, CONTENT_SETTINGS_TYPE_POPUPS, std::string()) ==
          CONTENT_SETTING_ALLOW) {
    return false;
  } else {
    if (blocked_popups_.size() < kMaximumNumberOfPopups) {
      blocked_popups_.Add(new BlockedRequest(params, window_features));
      TabSpecificContentSettings::FromWebContents(web_contents())->
          OnContentBlocked(CONTENT_SETTINGS_TYPE_POPUPS);
    }
    return true;
  }
}

void PopupBlockerTabHelper::AddBlockedPopup(const BlockedWindowParams& params) {
  chrome::NavigateParams nav_params =
      params.CreateNavigateParams(web_contents());

  if (blocked_popups_.size() < kMaximumNumberOfPopups) {
    blocked_popups_.Add(new BlockedRequest(nav_params, params.features()));
    TabSpecificContentSettings::FromWebContents(web_contents())->
        OnContentBlocked(CONTENT_SETTINGS_TYPE_POPUPS);
  }
}

void PopupBlockerTabHelper::ShowBlockedPopup(int32 id) {
  BlockedRequest* popup = blocked_popups_.Lookup(id);
  if (!popup)
    return;
  // We set user_gesture to true here, so the new popup gets correctly focused.
  popup->params.user_gesture = true;
#if defined(OS_ANDROID)
  TabModelList::HandlePopupNavigation(&popup->params);
#else
  chrome::Navigate(&popup->params);
#endif
  if (popup->params.target_contents) {
    popup->params.target_contents->Send(new ChromeViewMsg_SetWindowFeatures(
        popup->params.target_contents->GetRoutingID(), popup->window_features));
  }
  blocked_popups_.Remove(id);
  if (blocked_popups_.IsEmpty())
    PopupNotificationVisibilityChanged(false);
}

size_t PopupBlockerTabHelper::GetBlockedPopupsCount() const {
  return blocked_popups_.size();
}

PopupBlockerTabHelper::PopupIdMap
    PopupBlockerTabHelper::GetBlockedPopupRequests() {
  PopupIdMap result;
  for (IDMap<BlockedRequest, IDMapOwnPointer>::const_iterator iter(
           &blocked_popups_);
       !iter.IsAtEnd();
       iter.Advance()) {
    result[iter.GetCurrentKey()] = iter.GetCurrentValue()->params.url;
  }
  return result;
}

/* [<][>][^][v][top][bottom][index][help] */