fix: implement 'login' event for WebContents (#20954)
This commit is contained in:
parent
049bd09150
commit
034f4d5734
16 changed files with 239 additions and 247 deletions
|
@ -9,157 +9,78 @@
|
|||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "base/task/post_task.h"
|
||||
#include "base/values.h"
|
||||
#include "content/public/browser/browser_task_traits.h"
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
#include "content/public/browser/web_contents.h"
|
||||
#include "net/base/auth.h"
|
||||
#include "net/base/upload_bytes_element_reader.h"
|
||||
#include "net/base/upload_data_stream.h"
|
||||
#include "net/base/upload_element_reader.h"
|
||||
#include "net/base/upload_file_element_reader.h"
|
||||
#include "shell/browser/browser.h"
|
||||
#include "base/callback.h"
|
||||
#include "gin/dictionary.h"
|
||||
#include "shell/browser/api/atom_api_web_contents.h"
|
||||
#include "shell/common/gin_converters/callback_converter.h"
|
||||
#include "shell/common/gin_converters/net_converter.h"
|
||||
#include "shell/common/gin_converters/value_converter.h"
|
||||
|
||||
using content::BrowserThread;
|
||||
|
||||
namespace electron {
|
||||
|
||||
namespace {
|
||||
LoginHandler::LoginHandler(
|
||||
const net::AuthChallengeInfo& auth_info,
|
||||
content::WebContents* web_contents,
|
||||
bool is_main_frame,
|
||||
const GURL& url,
|
||||
scoped_refptr<net::HttpResponseHeaders> response_headers,
|
||||
bool first_auth_attempt,
|
||||
LoginAuthRequiredCallback auth_required_callback)
|
||||
|
||||
void GetUploadData(base::ListValue* upload_data_list,
|
||||
const net::URLRequest* request) {
|
||||
const net::UploadDataStream* upload_data = request->get_upload_for_testing();
|
||||
if (!upload_data)
|
||||
return;
|
||||
const std::vector<std::unique_ptr<net::UploadElementReader>>* readers =
|
||||
upload_data->GetElementReaders();
|
||||
for (const auto& reader : *readers) {
|
||||
auto upload_data_dict = std::make_unique<base::DictionaryValue>();
|
||||
if (reader->AsBytesReader()) {
|
||||
const net::UploadBytesElementReader* bytes_reader =
|
||||
reader->AsBytesReader();
|
||||
auto bytes = std::make_unique<base::Value>(
|
||||
std::vector<char>(bytes_reader->bytes(),
|
||||
bytes_reader->bytes() + bytes_reader->length()));
|
||||
upload_data_dict->Set("bytes", std::move(bytes));
|
||||
} else if (reader->AsFileReader()) {
|
||||
const net::UploadFileElementReader* file_reader = reader->AsFileReader();
|
||||
auto file_path = file_reader->path().AsUTF8Unsafe();
|
||||
upload_data_dict->SetKey("file", base::Value(file_path));
|
||||
}
|
||||
// else {
|
||||
// const storage::UploadBlobElementReader* blob_reader =
|
||||
// static_cast<storage::UploadBlobElementReader*>(reader.get());
|
||||
// upload_data_dict->SetString("blobUUID", blob_reader->uuid());
|
||||
// }
|
||||
upload_data_list->Append(std::move(upload_data_dict));
|
||||
}
|
||||
}
|
||||
|
||||
void FillRequestDetails(base::DictionaryValue* details,
|
||||
const net::URLRequest* request) {
|
||||
details->SetString("method", request->method());
|
||||
std::string url;
|
||||
if (!request->url_chain().empty())
|
||||
url = request->url().spec();
|
||||
details->SetKey("url", base::Value(url));
|
||||
details->SetString("referrer", request->referrer());
|
||||
auto list = std::make_unique<base::ListValue>();
|
||||
GetUploadData(list.get(), request);
|
||||
if (!list->empty())
|
||||
details->Set("uploadData", std::move(list));
|
||||
auto headers_value = std::make_unique<base::DictionaryValue>();
|
||||
for (net::HttpRequestHeaders::Iterator it(request->extra_request_headers());
|
||||
it.GetNext();) {
|
||||
headers_value->SetString(it.name(), it.value());
|
||||
}
|
||||
details->Set("headers", std::move(headers_value));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
LoginHandler::LoginHandler(net::URLRequest* request,
|
||||
const net::AuthChallengeInfo& auth_info,
|
||||
// net::NetworkDelegate::AuthCallback callback,
|
||||
net::AuthCredentials* credentials)
|
||||
: credentials_(credentials),
|
||||
auth_info_(std::make_unique<net::AuthChallengeInfo>(auth_info)),
|
||||
// auth_callback_(std::move(callback)),
|
||||
weak_factory_(this) {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
||||
|
||||
std::unique_ptr<base::DictionaryValue> request_details(
|
||||
new base::DictionaryValue);
|
||||
// TODO(zcbenz): Use the converters from net_converter.
|
||||
FillRequestDetails(request_details.get(), request);
|
||||
|
||||
// TODO(deepak1556): fix with network service
|
||||
// tracking issue: #19602
|
||||
CHECK(false) << "fix with network service";
|
||||
// web_contents_getter_ =
|
||||
// resource_request_info->GetWebContentsGetterForRequest();
|
||||
: WebContentsObserver(web_contents),
|
||||
auth_required_callback_(std::move(auth_required_callback)) {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||||
|
||||
base::PostTask(
|
||||
FROM_HERE, {BrowserThread::UI},
|
||||
base::BindOnce(&Browser::RequestLogin, base::Unretained(Browser::Get()),
|
||||
base::RetainedRef(this), std::move(request_details)));
|
||||
FROM_HERE, {base::CurrentThread()},
|
||||
base::BindOnce(&LoginHandler::EmitEvent, weak_factory_.GetWeakPtr(),
|
||||
auth_info, is_main_frame, url, response_headers,
|
||||
first_auth_attempt));
|
||||
}
|
||||
|
||||
void LoginHandler::EmitEvent(
|
||||
net::AuthChallengeInfo auth_info,
|
||||
bool is_main_frame,
|
||||
const GURL& url,
|
||||
scoped_refptr<net::HttpResponseHeaders> response_headers,
|
||||
bool first_auth_attempt) {
|
||||
v8::Isolate* isolate = v8::Isolate::GetCurrent();
|
||||
|
||||
auto api_web_contents = api::WebContents::From(isolate, web_contents());
|
||||
if (api_web_contents.IsEmpty()) {
|
||||
std::move(auth_required_callback_).Run(base::nullopt);
|
||||
return;
|
||||
}
|
||||
|
||||
v8::HandleScope scope(isolate);
|
||||
|
||||
auto details = gin::Dictionary::CreateEmpty(isolate);
|
||||
details.Set("url", url.spec());
|
||||
|
||||
// These parameters aren't documented, and I'm not sure that they're useful,
|
||||
// but we might as well stick 'em on the details object. If it turns out they
|
||||
// are useful, we can add them to the docs :)
|
||||
details.Set("isMainFrame", is_main_frame);
|
||||
details.Set("firstAuthAttempt", first_auth_attempt);
|
||||
details.Set("responseHeaders", response_headers.get());
|
||||
|
||||
bool default_prevented =
|
||||
api_web_contents->Emit("login", std::move(details), auth_info,
|
||||
base::BindOnce(&LoginHandler::CallbackFromJS,
|
||||
weak_factory_.GetWeakPtr()));
|
||||
if (!default_prevented) {
|
||||
std::move(auth_required_callback_).Run(base::nullopt);
|
||||
}
|
||||
}
|
||||
|
||||
LoginHandler::~LoginHandler() = default;
|
||||
|
||||
void LoginHandler::Login(const base::string16& username,
|
||||
const base::string16& password) {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||||
|
||||
base::PostTask(
|
||||
FROM_HERE, {BrowserThread::IO},
|
||||
base::BindOnce(&LoginHandler::DoLogin, weak_factory_.GetWeakPtr(),
|
||||
username, password));
|
||||
}
|
||||
|
||||
void LoginHandler::CancelAuth() {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||||
|
||||
base::PostTask(
|
||||
FROM_HERE, {BrowserThread::IO},
|
||||
base::BindOnce(&LoginHandler::DoCancelAuth, weak_factory_.GetWeakPtr()));
|
||||
}
|
||||
|
||||
void LoginHandler::NotifyRequestDestroyed() {
|
||||
// auth_callback_.Reset();
|
||||
credentials_ = nullptr;
|
||||
weak_factory_.InvalidateWeakPtrs();
|
||||
}
|
||||
|
||||
content::WebContents* LoginHandler::GetWebContents() const {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||||
// TODO(deepak1556): fix with network service
|
||||
// tracking issue: #19602
|
||||
CHECK(false) << "fix with network service";
|
||||
return web_contents_getter_.Run();
|
||||
}
|
||||
|
||||
void LoginHandler::DoCancelAuth() {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
||||
/*
|
||||
if (!auth_callback_.is_null())
|
||||
std::move(auth_callback_)
|
||||
.Run(net::NetworkDelegate::AUTH_REQUIRED_RESPONSE_CANCEL_AUTH);
|
||||
*/
|
||||
}
|
||||
|
||||
void LoginHandler::DoLogin(const base::string16& username,
|
||||
const base::string16& password) {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
||||
/*
|
||||
if (!auth_callback_.is_null()) {
|
||||
credentials_->Set(username, password);
|
||||
std::move(auth_callback_)
|
||||
.Run(net::NetworkDelegate::AUTH_REQUIRED_RESPONSE_SET_AUTH);
|
||||
}
|
||||
*/
|
||||
void LoginHandler::CallbackFromJS(base::string16 username,
|
||||
base::string16 password) {
|
||||
std::move(auth_required_callback_)
|
||||
.Run(net::AuthCredentials(username, password));
|
||||
}
|
||||
|
||||
} // namespace electron
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue