Skip to content

Commit

Permalink
Fix failing component auto-updates (#7164)
Browse files Browse the repository at this point in the history
* Fix broken automatic Component updates

* Reformat code

* Reorder includes to conform to style guide

* Make SequentialUpdateChecker constructor private

* Fix compilation failure

* Add comment
  • Loading branch information
mherrmann authored Jan 7, 2021
1 parent 8c4a6c9 commit 968c5c5
Show file tree
Hide file tree
Showing 4 changed files with 239 additions and 0 deletions.
103 changes: 103 additions & 0 deletions chromium_src/components/update_client/update_checker.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
/* Copyright (c) 2020 The Brave Authors. All rights reserved.
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "../../../../components/update_client/update_checker.cc"

namespace update_client {

SequentialUpdateChecker::SequentialUpdateChecker(
scoped_refptr<Configurator> config,
PersistedData* metadata)
: config_(config), metadata_(metadata) {
VLOG(3) << "SequentialUpdateChecker";
}

SequentialUpdateChecker::~SequentialUpdateChecker() {
VLOG(3) << "> ~SequentialUpdateChecker";
DCHECK(thread_checker_.CalledOnValidThread());
VLOG(3) << "< ~SequentialUpdateChecker";
}

void SequentialUpdateChecker::CheckForUpdates(
const std::string& session_id,
const std::vector<std::string>& ids_checked,
const IdToComponentPtrMap& components,
const base::flat_map<std::string, std::string>& additional_attributes,
bool enabled_component_updates,
UpdateCheckCallback update_check_callback) {
VLOG(3) << "> CheckForUpdates";

DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(!ids_checked.empty());

for (const auto& app_id : ids_checked) {
VLOG(3) << "> * " << app_id;
remaining_ids_.push_back(app_id);
}

session_id_ = session_id;
components_ = &components;
additional_attributes_ = additional_attributes;
enabled_component_updates_ = enabled_component_updates;
update_check_callback_ = std::move(update_check_callback);

CheckNext();

VLOG(3) << "< CheckForUpdates";
}

void SequentialUpdateChecker::CheckNext() {
VLOG(3) << "> CheckNext()";
DCHECK(!remaining_ids_.empty());
std::string id = remaining_ids_.front();
remaining_ids_.pop_front();
std::vector<std::string> id_vector = {id};

update_checker_ = UpdateChecker::Create(config_, metadata_);
update_checker_->CheckForUpdates(
session_id_, id_vector, *components_, additional_attributes_,
enabled_component_updates_,
base::BindOnce(&SequentialUpdateChecker::UpdateResultAvailable,
base::Unretained(this)));
VLOG(3) << "< CheckNext()";
}

void SequentialUpdateChecker::UpdateResultAvailable(
const base::Optional<ProtocolParser::Results>& results,
ErrorCategory error_category,
int error,
int retry_after_sec) {
VLOG(3) << "< UpdateResultAvailable(" << error << ")";
DCHECK(thread_checker_.CalledOnValidThread());

if (!error) {
DCHECK(results);
for (const auto& result : results->list)
results_.list.push_back(result);
}

bool done = error || remaining_ids_.empty();

if (done)
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::BindOnce(
std::move(update_check_callback_),
error ? base::nullopt
: base::make_optional<ProtocolParser::Results>(results_),
error_category, error, retry_after_sec));
else
CheckNext();
VLOG(3) << "> UpdateResultAvailable(" << error << ")";
}

std::unique_ptr<UpdateChecker> SequentialUpdateChecker::Create(
scoped_refptr<Configurator> config,
PersistedData* persistent) {
VLOG(3) << "Create";
return std::make_unique<SequentialUpdateChecker>(config, persistent);
}

} // namespace update_client
95 changes: 95 additions & 0 deletions chromium_src/components/update_client/update_checker.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/* Copyright (c) 2020 The Brave Authors. All rights reserved.
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef BRAVE_CHROMIUM_SRC_COMPONENTS_UPDATE_CLIENT_UPDATE_CHECKER_H_
#define BRAVE_CHROMIUM_SRC_COMPONENTS_UPDATE_CLIENT_UPDATE_CHECKER_H_

#include "../../../../components/update_client/update_checker.h"

#include <deque>
#include <string>
#include <vector>

#include "base/containers/flat_map.h"
#include "base/memory/ref_counted.h"
#include "base/optional.h"
#include "base/threading/thread_checker.h"
#include "components/update_client/component.h"
#include "components/update_client/configurator.h"
#include "components/update_client/persisted_data.h"
#include "components/update_client/update_client_errors.h"

namespace update_client {

// SequentialUpdateChecker delegates to UpdateChecker to perform a separate
// update request for each component, instead of one request for all components.
// We do for the following reason:
// Google's ToS do not allow distributing all components. In particular, the
// Widevine plugin must be fetched from Google servers. Brave's update server
// for components handles this as follows: When an update for a Google
// component is requested, the server responds with a HTTP redirect to
// Google's server. The problem is that this only works for update requests
// for single components. But Chromium's default implementation sends a list of
// components in one request, which in Brave's case is a mix of Google and Brave
// components. To solve this, we overwrite Chromium's implementation to perform
// separate update requests instead.
class SequentialUpdateChecker : public UpdateChecker {
public:
static std::unique_ptr<UpdateChecker> Create(
scoped_refptr<Configurator> config,
PersistedData* persistent);

void CheckForUpdates(
const std::string& session_id,
const std::vector<std::string>& ids_checked,
const IdToComponentPtrMap& components,
const base::flat_map<std::string, std::string>& additional_attributes,
bool enabled_component_updates,
UpdateCheckCallback update_check_callback) override;

// Needs to be public so std::make_unique(...) works in Create(...).
SequentialUpdateChecker(scoped_refptr<Configurator> config,
PersistedData* metadata);
~SequentialUpdateChecker() override;

private:
void CheckNext();
void UpdateResultAvailable(
const base::Optional<ProtocolParser::Results>& results,
ErrorCategory error_category,
int error,
int retry_after_sec);

base::ThreadChecker thread_checker_;

const scoped_refptr<Configurator> config_;
PersistedData* metadata_ = nullptr;

// Store the parameters to CheckForUpdates(...), so we can pass them multiple
// times to the original UpdateChecker implementation.
std::string session_id_;
// Needs to be a pointer because the values in IdToComponentPtrMap are of
// type std::unique_ptr, which we can't copy. Furthermore, it is okay to keep
// this pointer because IdToComponentPtrMap resides in in UpdateContext, which
// outlives this class.
const IdToComponentPtrMap* components_;
base::flat_map<std::string, std::string> additional_attributes_;
bool enabled_component_updates_;
UpdateCheckCallback update_check_callback_;

std::deque<std::string> remaining_ids_;

// The currently running update_checker_. We keep a smart pointer to it to
// keep it alive while this particular sequential update check takes place.
std::unique_ptr<UpdateChecker> update_checker_;
// Aggregates results from all sequential update requests.
ProtocolParser::Results results_;

DISALLOW_COPY_AND_ASSIGN(SequentialUpdateChecker);
};

} // namespace update_client

#endif // BRAVE_CHROMIUM_SRC_COMPONENTS_UPDATE_CLIENT_UPDATE_CHECKER_H_
24 changes: 24 additions & 0 deletions chromium_src/components/update_client/update_client.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/* Copyright (c) 2020 The Brave Authors. All rights reserved.
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "components/update_client/update_client.h"

#define UpdateClientFactory UpdateClientFactory_ChromiumImpl
#include "../../../../components/update_client/update_client.cc"
#undef UpdateClientFactory

#include "base/logging.h"

namespace update_client {

scoped_refptr<UpdateClient> UpdateClientFactory(
scoped_refptr<Configurator> config) {
VLOG(3) << "Brave UpdateClientFactory called";
return base::MakeRefCounted<UpdateClientImpl>(
config, base::MakeRefCounted<PingManager>(config),
&SequentialUpdateChecker::Create);
}

} // namespace update_client
17 changes: 17 additions & 0 deletions chromium_src/components/update_client/update_client.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/* Copyright (c) 2020 The Brave Authors. All rights reserved.
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef BRAVE_CHROMIUM_SRC_COMPONENTS_UPDATE_CLIENT_UPDATE_CLIENT_H_
#define BRAVE_CHROMIUM_SRC_COMPONENTS_UPDATE_CLIENT_UPDATE_CLIENT_H_

#define UpdateClientFactory \
UpdateClientFactory_ChromiumImpl(scoped_refptr<Configurator> config); \
scoped_refptr<UpdateClient> UpdateClientFactory

#include "../../../../components/update_client/update_client.h"

#undef UpdateClientFactory

#endif // BRAVE_CHROMIUM_SRC_COMPONENTS_UPDATE_CLIENT_UPDATE_CLIENT_H_

0 comments on commit 968c5c5

Please sign in to comment.