blob: 294408e90227772abda4ceff78064018fab62de0 [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SRC_DEVELOPER_DEBUG_ZXDB_CLIENT_SYMBOL_SERVER_H_
#define SRC_DEVELOPER_DEBUG_ZXDB_CLIENT_SYMBOL_SERVER_H_
#include <functional>
#include <map>
#include <memory>
#include <string>
#include <vector>
#include "lib/fit/function.h"
#include "src/developer/debug/zxdb/client/client_object.h"
#include "src/developer/debug/zxdb/common/err.h"
#include "src/developer/debug/zxdb/symbols/debug_symbol_file_type.h"
namespace zxdb {
class SymbolServer : public ClientObject {
public:
// Callback used to receive the results of trying to fetch symbols. The string given is the path
// where the symbols were downloaded. If the string is empty the symbols were unavailable. The
// error is only set in the event of a connection error. If the symbols are simply unavailable the
// error will not be set.
using FetchCallback = fit::callback<void(const Err&, const std::string&)>;
enum class State {
kInitializing, // The server just gets created. It will become kBusy or kReady shortly.
kAuth, // The user's credentials have failed authentication.
kBusy, // The server is doing authentication.
kReady, // The authentication is done and the server is ready to use.
kUnreachable, // Too many failed downloads and the server is unusable.
};
static std::unique_ptr<SymbolServer> FromURL(Session* session, const std::string& url,
bool require_authentication);
const std::string& name() const { return name_; }
const std::vector<std::string>& error_log() const { return error_log_; }
State state() const { return state_; }
void set_state_change_callback(fit::callback<void(SymbolServer*, State)> cb) {
state_change_callback_ = std::move(cb);
}
// Attempt to download symbols for the given build ID.
virtual void Fetch(const std::string& build_id, DebugSymbolFileType file_type,
FetchCallback cb) = 0;
const std::string& access_token() const { return access_token_; }
void set_access_token(const std::string& access_token) { access_token_ = access_token; }
const std::string& refresh_token() const { return refresh_token_; }
void set_refresh_token(const std::string& refresh_token) { refresh_token_ = refresh_token; }
protected:
explicit SymbolServer(Session* session, const std::string& name)
: ClientObject(session), name_(name) {}
void ChangeState(State state);
void IncrementRetries();
// Initialize the class. We want the constructor to do this, but the test mock might need to be
// manipulated first, so we break this out into a separate function.
void DoInit();
// TODO(https://fxbug.dev/42140066): There are currently no use cases where different buckets have
// different authentication mechanisms (everything is either public, or uses gcloud
// application-default credentials). This function, and the helpers below, could be shared in the
// base class (maybe an object?) to authenticate new servers as they are initialized, rather than
// delegating to the implementations.
virtual void DoAuthenticate(const std::map<std::string, std::string>& data,
fit::callback<void(const Err&)> cb) = 0;
FILE* GetGoogleApiAuthCache(const char* mode);
// Load authentication from debugger's config file. Returns whether the loading
// succeeds.
bool LoadCachedAuth();
// Load authentication from gcloud config file. Returns whether the loading succeeds.
bool LoadGCloudAuth();
// Use the refresh token to get a new access token.
void AuthRefresh();
std::vector<std::string> error_log_;
size_t retries_ = 0;
// Incremented each time the state becomes ready.
size_t ready_count_ = 0;
private:
State state_ = State::kInitializing;
// URL as originally used to construct the class. This is mostly to be used to identify the server
// in the UI. The actual URL may be processed to handle custom protocol identifiers etc.
std::string name_;
std::string access_token_;
std::string refresh_token_;
// client_id_ and client_secret_ might be different from kClientId and kClientSecret
// if we're using gcloud's credential.
std::string client_id_;
std::string client_secret_;
fit::callback<void(SymbolServer*, State)> state_change_callback_;
};
} // namespace zxdb
#endif // SRC_DEVELOPER_DEBUG_ZXDB_CLIENT_SYMBOL_SERVER_H_