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/pref_registry/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 #if !defined(OS_ANDROID) 37 std::string FormatTime(int64 time) { 38 base::Time::Exploded exploded; 39 base::Time::FromInternalValue(time).UTCExplode(&exploded); 40 return base::StringPrintf("%04d-%02d-%02d %02d:%02d:%02d.%03d", 41 exploded.year, exploded.month, exploded.day_of_month, 42 exploded.hour, exploded.minute, exploded.second, exploded.millisecond); 43 } 44 #endif // !defined(OS_ANDROID) 45 46 // This class receives JavaScript messages from the renderer. 47 // Note that the WebUI infrastructure runs on the UI thread, therefore all of 48 // this class's methods are expected to run on the UI thread. 49 class InstantUIMessageHandler 50 : public content::WebUIMessageHandler, 51 public base::SupportsWeakPtr<InstantUIMessageHandler> { 52 public: 53 InstantUIMessageHandler(); 54 virtual ~InstantUIMessageHandler(); 55 56 // WebUIMessageHandler implementation. 57 virtual void RegisterMessages() OVERRIDE; 58 59 private: 60 void GetPreferenceValue(const base::ListValue* args); 61 void SetPreferenceValue(const base::ListValue* args); 62 void GetDebugInfo(const base::ListValue* value); 63 void ClearDebugInfo(const base::ListValue* value); 64 65 DISALLOW_COPY_AND_ASSIGN(InstantUIMessageHandler); 66 }; 67 68 InstantUIMessageHandler::InstantUIMessageHandler() {} 69 70 InstantUIMessageHandler::~InstantUIMessageHandler() {} 71 72 void InstantUIMessageHandler::RegisterMessages() { 73 web_ui()->RegisterMessageCallback( 74 "getPreferenceValue", 75 base::Bind(&InstantUIMessageHandler::GetPreferenceValue, 76 base::Unretained(this))); 77 web_ui()->RegisterMessageCallback( 78 "setPreferenceValue", 79 base::Bind(&InstantUIMessageHandler::SetPreferenceValue, 80 base::Unretained(this))); 81 web_ui()->RegisterMessageCallback( 82 "getDebugInfo", 83 base::Bind(&InstantUIMessageHandler::GetDebugInfo, 84 base::Unretained(this))); 85 web_ui()->RegisterMessageCallback( 86 "clearDebugInfo", 87 base::Bind(&InstantUIMessageHandler::ClearDebugInfo, 88 base::Unretained(this))); 89 } 90 91 void InstantUIMessageHandler::GetPreferenceValue(const base::ListValue* args) { 92 std::string pref_name; 93 if (!args->GetString(0, &pref_name)) return; 94 95 base::StringValue pref_name_value(pref_name); 96 if (pref_name == prefs::kInstantUIZeroSuggestUrlPrefix) { 97 PrefService* prefs = Profile::FromWebUI(web_ui())->GetPrefs(); 98 base::StringValue arg(prefs->GetString(pref_name.c_str())); 99 web_ui()->CallJavascriptFunction( 100 "instantConfig.getPreferenceValueResult", pref_name_value, arg); 101 } 102 } 103 104 void InstantUIMessageHandler::SetPreferenceValue(const base::ListValue* args) { 105 std::string pref_name; 106 if (!args->GetString(0, &pref_name)) return; 107 108 if (pref_name == prefs::kInstantUIZeroSuggestUrlPrefix) { 109 std::string value; 110 if (!args->GetString(1, &value)) 111 return; 112 PrefService* prefs = Profile::FromWebUI(web_ui())->GetPrefs(); 113 prefs->SetString(pref_name.c_str(), value); 114 } 115 } 116 117 void InstantUIMessageHandler::GetDebugInfo(const base::ListValue* args) { 118 #if !defined(OS_ANDROID) 119 typedef std::pair<int64, std::string> DebugEvent; 120 121 if (!web_ui()->GetWebContents()) 122 return; 123 Browser* browser = chrome::FindBrowserWithWebContents( 124 web_ui()->GetWebContents()); 125 if (!browser || !browser->instant_controller()) 126 return; 127 128 InstantController* instant = browser->instant_controller()->instant(); 129 const std::list<DebugEvent>& events = instant->debug_events(); 130 131 base::DictionaryValue data; 132 base::ListValue* entries = new base::ListValue(); 133 for (std::list<DebugEvent>::const_iterator it = events.begin(); 134 it != events.end(); ++it) { 135 base::DictionaryValue* entry = new base::DictionaryValue(); 136 entry->SetString("time", FormatTime(it->first)); 137 entry->SetString("text", it->second); 138 entries->Append(entry); 139 } 140 data.Set("entries", entries); 141 142 web_ui()->CallJavascriptFunction("instantConfig.getDebugInfoResult", data); 143 #endif 144 } 145 146 void InstantUIMessageHandler::ClearDebugInfo(const base::ListValue* args) { 147 #if !defined(OS_ANDROID) 148 if (!web_ui()->GetWebContents()) 149 return; 150 Browser* browser = chrome::FindBrowserWithWebContents( 151 web_ui()->GetWebContents()); 152 if (!browser || !browser->instant_controller()) 153 return; 154 155 browser->instant_controller()->instant()->ClearDebugEvents(); 156 #endif 157 } 158 159 } // namespace 160 161 //////////////////////////////////////////////////////////////////////////////// 162 // InstantUI 163 164 InstantUI::InstantUI(content::WebUI* web_ui) : WebUIController(web_ui) { 165 web_ui->AddMessageHandler(new InstantUIMessageHandler()); 166 167 // Set up the chrome://instant/ source. 168 Profile* profile = Profile::FromWebUI(web_ui); 169 content::WebUIDataSource::Add(profile, CreateInstantHTMLSource()); 170 } 171 172 // static 173 void InstantUI::RegisterProfilePrefs( 174 user_prefs::PrefRegistrySyncable* registry) { 175 registry->RegisterStringPref( 176 prefs::kInstantUIZeroSuggestUrlPrefix, 177 std::string(), 178 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 179 } 180