1 // Copyright 2016 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/chromeos/app_mode/arc/arc_kiosk_app_launcher.h>
6
7 #include <memory>
8 #include <string>
9
10 #include "chrome/browser/ui/app_list/arc/arc_app_utils.h"
11 #include "chromeos/ui/base/window_pin_type.h"
12 #include "chromeos/ui/base/window_properties.h"
13 #include "components/arc/arc_util.h"
14 #include "components/arc/metrics/arc_metrics_constants.h"
15 #include "ui/aura/env.h"
16 #include "ui/base/ui_base_features.h"
17 #include "ui/events/event_constants.h"
18
19 namespace chromeos {
20
ArcKioskAppLauncher(content::BrowserContext * context,ArcAppListPrefs * prefs,const std::string & app_id,Delegate * delegate)21 ArcKioskAppLauncher::ArcKioskAppLauncher(content::BrowserContext* context,
22 ArcAppListPrefs* prefs,
23 const std::string& app_id,
24 Delegate* delegate)
25 : app_id_(app_id), prefs_(prefs), delegate_(delegate) {
26 prefs_->AddObserver(this);
27 aura::Env::GetInstance()->AddObserver(this);
28 // Launching the app by app id in landscape mode and in non-touch mode.
29 arc::LaunchApp(context, app_id_, ui::EF_NONE,
30 arc::UserInteractionType::NOT_USER_INITIATED);
31 }
32
~ArcKioskAppLauncher()33 ArcKioskAppLauncher::~ArcKioskAppLauncher() {
34 StopObserving();
35 }
36
OnTaskCreated(int32_t task_id,const std::string & package_name,const std::string & activity,const std::string & intent)37 void ArcKioskAppLauncher::OnTaskCreated(int32_t task_id,
38 const std::string& package_name,
39 const std::string& activity,
40 const std::string& intent) {
41 std::unique_ptr<ArcAppListPrefs::AppInfo> app = prefs_->GetApp(app_id_);
42 if (!app || app->package_name != package_name || app->activity != activity)
43 return;
44 task_id_ = task_id;
45 // The app window may have been created already.
46 for (aura::Window* window : windows_) {
47 if (CheckAndPinWindow(window))
48 break;
49 }
50 }
51
OnWindowInitialized(aura::Window * window)52 void ArcKioskAppLauncher::OnWindowInitialized(aura::Window* window) {
53 // The |window|’s task ID is not set yet. We need to observe
54 // the window until the |kApplicationIdKey| property is set.
55 window->AddObserver(this);
56 windows_.insert(window);
57 }
58
OnWindowPropertyChanged(aura::Window * window,const void * key,intptr_t old)59 void ArcKioskAppLauncher::OnWindowPropertyChanged(aura::Window* window,
60 const void* key,
61 intptr_t old) {
62 // If we do not know yet what task ID to look for, do nothing.
63 // Existing windows will be revisited the moment the task ID
64 // becomes known.
65 if (task_id_ == -1)
66 return;
67
68 // We are only interested in changes to |kApplicationIdKey|,
69 // but that constant is not accessible outside shell_surface.cc.
70 // So we react to all property changes.
71 CheckAndPinWindow(window);
72 }
73
OnWindowDestroying(aura::Window * window)74 void ArcKioskAppLauncher::OnWindowDestroying(aura::Window* window) {
75 window->RemoveObserver(this);
76 windows_.erase(window);
77 }
78
CheckAndPinWindow(aura::Window * const window)79 bool ArcKioskAppLauncher::CheckAndPinWindow(aura::Window* const window) {
80 DCHECK_GE(task_id_, 0);
81 if (arc::GetWindowTaskId(window) != task_id_)
82 return false;
83 // Stop observing as target window is already found.
84 StopObserving();
85 window->SetProperty(chromeos::kWindowPinTypeKey,
86 chromeos::WindowPinType::kTrustedPinned);
87 if (delegate_)
88 delegate_->OnAppWindowLaunched();
89 return true;
90 }
91
StopObserving()92 void ArcKioskAppLauncher::StopObserving() {
93 aura::Env::GetInstance()->RemoveObserver(this);
94 for (auto* window : windows_)
95 window->RemoveObserver(this);
96 windows_.clear();
97 prefs_->RemoveObserver(this);
98 }
99
100 } // namespace chromeos
101