diff options
Diffstat (limited to 'chrome/browser/dom_ui')
-rw-r--r-- | chrome/browser/dom_ui/chrome_url_data_manager.cc | 6 | ||||
-rw-r--r-- | chrome/browser/dom_ui/chrome_url_data_manager.h | 2 | ||||
-rw-r--r-- | chrome/browser/dom_ui/dom_ui.cc | 124 | ||||
-rw-r--r-- | chrome/browser/dom_ui/dom_ui.h | 86 | ||||
-rw-r--r-- | chrome/browser/dom_ui/dom_ui_contents.cc | 207 | ||||
-rw-r--r-- | chrome/browser/dom_ui/dom_ui_contents.h | 123 | ||||
-rw-r--r-- | chrome/browser/dom_ui/history_ui.cc | 303 | ||||
-rw-r--r-- | chrome/browser/dom_ui/history_ui.h | 83 | ||||
-rw-r--r-- | chrome/browser/dom_ui/new_tab_ui.cc | 104 | ||||
-rw-r--r-- | chrome/browser/dom_ui/new_tab_ui.h | 71 |
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 { |