1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "chrome/browser/ui/webui/instant_ui.h" 6 7#include "base/bind.h" 8#include "base/prefs/pref_service.h" 9#include "base/strings/stringprintf.h" 10#include "base/time/time.h" 11#include "chrome/browser/profiles/profile.h" 12#include "chrome/browser/ui/browser.h" 13#include "chrome/browser/ui/browser_finder.h" 14#include "chrome/browser/ui/browser_instant_controller.h" 15#include "chrome/browser/ui/search/instant_controller.h" 16#include "chrome/common/pref_names.h" 17#include "chrome/common/url_constants.h" 18#include "components/user_prefs/pref_registry_syncable.h" 19#include "content/public/browser/web_ui.h" 20#include "content/public/browser/web_ui_data_source.h" 21#include "content/public/browser/web_ui_message_handler.h" 22#include "grit/browser_resources.h" 23 24namespace { 25 26content::WebUIDataSource* CreateInstantHTMLSource() { 27 content::WebUIDataSource* source = 28 content::WebUIDataSource::Create(chrome::kChromeUIInstantHost); 29 source->SetJsonPath("strings.js"); 30 source->AddResourcePath("instant.js", IDR_INSTANT_JS); 31 source->AddResourcePath("instant.css", IDR_INSTANT_CSS); 32 source->SetDefaultResource(IDR_INSTANT_HTML); 33 return source; 34} 35 36std::string FormatTime(int64 time) { 37 base::Time::Exploded exploded; 38 base::Time::FromInternalValue(time).UTCExplode(&exploded); 39 return base::StringPrintf("%04d-%02d-%02d %02d:%02d:%02d.%03d", 40 exploded.year, exploded.month, exploded.day_of_month, 41 exploded.hour, exploded.minute, exploded.second, exploded.millisecond); 42} 43 44// This class receives JavaScript messages from the renderer. 45// Note that the WebUI infrastructure runs on the UI thread, therefore all of 46// this class's methods are expected to run on the UI thread. 47class InstantUIMessageHandler 48 : public content::WebUIMessageHandler, 49 public base::SupportsWeakPtr<InstantUIMessageHandler> { 50 public: 51 InstantUIMessageHandler(); 52 virtual ~InstantUIMessageHandler(); 53 54 // WebUIMessageHandler implementation. 55 virtual void RegisterMessages() OVERRIDE; 56 57 private: 58 void GetPreferenceValue(const base::ListValue* args); 59 void SetPreferenceValue(const base::ListValue* args); 60 void GetDebugInfo(const base::ListValue* value); 61 void ClearDebugInfo(const base::ListValue* value); 62 63 DISALLOW_COPY_AND_ASSIGN(InstantUIMessageHandler); 64}; 65 66InstantUIMessageHandler::InstantUIMessageHandler() {} 67 68InstantUIMessageHandler::~InstantUIMessageHandler() {} 69 70void InstantUIMessageHandler::RegisterMessages() { 71 web_ui()->RegisterMessageCallback( 72 "getPreferenceValue", 73 base::Bind(&InstantUIMessageHandler::GetPreferenceValue, 74 base::Unretained(this))); 75 web_ui()->RegisterMessageCallback( 76 "setPreferenceValue", 77 base::Bind(&InstantUIMessageHandler::SetPreferenceValue, 78 base::Unretained(this))); 79 web_ui()->RegisterMessageCallback( 80 "getDebugInfo", 81 base::Bind(&InstantUIMessageHandler::GetDebugInfo, 82 base::Unretained(this))); 83 web_ui()->RegisterMessageCallback( 84 "clearDebugInfo", 85 base::Bind(&InstantUIMessageHandler::ClearDebugInfo, 86 base::Unretained(this))); 87} 88 89void InstantUIMessageHandler::GetPreferenceValue(const base::ListValue* args) { 90 std::string pref_name; 91 if (!args->GetString(0, &pref_name)) return; 92 93 base::StringValue pref_name_value(pref_name); 94 if (pref_name == prefs::kInstantUIZeroSuggestUrlPrefix) { 95 PrefService* prefs = Profile::FromWebUI(web_ui())->GetPrefs(); 96 base::StringValue arg(prefs->GetString(pref_name.c_str())); 97 web_ui()->CallJavascriptFunction( 98 "instantConfig.getPreferenceValueResult", pref_name_value, arg); 99 } 100} 101 102void InstantUIMessageHandler::SetPreferenceValue(const base::ListValue* args) { 103 std::string pref_name; 104 if (!args->GetString(0, &pref_name)) return; 105 106 if (pref_name == prefs::kInstantUIZeroSuggestUrlPrefix) { 107 std::string value; 108 if (!args->GetString(1, &value)) 109 return; 110 PrefService* prefs = Profile::FromWebUI(web_ui())->GetPrefs(); 111 prefs->SetString(pref_name.c_str(), value); 112 } 113} 114 115void InstantUIMessageHandler::GetDebugInfo(const base::ListValue* args) { 116#if !defined(OS_ANDROID) 117 typedef std::pair<int64, std::string> DebugEvent; 118 119 if (!web_ui()->GetWebContents()) 120 return; 121 Browser* browser = chrome::FindBrowserWithWebContents( 122 web_ui()->GetWebContents()); 123 if (!browser || !browser->instant_controller()) 124 return; 125 126 InstantController* instant = browser->instant_controller()->instant(); 127 const std::list<DebugEvent>& events = instant->debug_events(); 128 129 base::DictionaryValue data; 130 base::ListValue* entries = new base::ListValue(); 131 for (std::list<DebugEvent>::const_iterator it = events.begin(); 132 it != events.end(); ++it) { 133 base::DictionaryValue* entry = new base::DictionaryValue(); 134 entry->SetString("time", FormatTime(it->first)); 135 entry->SetString("text", it->second); 136 entries->Append(entry); 137 } 138 data.Set("entries", entries); 139 140 web_ui()->CallJavascriptFunction("instantConfig.getDebugInfoResult", data); 141#endif 142} 143 144void InstantUIMessageHandler::ClearDebugInfo(const base::ListValue* args) { 145#if !defined(OS_ANDROID) 146 if (!web_ui()->GetWebContents()) 147 return; 148 Browser* browser = chrome::FindBrowserWithWebContents( 149 web_ui()->GetWebContents()); 150 if (!browser || !browser->instant_controller()) 151 return; 152 153 browser->instant_controller()->instant()->ClearDebugEvents(); 154#endif 155} 156 157} // namespace 158 159//////////////////////////////////////////////////////////////////////////////// 160// InstantUI 161 162InstantUI::InstantUI(content::WebUI* web_ui) : WebUIController(web_ui) { 163 web_ui->AddMessageHandler(new InstantUIMessageHandler()); 164 165 // Set up the chrome://instant/ source. 166 Profile* profile = Profile::FromWebUI(web_ui); 167 content::WebUIDataSource::Add(profile, CreateInstantHTMLSource()); 168} 169 170// static 171void InstantUI::RegisterProfilePrefs( 172 user_prefs::PrefRegistrySyncable* registry) { 173 registry->RegisterStringPref( 174 prefs::kInstantUIZeroSuggestUrlPrefix, 175 std::string(), 176 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 177} 178