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.
5 #include "chrome/browser/automation/testing_automation_provider.h"
7 #include "ash/new_window_delegate.h"
9 #include "ash/system/tray/system_tray_delegate.h"
10 #include "base/command_line.h"
11 #include "base/i18n/time_formatting.h"
12 #include "base/prefs/pref_service.h"
13 #include "base/strings/stringprintf.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "base/time/time.h"
16 #include "chrome/browser/automation/automation_provider_json.h"
17 #include "chrome/browser/automation/automation_provider_observers.h"
18 #include "chrome/browser/automation/automation_util.h"
19 #include "chrome/browser/browser_process.h"
20 #include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
21 #include "chrome/browser/chromeos/accessibility/accessibility_util.h"
22 #include "chrome/browser/chromeos/login/default_user_images.h"
23 #include "chrome/browser/chromeos/login/enrollment/enrollment_screen.h"
24 #include "chrome/browser/chromeos/login/existing_user_controller.h"
25 #include "chrome/browser/chromeos/login/login_display.h"
26 #include "chrome/browser/chromeos/login/login_display_host_impl.h"
27 #include "chrome/browser/chromeos/login/screen_locker.h"
28 #include "chrome/browser/chromeos/login/screens/eula_screen.h"
29 #include "chrome/browser/chromeos/login/screens/network_screen.h"
30 #include "chrome/browser/chromeos/login/screens/update_screen.h"
31 #include "chrome/browser/chromeos/login/screens/user_image_screen.h"
32 #include "chrome/browser/chromeos/login/startup_utils.h"
33 #include "chrome/browser/chromeos/login/webui_login_display.h"
34 #include "chrome/browser/chromeos/login/wizard_controller.h"
35 #include "chrome/browser/chromeos/net/proxy_config_handler.h"
36 #include "chrome/browser/chromeos/settings/cros_settings.h"
37 #include "chrome/browser/prefs/proxy_config_dictionary.h"
38 #include "chrome/browser/ui/browser.h"
39 #include "chrome/browser/ui/browser_window.h"
40 #include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h"
41 #include "chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h"
42 #include "chrome/common/pref_names.h"
43 #include "chromeos/audio/cras_audio_handler.h"
44 #include "chromeos/dbus/dbus_thread_manager.h"
45 #include "chromeos/dbus/session_manager_client.h"
46 #include "chromeos/dbus/update_engine_client.h"
47 #include "chromeos/settings/cros_settings_names.h"
48 #include "chromeos/settings/timezone_settings.h"
49 #include "content/public/browser/web_contents.h"
50 #include "policy/policy_constants.h"
51 #include "ui/views/widget/widget.h"
53 using chromeos::DBusThreadManager
;
54 using chromeos::ExistingUserController
;
55 using chromeos::UpdateEngineClient
;
57 using chromeos::UserManager
;
58 using chromeos::WizardController
;
62 void UpdateCheckCallback(AutomationJSONReply
* reply
,
63 UpdateEngineClient::UpdateCheckResult result
) {
64 if (result
== UpdateEngineClient::UPDATE_RESULT_SUCCESS
)
65 reply
->SendSuccess(NULL
);
67 reply
->SendError("update check failed");
73 #if defined(OS_CHROMEOS)
74 void TestingAutomationProvider::PowerChanged(
75 const power_manager::PowerSupplyProperties
& proto
) {
76 power_supply_properties_
= proto
;
80 void TestingAutomationProvider::AcceptOOBENetworkScreen(
81 base::DictionaryValue
* args
,
82 IPC::Message
* reply_message
) {
83 WizardController
* wizard_controller
= WizardController::default_controller();
84 if (!wizard_controller
|| wizard_controller
->current_screen()->GetName() !=
85 WizardController::kNetworkScreenName
) {
86 AutomationJSONReply(this, reply_message
).SendError(
87 "Network screen not active.");
90 // Observer will delete itself.
91 new WizardControllerObserver(wizard_controller
, this, reply_message
);
92 wizard_controller
->GetNetworkScreen()->OnContinuePressed();
95 void TestingAutomationProvider::AcceptOOBEEula(base::DictionaryValue
* args
,
96 IPC::Message
* reply_message
) {
98 bool usage_stats_reporting
;
99 if (!args
->GetBoolean("accepted", &accepted
) ||
100 !args
->GetBoolean("usage_stats_reporting", &usage_stats_reporting
)) {
101 AutomationJSONReply(this, reply_message
).SendError(
102 "Invalid or missing args.");
106 WizardController
* wizard_controller
= WizardController::default_controller();
107 if (!wizard_controller
|| wizard_controller
->current_screen()->GetName() !=
108 WizardController::kEulaScreenName
) {
109 AutomationJSONReply(this, reply_message
).SendError(
110 "EULA screen not active.");
113 // Observer will delete itself.
114 new WizardControllerObserver(wizard_controller
, this, reply_message
);
115 wizard_controller
->GetEulaScreen()->OnExit(accepted
, usage_stats_reporting
);
118 void TestingAutomationProvider::CancelOOBEUpdate(base::DictionaryValue
* args
,
119 IPC::Message
* reply_message
) {
120 if (chromeos::StartupUtils::IsOobeCompleted()) {
121 // Update already finished.
122 scoped_ptr
<base::DictionaryValue
> return_value(new base::DictionaryValue
);
123 return_value
->SetString("next_screen",
124 WizardController::kLoginScreenName
);
125 AutomationJSONReply(this, reply_message
).SendSuccess(return_value
.get());
128 WizardController
* wizard_controller
= WizardController::default_controller();
129 if (!wizard_controller
|| wizard_controller
->current_screen()->GetName() !=
130 WizardController::kUpdateScreenName
) {
131 AutomationJSONReply(this, reply_message
).SendError(
132 "Update screen not active.");
135 // Observer will delete itself.
136 new WizardControllerObserver(wizard_controller
, this, reply_message
);
137 wizard_controller
->GetUpdateScreen()->CancelUpdate();
140 void TestingAutomationProvider::GetLoginInfo(base::DictionaryValue
* args
,
141 IPC::Message
* reply_message
) {
142 AutomationJSONReply
reply(this, reply_message
);
143 scoped_ptr
<base::DictionaryValue
> return_value(new base::DictionaryValue
);
145 const UserManager
* user_manager
= UserManager::Get();
147 reply
.SendError("No user manager!");
148 const chromeos::ScreenLocker
* screen_locker
=
149 chromeos::ScreenLocker::default_screen_locker();
151 return_value
->SetString("login_ui_type", "webui");
152 return_value
->SetBoolean("is_owner", user_manager
->IsCurrentUserOwner());
153 return_value
->SetBoolean("is_logged_in", user_manager
->IsUserLoggedIn());
154 return_value
->SetBoolean("is_screen_locked", screen_locker
);
155 if (user_manager
->IsUserLoggedIn()) {
156 const User
* user
= user_manager
->GetLoggedInUser();
157 return_value
->SetBoolean("is_guest", user_manager
->IsLoggedInAsGuest());
158 return_value
->SetString("email", user
->email());
159 return_value
->SetString("display_email", user
->display_email());
160 switch (user
->image_index()) {
161 case User::kExternalImageIndex
:
162 return_value
->SetString("user_image", "file");
165 case User::kProfileImageIndex
:
166 return_value
->SetString("user_image", "profile");
170 return_value
->SetInteger("user_image", user
->image_index());
175 reply
.SendSuccess(return_value
.get());
178 // See the note under LoginAsGuest(). CreateAccount() causes a login as guest.
179 void TestingAutomationProvider::ShowCreateAccountUI(
180 base::DictionaryValue
* args
, IPC::Message
* reply_message
) {
181 ExistingUserController
* controller
=
182 ExistingUserController::current_controller();
183 // Return immediately, since we're going to die before the login is finished.
184 AutomationJSONReply(this, reply_message
).SendSuccess(NULL
);
185 controller
->CreateAccount();
188 // Logging in as guest will cause session_manager to restart Chrome with new
189 // flags. If you used EnableChromeTesting, you will have to call it again.
190 void TestingAutomationProvider::LoginAsGuest(base::DictionaryValue
* args
,
191 IPC::Message
* reply_message
) {
192 ExistingUserController
* controller
=
193 ExistingUserController::current_controller();
194 // Return immediately, since we're going to die before the login is finished.
195 AutomationJSONReply(this, reply_message
).SendSuccess(NULL
);
196 controller
->LoginAsGuest();
199 void TestingAutomationProvider::SubmitLoginForm(base::DictionaryValue
* args
,
200 IPC::Message
* reply_message
) {
201 AutomationJSONReply
reply(this, reply_message
);
203 std::string username
, password
;
204 if (!args
->GetString("username", &username
) ||
205 !args
->GetString("password", &password
)) {
206 reply
.SendError("Invalid or missing args.");
210 chromeos::ExistingUserController
* controller
=
211 chromeos::ExistingUserController::current_controller();
213 reply
.SendError("Unable to access ExistingUserController");
218 chromeos::WebUILoginDisplay
* webui_login_display
=
219 static_cast<chromeos::WebUILoginDisplay
*>(controller
->login_display());
220 VLOG(2) << "TestingAutomationProvider::SubmitLoginForm "
221 << "ShowSigninScreenForCreds(" << username
<< ", " << password
<< ")";
223 webui_login_display
->ShowSigninScreenForCreds(username
, password
);
224 reply
.SendSuccess(NULL
);
227 void TestingAutomationProvider::AddLoginEventObserver(
228 base::DictionaryValue
* args
, IPC::Message
* reply_message
) {
229 ExistingUserController
* controller
=
230 ExistingUserController::current_controller();
231 AutomationJSONReply
reply(this, reply_message
);
233 // This may happen due to SkipToLogin not being called.
234 reply
.SendError("Unable to access ExistingUserController");
238 if (!automation_event_queue_
.get())
239 automation_event_queue_
.reset(new AutomationEventQueue
);
241 int observer_id
= automation_event_queue_
->AddObserver(
242 new LoginEventObserver(automation_event_queue_
.get(), this));
244 // Return the observer's id.
245 base::DictionaryValue return_value
;
246 return_value
.SetInteger("observer_id", observer_id
);
247 reply
.SendSuccess(&return_value
);
250 void TestingAutomationProvider::SignOut(base::DictionaryValue
* args
,
251 IPC::Message
* reply_message
) {
252 ash::Shell::GetInstance()->system_tray_delegate()->SignOut();
253 // Sign out has the side effect of restarting the session_manager
254 // and chrome, thereby severing the automation channel, so it's
255 // not really necessary to send a reply back. The next line is
256 // for consistency with other methods.
257 AutomationJSONReply(this, reply_message
).SendSuccess(NULL
);
260 void TestingAutomationProvider::PickUserImage(base::DictionaryValue
* args
,
261 IPC::Message
* reply_message
) {
262 std::string image_type
;
263 int image_number
= -1;
264 if (!args
->GetString("image", &image_type
)
265 && !args
->GetInteger("image", &image_number
)) {
266 AutomationJSONReply(this, reply_message
).SendError(
267 "Invalid or missing args.");
270 WizardController
* wizard_controller
= WizardController::default_controller();
271 if (!wizard_controller
|| wizard_controller
->current_screen()->GetName() !=
272 WizardController::kUserImageScreenName
) {
273 AutomationJSONReply(this, reply_message
).SendError(
274 "User image screen not active.");
277 chromeos::UserImageScreen
* image_screen
=
278 wizard_controller
->GetUserImageScreen();
279 // Observer will delete itself unless error is returned.
280 WizardControllerObserver
* observer
=
281 new WizardControllerObserver(wizard_controller
, this, reply_message
);
282 if (image_type
== "profile") {
283 image_screen
->OnImageSelected("", image_type
, true);
284 image_screen
->OnImageAccepted();
285 } else if (image_type
.empty() && image_number
>= 0 &&
286 image_number
< chromeos::kDefaultImagesCount
) {
287 image_screen
->OnImageSelected(
288 chromeos::GetDefaultImageUrl(image_number
), image_type
, true);
289 image_screen
->OnImageAccepted();
291 AutomationJSONReply(this, reply_message
).SendError(
292 "Invalid or missing args.");
298 void TestingAutomationProvider::SkipToLogin(base::DictionaryValue
* args
,
299 IPC::Message
* reply_message
) {
300 bool skip_post_login_screens
;
301 // The argument name is a legacy. If set to |true|, this argument causes any
302 // screens that may otherwise be shown after login (registration, Terms of
303 // Service, user image selection) to be skipped.
304 if (!args
->GetBoolean("skip_image_selection", &skip_post_login_screens
)) {
305 AutomationJSONReply
reply(this, reply_message
);
306 reply
.SendError("Invalid or missing args.");
309 if (skip_post_login_screens
)
310 WizardController::SkipPostLoginScreensForTesting();
312 WizardController
* wizard_controller
= WizardController::default_controller();
313 if (!wizard_controller
) {
314 AutomationJSONReply
reply(this, reply_message
);
315 if (ExistingUserController::current_controller()) {
316 // Already at login screen.
317 scoped_ptr
<base::DictionaryValue
> return_value(new base::DictionaryValue
);
318 return_value
->SetString("next_screen",
319 WizardController::kLoginScreenName
);
320 reply
.SendSuccess(return_value
.get());
322 reply
.SendError("OOBE not active.");
327 // Observer will delete itself.
328 WizardControllerObserver
* observer
=
329 new WizardControllerObserver(wizard_controller
, this, reply_message
);
330 observer
->set_screen_to_wait_for(WizardController::kLoginScreenName
);
331 wizard_controller
->SkipToLoginForTesting(chromeos::LoginScreenContext());
334 void TestingAutomationProvider::GetOOBEScreenInfo(base::DictionaryValue
* args
,
335 IPC::Message
* reply_message
) {
336 static const char kScreenNameKey
[] = "screen_name";
337 AutomationJSONReply
reply(this, reply_message
);
338 scoped_ptr
<base::DictionaryValue
> return_value(new base::DictionaryValue
);
340 WizardController
* wizard_controller
= WizardController::default_controller();
341 if (wizard_controller
) {
342 if (wizard_controller
->login_screen_started()) {
343 return_value
->SetString(kScreenNameKey
,
344 WizardController::kLoginScreenName
);
346 return_value
->SetString(kScreenNameKey
,
347 wizard_controller
->current_screen()->GetName());
349 } else if (ExistingUserController::current_controller()) {
350 return_value
->SetString(kScreenNameKey
, WizardController::kLoginScreenName
);
352 // Already logged in.
353 reply
.SendSuccess(NULL
);
356 reply
.SendSuccess(return_value
.get());
359 void TestingAutomationProvider::LockScreen(base::DictionaryValue
* args
,
360 IPC::Message
* reply_message
) {
361 new ScreenLockUnlockObserver(this, reply_message
, true);
362 DBusThreadManager::Get()->GetSessionManagerClient()->RequestLockScreen();
365 void TestingAutomationProvider::UnlockScreen(base::DictionaryValue
* args
,
366 IPC::Message
* reply_message
) {
367 std::string password
;
368 if (!args
->GetString("password", &password
)) {
369 AutomationJSONReply(this, reply_message
).SendError(
370 "Invalid or missing args.");
374 chromeos::ScreenLocker
* screen_locker
=
375 chromeos::ScreenLocker::default_screen_locker();
376 if (!screen_locker
) {
377 AutomationJSONReply(this, reply_message
).SendError(
378 "No default screen locker. Are you sure the screen is locked?");
382 new ScreenUnlockObserver(this, reply_message
);
383 screen_locker
->AuthenticateByPassword(password
);
386 // Signing out could have undesirable side effects: session_manager is
387 // killed, so its children, including chrome and the window manager, will
388 // also be killed. Anything owned by chronos will probably be killed.
389 void TestingAutomationProvider::SignoutInScreenLocker(
390 base::DictionaryValue
* args
, IPC::Message
* reply_message
) {
391 AutomationJSONReply
reply(this, reply_message
);
392 chromeos::ScreenLocker
* screen_locker
=
393 chromeos::ScreenLocker::default_screen_locker();
394 if (!screen_locker
) {
396 "No default screen locker. Are you sure the screen is locked?");
400 // Send success before stopping session because if we're a child of
401 // session manager then we'll die when the session is stopped.
402 reply
.SendSuccess(NULL
);
403 screen_locker
->Signout();
406 void TestingAutomationProvider::GetBatteryInfo(base::DictionaryValue
* args
,
407 IPC::Message
* reply_message
) {
408 scoped_ptr
<base::DictionaryValue
> return_value(new base::DictionaryValue
);
410 const bool battery_is_present
= power_supply_properties_
.battery_state() !=
411 power_manager::PowerSupplyProperties_BatteryState_NOT_PRESENT
;
412 const bool line_power_on
= power_supply_properties_
.external_power() !=
413 power_manager::PowerSupplyProperties_ExternalPower_DISCONNECTED
;
415 return_value
->SetBoolean("battery_is_present", battery_is_present
);
416 return_value
->SetBoolean("line_power_on", line_power_on
);
418 if (battery_is_present
) {
419 const bool battery_is_full
= power_supply_properties_
.battery_state() ==
420 power_manager::PowerSupplyProperties_BatteryState_FULL
;
421 return_value
->SetBoolean("battery_fully_charged", battery_is_full
);
422 return_value
->SetDouble("battery_percentage",
423 power_supply_properties_
.battery_percent());
425 int64 time
= power_supply_properties_
.battery_time_to_full_sec();
426 if (time
> 0 || battery_is_full
)
427 return_value
->SetInteger("battery_seconds_to_full", time
);
429 int64 time
= power_supply_properties_
.battery_time_to_empty_sec();
431 return_value
->SetInteger("battery_seconds_to_empty", time
);
435 AutomationJSONReply(this, reply_message
).SendSuccess(return_value
.get());
438 void TestingAutomationProvider::ExecuteJavascriptInOOBEWebUI(
439 base::DictionaryValue
* args
, IPC::Message
* reply_message
) {
440 std::string javascript
, frame_xpath
;
441 if (!args
->GetString("javascript", &javascript
)) {
442 AutomationJSONReply(this, reply_message
)
443 .SendError("'javascript' missing or invalid");
446 if (!args
->GetString("frame_xpath", &frame_xpath
)) {
447 AutomationJSONReply(this, reply_message
)
448 .SendError("'frame_xpath' missing or invalid");
451 const UserManager
* user_manager
= UserManager::Get();
453 AutomationJSONReply(this, reply_message
).SendError(
457 if (user_manager
->IsUserLoggedIn()) {
458 AutomationJSONReply(this, reply_message
).SendError(
459 "User is already logged in.");
462 ExistingUserController
* controller
=
463 ExistingUserController::current_controller();
465 AutomationJSONReply(this, reply_message
).SendError(
466 "Unable to access ExistingUserController");
469 chromeos::LoginDisplayHostImpl
* webui_host
=
470 static_cast<chromeos::LoginDisplayHostImpl
*>(
471 controller
->login_display_host());
472 content::WebContents
* web_contents
=
473 webui_host
->GetOobeUI()->web_ui()->GetWebContents();
475 new DomOperationMessageSender(this, reply_message
, true);
476 ExecuteJavascriptInRenderViewFrame(base::ASCIIToUTF16(frame_xpath
),
477 base::ASCIIToUTF16(javascript
),
479 web_contents
->GetRenderViewHost());
482 void TestingAutomationProvider::EnableSpokenFeedback(
483 base::DictionaryValue
* args
, IPC::Message
* reply_message
) {
484 AutomationJSONReply
reply(this, reply_message
);
485 scoped_ptr
<base::DictionaryValue
> return_value(new base::DictionaryValue
);
487 if (!args
->GetBoolean("enabled", &enabled
)) {
488 reply
.SendError("Invalid or missing args.");
491 chromeos::AccessibilityManager::Get()->EnableSpokenFeedback(
492 enabled
, ash::A11Y_NOTIFICATION_NONE
);
494 reply
.SendSuccess(return_value
.get());
497 void TestingAutomationProvider::IsSpokenFeedbackEnabled(
498 base::DictionaryValue
* args
, IPC::Message
* reply_message
) {
499 AutomationJSONReply
reply(this, reply_message
);
500 scoped_ptr
<base::DictionaryValue
> return_value(new base::DictionaryValue
);
501 return_value
->SetBoolean(
503 chromeos::AccessibilityManager::Get()->IsSpokenFeedbackEnabled());
504 reply
.SendSuccess(return_value
.get());
507 void TestingAutomationProvider::GetTimeInfo(Browser
* browser
,
508 base::DictionaryValue
* args
,
509 IPC::Message
* reply_message
) {
510 scoped_ptr
<base::DictionaryValue
> return_value(new base::DictionaryValue
);
511 base::Time
time(base::Time::Now());
512 bool use_24hour_clock
= browser
&& browser
->profile()->GetPrefs()->GetBoolean(
513 prefs::kUse24HourClock
);
514 base::HourClockType hour_clock_type
=
515 use_24hour_clock
? base::k24HourClock
: base::k12HourClock
;
516 base::string16 display_time
= base::TimeFormatTimeOfDayWithHourClockType(
517 time
, hour_clock_type
, base::kDropAmPm
);
518 base::string16 timezone
=
519 chromeos::system::TimezoneSettings::GetInstance()->GetCurrentTimezoneID();
520 return_value
->SetString("display_time", display_time
);
521 return_value
->SetString("display_date", base::TimeFormatFriendlyDate(time
));
522 return_value
->SetString("timezone", timezone
);
523 AutomationJSONReply(this, reply_message
).SendSuccess(return_value
.get());
526 void TestingAutomationProvider::GetTimeInfo(base::DictionaryValue
* args
,
527 IPC::Message
* reply_message
) {
528 GetTimeInfo(NULL
, args
, reply_message
);
531 void TestingAutomationProvider::SetTimezone(base::DictionaryValue
* args
,
532 IPC::Message
* reply_message
) {
533 AutomationJSONReply
reply(this, reply_message
);
534 std::string timezone_id
;
535 if (!args
->GetString("timezone", &timezone_id
)) {
536 reply
.SendError("Invalid or missing args.");
539 chromeos::CrosSettings
* settings
= chromeos::CrosSettings::Get();
540 settings
->SetString(chromeos::kSystemTimezone
, timezone_id
);
541 reply
.SendSuccess(NULL
);
544 void TestingAutomationProvider::UpdateCheck(
545 base::DictionaryValue
* args
,
546 IPC::Message
* reply_message
) {
547 AutomationJSONReply
* reply
= new AutomationJSONReply(this, reply_message
);
548 DBusThreadManager::Get()->GetUpdateEngineClient()
549 ->RequestUpdateCheck(base::Bind(UpdateCheckCallback
, reply
));
552 void TestingAutomationProvider::GetVolumeInfo(base::DictionaryValue
* args
,
553 IPC::Message
* reply_message
) {
554 AutomationJSONReply
reply(this, reply_message
);
555 scoped_ptr
<base::DictionaryValue
> return_value(new base::DictionaryValue
);
556 chromeos::CrasAudioHandler
* audio_handler
= chromeos::CrasAudioHandler::Get();
557 if (!audio_handler
) {
558 reply
.SendError("CrasAudioHandler not initialized.");
561 return_value
->SetDouble("volume", audio_handler
->GetOutputVolumePercent());
562 return_value
->SetBoolean("is_mute", audio_handler
->IsOutputMuted());
563 reply
.SendSuccess(return_value
.get());
566 void TestingAutomationProvider::SetVolume(base::DictionaryValue
* args
,
567 IPC::Message
* reply_message
) {
568 AutomationJSONReply
reply(this, reply_message
);
569 double volume_percent
;
570 if (!args
->GetDouble("volume", &volume_percent
)) {
571 reply
.SendError("Invalid or missing args.");
574 chromeos::CrasAudioHandler
* audio_handler
= chromeos::CrasAudioHandler::Get();
575 if (!audio_handler
) {
576 reply
.SendError("CrasAudioHandler not initialized.");
579 audio_handler
->SetOutputVolumePercent(volume_percent
);
580 reply
.SendSuccess(NULL
);
583 void TestingAutomationProvider::SetMute(base::DictionaryValue
* args
,
584 IPC::Message
* reply_message
) {
585 AutomationJSONReply
reply(this, reply_message
);
587 if (!args
->GetBoolean("mute", &mute
)) {
588 reply
.SendError("Invalid or missing args.");
591 chromeos::CrasAudioHandler
* audio_handler
= chromeos::CrasAudioHandler::Get();
592 if (!audio_handler
) {
593 reply
.SendError("CrasAudioHandler not initialized.");
596 audio_handler
->SetOutputMute(mute
);
597 reply
.SendSuccess(NULL
);
600 void TestingAutomationProvider::OpenCrosh(base::DictionaryValue
* args
,
601 IPC::Message
* reply_message
) {
602 new NavigationNotificationObserver(
603 NULL
, this, reply_message
, 1, false, true);
604 ash::Shell::GetInstance()->new_window_delegate()->OpenCrosh();
607 void TestingAutomationProvider::AddChromeosObservers() {
608 chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->
612 void TestingAutomationProvider::RemoveChromeosObservers() {
613 chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->
614 RemoveObserver(this);