1 // Copyright 2020 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/updater/app/app_server.h"
6 
7 #include <memory>
8 
9 #include "base/bind.h"
10 #include "base/logging.h"
11 #include "base/memory/scoped_refptr.h"
12 #include "base/version.h"
13 #include "chrome/updater/configurator.h"
14 #include "chrome/updater/constants.h"
15 #include "chrome/updater/control_service.h"
16 #include "chrome/updater/control_service_impl.h"
17 #include "chrome/updater/control_service_impl_inactive.h"
18 #include "chrome/updater/persisted_data.h"
19 #include "chrome/updater/prefs.h"
20 #include "chrome/updater/update_service.h"
21 #include "chrome/updater/update_service_impl.h"
22 #include "chrome/updater/update_service_impl_inactive.h"
23 #include "chrome/updater/updater_version.h"
24 #include "components/prefs/pref_service.h"
25 
26 namespace updater {
27 
28 AppServer::AppServer() = default;
29 
30 AppServer::~AppServer() = default;
31 
Initialize()32 void AppServer::Initialize() {
33   first_task_ = ModeCheck();
34 }
35 
ModeCheck()36 base::OnceClosure AppServer::ModeCheck() {
37   std::unique_ptr<GlobalPrefs> global_prefs = CreateGlobalPrefs();
38   if (!global_prefs) {
39     return base::BindOnce(&AppServer::Shutdown, this,
40                           kErrorFailedToLockPrefsMutex);
41   }
42 
43   const base::Version this_version(UPDATER_VERSION_STRING);
44   const base::Version active_version(global_prefs->GetActiveVersion());
45 
46   VLOG(2) << "This version: " << this_version.GetString()
47           << ", active version: " << active_version.GetString();
48 
49   if (this_version < active_version) {
50     global_prefs = nullptr;
51     uninstall_ = true;
52     return base::BindOnce(&AppServer::ActiveDuty, this,
53                           MakeInactiveUpdateService(),
54                           MakeInactiveControlService());
55   }
56 
57   if (active_version != base::Version("0") && active_version != this_version) {
58     std::unique_ptr<LocalPrefs> local_prefs = CreateLocalPrefs();
59     if (!local_prefs->GetQualified()) {
60       global_prefs = nullptr;
61       return base::BindOnce(&AppServer::Qualify, this, std::move(local_prefs));
62     }
63   }
64 
65   if (this_version > active_version || global_prefs->GetSwapping()) {
66     if (!SwapVersions(global_prefs.get()))
67       return base::BindOnce(&AppServer::Shutdown, this, kErrorFailedToSwap);
68   }
69 
70   config_ = base::MakeRefCounted<Configurator>(std::move(global_prefs));
71   return base::BindOnce(&AppServer::ActiveDuty, this,
72                         base::MakeRefCounted<UpdateServiceImpl>(config_),
73                         base::MakeRefCounted<ControlServiceImpl>(config_));
74 }
75 
Uninitialize()76 void AppServer::Uninitialize() {
77   if (config_)
78     PrefsCommitPendingWrites(config_->GetPrefService());
79   if (uninstall_) {
80     VLOG(1) << "Uninstalling version " << UPDATER_VERSION_STRING;
81     UninstallSelf();
82   }
83 }
84 
FirstTaskRun()85 void AppServer::FirstTaskRun() {
86   std::move(first_task_).Run();
87 }
88 
Qualify(std::unique_ptr<LocalPrefs> local_prefs)89 void AppServer::Qualify(std::unique_ptr<LocalPrefs> local_prefs) {
90   // For now, assume qualification succeeds.
91   DVLOG(2) << __func__;
92   local_prefs->SetQualified(true);
93   PrefsCommitPendingWrites(local_prefs->GetPrefService());
94 
95   // Start ActiveDuty with inactive service implementations. To use active
96   // implementations, the server would have to ModeCheck again.
97   ActiveDuty(MakeInactiveUpdateService(), MakeInactiveControlService());
98 }
99 
SwapVersions(GlobalPrefs * global_prefs)100 bool AppServer::SwapVersions(GlobalPrefs* global_prefs) {
101   global_prefs->SetSwapping(true);
102   PrefsCommitPendingWrites(global_prefs->GetPrefService());
103   bool result = SwapRPCInterfaces();
104   if (!result)
105     return false;
106   global_prefs->SetActiveVersion(UPDATER_VERSION_STRING);
107   scoped_refptr<PersistedData> persisted_data =
108       base::MakeRefCounted<PersistedData>(global_prefs->GetPrefService());
109   if (!persisted_data->GetProductVersion(kUpdaterAppId).IsValid()) {
110     persisted_data->SetProductVersion(kUpdaterAppId,
111                                       base::Version(UPDATER_VERSION_STRING));
112   }
113   global_prefs->SetSwapping(false);
114   PrefsCommitPendingWrites(global_prefs->GetPrefService());
115   return true;
116 }
117 
118 }  // namespace updater
119