summaryrefslogtreecommitdiffstats
path: root/chrome/browser/dom_ui
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/dom_ui')
-rw-r--r--chrome/browser/dom_ui/chrome_url_data_manager.cc6
-rw-r--r--chrome/browser/dom_ui/chrome_url_data_manager.h2
-rw-r--r--chrome/browser/dom_ui/dom_ui.cc124
-rw-r--r--chrome/browser/dom_ui/dom_ui.h86
-rw-r--r--chrome/browser/dom_ui/dom_ui_contents.cc207
-rw-r--r--chrome/browser/dom_ui/dom_ui_contents.h123
-rw-r--r--chrome/browser/dom_ui/history_ui.cc303
-rw-r--r--chrome/browser/dom_ui/history_ui.h83
-rw-r--r--chrome/browser/dom_ui/new_tab_ui.cc104
-rw-r--r--chrome/browser/dom_ui/new_tab_ui.h71
10 files changed, 935 insertions, 174 deletions
diff --git a/chrome/browser/dom_ui/chrome_url_data_manager.cc b/chrome/browser/dom_ui/chrome_url_data_manager.cc
index b82506a..623ad8d 100644
--- a/chrome/browser/dom_ui/chrome_url_data_manager.cc
+++ b/chrome/browser/dom_ui/chrome_url_data_manager.cc
@@ -24,8 +24,8 @@
#endif
// The URL scheme used for internal chrome resources.
-// This URL scheme is never needed by code external to this module.
-static const char kChromeURLScheme[] = "chrome-resource";
+// TODO(glen): Choose a better location for this.
+static const char kChromeURLScheme[] = "chrome";
// The single global instance of ChromeURLDataManager.
ChromeURLDataManager chrome_url_data_manager;
@@ -123,7 +123,7 @@ void ChromeURLDataManager::URLToRequest(const GURL& url,
return;
}
- // Our input looks like: chrome-resource://source_name/extra_bits?foo .
+ // Our input looks like: chrome://source_name/extra_bits?foo .
// So the url's "host" is our source, and everything after the host is
// the path.
source_name->assign(url.host());
diff --git a/chrome/browser/dom_ui/chrome_url_data_manager.h b/chrome/browser/dom_ui/chrome_url_data_manager.h
index 895ff46..102ab99 100644
--- a/chrome/browser/dom_ui/chrome_url_data_manager.h
+++ b/chrome/browser/dom_ui/chrome_url_data_manager.h
@@ -16,7 +16,7 @@ class MessageLoop;
class URLRequest;
class URLRequestJob;
-// To serve dynamic data off of chrome-resource: URLs, implement the
+// To serve dynamic data off of chrome: URLs, implement the
// ChromeURLDataManager::DataSource interface and register your handler
// with AddDataSource.
diff --git a/chrome/browser/dom_ui/dom_ui.cc b/chrome/browser/dom_ui/dom_ui.cc
new file mode 100644
index 0000000..4fe9070
--- /dev/null
+++ b/chrome/browser/dom_ui/dom_ui.cc
@@ -0,0 +1,124 @@
+// 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.h"
+
+#include "base/json_reader.h"
+#include "base/json_writer.h"
+#include "chrome/common/l10n_util.h"
+
+///////////////////////////////////////////////////////////////////////////////
+// DOMMessageHandler
+
+DOMUI::DOMUI(DOMUIContents* contents) : contents_(contents) {
+}
+
+DOMUI::~DOMUI() {
+ STLDeleteContainerPairSecondPointers(message_callbacks_.begin(),
+ message_callbacks_.end());
+ STLDeleteContainerPointers(handlers_.begin(), handlers_.end());
+}
+
+// DOMUI, public: -------------------------------------------------------------
+
+void DOMUI::ProcessDOMUIMessage(const std::string& message,
+ const std::string& content) {
+ // Look up the callback for this message.
+ MessageCallbackMap::const_iterator callback =
+ message_callbacks_.find(message);
+ if (callback == message_callbacks_.end())
+ return;
+
+ // Convert the content JSON into a Value.
+ Value* value = NULL;
+ if (!content.empty()) {
+ if (!JSONReader::Read(content, &value, false)) {
+ // The page sent us something that we didn't understand.
+ // This probably indicates a programming error.
+ NOTREACHED();
+ return;
+ }
+ }
+
+ // Forward this message and content on.
+ callback->second->Run(value);
+ delete value;
+}
+
+void DOMUI::CallJavascriptFunction(const std::wstring& function_name,
+ const Value& arg) {
+ std::string json;
+ JSONWriter::Write(&arg, false, &json);
+ std::wstring javascript = function_name + L"(" + UTF8ToWide(json) + L");";
+
+ ExecuteJavascript(javascript);
+}
+
+void DOMUI::CallJavascriptFunction(
+ const std::wstring& function_name,
+ const Value& arg1, const Value& arg2) {
+ std::string json;
+ JSONWriter::Write(&arg1, false, &json);
+ std::wstring javascript = function_name + L"(" + UTF8ToWide(json);
+ JSONWriter::Write(&arg2, false, &json);
+ javascript += L"," + UTF8ToWide(json) + L");";
+
+ ExecuteJavascript(javascript);
+}
+
+void DOMUI::RegisterMessageCallback(const std::string &message,
+ MessageCallback *callback) {
+ message_callbacks_.insert(std::make_pair(message, callback));
+}
+
+// DOMUI, protected: ----------------------------------------------------------
+
+void DOMUI::AddMessageHandler(DOMMessageHandler* handler) {
+ handlers_.push_back(handler);
+}
+
+// DOMUI, private: ------------------------------------------------------------
+
+void DOMUI::ExecuteJavascript(const std::wstring& javascript) {
+ DCHECK(contents_);
+ contents_->render_view_host()->ExecuteJavascriptInWebFrame(std::wstring(),
+ javascript);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// DOMMessageHandler
+
+DOMMessageHandler::DOMMessageHandler(DOMUI *dom_ui) : dom_ui_(dom_ui) {
+}
+
+// DOMMessageHandler, protected: ----------------------------------------------
+
+void DOMMessageHandler::SetURLAndTitle(DictionaryValue* dictionary,
+ std::wstring title,
+ const GURL& gurl) {
+ std::wstring wstring_url = UTF8ToWide(gurl.spec());
+ dictionary->SetString(L"url", wstring_url);
+
+ bool using_url_as_the_title = false;
+ if (title.empty()) {
+ using_url_as_the_title = true;
+ title = wstring_url;
+ }
+
+ // Since the title can contain BiDi text, we need to mark the text as either
+ // RTL or LTR, depending on the characters in the string. If we use the URL
+ // as the title, we mark the title as LTR since URLs are always treated as
+ // left to right strings.
+ std::wstring title_to_set(title);
+ if (l10n_util::GetTextDirection() == l10n_util::RIGHT_TO_LEFT) {
+ if (using_url_as_the_title) {
+ l10n_util::WrapStringWithLTRFormatting(&title_to_set);
+ } else {
+ bool success =
+ l10n_util::AdjustStringForLocaleDirection(title, &title_to_set);
+ DCHECK(success ? (title != title_to_set) : (title == title_to_set));
+ }
+ }
+ dictionary->SetString(L"title", title_to_set);
+} \ No newline at end of file
diff --git a/chrome/browser/dom_ui/dom_ui.h b/chrome/browser/dom_ui/dom_ui.h
new file mode 100644
index 0000000..7b0b446
--- /dev/null
+++ b/chrome/browser/dom_ui/dom_ui.h
@@ -0,0 +1,86 @@
+// 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.
+
+#ifndef CHROME_BROWSER_DOM_UI_H__
+#define CHROME_BROWSER_DOM_UI_H__
+
+#include "base/task.h"
+#include "chrome/browser/dom_ui/dom_ui_contents.h"
+
+class Value;
+class DOMMessageHandler;
+
+// A DOMUI sets up the datasources and message handlers for a given HTML-based
+// UI. It is contained by a DOMUIContents.
+class DOMUI {
+ public:
+ DOMUI(DOMUIContents* contents);
+
+ virtual ~DOMUI();
+ virtual void Init() = 0;
+
+ // Called from DOMUIContents.
+ void ProcessDOMUIMessage(const std::string& message,
+ const std::string& content);
+
+ // Used by DOMMessageHandlers.
+ typedef Callback1<const Value*>::Type MessageCallback;
+ void RegisterMessageCallback (const std::string& message,
+ MessageCallback* callback);
+
+ // Call a Javascript function by sending its name and arguments down to
+ // the renderer. This is asynchronous; there's no way to get the result
+ // of the call, and should be thought of more like sending a message to
+ // the page.
+ // There are two function variants for one-arg and two-arg calls.
+ void CallJavascriptFunction(const std::wstring& function_name,
+ const Value& arg);
+ void CallJavascriptFunction(const std::wstring& function_name,
+ const Value& arg1,
+ const Value& arg2);
+
+ Profile* get_profile() { return contents_->profile(); }
+
+ protected:
+ void AddMessageHandler(DOMMessageHandler* handler);
+
+ DOMUIContents* contents_;
+
+ private:
+ // Execute a string of raw Javascript on the page.
+ void ExecuteJavascript(const std::wstring& javascript);
+
+ // The DOMMessageHandlers we own.
+ std::vector<DOMMessageHandler*> handlers_;
+
+ // A map of message name -> message handling callback.
+ typedef std::map<std::string, MessageCallback*> MessageCallbackMap;
+ MessageCallbackMap message_callbacks_;
+
+ DISALLOW_COPY_AND_ASSIGN(DOMUI);
+};
+
+// Messages sent from the DOM are forwarded via the DOMUIContents to handler
+// classes. These objects are owned by DOMUIHost and destroyed when the
+// host is destroyed.
+class DOMMessageHandler {
+ public:
+ explicit DOMMessageHandler(DOMUI* dom_ui);
+ virtual ~DOMMessageHandler();
+
+ protected:
+ // Adds "url" and "title" keys on incoming dictionary, setting title
+ // as the url as a fallback on empty title.
+ static void SetURLAndTitle(DictionaryValue* dictionary,
+ std::wstring title,
+ const GURL& gurl);
+
+ DOMUI* const dom_ui_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DOMMessageHandler);
+};
+
+
+#endif // CHROME_BROWSER_DOM_UI_H__ \ No newline at end of file
diff --git a/chrome/browser/dom_ui/dom_ui_contents.cc b/chrome/browser/dom_ui/dom_ui_contents.cc
new file mode 100644
index 0000000..260c68f
--- /dev/null
+++ b/chrome/browser/dom_ui/dom_ui_contents.cc
@@ -0,0 +1,207 @@
+// 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/dom_ui/dom_ui.h"
+#include "chrome/browser/dom_ui/history_ui.h"
+#include "chrome/browser/navigation_entry.h"
+#include "chrome/browser/render_view_host.h"
+#include "chrome/common/resource_bundle.h"
+
+// The scheme used for DOMUIContentses
+// TODO(glen): Merge this with the scheme in chrome_url_data_manager
+static const char kURLScheme[] = "chrome";
+
+// 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: URLs, and exposed in
+// our header file. The individual DOMUIs provide a chrome:
+// HTML source at the same host/path.
+bool DOMUIContentsCanHandleURL(GURL* url,
+ TabContentsType* result_type) {
+ if (!url->SchemeIs(kURLScheme))
+ return false;
+
+ // TODO: remove once the debugger is using DOMContentsUI
+ if (url->host().compare("debugger") == 0)
+ 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) {
+ 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;
+}
+
+bool DOMUIContents::NavigateToPendingEntry(bool reload) {
+ if (current_ui_) {
+ // Shut down our existing DOMUI.
+ delete current_ui_;
+ current_ui_ = NULL;
+ }
+
+ // Set up a new DOMUI.
+ NavigationEntry* pending_entry = controller()->GetPendingEntry();
+ current_ui_ = GetDOMUIForURL(pending_entry->url());
+ if (current_ui_)
+ current_ui_->Init();
+ else
+ return false;
+
+ // Let WebContents do whatever it's meant to do.
+ return WebContents::NavigateToPendingEntry(reload);
+}
+
+DOMUI* DOMUIContents::GetDOMUIForURL(const GURL &url) {
+ if (url.host() == HistoryUI::GetBaseURL().host())
+ return new HistoryUI(this);
+
+ return NULL;
+}
+
+void DOMUIContents::ProcessDOMUIMessage(const std::string& message,
+ const std::string& content) {
+ DCHECK(current_ui_);
+ current_ui_->ProcessDOMUIMessage(message, content);
+}
+
+// static
+const std::string DOMUIContents::GetScheme() {
+ return kURLScheme;
+} \ No newline at end of file
diff --git a/chrome/browser/dom_ui/dom_ui_contents.h b/chrome/browser/dom_ui/dom_ui_contents.h
new file mode 100644
index 0000000..c347c07
--- /dev/null
+++ b/chrome/browser/dom_ui/dom_ui_contents.h
@@ -0,0 +1,123 @@
+// 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.
+
+// Contains code for managing local HTML UI at chrome:// URLs.
+
+#ifndef CHROME_BROWSER_DOM_UI_CONTENTS_H__
+#define CHROME_BROWSER_DOM_UI_CONTENTS_H__
+
+#include "chrome/browser/dom_ui/chrome_url_data_manager.h"
+#include "chrome/browser/web_contents.h"
+#include "webkit/glue/webpreferences.h"
+
+class DOMUI;
+class render_view_host;
+
+// FavIconSource is the gateway between network-level chrome:
+// requests for favicons and the history backend that serves these.
+class FavIconSource : public ChromeURLDataManager::DataSource {
+ public:
+ explicit FavIconSource(Profile* profile);
+
+ // Called when the network layer has requested a resource underneath
+ // the path we registered.
+ virtual void StartDataRequest(const std::string& path, int request_id);
+
+ virtual std::string GetMimeType(const std::string&) const {
+ // Rely on image decoder inferring the correct type.
+ return std::string();
+ }
+
+ // Called when favicon data is available from the history backend.
+ void OnFavIconDataAvailable(
+ HistoryService::Handle request_handle,
+ bool know_favicon,
+ scoped_refptr<RefCountedBytes> data,
+ bool expired,
+ GURL url);
+
+ private:
+ Profile* const profile_;
+ CancelableRequestConsumerT<int, 0> cancelable_consumer_;
+
+ // Raw PNG representation of the favicon to show when the favicon
+ // database doesn't have a favicon for a webpage.
+ scoped_refptr<RefCountedBytes> default_favicon_;
+
+ DISALLOW_COPY_AND_ASSIGN(FavIconSource);
+};
+
+// ThumbnailSource is the gateway between network-level chrome:
+// requests for thumbnails and the history backend that serves these.
+class ThumbnailSource : public ChromeURLDataManager::DataSource {
+ public:
+ explicit ThumbnailSource(Profile* profile);
+
+ // Called when the network layer has requested a resource underneath
+ // the path we registered.
+ virtual void StartDataRequest(const std::string& path, int request_id);
+
+ virtual std::string GetMimeType(const std::string&) const {
+ // Rely on image decoder inferring the correct type.
+ return std::string();
+ }
+
+ // Called when thumbnail data is available from the history backend.
+ void OnThumbnailDataAvailable(
+ HistoryService::Handle request_handle,
+ scoped_refptr<RefCountedBytes> data);
+
+ private:
+ Profile* const profile_;
+ CancelableRequestConsumerT<int, 0> cancelable_consumer_;
+
+ // Raw PNG representation of the thumbnail to show when the thumbnail
+ // database doesn't have a thumbnail for a webpage.
+ scoped_refptr<RefCountedBytes> default_thumbnail_;
+
+ DISALLOW_COPY_AND_ASSIGN(ThumbnailSource);
+};
+
+// Exposed for use by BrowserURLHandler.
+bool DOMUIContentsCanHandleURL(GURL* url, TabContentsType* result_type);
+
+class DOMUIContents : public WebContents {
+ public:
+ DOMUIContents(Profile* profile,
+ SiteInstance* instance,
+ RenderViewHostFactory* render_view_factory);
+ ~DOMUIContents();
+
+ //
+ // WebContents overrides
+ //
+ virtual void ProcessDOMUIMessage(const std::string& message,
+ const std::string& content);
+ virtual bool CreateRenderViewForRenderManager(
+ RenderViewHost* render_view_host);
+ // Override this method so we can ensure that javascript and image loading
+ // are always on even for DOMUIHost tabs.
+ virtual WebPreferences GetWebkitPrefs();
+
+ //
+ // TabContents overrides
+ //
+ virtual void UpdateHistoryForNavigation(const GURL& url,
+ const ViewHostMsg_FrameNavigate_Params& params) { }
+ virtual bool NavigateToPendingEntry(bool reload);
+
+ // Return the scheme used. We currently use chrome:
+ static const std::string GetScheme();
+
+ private:
+ // Return a DOM UI for the provided URL.
+ DOMUI* GetDOMUIForURL(const GURL& url);
+
+ // The DOMUI we own and show.
+ DOMUI* current_ui_;
+
+ DISALLOW_COPY_AND_ASSIGN(DOMUIContents);
+};
+
+#endif // CHROME_BROWSER_DOM_UI_CONTENTS_H__ \ No newline at end of file
diff --git a/chrome/browser/dom_ui/history_ui.cc b/chrome/browser/dom_ui/history_ui.cc
new file mode 100644
index 0000000..370417d
--- /dev/null
+++ b/chrome/browser/dom_ui/history_ui.cc
@@ -0,0 +1,303 @@
+// 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/history_ui.h"
+
+#include "base/message_loop.h"
+#include "base/string_piece.h"
+#include "base/thread.h"
+#include "base/time.h"
+#include "base/time_format.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/browser_resources.h"
+#include "chrome/browser/history/history_types.h"
+#include "chrome/browser/profile.h"
+#include "chrome/browser/user_metrics.h"
+#include "chrome/common/jstemplate_builder.h"
+#include "chrome/common/l10n_util.h"
+#include "chrome/common/resource_bundle.h"
+#include "chrome/common/time_format.h"
+
+#include "chromium_strings.h"
+#include "generated_resources.h"
+
+using base::Time;
+
+// HistoryUI is accessible from chrome://history, and the raw HTML is
+// accessed from chrome://history.
+static const std::string kHistoryHost = "history";
+
+// Maximum number of search results to return in a given search. We should
+// eventually remove this.
+static const int kMaxSearchResults = 100;
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// HistoryHTMLSource
+//
+////////////////////////////////////////////////////////////////////////////////
+
+HistoryUIHTMLSource::HistoryUIHTMLSource()
+ : DataSource(kHistoryHost, MessageLoop::current()) {
+}
+
+void HistoryUIHTMLSource::StartDataRequest(const std::string& path,
+ int request_id) {
+ DictionaryValue localized_strings;
+ localized_strings.SetString(L"title",
+ l10n_util::GetString(IDS_HISTORY_TITLE));
+ localized_strings.SetString(L"loading",
+ l10n_util::GetString(IDS_HISTORY_LOADING));
+ localized_strings.SetString(L"newest",
+ l10n_util::GetString(IDS_HISTORY_NEWEST));
+ localized_strings.SetString(L"newer",
+ l10n_util::GetString(IDS_HISTORY_NEWER));
+ localized_strings.SetString(L"older",
+ l10n_util::GetString(IDS_HISTORY_OLDER));
+ localized_strings.SetString(L"searchresultsfor",
+ l10n_util::GetString(IDS_HISTORY_SEARCHRESULTSFOR));
+ localized_strings.SetString(L"history",
+ l10n_util::GetString(IDS_HISTORY_BROWSERESULTS));
+ localized_strings.SetString(L"cont",
+ l10n_util::GetString(IDS_HISTORY_CONTINUED));
+ localized_strings.SetString(L"searchbutton",
+ l10n_util::GetString(IDS_HISTORY_SEARCH_BUTTON));
+ localized_strings.SetString(L"noresults",
+ l10n_util::GetString(IDS_HISTORY_NO_RESULTS));
+ localized_strings.SetString(L"noitems",
+ l10n_util::GetString(IDS_HISTORY_NO_ITEMS));
+ localized_strings.SetString(L"delete",
+ l10n_util::GetString(IDS_HISTORY_DELETE));
+
+ static const StringPiece history_html(
+ ResourceBundle::GetSharedInstance().GetRawDataResource(
+ IDR_HISTORY_HTML));
+ const std::string full_html = jstemplate_builder::GetTemplateHtml(
+ history_html, &localized_strings, "t");
+
+ scoped_refptr<RefCountedBytes> html_bytes(new RefCountedBytes);
+ html_bytes->data.resize(full_html.size());
+ std::copy(full_html.begin(), full_html.end(), html_bytes->data.begin());
+
+ SendResponse(request_id, html_bytes);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// HistoryHandler
+//
+////////////////////////////////////////////////////////////////////////////////
+BrowsingHistoryHandler::BrowsingHistoryHandler(DOMUI* dom_ui)
+ : DOMMessageHandler(dom_ui),
+ search_text_() {
+ dom_ui_->RegisterMessageCallback("getHistory",
+ NewCallback(this, &BrowsingHistoryHandler::HandleGetHistory));
+
+ // Create our favicon data source.
+ g_browser_process->io_thread()->message_loop()->PostTask(FROM_HERE,
+ NewRunnableMethod(&chrome_url_data_manager,
+ &ChromeURLDataManager::AddDataSource,
+ new FavIconSource(dom_ui_->get_profile())));
+
+ // Get notifications when history is cleared.
+ NotificationService* service = NotificationService::current();
+ service->AddObserver(this, NOTIFY_HISTORY_URLS_DELETED,
+ Source<Profile>(dom_ui_->get_profile()));
+}
+
+BrowsingHistoryHandler::~BrowsingHistoryHandler() {
+ NotificationService* service = NotificationService::current();
+ service->RemoveObserver(this, NOTIFY_HISTORY_URLS_DELETED,
+ Source<Profile>(dom_ui_->get_profile()));
+}
+
+void BrowsingHistoryHandler::HandleGetHistory(const Value* value) {
+ // Anything in-flight is invalid.
+ cancelable_consumer_.CancelAllRequests();
+
+ // Get arguments (if any).
+ int month;
+ std::wstring query;
+ ExtractGetHistoryArguments(value, &month, &query);
+
+ // Set our query options.
+ history::QueryOptions options = CreateQueryOptions(month, query);
+
+ // Need to remember the query string for our results.
+ search_text_ = query;
+ HistoryService* hs =
+ dom_ui_->get_profile()->GetHistoryService(Profile::EXPLICIT_ACCESS);
+ hs->QueryHistory(search_text_,
+ options,
+ &cancelable_consumer_,
+ NewCallback(this, &BrowsingHistoryHandler::QueryComplete));
+}
+
+void BrowsingHistoryHandler::QueryComplete(
+ HistoryService::Handle request_handle,
+ history::QueryResults* results) {
+
+ ListValue results_value;
+ Time midnight_today = Time::Now().LocalMidnight();
+
+ for (size_t i = 0; i < results->size(); ++i) {
+ history::URLResult const &page = (*results)[i];
+ DictionaryValue* page_value = new DictionaryValue();
+ SetURLAndTitle(page_value, page.title(), page.url());
+
+ // Need to pass the time in epoch time (fastest JS conversion).
+ page_value->SetInteger(L"time",
+ static_cast<int>(page.visit_time().ToTimeT()));
+
+ // Until we get some JS i18n infrastructure, we also need to
+ // pass the dates in as strings. This could use some
+ // optimization.
+
+ // Only pass in the strings we need (search results need a shortdate
+ // and snippet, browse results need day and time information).
+ if (search_text_.empty()) {
+ // Figure out the relative date string.
+ std::wstring date_str = TimeFormat::RelativeDate(page.visit_time(),
+ &midnight_today);
+ if (date_str.empty()) {
+ date_str = base::TimeFormatFriendlyDate(page.visit_time());
+ } else {
+ date_str = l10n_util::GetStringF(
+ IDS_HISTORY_DATE_WITH_RELATIVE_TIME,
+ date_str, base::TimeFormatFriendlyDate(page.visit_time()));
+ }
+ page_value->SetString(L"dateRelativeDay", date_str);
+ page_value->SetString(L"dateTimeOfDay",
+ base::TimeFormatTimeOfDay(page.visit_time()));
+ } else {
+ page_value->SetString(L"dateShort",
+ base::TimeFormatShortDate(page.visit_time()));
+ page_value->SetString(L"snippet", page.snippet().text());
+ }
+
+ results_value.Append(page_value);
+ }
+
+ dom_ui_->CallJavascriptFunction(L"historyResult",
+ StringValue(search_text_), results_value);
+}
+
+void BrowsingHistoryHandler::ExtractGetHistoryArguments(const Value* value,
+ int* month, std::wstring* query) {
+ *month = 0;
+
+ if (value && value->GetType() == Value::TYPE_LIST) {
+ const ListValue* list_value = static_cast<const ListValue*>(value);
+ Value* list_member;
+
+ // Get search string.
+ if (list_value->Get(0, &list_member) &&
+ list_member->GetType() == Value::TYPE_STRING) {
+ const StringValue* string_value =
+ static_cast<const StringValue*>(list_member);
+ string_value->GetAsString(query);
+ }
+
+ // Get search month.
+ if (list_value->Get(1, &list_member) &&
+ list_member->GetType() == Value::TYPE_STRING) {
+ const StringValue* string_value =
+ static_cast<const StringValue*>(list_member);
+ std::wstring wstring_value;
+ string_value->GetAsString(&wstring_value);
+ *month = _wtoi(wstring_value.c_str());
+ }
+ }
+}
+
+history::QueryOptions BrowsingHistoryHandler::CreateQueryOptions(int month,
+ const std::wstring& query) {
+ history::QueryOptions options;
+
+ // Configure the begin point of the search to the start of the
+ // current month.
+ Time::Exploded exploded;
+ Time::Now().LocalMidnight().LocalExplode(&exploded);
+ exploded.day_of_month = 1;
+
+ if (month == 0) {
+ options.begin_time = Time::FromLocalExploded(exploded);
+
+ // Set the end time of this first search to null (which will
+ // show results from the future, should the user's clock have
+ // been set incorrectly).
+ options.end_time = Time();
+ } else {
+ // Set the end-time of this search to the end of the month that is
+ // |depth| months before the search end point. The end time is not
+ // inclusive, so we should feel free to set it to midnight on the
+ // first day of the following month.
+ exploded.month -= month - 1;
+ while (exploded.month < 1) {
+ exploded.month += 12;
+ exploded.year--;
+ }
+ options.end_time = Time::FromLocalExploded(exploded);
+
+ // Set the begin-time of the search to the start of the month
+ // that is |depth| months prior to search_start_.
+ if (exploded.month > 1) {
+ exploded.month--;
+ } else {
+ exploded.month = 12;
+ exploded.year--;
+ }
+ options.begin_time = Time::FromLocalExploded(exploded);
+ }
+
+ // If searching, only show the most recent entry and limit the number of
+ // results returned.
+ if (!query.empty()) {
+ options.max_count = kMaxSearchResults;
+ options.most_recent_visit_only = true;
+ }
+
+ return options;
+}
+
+void BrowsingHistoryHandler::Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ if (type != NOTIFY_HISTORY_URLS_DELETED) {
+ NOTREACHED();
+ return;
+ }
+
+ // Some URLs were deleted from history. Reload the most visited list.
+ HandleGetHistory(NULL);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// HistoryUIContents
+//
+////////////////////////////////////////////////////////////////////////////////
+
+HistoryUI::HistoryUI(DOMUIContents* contents) : DOMUI(contents) {
+}
+
+void HistoryUI::Init() {
+ AddMessageHandler(new BrowsingHistoryHandler(this));
+
+ HistoryUIHTMLSource* html_source = new HistoryUIHTMLSource();
+
+ // Set up the chrome://history/ source.
+ g_browser_process->io_thread()->message_loop()->PostTask(FROM_HERE,
+ NewRunnableMethod(&chrome_url_data_manager,
+ &ChromeURLDataManager::AddDataSource,
+ html_source));
+}
+
+// static
+GURL HistoryUI::GetBaseURL() {
+ std::string url = DOMUIContents::GetScheme();
+ url += "://";
+ url += kHistoryHost;
+ return GURL(url);
+} \ No newline at end of file
diff --git a/chrome/browser/dom_ui/history_ui.h b/chrome/browser/dom_ui/history_ui.h
new file mode 100644
index 0000000..742cf81
--- /dev/null
+++ b/chrome/browser/dom_ui/history_ui.h
@@ -0,0 +1,83 @@
+// 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.
+
+#ifndef CHROME_BROWSER_DOM_UI_HISTORY_UI_H__
+#define CHROME_BROWSER_DOM_UI_HISTORY_UI_H__
+
+#include "chrome/browser/dom_ui/chrome_url_data_manager.h"
+#include "chrome/browser/dom_ui/dom_ui.h"
+#include "chrome/browser/dom_ui/dom_ui_contents.h"
+
+class GURL;
+
+class HistoryUIHTMLSource : public ChromeURLDataManager::DataSource {
+ public:
+ HistoryUIHTMLSource();
+
+ // Called when the network layer has requested a resource underneath
+ // the path we registered.
+ virtual void StartDataRequest(const std::string& path, int request_id);
+ virtual std::string GetMimeType(const std::string&) const {
+ return "text/html";
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(HistoryUIHTMLSource);
+};
+
+// The handler for Javascript messages related to the "history" view.
+class BrowsingHistoryHandler : public DOMMessageHandler,
+ public NotificationObserver {
+ public:
+ explicit BrowsingHistoryHandler(DOMUI* dom_ui_);
+ virtual ~BrowsingHistoryHandler();
+
+ // Callback for the "getHistory" message.
+ void HandleGetHistory(const Value* value);
+
+ // NotificationObserver implementation.
+ virtual void Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details);
+
+ private:
+ // Callback from the history system when the most visited list is available.
+ void QueryComplete(HistoryService::Handle request_handle,
+ history::QueryResults* results);
+
+ // Extract the arguments from the call to HandleGetHistory.
+ void ExtractGetHistoryArguments(const Value* value,
+ int* month,
+ std::wstring* query);
+
+ // Get the query options for a given month and query.
+ history::QueryOptions CreateQueryOptions(int month,
+ const std::wstring& query);
+
+ // Current search text.
+ std::wstring search_text_;
+
+ // Our consumer for the history service.
+ CancelableRequestConsumerT<PageUsageData*, NULL> cancelable_consumer_;
+
+ DISALLOW_COPY_AND_ASSIGN(BrowsingHistoryHandler);
+};
+
+class HistoryUI : public DOMUI {
+ public:
+ explicit HistoryUI(DOMUIContents* contents);
+
+ // Return the URL for the front page of this UI.
+ static GURL GetBaseURL();
+
+ // DOMUI Implementation
+ virtual void Init();
+
+ private:
+ DOMUIContents* contents_;
+
+ DISALLOW_COPY_AND_ASSIGN(HistoryUI);
+};
+
+#endif // CHROME_BROWSER_DOM_UI_HISTORY_UI_H__ \ No newline at end of file
diff --git a/chrome/browser/dom_ui/new_tab_ui.cc b/chrome/browser/dom_ui/new_tab_ui.cc
index 1775e1e..7d1aa82 100644
--- a/chrome/browser/dom_ui/new_tab_ui.cc
+++ b/chrome/browser/dom_ui/new_tab_ui.cc
@@ -10,6 +10,7 @@
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/browser_resources.h"
+#include "chrome/browser/dom_ui/dom_ui_contents.h"
#include "chrome/browser/history_tab_ui.h"
#include "chrome/browser/history/page_usage_data.h"
#include "chrome/browser/navigation_entry.h"
@@ -36,12 +37,6 @@ using base::TimeTicks;
// The URL scheme used for the new tab.
static const char kNewTabUIScheme[] = "chrome-internal";
-// 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";
-
// The number of most visited pages we show.
const int kMostVisitedPages = 9;
@@ -263,101 +258,6 @@ void IncognitoTabHTMLSource::StartDataRequest(const std::string& path,
}
///////////////////////////////////////////////////////////////////////////////
-// 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_);
- }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// 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_);
- }
-}
-
-
-///////////////////////////////////////////////////////////////////////////////
// MostVisitedHandler
MostVisitedHandler::MostVisitedHandler(DOMUIHost* dom_ui_host)
@@ -847,7 +747,7 @@ bool NewTabUIHandleURL(GURL* url,
return false;
*result_type = TAB_CONTENTS_NEW_TAB_UI;
- *url = GURL("chrome-resource://new-tab/");
+ *url = GURL(DOMUIContents::GetScheme() + "://new-tab/");
return true;
}
diff --git a/chrome/browser/dom_ui/new_tab_ui.h b/chrome/browser/dom_ui/new_tab_ui.h
index 4995b4d..8f700b2 100644
--- a/chrome/browser/dom_ui/new_tab_ui.h
+++ b/chrome/browser/dom_ui/new_tab_ui.h
@@ -20,9 +20,9 @@ enum TabContentsType;
// Return the URL for the new tab page.
GURL NewTabUIURL();
-// If a |url| is a chrome: URL, this method sets up |url|, and |result_type|
-// to the appropriate values for displaying the new tab page and returns true.
-// Exposed for use by BrowserURLHandler.
+// If a |url| is a chrome-internal: URL, this method sets up |url|, and
+// |result_type| to the appropriate values for displaying the new tab page
+// and returns true. Exposed for use by BrowserURLHandler.
bool NewTabUIHandleURL(GURL* url, TabContentsType* result_type);
// The following classes aren't used outside of new_tab_ui.cc but are
@@ -69,71 +69,6 @@ class IncognitoTabHTMLSource : public ChromeURLDataManager::DataSource {
DISALLOW_EVIL_CONSTRUCTORS(IncognitoTabHTMLSource);
};
-// ThumbnailSource is the gateway between network-level chrome-resource:
-// requests for thumbnails and the history backend that serves these.
-class ThumbnailSource : public ChromeURLDataManager::DataSource {
- public:
- explicit ThumbnailSource(Profile* profile);
-
- // Called when the network layer has requested a resource underneath
- // the path we registered.
- virtual void StartDataRequest(const std::string& path, int request_id);
-
- virtual std::string GetMimeType(const std::string&) const {
- // Rely on image decoder inferring the correct type.
- return std::string();
- }
-
- // Called when thumbnail data is available from the history backend.
- void OnThumbnailDataAvailable(
- HistoryService::Handle request_handle,
- scoped_refptr<RefCountedBytes> data);
-
- private:
- Profile* profile_;
- CancelableRequestConsumerT<int, 0> cancelable_consumer_;
-
- // Raw PNG representation of the thumbnail to show when the thumbnail
- // database doesn't have a thumbnail for a webpage.
- scoped_refptr<RefCountedBytes> default_thumbnail_;
-
- DISALLOW_EVIL_CONSTRUCTORS(ThumbnailSource);
-};
-
-// ThumbnailSource is the gateway between network-level chrome-resource:
-// requests for favicons and the history backend that serves these.
-class FavIconSource : public ChromeURLDataManager::DataSource {
- public:
- explicit FavIconSource(Profile* profile);
-
- // Called when the network layer has requested a resource underneath
- // the path we registered.
- virtual void StartDataRequest(const std::string& path, int request_id);
-
- virtual std::string GetMimeType(const std::string&) const {
- // Rely on image decoder inferring the correct type.
- return std::string();
- }
-
- // Called when favicon data is available from the history backend.
- void OnFavIconDataAvailable(
- HistoryService::Handle request_handle,
- bool know_favicon,
- scoped_refptr<RefCountedBytes> data,
- bool expired,
- GURL url);
-
- private:
- Profile* profile_;
- CancelableRequestConsumerT<int, 0> cancelable_consumer_;
-
- // Raw PNG representation of the favicon to show when the favicon
- // database doesn't have a favicon for a webpage.
- scoped_refptr<RefCountedBytes> default_favicon_;
-
- DISALLOW_EVIL_CONSTRUCTORS(FavIconSource);
-};
-
// The handler for Javascript messages related to the "most visited" view.
class MostVisitedHandler : public DOMMessageHandler,
public NotificationObserver {