blob: 8be72fda3772d3c1b581be9a0a3cdac5babf7cfd [file] [log] [blame]
// Copyright (c) 2011 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.
#ifndef CONTENT_BROWSER_TAB_CONTENTS_INTERSTITIAL_PAGE_H_
#define CONTENT_BROWSER_TAB_CONTENTS_INTERSTITIAL_PAGE_H_
#pragma once
#include <map>
#include <string>
#include "base/memory/scoped_ptr.h"
#include "base/process_util.h"
#include "content/browser/renderer_host/render_view_host_delegate.h"
#include "content/common/notification_observer.h"
#include "content/common/notification_registrar.h"
#include "content/common/renderer_preferences.h"
#include "googleurl/src/gurl.h"
#include "ui/gfx/size.h"
class NavigationEntry;
class TabContents;
class TabContentsView;
// This class is a base class for interstitial pages, pages that show some
// informative message asking for user validation before reaching the target
// page. (Navigating to a page served over bad HTTPS or a page containing
// malware are typical cases where an interstitial is required.)
//
// If specified in its constructor, this class creates a navigation entry so
// that when the interstitial shows, the current entry is the target URL.
//
// InterstitialPage instances take care of deleting themselves when closed
// through a navigation, the TabContents closing them or the tab containing them
// being closed.
enum ResourceRequestAction {
BLOCK,
RESUME,
CANCEL
};
class InterstitialPage : public NotificationObserver,
public RenderViewHostDelegate {
public:
// The different state of actions the user can take in an interstitial.
enum ActionState {
NO_ACTION, // No action has been taken yet.
PROCEED_ACTION, // "Proceed" was selected.
DONT_PROCEED_ACTION // "Don't proceed" was selected.
};
// Creates an interstitial page to show in |tab|. |new_navigation| should be
// set to true when the interstitial is caused by loading a new page, in which
// case a temporary navigation entry is created with the URL |url| and
// added to the navigation controller (so the interstitial page appears as a
// new navigation entry). |new_navigation| should be false when the
// interstitial was triggered by a loading a sub-resource in a page.
InterstitialPage(TabContents* tab, bool new_navigation, const GURL& url);
virtual ~InterstitialPage();
// Shows the interstitial page in the tab.
virtual void Show();
// Hides the interstitial page. Warning: this deletes the InterstitialPage.
void Hide();
// Retrieves the InterstitialPage if any associated with the specified
// |tab_contents| (used by ui tests).
static InterstitialPage* GetInterstitialPage(TabContents* tab_contents);
// Sub-classes should return the HTML that should be displayed in the page.
virtual std::string GetHTMLContents();
// Reverts to the page showing before the interstitial.
// Sub-classes should call this method when the user has chosen NOT to proceed
// to the target URL.
// Warning: if |new_navigation| was set to true in the constructor, 'this'
// will be deleted when this method returns.
virtual void DontProceed();
// Sub-classes should call this method when the user has chosen to proceed to
// the target URL.
// Warning: 'this' has been deleted when this method returns.
virtual void Proceed();
// Allows the user to navigate away by disabling the interstitial, canceling
// the pending request, and unblocking the hidden renderer. The interstitial
// will stay visible until the navigation completes.
void CancelForNavigation();
// Sizes the RenderViewHost showing the actual interstitial page contents.
void SetSize(const gfx::Size& size);
ActionState action_taken() const { return action_taken_; }
// Sets the focus to the interstitial.
void Focus();
// Focus the first (last if reverse is true) element in the interstitial page.
// Called when tab traversing.
void FocusThroughTabTraversal(bool reverse);
virtual ViewType::Type GetRenderViewType() const;
// See description above field.
void set_reload_on_dont_proceed(bool value) {
reload_on_dont_proceed_ = value;
}
bool reload_on_dont_proceed() const { return reload_on_dont_proceed_; }
protected:
// NotificationObserver method:
virtual void Observe(int type,
const NotificationSource& source,
const NotificationDetails& details);
// RenderViewHostDelegate implementation:
virtual View* GetViewDelegate() OVERRIDE;
virtual const GURL& GetURL() const OVERRIDE;
virtual void RenderViewGone(RenderViewHost* render_view_host,
base::TerminationStatus status,
int error_code) OVERRIDE;
virtual void DidNavigate(
RenderViewHost* render_view_host,
const ViewHostMsg_FrameNavigate_Params& params) OVERRIDE;
virtual void UpdateTitle(RenderViewHost* render_view_host,
int32 page_id,
const string16& title,
base::i18n::TextDirection title_direction) OVERRIDE;
virtual RendererPreferences GetRendererPrefs(
content::BrowserContext* browser_context) const OVERRIDE;
// Invoked with the NavigationEntry that is going to be added to the
// navigation controller.
// Gives an opportunity to sub-classes to set states on the |entry|.
// Note that this is only called if the InterstitialPage was constructed with
// |create_navigation_entry| set to true.
virtual void UpdateEntry(NavigationEntry* entry) {}
bool enabled() const { return enabled_; }
TabContents* tab() const { return tab_; }
const GURL& url() const { return url_; }
RenderViewHost* render_view_host() const { return render_view_host_; }
void set_renderer_preferences(const RendererPreferences& prefs) {
renderer_preferences_ = prefs;
}
// Creates the RenderViewHost containing the interstitial content.
// Overriden in unit tests.
virtual RenderViewHost* CreateRenderViewHost();
// Creates the TabContentsView that shows the interstitial RVH.
// Overriden in unit tests.
virtual TabContentsView* CreateTabContentsView();
// Notification magic.
NotificationRegistrar notification_registrar_;
private:
// AutomationProvider needs access to Proceed and DontProceed to simulate
// user actions.
friend class AutomationProvider;
class InterstitialPageRVHViewDelegate;
// Initializes tab_to_interstitial_page_ in a thread-safe manner.
// Should be called before accessing tab_to_interstitial_page_.
static void InitInterstitialPageMap();
// Disable the interstitial:
// - if it is not yet showing, then it won't be shown.
// - any command sent by the RenderViewHost will be ignored.
void Disable();
// Executes the passed action on the ResourceDispatcher (on the IO thread).
// Used to block/resume/cancel requests for the RenderViewHost hidden by this
// interstitial.
void TakeActionOnResourceDispatcher(ResourceRequestAction action);
// The tab in which we are displayed.
TabContents* tab_;
// The URL that is shown when the interstitial is showing.
GURL url_;
// Whether this interstitial is shown as a result of a new navigation (in
// which case a transient navigation entry is created).
bool new_navigation_;
// Whether we should discard the pending navigation entry when not proceeding.
// This is to deal with cases where |new_navigation_| is true but a new
// pending entry was created since this interstitial was shown and we should
// not discard it.
bool should_discard_pending_nav_entry_;
// If true and the user chooses not to proceed the target NavigationController
// is reloaded. This is used when two NavigationControllers are merged
// (CopyStateFromAndPrune).
// The default is false.
bool reload_on_dont_proceed_;
// Whether this interstitial is enabled. See Disable() for more info.
bool enabled_;
// Whether the Proceed or DontProceed methods have been called yet.
ActionState action_taken_;
// The RenderViewHost displaying the interstitial contents.
RenderViewHost* render_view_host_;
// The IDs for the Render[View|Process]Host hidden by this interstitial.
int original_child_id_;
int original_rvh_id_;
// Whether or not we should change the title of the tab when hidden (to revert
// it to its original value).
bool should_revert_tab_title_;
// Whether or not the tab was loading resources when the interstitial was
// shown. We restore this state if the user proceeds from the interstitial.
bool tab_was_loading_;
// Whether the ResourceDispatcherHost has been notified to cancel/resume the
// resource requests blocked for the RenderViewHost.
bool resource_dispatcher_host_notified_;
// The original title of the tab that should be reverted to when the
// interstitial is hidden.
string16 original_tab_title_;
// Our RenderViewHostViewDelegate, necessary for accelerators to work.
scoped_ptr<InterstitialPageRVHViewDelegate> rvh_view_delegate_;
// We keep a map of the various blocking pages shown as the UI tests need to
// be able to retrieve them.
typedef std::map<TabContents*, InterstitialPage*> InterstitialPageMap;
static InterstitialPageMap* tab_to_interstitial_page_;
// Settings passed to the renderer.
RendererPreferences renderer_preferences_;
DISALLOW_COPY_AND_ASSIGN(InterstitialPage);
};
#endif // CONTENT_BROWSER_TAB_CONTENTS_INTERSTITIAL_PAGE_H_