1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
|
// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ash/arc/instance_throttle/arc_boot_phase_throttle_observer.h"
#include "base/logging.h"
#include "base/task/single_thread_task_runner.h"
#include "base/time/time.h"
#include "chrome/browser/ash/arc/arc_util.h"
#include "chrome/browser/ash/arc/session/arc_session_manager.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/sessions/session_restore.h"
#include "chromeos/ash/experiences/arc/session/arc_bridge_service.h"
#include "chromeos/ash/experiences/arc/session/arc_service_manager.h"
namespace arc {
namespace {
// Try to throttle ARC |kThrottleArcDelay| after app.mojom is connected.
constexpr base::TimeDelta kThrottleArcDelay = base::Seconds(10);
void RemoveMojoObservers(ArcBootPhaseThrottleObserver* observer) {
auto* arc_service_manager = arc::ArcServiceManager::Get();
if (!arc_service_manager)
return;
arc_service_manager->arc_bridge_service()->intent_helper()->RemoveObserver(
observer);
arc_service_manager->arc_bridge_service()->app()->RemoveObserver(observer);
}
} // namespace
ArcBootPhaseThrottleObserver::ArcBootPhaseThrottleObserver()
: ThrottleObserver(kArcBootPhaseThrottleObserverName) {}
ArcBootPhaseThrottleObserver::~ArcBootPhaseThrottleObserver() = default;
void ArcBootPhaseThrottleObserver::StartObserving(
content::BrowserContext* context,
const ObserverStateChangedCallback& callback) {
ThrottleObserver::StartObserving(context, callback);
auto* session_manager = ArcSessionManager::Get();
DCHECK(session_manager);
session_manager->AddObserver(this);
SessionRestore::AddObserver(this);
// If app() and/or intent_helper() are already connected to the instance in
// the guest, the OnConnectionReady() function is synchronously called before
// returning from AddObserver. For more details, see
// chromeos/ash/experiences/arc/session/connection_holder.h especially its
// AddObserver() function.
auto* arc_service_manager = arc::ArcServiceManager::Get();
// ArcServiceManager and objects owned by the manager are created very early
// in `ChromeBrowserMainPartsAsh::PreMainMessageLoopRun()` too.
DCHECK(arc_service_manager);
arc_service_manager->arc_bridge_service()->app()->AddObserver(this);
arc_service_manager->arc_bridge_service()->intent_helper()->AddObserver(this);
}
void ArcBootPhaseThrottleObserver::StopObserving() {
RemoveMojoObservers(this);
SessionRestore::RemoveObserver(this);
auto* session_manager = ArcSessionManager::Get();
DCHECK(session_manager);
session_manager->RemoveObserver(this);
ThrottleObserver::StopObserving();
}
void ArcBootPhaseThrottleObserver::OnArcStarted() {
arc_is_booting_ = true;
MaybeSetActive();
}
void ArcBootPhaseThrottleObserver::OnArcInitialStart() {
arc_is_booting_ = false;
MaybeSetActive();
}
void ArcBootPhaseThrottleObserver::OnArcSessionRestarting() {
arc_is_booting_ = true;
MaybeSetActive();
}
void ArcBootPhaseThrottleObserver::OnSessionRestoreStartedLoadingTabs() {
session_restore_loading_ = true;
MaybeSetActive();
}
void ArcBootPhaseThrottleObserver::OnSessionRestoreFinishedLoadingTabs() {
session_restore_loading_ = false;
MaybeSetActive();
}
void ArcBootPhaseThrottleObserver::OnConnectionReady() {
auto* arc_service_manager = arc::ArcServiceManager::Get();
const bool app_connected =
arc_service_manager &&
arc_service_manager->arc_bridge_service()->app()->IsConnected();
const bool intent_helper_connected =
arc_service_manager &&
arc_service_manager->arc_bridge_service()->intent_helper()->IsConnected();
if (!app_connected || !intent_helper_connected)
return;
// Only the first OnConnectionReady() calls need to be monitored. Remove the
// observers now.
RemoveMojoObservers(this);
DVLOG(1)
<< "app.mojom and intent_helper.mojom are connected. Throttle ARC in "
<< kThrottleArcDelay;
base::SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask(
FROM_HERE,
base::BindOnce(&ArcBootPhaseThrottleObserver::ThrottleArc,
weak_ptr_factory_.GetWeakPtr()),
kThrottleArcDelay);
}
// static
const base::TimeDelta&
ArcBootPhaseThrottleObserver::GetThrottleDelayForTesting() {
return kThrottleArcDelay;
}
void ArcBootPhaseThrottleObserver::ThrottleArc() {
DVLOG(1) << "Throttling ARC (reason: boot completed)";
arc_is_booting_ = false;
MaybeSetActive();
}
void ArcBootPhaseThrottleObserver::MaybeSetActive() {
if (!arc_is_booting_ || !*arc_is_booting_) {
// Skip other checks if ARC is not currently booting.
SetActive(false);
return;
}
auto* profile = Profile::FromBrowserContext(context());
const bool enabled_by_policy =
IsArcPlayStoreEnabledForProfile(profile) &&
IsArcPlayStoreEnabledPreferenceManagedForProfile(profile);
auto* session_manager = ArcSessionManager::Get();
DCHECK(session_manager);
const bool opt_in_boot =
!session_manager->skipped_terms_of_service_negotiation();
// ARC should be always be unthrottled during boot if ARC is enabled by
// managed policy, or if this is the opt-in boot. Else, only unthrottle ARC
// if a session restore is not currently taking place.
const bool always_unthrottle = enabled_by_policy || opt_in_boot;
const bool active = always_unthrottle || !session_restore_loading_;
SetActive(active);
}
} // namespace arc
|