[Wallet] Properly cleanup js providers when no longer needed (#36816)
This commit is contained in:
@@ -12,6 +12,7 @@
|
||||
#include "brave/components/brave_wallet/renderer/resource_helper.h"
|
||||
#include "brave/components/brave_wallet/renderer/v8_helper.h"
|
||||
#include "components/grit/brave_components_resources.h"
|
||||
#include "content/public/common/isolated_world_ids.h"
|
||||
#include "gin/converter.h"
|
||||
#include "gin/object_template_builder.h"
|
||||
#include "third_party/blink/public/platform/browser_interface_broker_proxy.h"
|
||||
@@ -30,8 +31,25 @@ constexpr char kCardano[] = "cardano";
|
||||
constexpr char kBrave[] = "brave";
|
||||
} // namespace
|
||||
|
||||
// content::RenderFrameObserver
|
||||
void JSCardanoProvider::Cleanup() {
|
||||
// No longer need that provider object. Reset mojo connection, clean bound v8
|
||||
// references, stop tracking the render frame.
|
||||
|
||||
cardano_provider_.reset();
|
||||
weak_ptr_factory_.InvalidateWeakPtrs();
|
||||
Dispose();
|
||||
}
|
||||
|
||||
void JSCardanoProvider::WillReleaseScriptContext(v8::Local<v8::Context> context,
|
||||
int32_t world_id) {
|
||||
if (world_id != content::ISOLATED_WORLD_ID_GLOBAL) {
|
||||
return;
|
||||
}
|
||||
Cleanup();
|
||||
}
|
||||
|
||||
void JSCardanoProvider::OnDestruct() {
|
||||
Cleanup();
|
||||
}
|
||||
|
||||
std::vector<std::string> JSCardanoProvider::GetSupportedExtensions() {
|
||||
|
||||
@@ -59,6 +59,11 @@ class JSCardanoProvider final : public gin::Wrappable<JSCardanoProvider>,
|
||||
std::string GetIcon();
|
||||
std::string GetApiVersion();
|
||||
|
||||
void Cleanup();
|
||||
|
||||
// content::RenderFrameObserver
|
||||
void WillReleaseScriptContext(v8::Local<v8::Context> context,
|
||||
int32_t world_id) override;
|
||||
void OnDestruct() override;
|
||||
|
||||
mojo::Remote<mojom::CardanoProvider> cardano_provider_;
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#include "base/containers/to_value_list.h"
|
||||
#include "components/grit/brave_components_strings.h"
|
||||
#include "content/public/common/isolated_world_ids.h"
|
||||
#include "content/public/renderer/v8_value_converter.h"
|
||||
#include "gin/converter.h"
|
||||
#include "gin/object_template_builder.h"
|
||||
@@ -48,8 +49,27 @@ v8::Local<v8::Value> ConvertError(
|
||||
return content::V8ValueConverter::Create()->ToV8Value(error_value, context);
|
||||
}
|
||||
|
||||
// content::RenderFrameObserver
|
||||
void JSCardanoWalletApi::OnDestruct() {}
|
||||
void JSCardanoWalletApi::Cleanup() {
|
||||
// No longer need that provider object. Reset mojo connection, clean bound v8
|
||||
// references, stop tracking the render frame.
|
||||
|
||||
cardano_api_.reset();
|
||||
weak_ptr_factory_.InvalidateWeakPtrs();
|
||||
Dispose();
|
||||
}
|
||||
|
||||
void JSCardanoWalletApi::WillReleaseScriptContext(
|
||||
v8::Local<v8::Context> context,
|
||||
int32_t world_id) {
|
||||
if (world_id != content::ISOLATED_WORLD_ID_GLOBAL) {
|
||||
return;
|
||||
}
|
||||
Cleanup();
|
||||
}
|
||||
|
||||
void JSCardanoWalletApi::OnDestruct() {
|
||||
Cleanup();
|
||||
}
|
||||
|
||||
// gin::Wrappable<JSCardanoProvider>
|
||||
gin::ObjectTemplateBuilder JSCardanoWalletApi::GetObjectTemplateBuilder(
|
||||
|
||||
@@ -51,6 +51,12 @@ class JSCardanoWalletApi final : public gin::Wrappable<JSCardanoWalletApi>,
|
||||
|
||||
private:
|
||||
bool EnsureConnected();
|
||||
|
||||
void Cleanup();
|
||||
|
||||
// content::RenderFrameObserver
|
||||
void WillReleaseScriptContext(v8::Local<v8::Context> context,
|
||||
int32_t world_id) override;
|
||||
void OnDestruct() override;
|
||||
|
||||
void HandleStringResult(v8::Global<v8::Context> global_context,
|
||||
|
||||
@@ -121,30 +121,33 @@ JSEthereumProvider::JSEthereumProvider(content::RenderFrame* render_frame)
|
||||
|
||||
JSEthereumProvider::~JSEthereumProvider() = default;
|
||||
|
||||
void JSEthereumProvider::OnDestruct() {}
|
||||
void JSEthereumProvider::Cleanup() {
|
||||
// No longer need that provider object. Reset mojo connection, clean bound v8
|
||||
// references, stop tracking the render frame.
|
||||
|
||||
receiver_.reset();
|
||||
weak_ptr_factory_.InvalidateWeakPtrs();
|
||||
Dispose();
|
||||
}
|
||||
|
||||
void JSEthereumProvider::OnDestruct() {
|
||||
Cleanup();
|
||||
}
|
||||
|
||||
void JSEthereumProvider::WillReleaseScriptContext(v8::Local<v8::Context>,
|
||||
int32_t world_id) {
|
||||
if (world_id != content::ISOLATED_WORLD_ID_GLOBAL) {
|
||||
return;
|
||||
}
|
||||
// Close mojo connection from browser to renderer.
|
||||
receiver_.reset();
|
||||
script_context_released_ = true;
|
||||
|
||||
Cleanup();
|
||||
}
|
||||
|
||||
void JSEthereumProvider::DidDispatchDOMContentLoadedEvent() {
|
||||
if (script_context_released_) {
|
||||
return;
|
||||
}
|
||||
ConnectEvent();
|
||||
}
|
||||
|
||||
void JSEthereumProvider::DidFinishLoad() {
|
||||
if (script_context_released_) {
|
||||
return;
|
||||
}
|
||||
|
||||
// These used to be called synchronously by `JSEthereumProvider::Install`
|
||||
// which appeared to cause rare crashes with certain extensions' behavior. See
|
||||
// https://github.com/brave/brave-browser/issues/45694 for details.
|
||||
|
||||
@@ -80,6 +80,8 @@ class JSEthereumProvider final : public gin::Wrappable<JSEthereumProvider>,
|
||||
mojo::Remote<mojom::EthereumProvider> ethereum_provider_;
|
||||
};
|
||||
|
||||
void Cleanup();
|
||||
|
||||
// content::RenderFrameObserver
|
||||
void OnDestruct() override;
|
||||
void WillReleaseScriptContext(v8::Local<v8::Context>,
|
||||
@@ -132,7 +134,6 @@ class JSEthereumProvider final : public gin::Wrappable<JSEthereumProvider>,
|
||||
mojo::Remote<mojom::EthereumProvider> ethereum_provider_;
|
||||
mojo::Receiver<mojom::EventsListener> receiver_{this};
|
||||
bool is_connected_ = false;
|
||||
bool script_context_released_ = false;
|
||||
std::string chain_id_;
|
||||
std::string first_allowed_account_;
|
||||
std::string uuid_;
|
||||
|
||||
@@ -102,9 +102,6 @@ JSSolanaProvider::JSSolanaProvider(content::RenderFrame* render_frame)
|
||||
|
||||
JSSolanaProvider::~JSSolanaProvider() = default;
|
||||
|
||||
void JSSolanaProvider::OnDestruct() {
|
||||
}
|
||||
|
||||
// static
|
||||
void JSSolanaProvider::Install(bool allow_overwrite_window_solana,
|
||||
content::RenderFrame* render_frame) {
|
||||
@@ -239,13 +236,25 @@ void JSSolanaProvider::DisconnectEvent() {
|
||||
FireEvent(kDisconnectEvent, std::vector<v8::Local<v8::Value>>());
|
||||
}
|
||||
|
||||
void JSSolanaProvider::Cleanup() {
|
||||
// No longer need that provider object. Reset mojo connection, clean bound v8
|
||||
// references, stop tracking the render frame.
|
||||
|
||||
receiver_.reset();
|
||||
weak_ptr_factory_.InvalidateWeakPtrs();
|
||||
Dispose();
|
||||
}
|
||||
|
||||
void JSSolanaProvider::OnDestruct() {
|
||||
Cleanup();
|
||||
}
|
||||
|
||||
void JSSolanaProvider::WillReleaseScriptContext(v8::Local<v8::Context>,
|
||||
int32_t world_id) {
|
||||
if (world_id != content::ISOLATED_WORLD_ID_GLOBAL) {
|
||||
return;
|
||||
}
|
||||
// Close mojo connection from browser to renderer
|
||||
receiver_.reset();
|
||||
Cleanup();
|
||||
}
|
||||
|
||||
bool JSSolanaProvider::EnsureConnected() {
|
||||
@@ -325,10 +334,9 @@ v8::Local<v8::Promise> JSSolanaProvider::Connect(gin::Arguments* arguments) {
|
||||
v8::Global<v8::Promise::Resolver>(isolate, resolver.ToLocalChecked()));
|
||||
solana_provider_->Connect(
|
||||
std::move(arg),
|
||||
// We don't need weak ptr for mojo bindings when owning mojo::Remote
|
||||
base::BindOnce(&JSSolanaProvider::OnConnect, base::Unretained(this),
|
||||
std::move(global_context), std::move(promise_resolver),
|
||||
isolate));
|
||||
base::BindOnce(&JSSolanaProvider::OnConnect,
|
||||
weak_ptr_factory_.GetWeakPtr(), std::move(global_context),
|
||||
std::move(promise_resolver), isolate));
|
||||
|
||||
return resolver.ToLocalChecked()->GetPromise();
|
||||
}
|
||||
@@ -403,7 +411,7 @@ v8::Local<v8::Promise> JSSolanaProvider::SignAndSendTransaction(
|
||||
solana_provider_->SignAndSendTransaction(
|
||||
std::move(param), std::move(send_options),
|
||||
base::BindOnce(&JSSolanaProvider::OnSignAndSendTransaction,
|
||||
base::Unretained(this), std::move(global_context),
|
||||
weak_ptr_factory_.GetWeakPtr(), std::move(global_context),
|
||||
std::move(promise_resolver), isolate));
|
||||
|
||||
return resolver.ToLocalChecked()->GetPromise();
|
||||
@@ -451,9 +459,9 @@ v8::Local<v8::Promise> JSSolanaProvider::SignMessage(
|
||||
v8::Global<v8::Promise::Resolver>(isolate, resolver.ToLocalChecked()));
|
||||
solana_provider_->SignMessage(
|
||||
blob_msg->GetBlob(), display_str,
|
||||
base::BindOnce(&JSSolanaProvider::OnSignMessage, base::Unretained(this),
|
||||
std::move(global_context), std::move(promise_resolver),
|
||||
isolate));
|
||||
base::BindOnce(&JSSolanaProvider::OnSignMessage,
|
||||
weak_ptr_factory_.GetWeakPtr(), std::move(global_context),
|
||||
std::move(promise_resolver), isolate));
|
||||
|
||||
return resolver.ToLocalChecked()->GetPromise();
|
||||
}
|
||||
@@ -499,9 +507,9 @@ v8::Local<v8::Promise> JSSolanaProvider::Request(gin::Arguments* arguments) {
|
||||
v8::Global<v8::Promise::Resolver>(isolate, resolver.ToLocalChecked()));
|
||||
solana_provider_->Request(
|
||||
std::move(arg_dict),
|
||||
base::BindOnce(&JSSolanaProvider::OnRequest, base::Unretained(this),
|
||||
std::move(global_context), std::move(promise_resolver),
|
||||
isolate, *method));
|
||||
base::BindOnce(&JSSolanaProvider::OnRequest,
|
||||
weak_ptr_factory_.GetWeakPtr(), std::move(global_context),
|
||||
std::move(promise_resolver), isolate, *method));
|
||||
|
||||
return resolver.ToLocalChecked()->GetPromise();
|
||||
}
|
||||
@@ -539,7 +547,7 @@ v8::Local<v8::Promise> JSSolanaProvider::SignTransaction(
|
||||
solana_provider_->SignTransaction(
|
||||
std::move(param),
|
||||
base::BindOnce(&JSSolanaProvider::OnSignTransaction,
|
||||
base::Unretained(this), std::move(global_context),
|
||||
weak_ptr_factory_.GetWeakPtr(), std::move(global_context),
|
||||
std::move(promise_resolver), isolate));
|
||||
|
||||
return resolver.ToLocalChecked()->GetPromise();
|
||||
@@ -587,7 +595,7 @@ v8::Local<v8::Promise> JSSolanaProvider::SignAllTransactions(
|
||||
solana_provider_->SignAllTransactions(
|
||||
std::move(params),
|
||||
base::BindOnce(&JSSolanaProvider::OnSignAllTransactions,
|
||||
base::Unretained(this), std::move(global_context),
|
||||
weak_ptr_factory_.GetWeakPtr(), std::move(global_context),
|
||||
std::move(promise_resolver), isolate));
|
||||
|
||||
return resolver.ToLocalChecked()->GetPromise();
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "brave/components/brave_wallet/common/brave_wallet.mojom.h"
|
||||
#include "content/public/renderer/render_frame.h"
|
||||
#include "content/public/renderer/render_frame_observer.h"
|
||||
@@ -47,6 +48,8 @@ class JSSolanaProvider final : public gin::Wrappable<JSSolanaProvider>,
|
||||
void DisconnectEvent() override;
|
||||
|
||||
private:
|
||||
void Cleanup();
|
||||
|
||||
// RenderFrameObserver implementation.
|
||||
void OnDestruct() override;
|
||||
void WillReleaseScriptContext(v8::Local<v8::Context>,
|
||||
@@ -187,6 +190,7 @@ class JSSolanaProvider final : public gin::Wrappable<JSSolanaProvider>,
|
||||
std::unique_ptr<content::V8ValueConverter> v8_value_converter_;
|
||||
mojo::Remote<mojom::SolanaProvider> solana_provider_;
|
||||
mojo::Receiver<mojom::SolanaEventsListener> receiver_{this};
|
||||
base::WeakPtrFactory<JSSolanaProvider> weak_ptr_factory_{this};
|
||||
};
|
||||
|
||||
} // namespace brave_wallet
|
||||
|
||||
Reference in New Issue
Block a user