OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/chromeos/accessibility/accessibility_util.h" | 5 #include "chrome/browser/chromeos/accessibility/accessibility_manager.h" |
6 | |
7 #include <queue> | |
8 | 6 |
9 #include "ash/high_contrast/high_contrast_controller.h" | 7 #include "ash/high_contrast/high_contrast_controller.h" |
10 #include "ash/magnifier/magnification_controller.h" | |
11 #include "ash/magnifier/partial_magnification_controller.h" | |
12 #include "ash/shell.h" | 8 #include "ash/shell.h" |
13 #include "ash/shell_delegate.h" | 9 #include "ash/system/tray/system_tray_notifier.h" |
14 #include "base/bind.h" | 10 #include "base/memory/scoped_ptr.h" |
15 #include "base/bind_helpers.h" | 11 #include "base/memory/singleton.h" |
16 #include "base/logging.h" | |
17 #include "base/metrics/histogram.h" | 12 #include "base/metrics/histogram.h" |
| 13 #include "base/prefs/pref_member.h" |
18 #include "base/prefs/pref_service.h" | 14 #include "base/prefs/pref_service.h" |
19 #include "chrome/browser/accessibility/accessibility_extension_api.h" | 15 #include "chrome/browser/accessibility/accessibility_extension_api.h" |
20 #include "chrome/browser/browser_process.h" | 16 #include "chrome/browser/browser_process.h" |
21 #include "chrome/browser/chromeos/accessibility/magnification_manager.h" | 17 #include "chrome/browser/chromeos/accessibility/magnification_manager.h" |
| 18 #include "chrome/browser/chromeos/login/user_manager.h" |
22 #include "chrome/browser/extensions/component_loader.h" | 19 #include "chrome/browser/extensions/component_loader.h" |
23 #include "chrome/browser/extensions/extension_service.h" | 20 #include "chrome/browser/extensions/extension_service.h" |
24 #include "chrome/browser/extensions/extension_system.h" | 21 #include "chrome/browser/extensions/extension_system.h" |
25 #include "chrome/browser/profiles/profile.h" | 22 #include "chrome/browser/profiles/profile.h" |
26 #include "chrome/browser/profiles/profile_manager.h" | 23 #include "chrome/browser/profiles/profile_manager.h" |
27 #include "chrome/browser/speech/tts_controller.h" | 24 #include "chrome/browser/speech/tts_controller.h" |
28 #include "chrome/browser/ui/singleton_tabs.h" | 25 #include "chrome/common/chrome_notification_types.h" |
29 #include "chrome/common/extensions/extension.h" | 26 #include "chrome/common/extensions/extension.h" |
30 #include "chrome/common/extensions/extension_messages.h" | 27 #include "chrome/common/extensions/extension_messages.h" |
31 #include "chrome/common/extensions/manifest_handlers/content_scripts_handler.h" | 28 #include "chrome/common/extensions/manifest_handlers/content_scripts_handler.h" |
32 #include "chrome/common/extensions/user_script.h" | |
33 #include "chrome/common/pref_names.h" | 29 #include "chrome/common/pref_names.h" |
34 #include "chrome/common/url_constants.h" | |
35 #include "content/public/browser/browser_accessibility_state.h" | 30 #include "content/public/browser/browser_accessibility_state.h" |
| 31 #include "content/public/browser/notification_observer.h" |
| 32 #include "content/public/browser/notification_registrar.h" |
36 #include "content/public/browser/notification_service.h" | 33 #include "content/public/browser/notification_service.h" |
37 #include "content/public/browser/render_process_host.h" | 34 #include "content/public/browser/render_process_host.h" |
38 #include "content/public/browser/render_view_host.h" | 35 #include "content/public/browser/render_view_host.h" |
39 #include "content/public/browser/web_contents.h" | 36 #include "content/public/browser/web_contents.h" |
40 #include "content/public/browser/web_ui.h" | 37 #include "content/public/browser/web_ui.h" |
41 #include "extensions/browser/file_reader.h" | 38 #include "extensions/browser/file_reader.h" |
42 #include "extensions/common/extension_resource.h" | 39 #include "extensions/common/extension_resource.h" |
43 #include "googleurl/src/gurl.h" | |
44 #include "grit/browser_resources.h" | 40 #include "grit/browser_resources.h" |
45 #include "grit/generated_resources.h" | 41 #include "grit/generated_resources.h" |
46 #include "ui/base/l10n/l10n_util.h" | 42 #include "ui/base/l10n/l10n_util.h" |
47 #include "ui/base/resource/resource_bundle.h" | 43 #include "ui/base/resource/resource_bundle.h" |
48 | 44 |
49 using content::RenderViewHost; | 45 using content::RenderViewHost; |
50 | 46 |
51 namespace chromeos { | 47 namespace chromeos { |
52 namespace accessibility { | 48 |
| 49 namespace { |
| 50 |
| 51 static chromeos::AccessibilityManager* g_accessibility_manager = NULL; |
53 | 52 |
54 // Helper class that directly loads an extension's content scripts into | 53 // Helper class that directly loads an extension's content scripts into |
55 // all of the frames corresponding to a given RenderViewHost. | 54 // all of the frames corresponding to a given RenderViewHost. |
56 class ContentScriptLoader { | 55 class ContentScriptLoader { |
57 public: | 56 public: |
58 // Initialize the ContentScriptLoader with the ID of the extension | 57 // Initialize the ContentScriptLoader with the ID of the extension |
59 // and the RenderViewHost where the scripts should be loaded. | 58 // and the RenderViewHost where the scripts should be loaded. |
60 ContentScriptLoader(const std::string& extension_id, | 59 ContentScriptLoader(const std::string& extension_id, |
61 int render_process_id, | 60 int render_process_id, |
62 int render_view_id) | 61 int render_view_id) |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
106 } | 105 } |
107 Run(); | 106 Run(); |
108 } | 107 } |
109 | 108 |
110 std::string extension_id_; | 109 std::string extension_id_; |
111 int render_process_id_; | 110 int render_process_id_; |
112 int render_view_id_; | 111 int render_view_id_; |
113 std::queue<extensions::ExtensionResource> resources_; | 112 std::queue<extensions::ExtensionResource> resources_; |
114 }; | 113 }; |
115 | 114 |
116 void UpdateChromeOSAccessibilityHistograms() { | 115 } // namespace |
117 UMA_HISTOGRAM_BOOLEAN("Accessibility.CrosSpokenFeedback", | 116 |
118 IsSpokenFeedbackEnabled()); | 117 /////////////////////////////////////////////////////////////////////////////// |
119 UMA_HISTOGRAM_BOOLEAN("Accessibility.CrosHighContrast", | 118 // AccessibilityStatusEventDetails |
120 IsHighContrastEnabled()); | 119 |
121 UMA_HISTOGRAM_BOOLEAN("Accessibility.CrosVirtualKeyboard", | 120 AccessibilityStatusEventDetails::AccessibilityStatusEventDetails( |
122 IsVirtualKeyboardEnabled()); | 121 bool enabled, |
123 if (MagnificationManager::Get()) { | 122 ash::AccessibilityNotificationVisibility notify) |
124 uint32 type = MagnificationManager::Get()->IsMagnifierEnabled() ? | 123 : enabled(enabled), |
125 MagnificationManager::Get()->GetMagnifierType() : 0; | 124 magnifier_type(ash::kDefaultMagnifierType), |
126 // '0' means magnifier is disabled. | 125 notify(notify) {} |
127 UMA_HISTOGRAM_ENUMERATION("Accessibility.CrosScreenMagnifier", | 126 |
128 type, | 127 AccessibilityStatusEventDetails::AccessibilityStatusEventDetails( |
129 ash::kMaxMagnifierType + 1); | 128 bool enabled, |
130 } | 129 ash::MagnifierType magnifier_type, |
| 130 ash::AccessibilityNotificationVisibility notify) |
| 131 : enabled(enabled), |
| 132 magnifier_type(magnifier_type), |
| 133 notify(notify) {} |
| 134 |
| 135 /////////////////////////////////////////////////////////////////////////////// |
| 136 // |
| 137 // AccessibilityManager |
| 138 |
| 139 // static |
| 140 void AccessibilityManager::Initialize() { |
| 141 CHECK(g_accessibility_manager == NULL); |
| 142 g_accessibility_manager = new AccessibilityManager(); |
131 } | 143 } |
132 | 144 |
133 void Initialize() { | 145 // static |
134 content::BrowserAccessibilityState::GetInstance()->AddHistogramCallback( | 146 void AccessibilityManager::Shutdown() { |
135 base::Bind(&UpdateChromeOSAccessibilityHistograms)); | 147 CHECK(g_accessibility_manager); |
| 148 delete g_accessibility_manager; |
| 149 g_accessibility_manager = NULL; |
136 } | 150 } |
137 | 151 |
138 void EnableSpokenFeedback(bool enabled, | 152 // static |
139 content::WebUI* login_web_ui, | 153 AccessibilityManager* AccessibilityManager::Get() { |
140 ash::AccessibilityNotificationVisibility notify) { | 154 return g_accessibility_manager; |
141 bool spoken_feedback_enabled = g_browser_process && | 155 } |
142 g_browser_process->local_state()->GetBoolean( | 156 |
143 prefs::kSpokenFeedbackEnabled); | 157 AccessibilityManager::AccessibilityManager() : profile_(NULL), |
144 if (spoken_feedback_enabled == enabled) { | 158 spoken_feedback_enabled_(false), |
| 159 high_contrast_enabled_(false) { |
| 160 notification_registrar_.Add(this, |
| 161 chrome::NOTIFICATION_SESSION_STARTED, |
| 162 content::NotificationService::AllSources()); |
| 163 notification_registrar_.Add(this, |
| 164 chrome::NOTIFICATION_PROFILE_CREATED, |
| 165 content::NotificationService::AllSources()); |
| 166 notification_registrar_.Add(this, |
| 167 chrome::NOTIFICATION_PROFILE_DESTROYED, |
| 168 content::NotificationService::AllSources()); |
| 169 notification_registrar_.Add(this, |
| 170 chrome::NOTIFICATION_LOGIN_WEBUI_VISIBLE, |
| 171 content::NotificationService::AllSources()); |
| 172 } |
| 173 |
| 174 AccessibilityManager::~AccessibilityManager() { |
| 175 CHECK(this == g_accessibility_manager); |
| 176 } |
| 177 |
| 178 void AccessibilityManager::EnableSpokenFeedback( |
| 179 bool enabled, |
| 180 content::WebUI* login_web_ui, |
| 181 ash::AccessibilityNotificationVisibility notify) { |
| 182 if (spoken_feedback_enabled_ == enabled) { |
145 DLOG(INFO) << "Spoken feedback is already " << | 183 DLOG(INFO) << "Spoken feedback is already " << |
146 (enabled ? "enabled" : "disabled") << ". Going to do nothing."; | 184 (enabled ? "enabled" : "disabled") << ". Going to do nothing."; |
147 return; | 185 return; |
148 } | 186 } |
149 | 187 |
150 g_browser_process->local_state()->SetBoolean( | 188 spoken_feedback_enabled_ = enabled; |
| 189 |
| 190 // Spoken feedback can't be enalbled without profile. |
| 191 if (!profile_) |
| 192 return; |
| 193 |
| 194 PrefService* pref_service = profile_->GetPrefs(); |
| 195 pref_service->SetBoolean( |
151 prefs::kSpokenFeedbackEnabled, enabled); | 196 prefs::kSpokenFeedbackEnabled, enabled); |
152 g_browser_process->local_state()->CommitPendingWrite(); | 197 pref_service->CommitPendingWrite(); |
153 ExtensionAccessibilityEventRouter::GetInstance()-> | 198 ExtensionAccessibilityEventRouter::GetInstance()-> |
154 SetAccessibilityEnabled(enabled); | 199 SetAccessibilityEnabled(enabled); |
155 | 200 |
156 AccessibilityStatusEventDetails details(enabled, notify); | 201 AccessibilityStatusEventDetails details(enabled, notify); |
157 content::NotificationService::current()->Notify( | 202 content::NotificationService::current()->Notify( |
158 chrome::NOTIFICATION_CROS_ACCESSIBILITY_TOGGLE_SPOKEN_FEEDBACK, | 203 chrome::NOTIFICATION_CROS_ACCESSIBILITY_TOGGLE_SPOKEN_FEEDBACK, |
159 content::NotificationService::AllSources(), | 204 content::NotificationService::AllSources(), |
160 content::Details<AccessibilityStatusEventDetails>(&details)); | 205 content::Details<AccessibilityStatusEventDetails>(&details)); |
161 | 206 |
162 Speak(l10n_util::GetStringUTF8( | 207 Speak(l10n_util::GetStringUTF8( |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
212 loader->Run(); // It cleans itself up when done. | 257 loader->Run(); // It cleans itself up when done. |
213 } | 258 } |
214 | 259 |
215 DLOG(INFO) << "ChromeVox was Loaded."; | 260 DLOG(INFO) << "ChromeVox was Loaded."; |
216 } else { // Unload ChromeVox | 261 } else { // Unload ChromeVox |
217 extension_service->component_loader()->Remove(path); | 262 extension_service->component_loader()->Remove(path); |
218 DLOG(INFO) << "ChromeVox was Unloaded."; | 263 DLOG(INFO) << "ChromeVox was Unloaded."; |
219 } | 264 } |
220 } | 265 } |
221 | 266 |
222 void EnableHighContrast(bool enabled) { | 267 bool AccessibilityManager::IsSpokenFeedbackEnabled() { |
223 PrefService* pref_service = g_browser_process->local_state(); | 268 return spoken_feedback_enabled_; |
224 pref_service->SetBoolean(prefs::kHighContrastEnabled, enabled); | |
225 pref_service->CommitPendingWrite(); | |
226 | |
227 AccessibilityStatusEventDetails detail(enabled, ash::A11Y_NOTIFICATION_NONE); | |
228 content::NotificationService::current()->Notify( | |
229 chrome::NOTIFICATION_CROS_ACCESSIBILITY_TOGGLE_HIGH_CONTRAST_MODE, | |
230 content::NotificationService::AllSources(), | |
231 content::Details<AccessibilityStatusEventDetails>(&detail)); | |
232 | |
233 #if defined(USE_ASH) | |
234 ash::Shell::GetInstance()->high_contrast_controller()->SetEnabled(enabled); | |
235 #endif | |
236 } | 269 } |
237 | 270 |
238 void EnableVirtualKeyboard(bool enabled) { | 271 void AccessibilityManager::ToggleSpokenFeedback( |
239 PrefService* pref_service = g_browser_process->local_state(); | 272 content::WebUI* login_web_ui, |
240 pref_service->SetBoolean(prefs::kVirtualKeyboardEnabled, enabled); | 273 ash::AccessibilityNotificationVisibility notify) { |
241 pref_service->CommitPendingWrite(); | 274 bool spoken_feedback_enabled = IsSpokenFeedbackEnabled(); |
| 275 spoken_feedback_enabled = !spoken_feedback_enabled; |
| 276 EnableSpokenFeedback(spoken_feedback_enabled, login_web_ui, notify); |
242 } | 277 } |
243 | 278 |
244 void ToggleSpokenFeedback(content::WebUI* login_web_ui, | 279 void AccessibilityManager::Speak(const std::string& text) { |
245 ash::AccessibilityNotificationVisibility notify) { | |
246 bool spoken_feedback_enabled = g_browser_process && | |
247 g_browser_process->local_state()->GetBoolean( | |
248 prefs::kSpokenFeedbackEnabled); | |
249 spoken_feedback_enabled = !spoken_feedback_enabled; | |
250 EnableSpokenFeedback(spoken_feedback_enabled, login_web_ui, notify); | |
251 }; | |
252 | |
253 void Speak(const std::string& text) { | |
254 UtteranceContinuousParameters params; | 280 UtteranceContinuousParameters params; |
255 | 281 |
256 Profile* profile = ProfileManager::GetDefaultProfile(); | 282 Utterance* utterance = new Utterance(profile_); |
257 Utterance* utterance = new Utterance(profile); | |
258 utterance->set_text(text); | 283 utterance->set_text(text); |
259 utterance->set_lang(g_browser_process->GetApplicationLocale()); | 284 utterance->set_lang(g_browser_process->GetApplicationLocale()); |
260 utterance->set_continuous_parameters(params); | 285 utterance->set_continuous_parameters(params); |
261 utterance->set_can_enqueue(false); | 286 utterance->set_can_enqueue(false); |
262 utterance->set_options(new DictionaryValue()); | 287 utterance->set_options(new DictionaryValue()); |
263 | 288 |
264 TtsController* controller = TtsController::GetInstance(); | 289 TtsController* controller = TtsController::GetInstance(); |
265 controller->SpeakOrEnqueue(utterance); | 290 controller->SpeakOrEnqueue(utterance); |
266 } | 291 } |
267 | 292 |
268 bool IsSpokenFeedbackEnabled() { | 293 void AccessibilityManager::MaybeSpeak(const std::string& text) { |
269 if (!g_browser_process) { | 294 if (IsSpokenFeedbackEnabled()) |
270 return false; | 295 Speak(text); |
271 } | |
272 PrefService* prefs = g_browser_process->local_state(); | |
273 bool spoken_feedback_enabled = prefs && | |
274 prefs->GetBoolean(prefs::kSpokenFeedbackEnabled); | |
275 return spoken_feedback_enabled; | |
276 } | 296 } |
277 | 297 |
278 bool IsHighContrastEnabled() { | 298 void AccessibilityManager::EnableHighContrast(bool enabled) { |
279 if (!g_browser_process) { | 299 if (high_contrast_enabled_ == enabled) |
280 return false; | 300 return; |
| 301 |
| 302 high_contrast_enabled_ = enabled; |
| 303 |
| 304 if (profile_) { |
| 305 PrefService* pref_service = profile_->GetPrefs(); |
| 306 pref_service->SetBoolean(prefs::kHighContrastEnabled, enabled); |
| 307 pref_service->CommitPendingWrite(); |
281 } | 308 } |
282 PrefService* prefs = g_browser_process->local_state(); | 309 |
283 bool high_contrast_enabled = prefs && | 310 AccessibilityStatusEventDetails detail(enabled, ash::A11Y_NOTIFICATION_NONE); |
284 prefs->GetBoolean(prefs::kHighContrastEnabled); | 311 content::NotificationService::current()->Notify( |
285 return high_contrast_enabled; | 312 chrome::NOTIFICATION_CROS_ACCESSIBILITY_TOGGLE_HIGH_CONTRAST_MODE, |
| 313 content::NotificationService::AllSources(), |
| 314 content::Details<AccessibilityStatusEventDetails>(&detail)); |
| 315 |
| 316 #if defined(USE_ASH) |
| 317 ash::Shell::GetInstance()->high_contrast_controller()->SetEnabled(enabled); |
| 318 #endif |
286 } | 319 } |
287 | 320 |
288 bool IsVirtualKeyboardEnabled() { | 321 bool AccessibilityManager::IsHighContrastEnabled() { |
289 if (!g_browser_process) { | 322 return high_contrast_enabled_; |
290 return false; | |
291 } | |
292 PrefService* prefs = g_browser_process->local_state(); | |
293 bool virtual_keyboard_enabled = prefs && | |
294 prefs->GetBoolean(prefs::kVirtualKeyboardEnabled); | |
295 return virtual_keyboard_enabled; | |
296 } | 323 } |
297 | 324 |
298 void MaybeSpeak(const std::string& utterance) { | 325 void AccessibilityManager::UpdateSpokenFeedbackStatusFromPref() { |
299 if (IsSpokenFeedbackEnabled()) | 326 if (!profile_) |
300 Speak(utterance); | 327 return; |
| 328 |
| 329 PrefService* pref_service = profile_->GetPrefs(); |
| 330 bool spoken_feedback_enabled = |
| 331 pref_service->GetBoolean(prefs::kSpokenFeedbackEnabled); |
| 332 EnableSpokenFeedback( |
| 333 spoken_feedback_enabled, NULL, ash::A11Y_NOTIFICATION_NONE); |
301 } | 334 } |
302 | 335 |
303 void ShowAccessibilityHelp(Browser* browser) { | 336 void AccessibilityManager::UpdateHighContrastStatusFromPref() { |
304 chrome::ShowSingletonTab(browser, GURL(chrome::kChromeAccessibilityHelpURL)); | 337 if (!profile_) |
| 338 return; |
| 339 |
| 340 PrefService* pref_service = profile_->GetPrefs(); |
| 341 bool high_contrast_enabled = |
| 342 pref_service->GetBoolean(prefs::kHighContrastEnabled); |
| 343 EnableHighContrast(high_contrast_enabled); |
305 } | 344 } |
306 | 345 |
307 } // namespace accessibility | 346 void AccessibilityManager::SetProfile(Profile* profile) { |
| 347 pref_change_registrar_.reset(); |
| 348 |
| 349 if (profile) { |
| 350 pref_change_registrar_.reset(new PrefChangeRegistrar); |
| 351 pref_change_registrar_->Init(profile->GetPrefs()); |
| 352 pref_change_registrar_->Add( |
| 353 prefs::kSpokenFeedbackEnabled, |
| 354 base::Bind(&AccessibilityManager::UpdateSpokenFeedbackStatusFromPref, |
| 355 base::Unretained(this))); |
| 356 pref_change_registrar_->Add( |
| 357 prefs::kHighContrastEnabled, |
| 358 base::Bind(&AccessibilityManager::UpdateHighContrastStatusFromPref, |
| 359 base::Unretained(this))); |
| 360 |
| 361 content::BrowserAccessibilityState::GetInstance()->AddHistogramCallback( |
| 362 base::Bind( |
| 363 &AccessibilityManager::UpdateChromeOSAccessibilityHistograms, |
| 364 base::Unretained(this))); |
| 365 } |
| 366 |
| 367 profile_ = profile; |
| 368 UpdateSpokenFeedbackStatusFromPref(); |
| 369 UpdateHighContrastStatusFromPref(); |
| 370 } |
| 371 |
| 372 void AccessibilityManager::SetProfileForTest(Profile* profile) { |
| 373 SetProfile(profile); |
| 374 } |
| 375 |
| 376 void AccessibilityManager::UpdateChromeOSAccessibilityHistograms() { |
| 377 UMA_HISTOGRAM_BOOLEAN("Accessibility.CrosSpokenFeedback", |
| 378 IsSpokenFeedbackEnabled()); |
| 379 UMA_HISTOGRAM_BOOLEAN("Accessibility.CrosHighContrast", |
| 380 IsHighContrastEnabled()); |
| 381 UMA_HISTOGRAM_BOOLEAN("Accessibility.CrosVirtualKeyboard", |
| 382 accessibility::IsVirtualKeyboardEnabled()); |
| 383 if (MagnificationManager::Get()) { |
| 384 uint32 type = MagnificationManager::Get()->IsMagnifierEnabled() ? |
| 385 MagnificationManager::Get()->GetMagnifierType() : 0; |
| 386 // '0' means magnifier is disabled. |
| 387 UMA_HISTOGRAM_ENUMERATION("Accessibility.CrosScreenMagnifier", |
| 388 type, |
| 389 ash::kMaxMagnifierType + 1); |
| 390 } |
| 391 } |
| 392 |
| 393 void AccessibilityManager::Observe( |
| 394 int type, |
| 395 const content::NotificationSource& source, |
| 396 const content::NotificationDetails& details) { |
| 397 switch (type) { |
| 398 case chrome::NOTIFICATION_LOGIN_WEBUI_VISIBLE: |
| 399 case chrome::NOTIFICATION_SESSION_STARTED: { |
| 400 Profile* profile = ProfileManager::GetDefaultProfile(); |
| 401 if (!profile->IsGuestSession()) |
| 402 SetProfile(profile); |
| 403 break; |
| 404 } |
| 405 case chrome::NOTIFICATION_PROFILE_CREATED: { |
| 406 Profile* profile = content::Source<Profile>(source).ptr(); |
| 407 if (profile->IsGuestSession() && !profile->IsOffTheRecord()) |
| 408 SetProfile(profile); |
| 409 |
| 410 // On guest mode, 2 non-OTR profiles are created. We should use the |
| 411 // first one, not second one. |
| 412 notification_registrar_.Remove( |
| 413 this, |
| 414 chrome::NOTIFICATION_PROFILE_CREATED, |
| 415 content::NotificationService::AllSources()); |
| 416 break; |
| 417 } |
| 418 case chrome::NOTIFICATION_PROFILE_DESTROYED: { |
| 419 SetProfile(NULL); |
| 420 break; |
| 421 } |
| 422 } |
| 423 } |
| 424 |
308 } // namespace chromeos | 425 } // namespace chromeos |
OLD | NEW |