Commit d0b05b8d authored by Majid Valipour's avatar Majid Valipour Committed by Chromium LUCI CQ

[WebID] Avoid accessing IDP web contents after token is provided

Previously we would access the IDP web contents which was leading to
crash.

Bug: 1141125

Change-Id: I5943d38e51f8e14fbf0488d0a104cd56b39ea5fc
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2586112
Commit-Queue: Majid Valipour <majidvp@chromium.org>
Reviewed-by: default avatarKen Buchanan <kenrb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#836286}
parent 0687be6a
...@@ -281,12 +281,19 @@ void FederatedAuthRequestImpl::CompleteRequest( ...@@ -281,12 +281,19 @@ void FederatedAuthRequestImpl::CompleteRequest(
// ---- Provider logic ----- // ---- Provider logic -----
void FederatedAuthRequestImpl::ProvideIdToken(const std::string& id_token, void FederatedAuthRequestImpl::ProvideIdToken(
ProvideIdTokenCallback callback) { const std::string& id_token,
WebContents* web_contents = ProvideIdTokenCallback idp_callback) {
// The ptr below is actually the same as |idp_web_contents_| but because this
// is a different instance of |FederatedAuthRequestImpl| for which
// |idp_web_contents_| has not been initialized.
//
// TODO(majidvp): We should have two separate mojo service for request and
// response sides would have make this more obvious. http://crbug.com/1141125
WebContents* idp_web_contents =
content::WebContents::FromRenderFrameHost(render_frame_host()); content::WebContents::FromRenderFrameHost(render_frame_host());
auto* request_callback_data =
auto* request_callback_data = IdTokenRequestCallbackData::Get(web_contents); IdTokenRequestCallbackData::Get(idp_web_contents);
// TODO(majidvp): This may happen if the page is not loaded by the browser's // TODO(majidvp): This may happen if the page is not loaded by the browser's
// WebID machinery. We need a way for IDP logic to detect that and not provide // WebID machinery. We need a way for IDP logic to detect that and not provide
...@@ -294,21 +301,27 @@ void FederatedAuthRequestImpl::ProvideIdToken(const std::string& id_token, ...@@ -294,21 +301,27 @@ void FederatedAuthRequestImpl::ProvideIdToken(const std::string& id_token,
// to not expose this in JS somehow. Investigate this further. // to not expose this in JS somehow. Investigate this further.
// http://crbug.com/1141125 // http://crbug.com/1141125
if (!request_callback_data) { if (!request_callback_data) {
std::move(callback).Run(ProvideIdTokenStatus::kError); std::move(idp_callback).Run(ProvideIdTokenStatus::kError);
return; return;
} }
if (request_callback_data->Notify(id_token)) { // After running the RP done callback the IDP sign-in page gets closed and its
std::move(callback).Run(ProvideIdTokenStatus::kSuccess); // web contents cleared in `FederatedAuthRequestImpl::CompleteRequest()`. So
} else { // we should not access |idp_web_contents| or any of its associated objects
std::move(callback).Run(ProvideIdTokenStatus::kErrorTooManyResponses); // as it may already be destructed. This is why we first run any logic that
// needs to touch the IDP web contents and then run the RP done callback.
auto rp_done_callback = request_callback_data->TakeDoneCallback();
IdTokenRequestCallbackData::Remove(idp_web_contents);
if (!rp_done_callback) {
std::move(idp_callback).Run(ProvideIdTokenStatus::kErrorTooManyResponses);
return;
} }
std::move(idp_callback).Run(ProvideIdTokenStatus::kSuccess);
// After calling `Notify` it is safe to remove the callback data. std::move(rp_done_callback).Run(id_token);
// TODO(majidvp): This is now causing a DHECK. I belive it is because we are // Don't access |idp_web_contents| passed this point.
// not calling it on the same RunLoop as the one that set it but needs more
// investigation.
// IdTokenRequestCallbackData::Remove(web_contents);
} }
} // namespace content } // namespace content
...@@ -14,12 +14,8 @@ IdTokenRequestCallbackData::IdTokenRequestCallbackData(DoneCallback callback) ...@@ -14,12 +14,8 @@ IdTokenRequestCallbackData::IdTokenRequestCallbackData(DoneCallback callback)
: callback_(std::move(callback)) {} : callback_(std::move(callback)) {}
IdTokenRequestCallbackData::~IdTokenRequestCallbackData() = default; IdTokenRequestCallbackData::~IdTokenRequestCallbackData() = default;
bool IdTokenRequestCallbackData::Notify(const std::string& id_token) { DoneCallback IdTokenRequestCallbackData::TakeDoneCallback() {
if (!callback_) { return std::move(callback_);
return false;
}
std::move(callback_).Run(id_token);
return true;
} }
// static // static
......
...@@ -35,8 +35,7 @@ class CONTENT_EXPORT IdTokenRequestCallbackData ...@@ -35,8 +35,7 @@ class CONTENT_EXPORT IdTokenRequestCallbackData
explicit IdTokenRequestCallbackData(DoneCallback callback); explicit IdTokenRequestCallbackData(DoneCallback callback);
~IdTokenRequestCallbackData() override; ~IdTokenRequestCallbackData() override;
// Invoke the callback (if it is still valid) passing the provided id_token. DoneCallback TakeDoneCallback();
bool Notify(const std::string& id_token);
static void Set(WebContents* web_contents, DoneCallback callback); static void Set(WebContents* web_contents, DoneCallback callback);
static IdTokenRequestCallbackData* Get(WebContents* web_contents); static IdTokenRequestCallbackData* Get(WebContents* web_contents);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment