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 34namespace { 35 36/////////////////////////////////////////////////////////////////////////////// 37// 38// FlagsUIHTMLSource 39// 40/////////////////////////////////////////////////////////////////////////////// 41 42class 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 62void 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. 130class 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 151void 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 160void 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 170void 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 188void 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 210FlagsUI::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 220RefCountedMemory* FlagsUI::GetFaviconResourceBytes() { 221 return ResourceBundle::GetSharedInstance(). 222 LoadDataResourceBytes(IDR_FLAGS); 223} 224 225// static 226void FlagsUI::RegisterPrefs(PrefService* prefs) { 227 prefs->RegisterListPref(prefs::kEnabledLabsExperiments); 228} 229