1// Copyright 2013 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/extensions/api/screenlock_private/screenlock_private_api.h"
6
7#include "base/lazy_instance.h"
8#include "base/values.h"
9#include "chrome/browser/profiles/profile.h"
10#include "chrome/browser/signin/easy_unlock_service.h"
11#include "chrome/common/extensions/api/screenlock_private.h"
12#include "chrome/common/extensions/extension_constants.h"
13#include "extensions/browser/app_window/app_window_registry.h"
14#include "extensions/browser/event_router.h"
15
16namespace screenlock = extensions::api::screenlock_private;
17
18namespace extensions {
19
20namespace {
21
22screenlock::AuthType FromLockHandlerAuthType(
23    ScreenlockBridge::LockHandler::AuthType auth_type) {
24  switch (auth_type) {
25    case ScreenlockBridge::LockHandler::OFFLINE_PASSWORD:
26      return screenlock::AUTH_TYPE_OFFLINEPASSWORD;
27    case ScreenlockBridge::LockHandler::NUMERIC_PIN:
28      return screenlock::AUTH_TYPE_NUMERICPIN;
29    case ScreenlockBridge::LockHandler::USER_CLICK:
30      return screenlock::AUTH_TYPE_USERCLICK;
31    case ScreenlockBridge::LockHandler::ONLINE_SIGN_IN:
32      // Apps should treat forced online sign in same as system password.
33      return screenlock::AUTH_TYPE_OFFLINEPASSWORD;
34    case ScreenlockBridge::LockHandler::EXPAND_THEN_USER_CLICK:
35      // This type is used for public sessions, which do not support screen
36      // locking.
37      NOTREACHED();
38      return screenlock::AUTH_TYPE_NONE;
39    case ScreenlockBridge::LockHandler::FORCE_OFFLINE_PASSWORD:
40      return screenlock::AUTH_TYPE_OFFLINEPASSWORD;
41  }
42  NOTREACHED();
43  return screenlock::AUTH_TYPE_OFFLINEPASSWORD;
44}
45
46}  // namespace
47
48ScreenlockPrivateGetLockedFunction::ScreenlockPrivateGetLockedFunction() {}
49
50ScreenlockPrivateGetLockedFunction::~ScreenlockPrivateGetLockedFunction() {}
51
52bool ScreenlockPrivateGetLockedFunction::RunAsync() {
53  SetResult(new base::FundamentalValue(ScreenlockBridge::Get()->IsLocked()));
54  SendResponse(error_.empty());
55  return true;
56}
57
58ScreenlockPrivateSetLockedFunction::ScreenlockPrivateSetLockedFunction() {}
59
60ScreenlockPrivateSetLockedFunction::~ScreenlockPrivateSetLockedFunction() {}
61
62bool ScreenlockPrivateSetLockedFunction::RunAsync() {
63  scoped_ptr<screenlock::SetLocked::Params> params(
64      screenlock::SetLocked::Params::Create(*args_));
65  EXTENSION_FUNCTION_VALIDATE(params.get());
66  if (params->locked) {
67    if (extension()->id() == extension_misc::kEasyUnlockAppId &&
68        AppWindowRegistry::Get(browser_context())
69            ->GetAppWindowForAppAndKey(extension()->id(),
70                                       "easy_unlock_pairing")) {
71      // Mark the Easy Unlock behaviour on the lock screen as the one initiated
72      // by the Easy Unlock setup app as a trial one.
73      // TODO(tbarzic): Move this logic to a new easyUnlockPrivate function.
74      EasyUnlockService* service = EasyUnlockService::Get(GetProfile());
75      if (service)
76        service->SetTrialRun();
77    }
78    ScreenlockBridge::Get()->Lock(GetProfile());
79  } else {
80    ScreenlockBridge::Get()->Unlock(GetProfile());
81  }
82  SendResponse(error_.empty());
83  return true;
84}
85
86ScreenlockPrivateAcceptAuthAttemptFunction::
87    ScreenlockPrivateAcceptAuthAttemptFunction() {}
88
89ScreenlockPrivateAcceptAuthAttemptFunction::
90    ~ScreenlockPrivateAcceptAuthAttemptFunction() {}
91
92bool ScreenlockPrivateAcceptAuthAttemptFunction::RunSync() {
93  scoped_ptr<screenlock::AcceptAuthAttempt::Params> params(
94      screenlock::AcceptAuthAttempt::Params::Create(*args_));
95  EXTENSION_FUNCTION_VALIDATE(params.get());
96
97  Profile* profile = Profile::FromBrowserContext(browser_context());
98  EasyUnlockService* service = EasyUnlockService::Get(profile);
99  if (service)
100    service->FinalizeUnlock(params->accept);
101  return true;
102}
103
104ScreenlockPrivateEventRouter::ScreenlockPrivateEventRouter(
105    content::BrowserContext* context)
106    : browser_context_(context) {
107  ScreenlockBridge::Get()->AddObserver(this);
108}
109
110ScreenlockPrivateEventRouter::~ScreenlockPrivateEventRouter() {}
111
112void ScreenlockPrivateEventRouter::OnScreenDidLock() {
113  DispatchEvent(screenlock::OnChanged::kEventName,
114      new base::FundamentalValue(true));
115}
116
117void ScreenlockPrivateEventRouter::OnScreenDidUnlock() {
118  DispatchEvent(screenlock::OnChanged::kEventName,
119      new base::FundamentalValue(false));
120}
121
122void ScreenlockPrivateEventRouter::OnFocusedUserChanged(
123    const std::string& user_id) {
124}
125
126void ScreenlockPrivateEventRouter::DispatchEvent(
127    const std::string& event_name,
128    base::Value* arg) {
129  scoped_ptr<base::ListValue> args(new base::ListValue());
130  if (arg)
131    args->Append(arg);
132  scoped_ptr<extensions::Event> event(new extensions::Event(
133      event_name, args.Pass()));
134  extensions::EventRouter::Get(browser_context_)->BroadcastEvent(event.Pass());
135}
136
137static base::LazyInstance<extensions::BrowserContextKeyedAPIFactory<
138    ScreenlockPrivateEventRouter> > g_factory = LAZY_INSTANCE_INITIALIZER;
139
140// static
141extensions::BrowserContextKeyedAPIFactory<ScreenlockPrivateEventRouter>*
142ScreenlockPrivateEventRouter::GetFactoryInstance() {
143  return g_factory.Pointer();
144}
145
146void ScreenlockPrivateEventRouter::Shutdown() {
147  ScreenlockBridge::Get()->RemoveObserver(this);
148}
149
150bool ScreenlockPrivateEventRouter::OnAuthAttempted(
151    ScreenlockBridge::LockHandler::AuthType auth_type,
152    const std::string& value) {
153  extensions::EventRouter* router =
154      extensions::EventRouter::Get(browser_context_);
155  if (!router->HasEventListener(screenlock::OnAuthAttempted::kEventName))
156    return false;
157
158  scoped_ptr<base::ListValue> args(new base::ListValue());
159  args->AppendString(screenlock::ToString(FromLockHandlerAuthType(auth_type)));
160  args->AppendString(value);
161
162  scoped_ptr<extensions::Event> event(new extensions::Event(
163      screenlock::OnAuthAttempted::kEventName, args.Pass()));
164  router->BroadcastEvent(event.Pass());
165  return true;
166}
167
168}  // namespace extensions
169