blob: d6d467dcaf16e6f21b1402951f14ec8ce606cf8b [file] [log] [blame]
// Copyright 2012 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/search/instant_loader.h"
#include "chrome/browser/content_settings/tab_specific_content_settings.h"
#include "chrome/browser/extensions/api/web_navigation/web_navigation_api.h"
#include "chrome/browser/favicon/favicon_tab_helper.h"
#include "chrome/browser/safe_browsing/safe_browsing_tab_observer.h"
#include "chrome/browser/search/search.h"
#include "chrome/browser/tab_contents/tab_util.h"
#include "chrome/browser/ui/blocked_content/blocked_content_tab_helper.h"
#include "chrome/browser/ui/bookmarks/bookmark_tab_helper.h"
#include "chrome/browser/ui/search/search_tab_helper.h"
#include "chrome/browser/ui/tab_contents/core_tab_helper.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/notification_source.h"
#include "content/public/browser/notification_types.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/site_instance.h"
#include "content/public/browser/web_contents_view.h"
#include "grit/generated_resources.h"
#include "ui/base/l10n/l10n_util.h"
namespace {
// This HTTP header and value are set on loads that originate from Instant.
const char kInstantHeader[] = "X-Purpose: Instant";
} // namespace
InstantLoader::Delegate::~Delegate() {
}
InstantLoader::InstantLoader(Delegate* delegate)
: delegate_(delegate), stale_page_timer_(false, false) {}
InstantLoader::~InstantLoader() {
}
void InstantLoader::Init(const GURL& instant_url,
Profile* profile,
const base::Closure& on_stale_callback) {
content::WebContents::CreateParams create_params(profile);
create_params.site_instance = content::SiteInstance::CreateForURL(
profile, chrome::GetPrivilegedURLForInstant(instant_url, profile));
SetContents(scoped_ptr<content::WebContents>(
content::WebContents::Create(create_params)));
instant_url_ = instant_url;
on_stale_callback_ = on_stale_callback;
}
void InstantLoader::Load() {
DVLOG(1) << "LoadURL: " << instant_url_;
contents_->GetController().LoadURL(
instant_url_, content::Referrer(),
content::PAGE_TRANSITION_GENERATED, kInstantHeader);
// Explicitly set the new tab title and virtual URL.
//
// This ensures that the title is set even before we get a title from the
// page, preventing a potential flicker of the URL, and also ensures that
// (unless overridden by the page) the new tab title matches the browser UI
// locale.
content::NavigationEntry* entry = contents_->GetController().GetActiveEntry();
if (entry)
entry->SetTitle(l10n_util::GetStringUTF16(IDS_NEW_TAB_TITLE));
contents_->WasHidden();
int staleness_timeout_ms = chrome::GetInstantLoaderStalenessTimeoutSec() *
1000;
if (staleness_timeout_ms > 0) {
stale_page_timer_.Start(
FROM_HERE,
base::TimeDelta::FromMilliseconds(staleness_timeout_ms),
on_stale_callback_);
}
}
void InstantLoader::SetContents(scoped_ptr<content::WebContents> new_contents) {
contents_.reset(new_contents.release());
contents_->SetDelegate(this);
// Set up various tab helpers. The rest will get attached when (if) the
// contents is added to the tab strip.
// Tab helpers to control popups.
BlockedContentTabHelper::CreateForWebContents(contents());
BlockedContentTabHelper::FromWebContents(contents())->
SetAllContentsBlocked(true);
TabSpecificContentSettings::CreateForWebContents(contents());
TabSpecificContentSettings::FromWebContents(contents())->
SetPopupsBlocked(true);
// Bookmarks (Users can bookmark the Instant NTP. This ensures the bookmarked
// state is correctly set when the contents are swapped into a tab.)
BookmarkTabHelper::CreateForWebContents(contents());
// A tab helper to catch prerender content swapping shenanigans.
CoreTabHelper::CreateForWebContents(contents());
CoreTabHelper::FromWebContents(contents())->set_delegate(this);
SearchTabHelper::CreateForWebContents(contents());
// Observers.
extensions::WebNavigationTabObserver::CreateForWebContents(contents());
// Favicons, required by the Task Manager.
FaviconTabHelper::CreateForWebContents(contents());
// And some flat-out paranoia.
safe_browsing::SafeBrowsingTabObserver::CreateForWebContents(contents());
#if defined(OS_MACOSX)
// If |contents_| doesn't yet have a RWHV, SetTakesFocusOnlyOnMouseDown() will
// be called later, when NOTIFICATION_RENDER_VIEW_HOST_CHANGED is received.
if (content::RenderWidgetHostView* rwhv =
contents_->GetRenderWidgetHostView())
rwhv->SetTakesFocusOnlyOnMouseDown(true);
registrar_.Add(this, content::NOTIFICATION_RENDER_VIEW_HOST_CHANGED,
content::Source<content::NavigationController>(
&contents_->GetController()));
#endif
}
scoped_ptr<content::WebContents> InstantLoader::ReleaseContents() {
stale_page_timer_.Stop();
contents_->SetDelegate(NULL);
// Undo tab helper work done in SetContents().
BlockedContentTabHelper::FromWebContents(contents())->
SetAllContentsBlocked(false);
TabSpecificContentSettings::FromWebContents(contents())->
SetPopupsBlocked(false);
CoreTabHelper::FromWebContents(contents())->set_delegate(NULL);
#if defined(OS_MACOSX)
if (content::RenderWidgetHostView* rwhv =
contents_->GetRenderWidgetHostView())
rwhv->SetTakesFocusOnlyOnMouseDown(false);
registrar_.Remove(this, content::NOTIFICATION_RENDER_VIEW_HOST_CHANGED,
content::Source<content::NavigationController>(
&contents_->GetController()));
#endif
return contents_.Pass();
}
void InstantLoader::Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) {
#if defined(OS_MACOSX)
if (type == content::NOTIFICATION_RENDER_VIEW_HOST_CHANGED) {
if (content::RenderWidgetHostView* rwhv =
contents_->GetRenderWidgetHostView())
rwhv->SetTakesFocusOnlyOnMouseDown(true);
return;
}
#endif
NOTREACHED();
}
void InstantLoader::SwapTabContents(content::WebContents* old_contents,
content::WebContents* new_contents) {
DCHECK_EQ(old_contents, contents());
// We release here without deleting since the caller has the responsibility
// for deleting the old WebContents.
ignore_result(ReleaseContents().release());
SetContents(scoped_ptr<content::WebContents>(new_contents));
delegate_->OnSwappedContents();
}
bool InstantLoader::ShouldSuppressDialogs() {
// Messages shown during Instant cancel Instant, so we suppress them.
return true;
}
bool InstantLoader::ShouldFocusPageAfterCrash() {
return false;
}
void InstantLoader::CanDownload(content::RenderViewHost* /* render_view_host */,
int /* request_id */,
const std::string& /* request_method */,
const base::Callback<void(bool)>& callback) {
// Downloads are disabled.
callback.Run(false);
}
bool InstantLoader::OnGoToEntryOffset(int /* offset */) {
return false;
}
content::WebContents* InstantLoader::OpenURLFromTab(
content::WebContents* source,
const content::OpenURLParams& params) {
return delegate_->OpenURLFromTab(source, params);
}