blob: 298ebe8d9a2435e893ce1e0196b7634939dc46d3 [file] [log] [blame]
// Copyright (c) 2012 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/ui/webui/instant_ui.h"
#include <stdint.h>
#include <memory>
#include <utility>
#include "base/bind.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/strings/stringprintf.h"
#include "base/time/time.h"
#include "base/values.h"
#include "build/build_config.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/browser_instant_controller.h"
#include "chrome/browser/ui/search/instant_controller.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h"
#include "chrome/grit/browser_resources.h"
#include "components/pref_registry/pref_registry_syncable.h"
#include "components/prefs/pref_service.h"
#include "content/public/browser/web_ui.h"
#include "content/public/browser/web_ui_data_source.h"
#include "content/public/browser/web_ui_message_handler.h"
#if !defined(OS_ANDROID)
#include "chrome/browser/ui/browser.h"
#endif
namespace {
content::WebUIDataSource* CreateInstantHTMLSource() {
content::WebUIDataSource* source =
content::WebUIDataSource::Create(chrome::kChromeUIInstantHost);
source->SetJsonPath("strings.js");
source->AddResourcePath("instant.js", IDR_INSTANT_JS);
source->AddResourcePath("instant.css", IDR_INSTANT_CSS);
source->SetDefaultResource(IDR_INSTANT_HTML);
return source;
}
#if !defined(OS_ANDROID)
std::string FormatTime(int64_t time) {
base::Time::Exploded exploded;
base::Time::FromInternalValue(time).UTCExplode(&exploded);
return base::StringPrintf("%04d-%02d-%02d %02d:%02d:%02d.%03d",
exploded.year, exploded.month, exploded.day_of_month,
exploded.hour, exploded.minute, exploded.second, exploded.millisecond);
}
#endif // !defined(OS_ANDROID)
// This class receives JavaScript messages from the renderer.
// Note that the WebUI infrastructure runs on the UI thread, therefore all of
// this class's methods are expected to run on the UI thread.
class InstantUIMessageHandler
: public content::WebUIMessageHandler,
public base::SupportsWeakPtr<InstantUIMessageHandler> {
public:
InstantUIMessageHandler();
~InstantUIMessageHandler() override;
// WebUIMessageHandler implementation.
void RegisterMessages() override;
private:
void GetPreferenceValue(const base::ListValue* args);
void SetPreferenceValue(const base::ListValue* args);
void GetDebugInfo(const base::ListValue* value);
void ClearDebugInfo(const base::ListValue* value);
DISALLOW_COPY_AND_ASSIGN(InstantUIMessageHandler);
};
InstantUIMessageHandler::InstantUIMessageHandler() {}
InstantUIMessageHandler::~InstantUIMessageHandler() {}
void InstantUIMessageHandler::RegisterMessages() {
web_ui()->RegisterMessageCallback(
"getPreferenceValue",
base::Bind(&InstantUIMessageHandler::GetPreferenceValue,
base::Unretained(this)));
web_ui()->RegisterMessageCallback(
"setPreferenceValue",
base::Bind(&InstantUIMessageHandler::SetPreferenceValue,
base::Unretained(this)));
web_ui()->RegisterMessageCallback(
"getDebugInfo",
base::Bind(&InstantUIMessageHandler::GetDebugInfo,
base::Unretained(this)));
web_ui()->RegisterMessageCallback(
"clearDebugInfo",
base::Bind(&InstantUIMessageHandler::ClearDebugInfo,
base::Unretained(this)));
}
void InstantUIMessageHandler::GetPreferenceValue(const base::ListValue* args) {
std::string pref_name;
if (!args->GetString(0, &pref_name)) return;
base::Value pref_name_value(pref_name);
if (pref_name == prefs::kInstantUIZeroSuggestUrlPrefix) {
PrefService* prefs = Profile::FromWebUI(web_ui())->GetPrefs();
base::Value arg(prefs->GetString(pref_name.c_str()));
web_ui()->CallJavascriptFunctionUnsafe(
"instantConfig.getPreferenceValueResult", pref_name_value, arg);
}
}
void InstantUIMessageHandler::SetPreferenceValue(const base::ListValue* args) {
std::string pref_name;
if (!args->GetString(0, &pref_name)) return;
if (pref_name == prefs::kInstantUIZeroSuggestUrlPrefix) {
std::string value;
if (!args->GetString(1, &value))
return;
PrefService* prefs = Profile::FromWebUI(web_ui())->GetPrefs();
prefs->SetString(pref_name, value);
}
}
void InstantUIMessageHandler::GetDebugInfo(const base::ListValue* args) {
#if !defined(OS_ANDROID)
typedef std::pair<int64_t, std::string> DebugEvent;
if (!web_ui()->GetWebContents())
return;
Browser* browser = chrome::FindBrowserWithWebContents(
web_ui()->GetWebContents());
if (!browser || !browser->instant_controller())
return;
InstantController* instant = browser->instant_controller()->instant();
const std::list<DebugEvent>& events = instant->debug_events();
base::DictionaryValue data;
auto entries = base::MakeUnique<base::ListValue>();
for (std::list<DebugEvent>::const_iterator it = events.begin();
it != events.end(); ++it) {
std::unique_ptr<base::DictionaryValue> entry(new base::DictionaryValue());
entry->SetString("time", FormatTime(it->first));
entry->SetString("text", it->second);
entries->Append(std::move(entry));
}
data.Set("entries", std::move(entries));
web_ui()->CallJavascriptFunctionUnsafe("instantConfig.getDebugInfoResult",
data);
#endif
}
void InstantUIMessageHandler::ClearDebugInfo(const base::ListValue* args) {
#if !defined(OS_ANDROID)
if (!web_ui()->GetWebContents())
return;
Browser* browser = chrome::FindBrowserWithWebContents(
web_ui()->GetWebContents());
if (!browser || !browser->instant_controller())
return;
browser->instant_controller()->instant()->ClearDebugEvents();
#endif
}
} // namespace
////////////////////////////////////////////////////////////////////////////////
// InstantUI
InstantUI::InstantUI(content::WebUI* web_ui) : WebUIController(web_ui) {
web_ui->AddMessageHandler(base::MakeUnique<InstantUIMessageHandler>());
// Set up the chrome://instant/ source.
Profile* profile = Profile::FromWebUI(web_ui);
content::WebUIDataSource::Add(profile, CreateInstantHTMLSource());
}
// static
void InstantUI::RegisterProfilePrefs(
user_prefs::PrefRegistrySyncable* registry) {
registry->RegisterStringPref(prefs::kInstantUIZeroSuggestUrlPrefix,
std::string());
}