1 // Copyright 2019 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/window_throttle_observer_base.h"
6
7 #include "ash/public/cpp/shell_window_ids.h"
8 #include "components/exo/wm_helper.h"
9 #include "ui/aura/window.h"
10 #include "ui/wm/public/activation_change_observer.h"
11
12 namespace chromeos {
13 namespace {
14
15 // Returns true if the window is in the app list window container.
IsAppListWindow(const aura::Window * window)16 bool IsAppListWindow(const aura::Window* window) {
17 if (!window)
18 return false;
19
20 const aura::Window* parent = window->parent();
21 return parent &&
22 parent->id() == ash::ShellWindowId::kShellWindowId_AppListContainer;
23 }
24
25 // Returns true if this window activation should be ignored (app list
26 // opening/closing), or false if it should be processed.
ShouldIgnoreWindowActivation(wm::ActivationChangeObserver::ActivationReason reason,aura::Window * gained_active,aura::Window * lost_active)27 bool ShouldIgnoreWindowActivation(
28 wm::ActivationChangeObserver::ActivationReason reason,
29 aura::Window* gained_active,
30 aura::Window* lost_active) {
31 // The current active window defines whether the instance should be
32 // throttled or not i.e. if it's a native window then throttle Android, if
33 // it's an Android window then unthrottle it.
34 //
35 // However, the app list needs to be handled differently. The app list is
36 // deemed as an temporary overlay over the user's main window for browsing
37 // through or selecting an app. Consequently, if the app list is brought
38 // over a Chrome window then IsAppListWindow(gained_active) is true and this
39 // event is ignored. The instance continues to be throttled. Once the app
40 // list is closed then IsAppListWindow(lost_active) is true and the instance
41 // continues to be throttled. Similarly, if the app list is brought over an
42 // Android window, the instance continues to be unthrottled.
43 //
44 // On launching an app from the app list on Chrome OS the following events
45 // happen -
46 //
47 // - When an Android app icon is clicked the instance is unthrottled. This
48 // logic resides in |LaunchAppWithIntent| in
49 // src/chrome/browser/ui/app_list/arc/arc_app_utils.cc.
50 //
51 // - Between the time the app opens there is a narrow slice of time where
52 // this callback is triggered with |lost_active| equal to the app list
53 // window and the gained active possibly a native window. Without the check
54 // below the instance will be throttled again, further delaying the app
55 // launch. If the app was a native one then the instance was throttled
56 // anyway.
57 if (IsAppListWindow(lost_active) || IsAppListWindow(gained_active))
58 return true;
59 return false;
60 }
61
62 } // namespace
63
WindowThrottleObserverBase(ThrottleObserver::PriorityLevel level,std::string name)64 WindowThrottleObserverBase::WindowThrottleObserverBase(
65 ThrottleObserver::PriorityLevel level,
66 std::string name)
67 : ThrottleObserver(level, name) {}
68
StartObserving(content::BrowserContext * context,const ObserverStateChangedCallback & callback)69 void WindowThrottleObserverBase::StartObserving(
70 content::BrowserContext* context,
71 const ObserverStateChangedCallback& callback) {
72 ThrottleObserver::StartObserving(context, callback);
73 if (!exo::WMHelper::HasInstance()) // for unit testing
74 return;
75 exo::WMHelper::GetInstance()->AddActivationObserver(this);
76 }
77
StopObserving()78 void WindowThrottleObserverBase::StopObserving() {
79 ThrottleObserver::StopObserving();
80 if (!exo::WMHelper::HasInstance())
81 return;
82 exo::WMHelper::GetInstance()->RemoveActivationObserver(this);
83 }
84
OnWindowActivated(ActivationReason reason,aura::Window * gained_active,aura::Window * lost_active)85 void WindowThrottleObserverBase::OnWindowActivated(ActivationReason reason,
86 aura::Window* gained_active,
87 aura::Window* lost_active) {
88 if (ShouldIgnoreWindowActivation(reason, gained_active, lost_active))
89 return;
90 SetActive(ProcessWindowActivation(reason, gained_active, lost_active));
91 }
92
93 } // namespace chromeos
94