diff options
author | pam@chromium.org <pam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-06-21 19:13:14 +0000 |
---|---|---|
committer | pam@chromium.org <pam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-06-21 19:13:14 +0000 |
commit | 95ae24fa0b69528d039a27d11219cccb95b9550f (patch) | |
tree | a7a006d7fd637c459850649a15f45d897142cb22 /chrome/browser/dom_ui | |
parent | 95a40d7a887a82b35d9817df40c910c0d021d344 (diff) | |
download | chromium_src-95ae24fa0b69528d039a27d11219cccb95b9550f.zip chromium_src-95ae24fa0b69528d039a27d11219cccb95b9550f.tar.gz chromium_src-95ae24fa0b69528d039a27d11219cccb95b9550f.tar.bz2 |
Fork chrome://history/ for development of a new UI, currently called
chrome://history2/.
BUG=2093
TEST=launch browser, navigate to chrome://history2/
Review URL: http://codereview.chromium.org/2852015
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@50371 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/dom_ui')
-rw-r--r-- | chrome/browser/dom_ui/dom_ui_factory.cc | 6 | ||||
-rw-r--r-- | chrome/browser/dom_ui/history2_ui.cc | 413 | ||||
-rw-r--r-- | chrome/browser/dom_ui/history2_ui.h | 113 |
3 files changed, 532 insertions, 0 deletions
diff --git a/chrome/browser/dom_ui/dom_ui_factory.cc b/chrome/browser/dom_ui/dom_ui_factory.cc index d47e266..24b0481 100644 --- a/chrome/browser/dom_ui/dom_ui_factory.cc +++ b/chrome/browser/dom_ui/dom_ui_factory.cc @@ -10,6 +10,7 @@ #include "chrome/browser/dom_ui/downloads_ui.h" #include "chrome/browser/dom_ui/devtools_ui.h" #include "chrome/browser/dom_ui/history_ui.h" +#include "chrome/browser/dom_ui/history2_ui.h" #include "chrome/browser/dom_ui/html_dialog_ui.h" #include "chrome/browser/dom_ui/net_internals_ui.h" #include "chrome/browser/dom_ui/new_tab_ui.h" @@ -104,6 +105,8 @@ static DOMUIFactoryFunction GetDOMUIFactoryFunction(const GURL& url) { return &NewDOMUI<ExtensionsUI>; if (url.host() == chrome::kChromeUIHistoryHost) return &NewDOMUI<HistoryUI>; + if (url.host() == chrome::kChromeUIHistory2Host) + return &NewDOMUI<HistoryUI2>; if (url.host() == chrome::kChromeUINetInternalsHost) return &NewDOMUI<NetInternalsUI>; if (url.host() == chrome::kChromeUIPluginsHost) @@ -176,6 +179,9 @@ RefCountedMemory* DOMUIFactory::GetFaviconResourceBytes(Profile* profile, if (page_url.host() == chrome::kChromeUIHistoryHost) return HistoryUI::GetFaviconResourceBytes(); + if (page_url.host() == chrome::kChromeUIHistory2Host) + return HistoryUI2::GetFaviconResourceBytes(); + if (page_url.host() == chrome::kChromeUIPluginsHost) return PluginsUI::GetFaviconResourceBytes(); diff --git a/chrome/browser/dom_ui/history2_ui.cc b/chrome/browser/dom_ui/history2_ui.cc new file mode 100644 index 0000000..3fd433d --- /dev/null +++ b/chrome/browser/dom_ui/history2_ui.cc @@ -0,0 +1,413 @@ +// Copyright (c) 2010 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/history2_ui.h" + +#include "app/l10n_util.h" +#include "app/resource_bundle.h" +#include "base/callback.h" +#include "base/i18n/time_formatting.h" +#include "base/message_loop.h" +#include "base/singleton.h" +#include "base/string_piece.h" +#include "base/string_util.h" +#include "base/thread.h" +#include "base/time.h" +#include "base/values.h" +#include "chrome/browser/bookmarks/bookmark_model.h" +#include "chrome/browser/browser.h" +#include "chrome/browser/chrome_thread.h" +#include "chrome/browser/dom_ui/dom_ui_favicon_source.h" +#include "chrome/browser/metrics/user_metrics.h" +#include "chrome/browser/history/history_types.h" +#include "chrome/browser/profile.h" +#include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/tab_contents/tab_contents_delegate.h" +#include "chrome/common/jstemplate_builder.h" +#include "chrome/common/notification_service.h" +#include "chrome/common/time_format.h" +#include "chrome/common/url_constants.h" +#include "net/base/escape.h" + +#include "grit/browser_resources.h" +#include "grit/chromium_strings.h" +#include "grit/generated_resources.h" +#include "grit/locale_settings.h" +#include "grit/theme_resources.h" + +// Maximum number of search results to return in a given search. We should +// eventually remove this. +static const int kMaxSearchResults = 100; + +//////////////////////////////////////////////////////////////////////////////// +// +// HistoryHTMLSource +// +//////////////////////////////////////////////////////////////////////////////// + +HistoryUIHTMLSource2::HistoryUIHTMLSource2() + : DataSource(chrome::kChromeUIHistory2Host, MessageLoop::current()) { +} + +void HistoryUIHTMLSource2::StartDataRequest(const std::string& path, + bool is_off_the_record, + int request_id) { + DictionaryValue localized_strings; + localized_strings.SetString(L"loading", + l10n_util::GetString(IDS_HISTORY_LOADING)); + 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"edithistory", + l10n_util::GetString(IDS_HISTORY_START_EDITING_HISTORY)); + localized_strings.SetString(L"doneediting", + l10n_util::GetString(IDS_HISTORY_STOP_EDITING_HISTORY)); + localized_strings.SetString(L"removeselected", + l10n_util::GetString(IDS_HISTORY_REMOVE_SELECTED_ITEMS)); + localized_strings.SetString(L"clearallhistory", + l10n_util::GetString(IDS_HISTORY_OPEN_CLEAR_BROWSING_DATA_DIALOG)); + localized_strings.SetString(L"deletewarning", + l10n_util::GetString(IDS_HISTORY_DELETE_PRIOR_VISITS_WARNING)); + + SetFontAndTextDirection(&localized_strings); + + static const base::StringPiece history_html( + ResourceBundle::GetSharedInstance().GetRawDataResource( + IDR_HISTORY2_HTML)); + const std::string full_html = jstemplate_builder::GetI18nTemplateHtml( + history_html, &localized_strings); + + 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 +// +//////////////////////////////////////////////////////////////////////////////// +BrowsingHistoryHandler2::BrowsingHistoryHandler2() + : search_text_() { +} + +BrowsingHistoryHandler2::~BrowsingHistoryHandler2() { + cancelable_search_consumer_.CancelAllRequests(); + cancelable_delete_consumer_.CancelAllRequests(); +} + +DOMMessageHandler* BrowsingHistoryHandler2::Attach(DOMUI* dom_ui) { + // Create our favicon data source. + ChromeThread::PostTask( + ChromeThread::IO, FROM_HERE, + NewRunnableMethod( + Singleton<ChromeURLDataManager>::get(), + &ChromeURLDataManager::AddDataSource, + make_scoped_refptr(new DOMUIFavIconSource(dom_ui->GetProfile())))); + + // Get notifications when history is cleared. + registrar_.Add(this, NotificationType::HISTORY_URLS_DELETED, + Source<Profile>(dom_ui->GetProfile()->GetOriginalProfile())); + return DOMMessageHandler::Attach(dom_ui); +} + +void BrowsingHistoryHandler2::RegisterMessages() { + dom_ui_->RegisterMessageCallback("getHistory", + NewCallback(this, &BrowsingHistoryHandler2::HandleGetHistory)); + dom_ui_->RegisterMessageCallback("searchHistory", + NewCallback(this, &BrowsingHistoryHandler2::HandleSearchHistory)); + dom_ui_->RegisterMessageCallback("removeURLsOnOneDay", + NewCallback(this, &BrowsingHistoryHandler2::HandleRemoveURLsOnOneDay)); + dom_ui_->RegisterMessageCallback("clearBrowsingData", + NewCallback(this, &BrowsingHistoryHandler2::HandleClearBrowsingData)); +} + +void BrowsingHistoryHandler2::HandleGetHistory(const Value* value) { + // Anything in-flight is invalid. + cancelable_search_consumer_.CancelAllRequests(); + + // Get arguments (if any). + int day = 0; + ExtractIntegerValue(value, &day); + + // Set our query options. + history::QueryOptions options; + options.begin_time = base::Time::Now().LocalMidnight(); + options.begin_time -= base::TimeDelta::FromDays(day); + options.end_time = base::Time::Now().LocalMidnight(); + options.end_time -= base::TimeDelta::FromDays(day - 1); + + // Need to remember the query string for our results. + search_text_ = std::wstring(); + + HistoryService* hs = + dom_ui_->GetProfile()->GetHistoryService(Profile::EXPLICIT_ACCESS); + hs->QueryHistory(search_text_, + options, + &cancelable_search_consumer_, + NewCallback(this, &BrowsingHistoryHandler2::QueryComplete)); +} + +void BrowsingHistoryHandler2::HandleSearchHistory(const Value* value) { + // Anything in-flight is invalid. + cancelable_search_consumer_.CancelAllRequests(); + + // Get arguments (if any). + int month = 0; + std::wstring query; + ExtractSearchHistoryArguments(value, &month, &query); + + // Set the query ranges for the given month. + history::QueryOptions options = CreateMonthQueryOptions(month); + + // When searching, limit the number of results returned. + options.max_count = kMaxSearchResults; + + // Need to remember the query string for our results. + search_text_ = query; + HistoryService* hs = + dom_ui_->GetProfile()->GetHistoryService(Profile::EXPLICIT_ACCESS); + hs->QueryHistory(search_text_, + options, + &cancelable_search_consumer_, + NewCallback(this, &BrowsingHistoryHandler2::QueryComplete)); +} + +void BrowsingHistoryHandler2::HandleRemoveURLsOnOneDay(const Value* value) { + if (cancelable_delete_consumer_.HasPendingRequests()) { + dom_ui_->CallJavascriptFunction(L"deleteFailed"); + return; + } + + DCHECK(value && value->GetType() == Value::TYPE_LIST); + + // Get day to delete data from. + int visit_time = 0; + ExtractIntegerValue(value, &visit_time); + base::Time::Exploded exploded; + base::Time::FromTimeT( + static_cast<time_t>(visit_time)).LocalExplode(&exploded); + exploded.hour = exploded.minute = exploded.second = exploded.millisecond = 0; + base::Time begin_time = base::Time::FromLocalExploded(exploded); + base::Time end_time = begin_time + base::TimeDelta::FromDays(1); + + // Get URLs. + std::set<GURL> urls; + const ListValue* list_value = static_cast<const ListValue*>(value); + for (ListValue::const_iterator v = list_value->begin() + 1; + v != list_value->end(); ++v) { + if ((*v)->GetType() != Value::TYPE_STRING) + continue; + const StringValue* string_value = static_cast<const StringValue*>(*v); + string16 string16_value; + if (!string_value->GetAsUTF16(&string16_value)) + continue; + urls.insert(GURL(string16_value)); + } + + HistoryService* hs = + dom_ui_->GetProfile()->GetHistoryService(Profile::EXPLICIT_ACCESS); + hs->ExpireHistoryBetween( + urls, begin_time, end_time, &cancelable_delete_consumer_, + NewCallback(this, &BrowsingHistoryHandler2::RemoveComplete)); +} + +void BrowsingHistoryHandler2::HandleClearBrowsingData(const Value* value) { + dom_ui_->tab_contents()->delegate()->GetBrowser()-> + OpenClearBrowsingDataDialog(); +} + +void BrowsingHistoryHandler2::QueryComplete( + HistoryService::Handle request_handle, + history::QueryResults* results) { + + ListValue results_value; + base::Time midnight_today = base::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()); + } + page_value->SetBoolean(L"starred", + dom_ui_->GetProfile()->GetBookmarkModel()->IsBookmarked(page.url())); + results_value.Append(page_value); + } + + DictionaryValue info_value; + info_value.SetString(L"term", search_text_); + info_value.SetBoolean(L"finished", results->reached_beginning()); + + dom_ui_->CallJavascriptFunction(L"historyResult", info_value, results_value); +} + +void BrowsingHistoryHandler2::RemoveComplete() { + // Some Visits were deleted from history. Reload the list. + dom_ui_->CallJavascriptFunction(L"deleteComplete"); +} + +void BrowsingHistoryHandler2::ExtractSearchHistoryArguments(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); + string16 string16_value; + string_value->GetAsUTF16(&string16_value); + *month = StringToInt(string16_value); + } + } +} + +history::QueryOptions BrowsingHistoryHandler2::CreateMonthQueryOptions( + int month) { + history::QueryOptions options; + + // Configure the begin point of the search to the start of the + // current month. + base::Time::Exploded exploded; + base::Time::Now().LocalMidnight().LocalExplode(&exploded); + exploded.day_of_month = 1; + + if (month == 0) { + options.begin_time = base::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 = base::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 = base::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 = base::Time::FromLocalExploded(exploded); + } + + return options; +} + +void BrowsingHistoryHandler2::Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details) { + if (type != NotificationType::HISTORY_URLS_DELETED) { + NOTREACHED(); + return; + } + + // Some URLs were deleted from history. Reload the list. + dom_ui_->CallJavascriptFunction(L"historyDeleted"); +} + +//////////////////////////////////////////////////////////////////////////////// +// +// HistoryUIContents +// +//////////////////////////////////////////////////////////////////////////////// + +HistoryUI2::HistoryUI2(TabContents* contents) : DOMUI(contents) { + AddMessageHandler((new BrowsingHistoryHandler2())->Attach(this)); + + HistoryUIHTMLSource2* html_source = new HistoryUIHTMLSource2(); + + // Set up the chrome://history2/ source. + ChromeThread::PostTask( + ChromeThread::IO, FROM_HERE, + NewRunnableMethod( + Singleton<ChromeURLDataManager>::get(), + &ChromeURLDataManager::AddDataSource, + make_scoped_refptr(html_source))); +} + +// static +const GURL HistoryUI2::GetHistoryURLWithSearchText(const std::wstring& text) { + return GURL(std::string(chrome::kChromeUIHistory2URL) + "#q=" + + EscapeQueryParamValue(WideToUTF8(text), true)); +} + +// static +RefCountedMemory* HistoryUI2::GetFaviconResourceBytes() { + return ResourceBundle::GetSharedInstance(). + LoadDataResourceBytes(IDR_HISTORY_FAVICON); +} diff --git a/chrome/browser/dom_ui/history2_ui.h b/chrome/browser/dom_ui/history2_ui.h new file mode 100644 index 0000000..042e0c4 --- /dev/null +++ b/chrome/browser/dom_ui/history2_ui.h @@ -0,0 +1,113 @@ +// Copyright (c) 2010 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_HISTORY2_UI_H_ +#define CHROME_BROWSER_DOM_UI_HISTORY2_UI_H_ + +#include <string> +#include <vector> + +#include "chrome/browser/dom_ui/chrome_url_data_manager.h" +#include "chrome/browser/dom_ui/dom_ui.h" +#include "chrome/browser/cancelable_request.h" +#include "chrome/browser/history/history.h" +#include "chrome/common/notification_registrar.h" + +class GURL; + +// Temporary fork for development of new history UI. +// TODO(pamg): merge back in when new UI is complete. + +class HistoryUIHTMLSource2 : public ChromeURLDataManager::DataSource { + public: + HistoryUIHTMLSource2(); + + // Called when the network layer has requested a resource underneath + // the path we registered. + virtual void StartDataRequest(const std::string& path, + bool is_off_the_record, + int request_id); + + virtual std::string GetMimeType(const std::string&) const { + return "text/html"; + } + + private: + ~HistoryUIHTMLSource2() {} + + DISALLOW_COPY_AND_ASSIGN(HistoryUIHTMLSource2); +}; + +// The handler for Javascript messages related to the "history" view. +class BrowsingHistoryHandler2 : public DOMMessageHandler, + public NotificationObserver { + public: + BrowsingHistoryHandler2(); + virtual ~BrowsingHistoryHandler2(); + + // DOMMessageHandler implementation. + virtual DOMMessageHandler* Attach(DOMUI* dom_ui); + virtual void RegisterMessages(); + + // Callback for the "getHistory" message. + void HandleGetHistory(const Value* value); + + // Callback for the "searchHistory" message. + void HandleSearchHistory(const Value* value); + + // Callback for the "removeURLsOnOneDay" message. + void HandleRemoveURLsOnOneDay(const Value* value); + + // Handle for "clearBrowsingData" message. + void HandleClearBrowsingData(const Value* value); + + // NotificationObserver implementation. + virtual void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details); + + private: + // Callback from the history system when the history list is available. + void QueryComplete(HistoryService::Handle request_handle, + history::QueryResults* results); + + // Callback from the history system when visits were deleted. + void RemoveComplete(); + + // Extract the arguments from the call to HandleSearchHistory. + void ExtractSearchHistoryArguments(const Value* value, + int* month, + std::wstring* query); + + // Figure out the query options for a month-wide query. + history::QueryOptions CreateMonthQueryOptions(int month); + + NotificationRegistrar registrar_; + + // Current search text. + std::wstring search_text_; + + // Our consumer for search requests to the history service. + CancelableRequestConsumerT<int, 0> cancelable_search_consumer_; + + // Our consumer for delete requests to the history service. + CancelableRequestConsumerT<int, 0> cancelable_delete_consumer_; + + DISALLOW_COPY_AND_ASSIGN(BrowsingHistoryHandler2); +}; + +class HistoryUI2 : public DOMUI { + public: + explicit HistoryUI2(TabContents* contents); + + // Return the URL for a given search term. + static const GURL GetHistoryURLWithSearchText(const std::wstring& text); + + static RefCountedMemory* GetFaviconResourceBytes(); + + private: + DISALLOW_COPY_AND_ASSIGN(HistoryUI2); +}; + +#endif // CHROME_BROWSER_DOM_UI_HISTORY2_UI_H_ |