1 // Copyright (c) 2011 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/flags_ui.h" 6 7 #include <string> 8 9 #include "base/memory/singleton.h" 10 #include "base/values.h" 11 #include "chrome/browser/about_flags.h" 12 #include "chrome/browser/browser_process.h" 13 #include "chrome/browser/prefs/pref_service.h" 14 #include "chrome/browser/profiles/profile.h" 15 #include "chrome/browser/ui/browser_list.h" 16 #include "chrome/browser/ui/webui/chrome_url_data_manager.h" 17 #include "chrome/common/jstemplate_builder.h" 18 #include "chrome/common/pref_names.h" 19 #include "chrome/common/url_constants.h" 20 #include "content/browser/browser_thread.h" 21 #include "content/browser/tab_contents/tab_contents.h" 22 #include "grit/browser_resources.h" 23 #include "grit/chromium_strings.h" 24 #include "grit/generated_resources.h" 25 #include "grit/theme_resources.h" 26 #include "ui/base/l10n/l10n_util.h" 27 #include "ui/base/resource/resource_bundle.h" 28 29 #if defined(OS_CHROMEOS) 30 #include "chrome/browser/chromeos/user_cros_settings_provider.h" 31 #include "chrome/browser/chromeos/login/user_manager.h" 32 #endif 33 34 namespace { 35 36 /////////////////////////////////////////////////////////////////////////////// 37 // 38 // FlagsUIHTMLSource 39 // 40 /////////////////////////////////////////////////////////////////////////////// 41 42 class FlagsUIHTMLSource : public ChromeURLDataManager::DataSource { 43 public: 44 FlagsUIHTMLSource() 45 : DataSource(chrome::kChromeUIFlagsHost, MessageLoop::current()) {} 46 47 // Called when the network layer has requested a resource underneath 48 // the path we registered. 49 virtual void StartDataRequest(const std::string& path, 50 bool is_incognito, 51 int request_id); 52 virtual std::string GetMimeType(const std::string&) const { 53 return "text/html"; 54 } 55 56 private: 57 ~FlagsUIHTMLSource() {} 58 59 DISALLOW_COPY_AND_ASSIGN(FlagsUIHTMLSource); 60 }; 61 62 void FlagsUIHTMLSource::StartDataRequest(const std::string& path, 63 bool is_incognito, 64 int request_id) { 65 // Strings used in the JsTemplate file. 66 DictionaryValue localized_strings; 67 localized_strings.SetString("flagsLongTitle", 68 l10n_util::GetStringUTF16(IDS_FLAGS_LONG_TITLE)); 69 localized_strings.SetString("flagsTableTitle", 70 l10n_util::GetStringUTF16(IDS_FLAGS_TABLE_TITLE)); 71 localized_strings.SetString("flagsNoExperimentsAvailable", 72 l10n_util::GetStringUTF16(IDS_FLAGS_NO_EXPERIMENTS_AVAILABLE)); 73 localized_strings.SetString("flagsWarningHeader", l10n_util::GetStringUTF16( 74 IDS_FLAGS_WARNING_HEADER)); 75 localized_strings.SetString("flagsBlurb", l10n_util::GetStringUTF16( 76 IDS_FLAGS_WARNING_TEXT)); 77 localized_strings.SetString("flagsRestartNotice", l10n_util::GetStringFUTF16( 78 IDS_FLAGS_RELAUNCH_NOTICE, 79 l10n_util::GetStringUTF16( 80 #if defined(OS_CHROMEOS) 81 IDS_PRODUCT_OS_NAME 82 #else 83 IDS_PRODUCT_NAME 84 #endif 85 ))); 86 localized_strings.SetString("flagsRestartButton", 87 l10n_util::GetStringUTF16(IDS_FLAGS_RELAUNCH_BUTTON)); 88 localized_strings.SetString("disable", 89 l10n_util::GetStringUTF16(IDS_FLAGS_DISABLE)); 90 localized_strings.SetString("enable", 91 l10n_util::GetStringUTF16(IDS_FLAGS_ENABLE)); 92 93 base::StringPiece html = 94 ResourceBundle::GetSharedInstance().GetRawDataResource(IDR_FLAGS_HTML); 95 #if defined (OS_CHROMEOS) 96 if (!chromeos::UserManager::Get()->current_user_is_owner()) { 97 html = ResourceBundle::GetSharedInstance().GetRawDataResource( 98 IDR_FLAGS_HTML_WARNING); 99 100 // Set the strings to show which user can actually change the flags 101 localized_strings.SetString("ownerOnly", l10n_util::GetStringUTF16( 102 IDS_OPTIONS_ACCOUNTS_OWNER_ONLY)); 103 localized_strings.SetString("ownerUserId", UTF8ToUTF16( 104 chromeos::UserCrosSettingsProvider::cached_owner())); 105 } 106 #endif 107 static const base::StringPiece flags_html(html); 108 ChromeURLDataManager::DataSource::SetFontAndTextDirection(&localized_strings); 109 110 std::string full_html(flags_html.data(), flags_html.size()); 111 jstemplate_builder::AppendJsonHtml(&localized_strings, &full_html); 112 jstemplate_builder::AppendI18nTemplateSourceHtml(&full_html); 113 jstemplate_builder::AppendI18nTemplateProcessHtml(&full_html); 114 jstemplate_builder::AppendJsTemplateSourceHtml(&full_html); 115 116 scoped_refptr<RefCountedBytes> html_bytes(new RefCountedBytes); 117 html_bytes->data.resize(full_html.size()); 118 std::copy(full_html.begin(), full_html.end(), html_bytes->data.begin()); 119 120 SendResponse(request_id, html_bytes); 121 } 122 123 //////////////////////////////////////////////////////////////////////////////// 124 // 125 // FlagsDOMHandler 126 // 127 //////////////////////////////////////////////////////////////////////////////// 128 129 // The handler for Javascript messages for the about:flags page. 130 class FlagsDOMHandler : public WebUIMessageHandler { 131 public: 132 FlagsDOMHandler() {} 133 virtual ~FlagsDOMHandler() {} 134 135 // WebUIMessageHandler implementation. 136 virtual void RegisterMessages(); 137 138 // Callback for the "requestFlagsExperiments" message. 139 void HandleRequestFlagsExperiments(const ListValue* args); 140 141 // Callback for the "enableFlagsExperiment" message. 142 void HandleEnableFlagsExperimentMessage(const ListValue* args); 143 144 // Callback for the "restartBrowser" message. Restores all tabs on restart. 145 void HandleRestartBrowser(const ListValue* args); 146 147 private: 148 DISALLOW_COPY_AND_ASSIGN(FlagsDOMHandler); 149 }; 150 151 void FlagsDOMHandler::RegisterMessages() { 152 web_ui_->RegisterMessageCallback("requestFlagsExperiments", 153 NewCallback(this, &FlagsDOMHandler::HandleRequestFlagsExperiments)); 154 web_ui_->RegisterMessageCallback("enableFlagsExperiment", 155 NewCallback(this, &FlagsDOMHandler::HandleEnableFlagsExperimentMessage)); 156 web_ui_->RegisterMessageCallback("restartBrowser", 157 NewCallback(this, &FlagsDOMHandler::HandleRestartBrowser)); 158 } 159 160 void FlagsDOMHandler::HandleRequestFlagsExperiments(const ListValue* args) { 161 DictionaryValue results; 162 results.Set("flagsExperiments", 163 about_flags::GetFlagsExperimentsData( 164 g_browser_process->local_state())); 165 results.SetBoolean("needsRestart", 166 about_flags::IsRestartNeededToCommitChanges()); 167 web_ui_->CallJavascriptFunction("returnFlagsExperiments", results); 168 } 169 170 void FlagsDOMHandler::HandleEnableFlagsExperimentMessage( 171 const ListValue* args) { 172 DCHECK_EQ(2u, args->GetSize()); 173 if (args->GetSize() != 2) 174 return; 175 176 std::string experiment_internal_name; 177 std::string enable_str; 178 if (!args->GetString(0, &experiment_internal_name) || 179 !args->GetString(1, &enable_str)) 180 return; 181 182 about_flags::SetExperimentEnabled( 183 g_browser_process->local_state(), 184 experiment_internal_name, 185 enable_str == "true"); 186 } 187 188 void FlagsDOMHandler::HandleRestartBrowser(const ListValue* args) { 189 #if !defined(OS_CHROMEOS) 190 // Set the flag to restore state after the restart. 191 PrefService* pref_service = g_browser_process->local_state(); 192 pref_service->SetBoolean(prefs::kRestartLastSessionOnShutdown, true); 193 BrowserList::CloseAllBrowsersAndExit(); 194 #else 195 // For CrOS instead of browser restart (which is not supported) perform a full 196 // sign out. Session will be only restored is user has that setting set. 197 // Same session restore behavior happens in case of full restart after update. 198 BrowserList::GetLastActive()->Exit(); 199 #endif 200 } 201 202 } // namespace 203 204 /////////////////////////////////////////////////////////////////////////////// 205 // 206 // FlagsUI 207 // 208 /////////////////////////////////////////////////////////////////////////////// 209 210 FlagsUI::FlagsUI(TabContents* contents) : WebUI(contents) { 211 AddMessageHandler((new FlagsDOMHandler())->Attach(this)); 212 213 FlagsUIHTMLSource* html_source = new FlagsUIHTMLSource(); 214 215 // Set up the about:flags source. 216 contents->profile()->GetChromeURLDataManager()->AddDataSource(html_source); 217 } 218 219 // static 220 RefCountedMemory* FlagsUI::GetFaviconResourceBytes() { 221 return ResourceBundle::GetSharedInstance(). 222 LoadDataResourceBytes(IDR_FLAGS); 223 } 224 225 // static 226 void FlagsUI::RegisterPrefs(PrefService* prefs) { 227 prefs->RegisterListPref(prefs::kEnabledLabsExperiments); 228 } 229