Skip to content

Commit

Permalink
Mitigate perf degradation cause by loading wallet-standard (Uplift of #…
Browse files Browse the repository at this point in the history
  • Loading branch information
darkdh committed Jan 28, 2023
1 parent eb24519 commit 2bfe41f
Show file tree
Hide file tree
Showing 15 changed files with 207 additions and 89 deletions.
25 changes: 18 additions & 7 deletions browser/brave_wallet/solana_provider_renderer_browsertest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,9 @@ std::string VectorToArrayString(const std::vector<uint8_t>& vec) {
std::string result;
for (size_t i = 0; i < vec.size(); ++i) {
base::StrAppend(&result, {base::NumberToString(vec[i])});
if (i != vec.size() - 1)
if (i != vec.size() - 1) {
base::StrAppend(&result, {", "});
}
}
return result;
}
Expand Down Expand Up @@ -305,10 +306,11 @@ class TestSolanaProvider final : public brave_wallet::mojom::SolanaProvider {
}
void Disconnect() override {
// Used to test onAccountChanged
if (emit_empty_account_changed_)
if (emit_empty_account_changed_) {
events_listener_->AccountChangedEvent(absl::nullopt);
else
} else {
events_listener_->AccountChangedEvent(kTestPublicKey);
}
}
void IsConnected(IsConnectedCallback callback) override {
if (error_ == SolanaProviderError::kSuccess) {
Expand All @@ -335,9 +337,10 @@ class TestSolanaProvider final : public brave_wallet::mojom::SolanaProvider {
void SignAllTransactions(
std::vector<brave_wallet::mojom::SolanaSignTransactionParamPtr> params,
SignAllTransactionsCallback callback) override {
for (const auto& param : params)
for (const auto& param : params) {
EXPECT_EQ(param->encoded_serialized_msg,
brave_wallet::Base58Encode(kSerializedMessage));
}
if (error_ == SolanaProviderError::kSuccess) {
std::move(callback).Run(SolanaProviderError::kSuccess, "",
{kSignedTx, kSignedTx});
Expand Down Expand Up @@ -400,6 +403,11 @@ class TestSolanaProvider final : public brave_wallet::mojom::SolanaProvider {
}
}

void IsSolanaKeyringCreated(
IsSolanaKeyringCreatedCallback callback) override {
std::move(callback).Run(true);
}

void SetError(SolanaProviderError error, const std::string& error_message) {
error_ = error;
error_message_ = error_message;
Expand Down Expand Up @@ -445,15 +453,17 @@ class TestBraveContentBrowserClient : public BraveContentBrowserClient {
}

TestSolanaProvider* GetProvider(content::RenderFrameHost* frame_host) {
if (!provider_map_.contains(frame_host))
if (!provider_map_.contains(frame_host)) {
return nullptr;
}
return static_cast<TestSolanaProvider*>(
provider_map_.at(frame_host)->impl());
}
bool WaitForBinding(content::RenderFrameHost* render_frame_host,
base::OnceClosure callback) {
if (IsBound(render_frame_host))
if (IsBound(render_frame_host)) {
return false;
}
quit_on_binding_ = std::move(callback);
return true;
}
Expand All @@ -471,8 +481,9 @@ class TestBraveContentBrowserClient : public BraveContentBrowserClient {
base::BindOnce(&TestBraveContentBrowserClient::OnDisconnect,
weak_ptr_factory_.GetWeakPtr(), frame_host));
provider_map_[frame_host] = provider;
if (quit_on_binding_)
if (quit_on_binding_) {
std::move(quit_on_binding_).Run();
}
}
void OnDisconnect(content::RenderFrameHost* frame_host) {
provider_map_.erase(frame_host);
Expand Down
7 changes: 7 additions & 0 deletions components/brave_wallet/browser/solana_provider_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -600,6 +600,13 @@ void SolanaProviderImpl::Request(base::Value::Dict arg,
}
}

void SolanaProviderImpl::IsSolanaKeyringCreated(
IsSolanaKeyringCreatedCallback callback) {
DCHECK(keyring_service_);
std::move(callback).Run(
!!keyring_service_->GetSelectedAccount(mojom::CoinType::SOL));
}

bool SolanaProviderImpl::IsAccountConnected(const std::string& account) {
return delegate_->IsSolanaAccountConnected(account);
}
Expand Down
2 changes: 2 additions & 0 deletions components/brave_wallet/browser/solana_provider_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ class SolanaProviderImpl final : public mojom::SolanaProvider,
SignMessageCallback callback) override;
void Request(base::Value::Dict arg, RequestCallback callback) override;

void IsSolanaKeyringCreated(IsSolanaKeyringCreatedCallback callback) override;

private:
FRIEND_TEST_ALL_PREFIXES(SolanaProviderImplUnitTest, GetDeserializedMessage);

Expand Down
3 changes: 3 additions & 0 deletions components/brave_wallet/common/brave_wallet.mojom
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,9 @@ interface SolanaProvider {
=> (SolanaProviderError error, string error_message,
mojo_base.mojom.DictionaryValue result);

// DO NOT USE: This is supposed to be a temporary solution for us to decide
// whether to load wallet-standard js module
IsSolanaKeyringCreated() => (bool created);
};

// Used by the WebUI page to bootstrap bidirectional communication.
Expand Down
62 changes: 38 additions & 24 deletions components/brave_wallet/renderer/js_ethereum_provider.cc
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,6 @@

namespace {

static base::NoDestructor<std::string> g_provider_script("");

constexpr char kEthereum[] = "ethereum";
constexpr char kEmit[] = "emit";
constexpr char kIsBraveWallet[] = "isBraveWallet";
Expand Down Expand Up @@ -74,8 +72,9 @@ void JSEthereumProvider::SendResponse(
bool force_json_response,
base::Value formed_response,
bool success) {
if (!render_frame())
if (!render_frame()) {
return;
}
v8::HandleScope handle_scope(isolate);
v8::MicrotasksScope microtasks(isolate,
v8::MicrotasksScope::kDoNotRunMicrotasks);
Expand Down Expand Up @@ -112,10 +111,6 @@ void JSEthereumProvider::SendResponse(

JSEthereumProvider::JSEthereumProvider(content::RenderFrame* render_frame)
: RenderFrameObserver(render_frame) {
if (g_provider_script->empty()) {
*g_provider_script = LoadDataResource(
IDR_BRAVE_WALLET_SCRIPT_ETHEREUM_PROVIDER_SCRIPT_BUNDLE_JS);
}
EnsureConnected();
}

Expand All @@ -125,22 +120,25 @@ gin::WrapperInfo JSEthereumProvider::kWrapperInfo = {gin::kEmbedderNativeGin};

void JSEthereumProvider::WillReleaseScriptContext(v8::Local<v8::Context>,
int32_t world_id) {
if (world_id != content::ISOLATED_WORLD_ID_GLOBAL)
if (world_id != content::ISOLATED_WORLD_ID_GLOBAL) {
return;
}
// Close mojo connection from browser to renderer.
receiver_.reset();
script_context_released_ = true;
}

void JSEthereumProvider::DidDispatchDOMContentLoadedEvent() {
if (script_context_released_)
if (script_context_released_) {
return;
}
ConnectEvent();
}

bool JSEthereumProvider::EnsureConnected() {
if (!render_frame())
if (!render_frame()) {
return false;
}

if (!ethereum_provider_.is_bound()) {
render_frame()->GetBrowserInterfaceBroker()->GetInterface(
Expand All @@ -160,22 +158,25 @@ void JSEthereumProvider::Install(bool allow_overwrite_window_ethereum_provider,
v8::HandleScope handle_scope(isolate);
v8::Local<v8::Context> context =
render_frame->GetWebFrame()->MainWorldScriptContext();
if (context.IsEmpty())
if (context.IsEmpty()) {
return;
}
v8::Context::Scope context_scope(context);

// Check window.ethereum existence.
v8::Local<v8::Object> global = context->Global();
v8::Local<v8::Value> ethereum_value =
global->Get(context, gin::StringToV8(isolate, kEthereum))
.ToLocalChecked();
if (!ethereum_value->IsUndefined())
if (!ethereum_value->IsUndefined()) {
return;
}

gin::Handle<JSEthereumProvider> provider =
gin::CreateHandle(isolate, new JSEthereumProvider(render_frame));
if (provider.IsEmpty())
if (provider.IsEmpty()) {
return;
}
v8::Local<v8::Value> provider_value = provider.ToV8();

if (!allow_overwrite_window_ethereum_provider) {
Expand Down Expand Up @@ -226,7 +227,10 @@ void JSEthereumProvider::Install(bool allow_overwrite_window_ethereum_provider,
gin::StringToV8(isolate, kIsUnlocked), false);

blink::WebLocalFrame* web_frame = render_frame->GetWebFrame();
ExecuteScript(web_frame, *g_provider_script, kEthereumProviderScript);
ExecuteScript(web_frame,
LoadDataResource(
IDR_BRAVE_WALLET_SCRIPT_ETHEREUM_PROVIDER_SCRIPT_BUNDLE_JS),
kEthereumProviderScript);
}

bool JSEthereumProvider::GetIsBraveWallet() {
Expand Down Expand Up @@ -260,8 +264,9 @@ v8::Local<v8::Value> JSEthereumProvider::GetSelectedAddress(
v8::Isolate* isolate) {
// Note this does not return the selected account, but it returns the first
// connected account that was given permissions.
if (first_allowed_account_.empty())
if (first_allowed_account_.empty()) {
return v8::Undefined(isolate);
}
return gin::StringToV8(isolate, first_allowed_account_);
}

Expand Down Expand Up @@ -296,8 +301,9 @@ const char* JSEthereumProvider::GetTypeName() {
// 3) ethereum.send(payload: JsonRpcRequest): unknown;
// Only valid for: eth_accounts, eth_coinbase, eth_uninstallFilter, etc.
v8::Local<v8::Promise> JSEthereumProvider::SendMethod(gin::Arguments* args) {
if (!EnsureConnected())
if (!EnsureConnected()) {
return v8::Local<v8::Promise>();
}
v8::Isolate* isolate = args->isolate();
if (args->Length() == 0) {
args->ThrowError();
Expand Down Expand Up @@ -363,8 +369,9 @@ v8::Local<v8::Promise> JSEthereumProvider::SendMethod(gin::Arguments* args) {
params = base::Value::ToUniquePtrValue(base::ListValue());
}

if (!EnsureConnected())
if (!EnsureConnected()) {
return v8::Local<v8::Promise>();
}

v8::MaybeLocal<v8::Promise::Resolver> resolver =
v8::Promise::Resolver::New(isolate->GetCurrentContext());
Expand All @@ -387,8 +394,9 @@ v8::Local<v8::Promise> JSEthereumProvider::SendMethod(gin::Arguments* args) {
}

void JSEthereumProvider::SendAsync(gin::Arguments* args) {
if (!EnsureConnected())
if (!EnsureConnected()) {
return;
}
v8::Isolate* isolate = args->isolate();
v8::Local<v8::Value> input;
v8::Local<v8::Function> callback;
Expand Down Expand Up @@ -420,14 +428,16 @@ bool JSEthereumProvider::IsConnected() {

v8::Local<v8::Promise> JSEthereumProvider::Request(v8::Isolate* isolate,
v8::Local<v8::Value> input) {
if (!input->IsObject())
if (!input->IsObject()) {
return v8::Local<v8::Promise>();
}
std::unique_ptr<base::Value> input_value =
content::V8ValueConverter::Create()->FromV8Value(
input, isolate->GetCurrentContext());

if (!EnsureConnected())
if (!EnsureConnected()) {
return v8::Local<v8::Promise>();
}

v8::MaybeLocal<v8::Promise::Resolver> resolver =
v8::Promise::Resolver::New(isolate->GetCurrentContext());
Expand Down Expand Up @@ -469,8 +479,9 @@ void JSEthereumProvider::OnRequestOrSendAsync(
}

v8::Local<v8::Promise> JSEthereumProvider::Enable(v8::Isolate* isolate) {
if (!EnsureConnected())
if (!EnsureConnected()) {
return v8::Local<v8::Promise>();
}

v8::MaybeLocal<v8::Promise::Resolver> resolver =
v8::Promise::Resolver::New(isolate->GetCurrentContext());
Expand All @@ -493,8 +504,9 @@ v8::Local<v8::Promise> JSEthereumProvider::Enable(v8::Isolate* isolate) {
}

v8::Local<v8::Promise> JSEthereumProvider::IsUnlocked(v8::Isolate* isolate) {
if (!EnsureConnected())
if (!EnsureConnected()) {
return v8::Local<v8::Promise>();
}

v8::MaybeLocal<v8::Promise::Resolver> resolver =
v8::Promise::Resolver::New(isolate->GetCurrentContext());
Expand Down Expand Up @@ -537,8 +549,9 @@ void JSEthereumProvider::FireEvent(const std::string& event,
}

void JSEthereumProvider::ConnectEvent() {
if (!EnsureConnected())
if (!EnsureConnected()) {
return;
}

ethereum_provider_->GetChainId(base::BindOnce(
&JSEthereumProvider::OnGetChainId, weak_ptr_factory_.GetWeakPtr()));
Expand All @@ -557,8 +570,9 @@ void JSEthereumProvider::DisconnectEvent(const std::string& message) {
}

void JSEthereumProvider::ChainChangedEvent(const std::string& chain_id) {
if (chain_id_ == chain_id)
if (chain_id_ == chain_id) {
return;
}

FireEvent(ethereum::kChainChangedEvent, base::Value(chain_id));
chain_id_ = chain_id;
Expand Down
Loading

0 comments on commit 2bfe41f

Please sign in to comment.