blob: fa4abc06e4b3f5bf410cffd1f0f2c152573421f1 [file] [log] [blame]
// Copyright 2019 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef COBALT_UPDATER_UPDATER_MODULE_H_
#define COBALT_UPDATER_UPDATER_MODULE_H_
#include <map>
#include <memory>
#include <string>
#include "base/memory/scoped_refptr.h"
#include "base/message_loop/message_loop.h"
#include "base/threading/thread.h"
#include "cobalt/extension/updater_notification.h"
#include "cobalt/network/network_module.h"
#include "cobalt/updater/configurator.h"
#include "components/prefs/pref_service.h"
#include "components/update_client/crx_update_item.h"
#include "components/update_client/update_client.h"
#include "starboard/event.h"
namespace cobalt {
namespace updater {
using update_client::ComponentState;
enum class UpdaterStatus {
kNewUpdate,
kChecking,
kUpdateAvailable,
kDownloadingDiff,
kDownloading,
kSlotLocked,
kDownloaded,
kUpdatingDiff,
kUpdating,
kUpdated,
kUpToDate,
kUpdateError,
kUninstalled,
kRun
};
// Mapping a component state to an updater status.
const std::map<ComponentState, UpdaterStatus> component_to_updater_status_map =
{
{ComponentState::kNew, UpdaterStatus::kNewUpdate},
{ComponentState::kChecking, UpdaterStatus::kChecking},
{ComponentState::kCanUpdate, UpdaterStatus::kUpdateAvailable},
{ComponentState::kDownloadingDiff, UpdaterStatus::kDownloadingDiff},
{ComponentState::kDownloading, UpdaterStatus::kDownloading},
{ComponentState::kDownloaded, UpdaterStatus::kDownloaded},
{ComponentState::kUpdatingDiff, UpdaterStatus::kUpdatingDiff},
{ComponentState::kUpdating, UpdaterStatus::kUpdating},
{ComponentState::kUpdated, UpdaterStatus::kUpdated},
{ComponentState::kUpToDate, UpdaterStatus::kUpToDate},
{ComponentState::kUpdateError, UpdaterStatus::kUpdateError},
{ComponentState::kUninstalled, UpdaterStatus::kUninstalled},
{ComponentState::kRun, UpdaterStatus::kRun},
};
// Translating an updater status to a status string.
const std::map<UpdaterStatus, const char*> updater_status_string_map = {
{UpdaterStatus::kNewUpdate, "Will check for update soon"},
{UpdaterStatus::kChecking, "Checking for update"},
{UpdaterStatus::kUpdateAvailable, "Update is available"},
{UpdaterStatus::kDownloadingDiff, "Downloading delta update"},
{UpdaterStatus::kDownloading, "Downloading update"},
{UpdaterStatus::kSlotLocked, "Slot is locked"},
{UpdaterStatus::kDownloaded, "Update is downloaded"},
{UpdaterStatus::kUpdatingDiff, "Installing delta update"},
{UpdaterStatus::kUpdating, "Installing update"},
{UpdaterStatus::kUpdated, "Update installed, pending restart"},
{UpdaterStatus::kUpToDate, "App is up to date"},
{UpdaterStatus::kUpdateError, "Failed to update"},
{UpdaterStatus::kUninstalled, "Update uninstalled"},
{UpdaterStatus::kRun, "Transitioning..."},
};
// An interface that observes the updater. It provides notifications when the
// updater changes status.
class Observer : public update_client::UpdateClient::Observer {
public:
Observer(scoped_refptr<update_client::UpdateClient> update_client,
scoped_refptr<Configurator> updater_configurator)
: update_client_(update_client),
updater_configurator_(updater_configurator) {
const CobaltExtensionUpdaterNotificationApi* updater_notification_ext =
static_cast<const CobaltExtensionUpdaterNotificationApi*>(
SbSystemGetExtension(kCobaltExtensionUpdaterNotificationName));
if (updater_notification_ext &&
strcmp(updater_notification_ext->name,
kCobaltExtensionUpdaterNotificationName) == 0 &&
updater_notification_ext->version >= 1) {
updater_notification_ext_ = updater_notification_ext;
} else {
updater_notification_ext_ = nullptr;
}
}
// Overrides for update_client::UpdateClient::Observer.
void OnEvent(Events event, const std::string& id) override;
private:
scoped_refptr<update_client::UpdateClient> update_client_;
scoped_refptr<Configurator> updater_configurator_;
update_client::CrxUpdateItem crx_update_item_;
const CobaltExtensionUpdaterNotificationApi* updater_notification_ext_;
DISALLOW_COPY_AND_ASSIGN(Observer);
};
// UpdaterModule checks for available Cobalt update and downloads the update
// that matches the underlying Starboard ABI (SABI) configuration. Then
// the update is unpacked to a dedicated location for installation. The update
// checks run according to a schedule defined by the Cobalt application.
class UpdaterModule {
public:
explicit UpdaterModule(network::NetworkModule* network_module);
~UpdaterModule();
void Suspend();
void Resume();
std::string GetUpdaterChannel() const;
void SetUpdaterChannel(const std::string& updater_channel);
void CompareAndSwapChannelChanged(int old_value, int new_value);
void RunUpdateCheck();
std::string GetUpdaterStatus() const;
void ResetInstallations();
int GetInstallationIndex() const;
private:
base::Thread updater_thread_;
scoped_refptr<update_client::UpdateClient> update_client_;
std::unique_ptr<Observer> updater_observer_;
network::NetworkModule* network_module_;
scoped_refptr<Configurator> updater_configurator_;
int update_check_count_ = 0;
bool is_updater_running_;
THREAD_CHECKER(thread_checker_);
int GetUpdateCheckCount() { return update_check_count_; }
void IncrementUpdateCheckCount() { update_check_count_++; }
void Initialize();
void Finalize();
void MarkSuccessful();
void Update();
};
} // namespace updater
} // namespace cobalt
#endif // COBALT_UPDATER_UPDATER_MODULE_H_