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 24 namespace { 25 26 content::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 36 std::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. 47 class 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 66 InstantUIMessageHandler::InstantUIMessageHandler() {} 67 68 InstantUIMessageHandler::~InstantUIMessageHandler() {} 69 70 void 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 89 void 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 102 void 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 115 void 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 144 void 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 162 InstantUI::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 171 void InstantUI::RegisterProfilePrefs( 172 user_prefs::PrefRegistrySyncable* registry) { 173 registry->RegisterStringPref( 174 prefs::kInstantUIZeroSuggestUrlPrefix, 175 std::string(), 176 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 177 } 178