-
Notifications
You must be signed in to change notification settings - Fork 885
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
Adds event emitter to window.ethereum object #8718
Changes from all commits
2389e59
e572fb1
af6e4d0
2fc1c62
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
/* Copyright (c) 2021 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 "brave/components/brave_wallet/common/web3_provider_constants.h" | ||
|
||
namespace brave_wallet { | ||
|
||
const char kConnectEvent[] = "connect"; | ||
const char kDisconnectEvent[] = "disconnect"; | ||
const char kChainChangedEvent[] = "chainChanged"; | ||
const char kAccountsChangedEvent[] = "accountsChanged"; | ||
|
||
} // namespace brave_wallet |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,4 +3,5 @@ include_rules = [ | |
"+gin", | ||
"+third_party/blink/public", | ||
"+v8/include", | ||
"+ui/base", | ||
] |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,13 +6,16 @@ | |
#include "brave/components/brave_wallet/renderer/brave_wallet_js_handler.h" | ||
|
||
#include <utility> | ||
#include <vector> | ||
|
||
#include "base/json/json_writer.h" | ||
#include "base/no_destructor.h" | ||
#include "base/strings/string_number_conversions.h" | ||
#include "base/strings/stringprintf.h" | ||
#include "base/strings/utf_string_conversions.h" | ||
#include "brave/components/brave_wallet/common/web3_provider_constants.h" | ||
#include "brave/components/brave_wallet/renderer/brave_wallet_response_helpers.h" | ||
#include "brave/components/brave_wallet/renderer/web3_provider_constants.h" | ||
#include "brave/components/brave_wallet/resources/grit/brave_wallet_script_generated.h" | ||
#include "content/public/renderer/render_frame.h" | ||
#include "content/public/renderer/v8_value_converter.h" | ||
#include "gin/arguments.h" | ||
|
@@ -21,12 +24,75 @@ | |
#include "third_party/blink/public/web/blink.h" | ||
#include "third_party/blink/public/web/web_local_frame.h" | ||
#include "third_party/blink/public/web/web_script_source.h" | ||
#include "ui/base/resource/resource_bundle.h" | ||
|
||
namespace { | ||
|
||
static base::NoDestructor<std::string> g_provider_script(""); | ||
|
||
// Hardcode id to 1 as it is unused | ||
const uint32_t kRequestId = 1; | ||
const char kRequestJsonRPC[] = "2.0"; | ||
|
||
std::string LoadDataResource(const int id) { | ||
auto& resource_bundle = ui::ResourceBundle::GetSharedInstance(); | ||
if (resource_bundle.IsGzipped(id)) { | ||
return resource_bundle.LoadDataResourceString(id); | ||
} | ||
|
||
return resource_bundle.GetRawDataResource(id).as_string(); | ||
} | ||
|
||
v8::MaybeLocal<v8::Value> GetProperty(v8::Local<v8::Context> context, | ||
v8::Local<v8::Value> object, | ||
const std::u16string& name) { | ||
v8::Isolate* isolate = context->GetIsolate(); | ||
v8::Local<v8::String> name_str = | ||
gin::ConvertToV8(isolate, name).As<v8::String>(); | ||
v8::Local<v8::Object> object_obj; | ||
if (!object->ToObject(context).ToLocal(&object_obj)) { | ||
return v8::MaybeLocal<v8::Value>(); | ||
} | ||
|
||
return object_obj->Get(context, name_str); | ||
} | ||
|
||
void CallMethodOfObject(blink::WebLocalFrame* web_frame, | ||
const std::u16string& object_name, | ||
const std::u16string& method_name, | ||
base::Value arguments) { | ||
if (web_frame->IsProvisional()) | ||
return; | ||
v8::Local<v8::Context> context = web_frame->MainWorldScriptContext(); | ||
v8::Context::Scope context_scope(context); | ||
v8::Local<v8::Value> object; | ||
v8::Local<v8::Value> method; | ||
if (!GetProperty(context, context->Global(), object_name).ToLocal(&object) || | ||
!GetProperty(context, object, method_name).ToLocal(&method)) { | ||
return; | ||
} | ||
std::vector<v8::Local<v8::Value>> args; | ||
for (auto const& argument : arguments.GetList()) { | ||
args.push_back(content::V8ValueConverter::Create()->ToV8Value(&argument, | ||
context)); | ||
} | ||
|
||
web_frame->ExecuteMethodAndReturnValue( | ||
v8::Local<v8::Function>::Cast(method), object, | ||
static_cast<int>(args.size()), args.data()).ToLocalChecked(); | ||
} | ||
|
||
} // namespace | ||
|
||
namespace brave_wallet { | ||
|
||
BraveWalletJSHandler::BraveWalletJSHandler(content::RenderFrame* render_frame) | ||
: render_frame_(render_frame) {} | ||
: render_frame_(render_frame) { | ||
if (g_provider_script->empty()) { | ||
*g_provider_script = | ||
LoadDataResource(IDR_BRAVE_WALLET_SCRIPT_BRAVE_WALLET_SCRIPT_BUNDLE_JS); | ||
} | ||
} | ||
|
||
BraveWalletJSHandler::~BraveWalletJSHandler() = default; | ||
|
||
|
@@ -49,6 +115,7 @@ void BraveWalletJSHandler::AddJavaScriptObjectToFrame( | |
v8::Context::Scope context_scope(context); | ||
|
||
CreateEthereumObject(isolate, context); | ||
InjectInitScript(); | ||
} | ||
|
||
void BraveWalletJSHandler::CreateEthereumObject( | ||
|
@@ -107,6 +174,9 @@ v8::Local<v8::Promise> BraveWalletJSHandler::Request( | |
if (!out || !out->is_dict() || !out->GetAsDictionary(&out_dict)) | ||
return v8::Local<v8::Promise>(); | ||
|
||
// Hardcode id to 1 as it is unused | ||
ALLOW_UNUSED_LOCAL(out_dict->SetIntPath("id", kRequestId)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. weird that these were needed, I don't see them used in other places, but I guess it's ok because other places also ignore the result |
||
ALLOW_UNUSED_LOCAL(out_dict->SetStringPath("jsonrpc", kRequestJsonRPC)); | ||
std::string formed_input; | ||
if (!base::JSONWriter::Write(*out_dict, &formed_input)) | ||
return v8::Local<v8::Promise>(); | ||
|
@@ -165,4 +235,43 @@ void BraveWalletJSHandler::OnRequest( | |
} | ||
} | ||
|
||
void BraveWalletJSHandler::ExecuteScript(const std::string script) { | ||
blink::WebLocalFrame* web_frame = render_frame_->GetWebFrame(); | ||
if (web_frame->IsProvisional()) | ||
return; | ||
|
||
web_frame->ExecuteScript(blink::WebString::FromUTF8(script)); | ||
} | ||
|
||
void BraveWalletJSHandler::InjectInitScript() { | ||
ExecuteScript(*g_provider_script); | ||
} | ||
|
||
void BraveWalletJSHandler::FireEvent(const std::string& event, | ||
const std::string& event_args) { | ||
base::Value args = base::Value(base::Value::Type::LIST); | ||
args.Append(event); | ||
args.Append(event_args); | ||
CallMethodOfObject(render_frame_->GetWebFrame(), | ||
u"ethereum", | ||
u"emit", | ||
std::move(args)); | ||
} | ||
|
||
void BraveWalletJSHandler::ConnectEvent(const std::string& chain_id) { | ||
FireEvent(kConnectEvent, chain_id); | ||
} | ||
|
||
void BraveWalletJSHandler::DisconnectEvent(const std::string& message) { | ||
FireEvent(kDisconnectEvent, message); | ||
} | ||
|
||
void BraveWalletJSHandler::ChainChangedEvent(const std::string& chain_id) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think we want methods for each specific event, we should just have a list of constants for them There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I will do that in upcoming PRs. As some events will come from browser process via mojo, some will not like connect, on connect we will ask a browser process what chain id is. That place is going to be changed in some kind in the upcoming PRs. Just some things are unknown yet till we investigate how and when exactly we should fire events. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can we also add better error handling in a follow-up PR so the called gets notified if there are any JS errors? |
||
FireEvent(kChainChangedEvent, chain_id); | ||
} | ||
|
||
void BraveWalletJSHandler::AccountsChangedEvent(const std::string& accounts) { | ||
FireEvent(kAccountsChangedEvent, accounts); | ||
} | ||
|
||
} // namespace brave_wallet |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import("//brave/components/common/typescript.gni") | ||
import("//tools/grit/grit_rule.gni") | ||
import("//tools/grit/repack.gni") | ||
|
||
transpile_web_ui("brave_wallet_script_resources") { | ||
entry_points = [ [ | ||
"brave_wallet_script", | ||
rebase_path("brave_wallet_provider.js"), | ||
] ] | ||
|
||
resource_name = "brave_wallet_script" | ||
} | ||
|
||
pack_web_resources("ethereum_provider_generated_resources") { | ||
resource_name = "brave_wallet_script" | ||
output_dir = "$root_gen_dir/brave/components/brave_wallet/resources" | ||
deps = [ ":brave_wallet_script_resources" ] | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
// Copyright (c) 2021 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/. | ||
|
||
(function() { | ||
if (!window.ethereum) { | ||
return | ||
} | ||
var EventEmitter = require('events') | ||
var BraveWeb3ProviderEventEmitter = new EventEmitter() | ||
window.ethereum.on = BraveWeb3ProviderEventEmitter.on | ||
window.ethereum.emit = BraveWeb3ProviderEventEmitter.emit | ||
window.ethereum.removeListener = | ||
BraveWeb3ProviderEventEmitter.removeListener | ||
})() |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -89,11 +89,14 @@ repack("resources") { | |
] | ||
} | ||
|
||
if (brave_wallet_enabled && !is_android) { | ||
deps += [ "//brave/components/brave_wallet_ui:resources" ] | ||
sources += [ | ||
"$root_gen_dir/brave/components/brave_wallet/resources/brave_wallet.pak", | ||
] | ||
if (brave_wallet_enabled) { | ||
if (!is_android) { | ||
deps += [ "//brave/components/brave_wallet_ui:resources" ] | ||
sources += [ "$root_gen_dir/brave/components/brave_wallet/resources/brave_wallet.pak" ] | ||
} | ||
|
||
deps += [ "//brave/components/brave_wallet/resources:ethereum_provider_generated_resources" ] | ||
sources += [ "$root_gen_dir/brave/components/brave_wallet/resources/brave_wallet_script_generated.pak" ] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. there's no reason to expose additional pak files here, we should repack everything inside brave_wallet into a single output. See https://github.com/brave/brave-core/pull/8703/files#diff-5303bb2b8878c4fce006fc3b8bb18f3d4e0f386dbea78d4c8c37a23323762389R55 |
||
} | ||
|
||
output = "$root_gen_dir/components/brave_components_resources.pak" | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is fine for now, but I don't think we need to store this in a static var. LoadDataResource loads from memory so there's really no benefit to doing this