blob: 9d80db3cbd6bbe9a4de5c09c12371050b4e51863 [file] [log] [blame]
// Copyright (c) 2006-2008 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/dom_ui/dom_ui_contents.h"
#include "chrome/browser/debugger/debugger_contents.h"
#include "chrome/browser/dom_ui/dev_tools_ui.h"
#include "chrome/browser/dom_ui/dom_ui.h"
#include "chrome/browser/dom_ui/downloads_ui.h"
#include "chrome/browser/dom_ui/history_ui.h"
#include "chrome/browser/dom_ui/new_tab_ui.h"
#include "chrome/browser/extensions/extensions_ui.h"
#include "chrome/browser/renderer_host/render_view_host.h"
#include "chrome/browser/tab_contents/navigation_entry.h"
#include "chrome/common/l10n_util.h"
#include "chrome/common/resource_bundle.h"
#include "chrome/common/url_constants.h"
#include "grit/generated_resources.h"
// The path used in internal URLs to thumbnail data.
static const char kThumbnailPath[] = "thumb";
// The path used in internal URLs to favicon data.
static const char kFavIconPath[] = "favicon";
///////////////////////////////////////////////////////////////////////////////
// FavIconSource
FavIconSource::FavIconSource(Profile* profile)
: DataSource(kFavIconPath, MessageLoop::current()), profile_(profile) {}
void FavIconSource::StartDataRequest(const std::string& path, int request_id) {
HistoryService* hs = profile_->GetHistoryService(Profile::EXPLICIT_ACCESS);
if (hs) {
HistoryService::Handle handle;
if (path.size() > 8 && path.substr(0, 8) == "iconurl/") {
handle = hs->GetFavIcon(
GURL(path.substr(8)),
&cancelable_consumer_,
NewCallback(this, &FavIconSource::OnFavIconDataAvailable));
} else {
handle = hs->GetFavIconForURL(
GURL(path),
&cancelable_consumer_,
NewCallback(this, &FavIconSource::OnFavIconDataAvailable));
}
// Attach the ChromeURLDataManager request ID to the history request.
cancelable_consumer_.SetClientData(hs, handle, request_id);
} else {
SendResponse(request_id, NULL);
}
}
void FavIconSource::OnFavIconDataAvailable(
HistoryService::Handle request_handle,
bool know_favicon,
scoped_refptr<RefCountedBytes> data,
bool expired,
GURL icon_url) {
HistoryService* hs =
profile_->GetHistoryService(Profile::EXPLICIT_ACCESS);
int request_id = cancelable_consumer_.GetClientData(hs, request_handle);
if (know_favicon && data.get() && !data->data.empty()) {
// Forward the data along to the networking system.
SendResponse(request_id, data);
} else {
if (!default_favicon_.get()) {
default_favicon_ = new RefCountedBytes;
ResourceBundle::GetSharedInstance().LoadImageResourceBytes(
IDR_DEFAULT_FAVICON, &default_favicon_->data);
}
SendResponse(request_id, default_favicon_);
}
}
///////////////////////////////////////////////////////////////////////////////
// ThumbnailSource
ThumbnailSource::ThumbnailSource(Profile* profile)
: DataSource(kThumbnailPath, MessageLoop::current()), profile_(profile) {}
void ThumbnailSource::StartDataRequest(const std::string& path,
int request_id) {
HistoryService* hs = profile_->GetHistoryService(Profile::EXPLICIT_ACCESS);
if (hs) {
HistoryService::Handle handle = hs->GetPageThumbnail(
GURL(path),
&cancelable_consumer_,
NewCallback(this, &ThumbnailSource::OnThumbnailDataAvailable));
// Attach the ChromeURLDataManager request ID to the history request.
cancelable_consumer_.SetClientData(hs, handle, request_id);
} else {
// Tell the caller that no thumbnail is available.
SendResponse(request_id, NULL);
}
}
void ThumbnailSource::OnThumbnailDataAvailable(
HistoryService::Handle request_handle,
scoped_refptr<RefCountedBytes> data) {
HistoryService* hs =
profile_->GetHistoryService(Profile::EXPLICIT_ACCESS);
int request_id = cancelable_consumer_.GetClientData(hs, request_handle);
// Forward the data along to the networking system.
if (data.get() && !data->data.empty()) {
SendResponse(request_id, data);
} else {
if (!default_thumbnail_.get()) {
default_thumbnail_ = new RefCountedBytes;
ResourceBundle::GetSharedInstance().LoadImageResourceBytes(
IDR_DEFAULT_THUMBNAIL, &default_thumbnail_->data);
}
SendResponse(request_id, default_thumbnail_);
}
}
///////////////////////////////////////////////////////////////////////////////
// DOMUIContents
// This is the top-level URL handler for chrome-ui: URLs, and exposed in
// our header file. The individual DOMUIs provide a chrome-ui:// HTML source
// at the same host/path.
bool DOMUIContentsCanHandleURL(GURL* url,
TabContentsType* result_type) {
// chrome-internal is a scheme we used to use for the new tab page.
if (!url->SchemeIs(chrome::kChromeUIScheme) &&
!url->SchemeIs(chrome::kChromeInternalScheme))
return false;
*result_type = TAB_CONTENTS_DOM_UI;
return true;
}
DOMUIContents::DOMUIContents(Profile* profile,
SiteInstance* instance,
RenderViewHostFactory* render_view_factory)
: WebContents(profile,
instance,
render_view_factory,
MSG_ROUTING_NONE,
NULL),
current_ui_(NULL),
current_url_(GURL()) {
set_type(TAB_CONTENTS_DOM_UI);
}
DOMUIContents::~DOMUIContents() {
if (current_ui_)
delete current_ui_;
}
bool DOMUIContents::CreateRenderViewForRenderManager(
RenderViewHost* render_view_host) {
// Be sure to enable DOM UI bindings on the RenderViewHost before
// CreateRenderView is called. Since a cross-site transition may be
// involved, this may or may not be the same RenderViewHost that we had when
// we were created.
render_view_host->AllowDOMUIBindings();
return WebContents::CreateRenderViewForRenderManager(render_view_host);
}
WebPreferences DOMUIContents::GetWebkitPrefs() {
// Get the users preferences then force image loading to always be on.
WebPreferences web_prefs = WebContents::GetWebkitPrefs();
web_prefs.loads_images_automatically = true;
web_prefs.javascript_enabled = true;
return web_prefs;
}
void DOMUIContents::RenderViewCreated(RenderViewHost* render_view_host) {
if (current_ui_)
current_ui_->RenderViewCreated(render_view_host);
}
bool DOMUIContents::ShouldDisplayFavIcon() {
if (InitCurrentUI(false))
return current_ui_->ShouldDisplayFavIcon();
return true;
}
bool DOMUIContents::IsBookmarkBarAlwaysVisible() {
if (InitCurrentUI(false))
return current_ui_->IsBookmarkBarAlwaysVisible();
return false;
}
void DOMUIContents::SetInitialFocus() {
if (InitCurrentUI(false))
current_ui_->SetInitialFocus();
else
TabContents::SetInitialFocus();
}
const string16& DOMUIContents::GetTitle() const {
// Workaround for new tab page - we may be asked for a title before
// the content is ready, and we don't even want to display a 'loading...'
// message, so we force it here.
if (controller()->GetActiveEntry() &&
controller()->GetActiveEntry()->url().host() ==
NewTabUI::GetBaseURL().host()) {
static string16* newtab_title = new string16(WideToUTF16Hack(
l10n_util::GetString(IDS_NEW_TAB_TITLE)));
return *newtab_title;
}
return WebContents::GetTitle();
}
bool DOMUIContents::ShouldDisplayURL() {
if (InitCurrentUI(false))
return current_ui_->ShouldDisplayURL();
return TabContents::ShouldDisplayURL();
}
void DOMUIContents::RequestOpenURL(const GURL& url, const GURL& referrer,
WindowOpenDisposition disposition) {
if (InitCurrentUI(false))
current_ui_->RequestOpenURL(url, referrer, disposition);
else
WebContents::RequestOpenURL(url, referrer, disposition);
}
bool DOMUIContents::NavigateToPendingEntry(bool reload) {
InitCurrentUI(reload);
// Let WebContents do whatever it's meant to do.
return WebContents::NavigateToPendingEntry(reload);
}
void DOMUIContents::ProcessDOMUIMessage(const std::string& message,
const std::string& content) {
DCHECK(current_ui_);
current_ui_->ProcessDOMUIMessage(message, content);
}
bool DOMUIContents::InitCurrentUI(bool reload) {
if (!controller()->GetActiveEntry())
return false;
GURL url = controller()->GetActiveEntry()->url();
if (url.is_empty() || !url.is_valid())
return false;
if (reload || url.host() != current_url_.host()) {
// Shut down our existing DOMUI.
delete current_ui_;
current_ui_ = NULL;
// Set up a new DOMUI.
current_ui_ = GetDOMUIForURL(url);
if (current_ui_) {
current_ui_->Init();
current_url_ = url;
return true;
}
} else if (current_ui_) {
return true;
}
return false;
}
// static
const std::string DOMUIContents::GetScheme() {
return chrome::kChromeUIScheme;
}
DOMUI* DOMUIContents::GetDOMUIForURL(const GURL &url) {
if (url.host() == NewTabUI::GetBaseURL().host() ||
url.SchemeIs(chrome::kChromeInternalScheme)) {
return new NewTabUI(this);
}
if (url.host() == HistoryUI::GetBaseURL().host()) {
return new HistoryUI(this);
}
if (url.host() == DownloadsUI::GetBaseURL().host()) {
return new DownloadsUI(this);
}
#if defined(OS_WIN)
// TODO(port): include this once these are converted to HTML
if (url.host() == ExtensionsUI::GetBaseURL().host()) {
return new ExtensionsUI(this);
}
if (url.host() == DebuggerContents::GetBaseURL().host()) {
return new DebuggerContents(this);
}
if (url.host() == DevToolsUI::GetBaseURL().host()) {
return new DevToolsUI(this);
}
#else
NOTIMPLEMENTED();
#endif
return NULL;
}