Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wrap window.ethereum._metamask in gin::Wrappable (uplift to 1.51.x) #18419

Merged
merged 1 commit into from
May 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
132 changes: 73 additions & 59 deletions components/brave_wallet/renderer/js_ethereum_provider.cc
Original file line number Diff line number Diff line change
Expand Up @@ -64,22 +64,6 @@ constexpr char kIsUnlocked[] = "isUnlocked";

namespace brave_wallet {

void JSEthereumProvider::OnIsUnlocked(
v8::Global<v8::Context> global_context,
v8::Global<v8::Promise::Resolver> promise_resolver,
v8::Isolate* isolate,
bool locked) {
v8::HandleScope handle_scope(isolate);
v8::Local<v8::Promise::Resolver> resolver = promise_resolver.Get(isolate);
v8::Local<v8::Context> context = global_context.Get(isolate);
v8::MicrotasksScope microtasks(isolate, context->GetMicrotaskQueue(),
v8::MicrotasksScope::kDoNotRunMicrotasks);
base::Value result = base::Value(!locked);
v8::Local<v8::Value> local_result =
content::V8ValueConverter::Create()->ToV8Value(result, context);
std::ignore = resolver->Resolve(context, local_result);
}

void JSEthereumProvider::SendResponse(
base::Value id,
v8::Global<v8::Context> global_context,
Expand Down Expand Up @@ -234,26 +218,6 @@ void JSEthereumProvider::Install(bool allow_overwrite_window_ethereum_provider,
SetOwnPropertyWritable(context, provider_object,
gin::StringToV8(isolate, kIsMetaMask), true);

// Set non-writable _metamask obj with non-writable isUnlocked method.
v8::Local<v8::Value> metamask_value;
v8::Local<v8::Object> metamask_obj = v8::Object::New(isolate);
provider_object
->Set(context, gin::StringToSymbol(isolate, kMetaMask), metamask_obj)
.Check();
SetOwnPropertyWritable(context, provider_object,
gin::StringToV8(isolate, kMetaMask), false);

metamask_obj
->Set(context, gin::StringToSymbol(isolate, kIsUnlocked),
gin::CreateFunctionTemplate(
isolate, base::BindRepeating(&JSEthereumProvider::IsUnlocked,
base::Unretained(provider.get())))
->GetFunction(context)
.ToLocalChecked())
.Check();
SetOwnPropertyWritable(context, metamask_obj,
gin::StringToV8(isolate, kIsUnlocked), false);

ExecuteScript(web_frame,
LoadDataResource(
IDR_BRAVE_WALLET_SCRIPT_ETHEREUM_PROVIDER_SCRIPT_BUNDLE_JS),
Expand All @@ -268,6 +232,78 @@ bool JSEthereumProvider::GetIsMetaMask() {
return true;
}

gin::WrapperInfo JSEthereumProvider::MetaMask::kWrapperInfo = {
gin::kEmbedderNativeGin};

JSEthereumProvider::MetaMask::MetaMask(content::RenderFrame* render_frame)
: render_frame_(render_frame) {}
JSEthereumProvider::MetaMask::~MetaMask() = default;

gin::ObjectTemplateBuilder
JSEthereumProvider::MetaMask::GetObjectTemplateBuilder(v8::Isolate* isolate) {
return gin::Wrappable<MetaMask>::GetObjectTemplateBuilder(isolate).SetMethod(
kIsUnlocked, &JSEthereumProvider::MetaMask::IsUnlocked);
}

const char* JSEthereumProvider::MetaMask::GetTypeName() {
return kMetaMask;
}

v8::Local<v8::Promise> JSEthereumProvider::MetaMask::IsUnlocked(
v8::Isolate* isolate) {
if (!ethereum_provider_.is_bound()) {
render_frame_->GetBrowserInterfaceBroker()->GetInterface(
ethereum_provider_.BindNewPipeAndPassReceiver());
}

v8::MaybeLocal<v8::Promise::Resolver> resolver =
v8::Promise::Resolver::New(isolate->GetCurrentContext());
if (resolver.IsEmpty()) {
return v8::Local<v8::Promise>();
}

auto global_context(
v8::Global<v8::Context>(isolate, isolate->GetCurrentContext()));
auto promise_resolver(
v8::Global<v8::Promise::Resolver>(isolate, resolver.ToLocalChecked()));
auto context(v8::Global<v8::Context>(isolate, isolate->GetCurrentContext()));
ethereum_provider_->IsLocked(base::BindOnce(
&JSEthereumProvider::MetaMask::OnIsUnlocked, base::Unretained(this),
std::move(global_context), std::move(promise_resolver), isolate));

return resolver.ToLocalChecked()->GetPromise();
}

void JSEthereumProvider::MetaMask::OnIsUnlocked(
v8::Global<v8::Context> global_context,
v8::Global<v8::Promise::Resolver> promise_resolver,
v8::Isolate* isolate,
bool locked) {
v8::HandleScope handle_scope(isolate);
v8::Local<v8::Promise::Resolver> resolver = promise_resolver.Get(isolate);
v8::Local<v8::Context> context = global_context.Get(isolate);
v8::MicrotasksScope microtasks(isolate, context->GetMicrotaskQueue(),
v8::MicrotasksScope::kDoNotRunMicrotasks);
base::Value result = base::Value(!locked);
v8::Local<v8::Value> local_result =
content::V8ValueConverter::Create()->ToV8Value(result, context);
std::ignore = resolver->Resolve(context, local_result);
}

v8::Local<v8::Value> JSEthereumProvider::GetMetaMask(v8::Isolate* isolate) {
// Set non-writable _metamask obj with non-writable isUnlocked method.
gin::Handle<MetaMask> metamask =
gin::CreateHandle(isolate, new MetaMask(render_frame()));
if (metamask.IsEmpty()) {
return v8::Undefined(isolate);
}
v8::Local<v8::Value> metamask_value = metamask.ToV8();
SetOwnPropertyWritable(isolate->GetCurrentContext(),
metamask_value.As<v8::Object>(),
gin::StringToV8(isolate, kIsUnlocked), false);
return metamask_value;
}

std::string JSEthereumProvider::GetChainId() {
return chain_id_;
}
Expand Down Expand Up @@ -304,6 +340,7 @@ gin::ObjectTemplateBuilder JSEthereumProvider::GetObjectTemplateBuilder(
return gin::Wrappable<JSEthereumProvider>::GetObjectTemplateBuilder(isolate)
.SetProperty(kIsBraveWallet, &JSEthereumProvider::GetIsBraveWallet)
.SetProperty(kIsMetaMask, &JSEthereumProvider::GetIsMetaMask)
.SetProperty(kMetaMask, &JSEthereumProvider::GetMetaMask)
.SetProperty("chainId", &JSEthereumProvider::GetChainId)
.SetProperty("networkVersion", &JSEthereumProvider::GetNetworkVersion)
.SetProperty("selectedAddress", &JSEthereumProvider::GetSelectedAddress)
Expand Down Expand Up @@ -529,29 +566,6 @@ v8::Local<v8::Promise> JSEthereumProvider::Enable(v8::Isolate* isolate) {
return resolver.ToLocalChecked()->GetPromise();
}

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

v8::MaybeLocal<v8::Promise::Resolver> resolver =
v8::Promise::Resolver::New(isolate->GetCurrentContext());
if (resolver.IsEmpty()) {
return v8::Local<v8::Promise>();
}

auto global_context(
v8::Global<v8::Context>(isolate, isolate->GetCurrentContext()));
auto promise_resolver(
v8::Global<v8::Promise::Resolver>(isolate, resolver.ToLocalChecked()));
auto context(v8::Global<v8::Context>(isolate, isolate->GetCurrentContext()));
ethereum_provider_->IsLocked(base::BindOnce(
&JSEthereumProvider::OnIsUnlocked, weak_ptr_factory_.GetWeakPtr(),
std::move(global_context), std::move(promise_resolver), isolate));

return resolver.ToLocalChecked()->GetPromise();
}

void JSEthereumProvider::FireEvent(const std::string& event,
base::ValueView event_args) {
if (!render_frame()) {
Expand Down
30 changes: 25 additions & 5 deletions components/brave_wallet/renderer/js_ethereum_provider.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,30 @@ class JSEthereumProvider final : public gin::Wrappable<JSEthereumProvider>,
explicit JSEthereumProvider(content::RenderFrame* render_frame);
~JSEthereumProvider() override;

class MetaMask final : public gin::Wrappable<MetaMask> {
public:
static gin::WrapperInfo kWrapperInfo;

explicit MetaMask(content::RenderFrame*);
~MetaMask() override;
MetaMask(const MetaMask&) = delete;
MetaMask& operator=(const MetaMask&) = delete;

// gin::WrappableBase
gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
v8::Isolate* isolate) override;
const char* GetTypeName() override;
v8::Local<v8::Promise> IsUnlocked(v8::Isolate* isolate);

private:
void OnIsUnlocked(v8::Global<v8::Context> global_context,
v8::Global<v8::Promise::Resolver> promise_resolver,
v8::Isolate* isolate,
bool locked);
raw_ptr<content::RenderFrame> render_frame_;
mojo::Remote<mojom::EthereumProvider> ethereum_provider_;
};

// content::RenderFrameObserver
void OnDestruct() override {}
void WillReleaseScriptContext(v8::Local<v8::Context>,
Expand All @@ -66,6 +90,7 @@ class JSEthereumProvider final : public gin::Wrappable<JSEthereumProvider>,

bool GetIsBraveWallet();
bool GetIsMetaMask();
v8::Local<v8::Value> GetMetaMask(v8::Isolate* isolate);
std::string GetChainId();
v8::Local<v8::Value> GetNetworkVersion(v8::Isolate* isolate);
v8::Local<v8::Value> GetSelectedAddress(v8::Isolate* isolate);
Expand All @@ -75,7 +100,6 @@ class JSEthereumProvider final : public gin::Wrappable<JSEthereumProvider>,
v8::Local<v8::Value> input);
bool IsConnected();
v8::Local<v8::Promise> Enable(v8::Isolate* isolate);
v8::Local<v8::Promise> IsUnlocked(v8::Isolate* isolate);
v8::Local<v8::Promise> SendMethod(gin::Arguments* args);
void SendAsync(gin::Arguments* args);

Expand All @@ -89,10 +113,6 @@ class JSEthereumProvider final : public gin::Wrappable<JSEthereumProvider>,
const std::string& first_allowed_account,
const bool update_bind_js_properties);

void OnIsUnlocked(v8::Global<v8::Context> global_context,
v8::Global<v8::Promise::Resolver> promise_resolver,
v8::Isolate* isolate,
bool locked);
void SendResponse(base::Value id,
v8::Global<v8::Context> global_context,
std::unique_ptr<v8::Global<v8::Function>> callback,
Expand Down