| Index: chrome/browser/dom_ui/history_ui.cc
|
| ===================================================================
|
| --- chrome/browser/dom_ui/history_ui.cc (revision 0)
|
| +++ chrome/browser/dom_ui/history_ui.cc (revision 0)
|
| @@ -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);
|
| +}
|
|
|
| Property changes on: chrome\browser\dom_ui\history_ui.cc
|
| ___________________________________________________________________
|
| Added: svn:eol-style
|
| + LF
|
|
|
|
|