Commit 3d8e2c2a authored by Guido Urdaneta's avatar Guido Urdaneta Committed by Commit Bot

[AudioOutputDevices] Check frame before checking device authorization.

This attempts to address an unusual crash involving WebLocalFrame and
SetSinkIdResolver.
This CL also removes a timer to fire an asynchronous task and uses
a per-frame task runner instead.

Bug: 941380
Change-Id: I9acf17ca3fd7d3dd8253b4e278adf583f4205f85
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1524267Reviewed-by: default avatarMarina Ciocea <marinaciocea@chromium.org>
Commit-Queue: Guido Urdaneta <guidou@chromium.org>
Cr-Commit-Position: refs/heads/master@{#641563}
parent b8ead26c
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h" #include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
#include "third_party/blink/renderer/modules/audio_output_devices/set_sink_id_callbacks.h" #include "third_party/blink/renderer/modules/audio_output_devices/set_sink_id_callbacks.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h" #include "third_party/blink/renderer/platform/bindings/script_state.h"
#include "third_party/blink/renderer/platform/heap/persistent.h"
namespace blink { namespace blink {
...@@ -34,11 +35,10 @@ class SetSinkIdResolver : public ScriptPromiseResolver { ...@@ -34,11 +35,10 @@ class SetSinkIdResolver : public ScriptPromiseResolver {
void Trace(blink::Visitor*) override; void Trace(blink::Visitor*) override;
private: private:
void TimerFired(TimerBase*); void DoSetSinkId();
Member<HTMLMediaElement> element_; Member<HTMLMediaElement> element_;
String sink_id_; String sink_id_;
TaskRunnerTimer<SetSinkIdResolver> timer_;
DISALLOW_COPY_AND_ASSIGN(SetSinkIdResolver); DISALLOW_COPY_AND_ASSIGN(SetSinkIdResolver);
}; };
...@@ -57,24 +57,23 @@ SetSinkIdResolver::SetSinkIdResolver(ScriptState* script_state, ...@@ -57,24 +57,23 @@ SetSinkIdResolver::SetSinkIdResolver(ScriptState* script_state,
const String& sink_id) const String& sink_id)
: ScriptPromiseResolver(script_state), : ScriptPromiseResolver(script_state),
element_(element), element_(element),
sink_id_(sink_id), sink_id_(sink_id) {}
timer_(ExecutionContext::From(script_state)
->GetTaskRunner(TaskType::kMiscPlatformAPI),
this,
&SetSinkIdResolver::TimerFired) {}
void SetSinkIdResolver::StartAsync() { void SetSinkIdResolver::StartAsync() {
timer_.StartOneShot(TimeDelta(), FROM_HERE); ExecutionContext* context = GetExecutionContext();
if (!context)
return;
context->GetTaskRunner(TaskType::kInternalMedia)
->PostTask(FROM_HERE, WTF::Bind(&SetSinkIdResolver::DoSetSinkId,
WrapWeakPersistent(this)));
} }
void SetSinkIdResolver::TimerFired(TimerBase* timer) { void SetSinkIdResolver::DoSetSinkId() {
ExecutionContext* context = GetExecutionContext(); ExecutionContext* context = GetExecutionContext();
std::unique_ptr<SetSinkIdCallbacks> callbacks = std::unique_ptr<SetSinkIdCallbacks> callbacks =
std::make_unique<SetSinkIdCallbacks>(this, *element_, sink_id_); std::make_unique<SetSinkIdCallbacks>(this, *element_, sink_id_);
WebMediaPlayer* web_media_player = element_->GetWebMediaPlayer(); WebMediaPlayer* web_media_player = element_->GetWebMediaPlayer();
if (web_media_player) { if (web_media_player) {
// Using release() to transfer ownership because |webMediaPlayer| is a
// platform object that takes raw pointers.
web_media_player->SetSinkId(sink_id_, std::move(callbacks)); web_media_player->SetSinkId(sink_id_, std::move(callbacks));
return; return;
} }
...@@ -93,8 +92,15 @@ void SetSinkIdResolver::TimerFired(TimerBase* timer) { ...@@ -93,8 +92,15 @@ void SetSinkIdResolver::TimerFired(TimerBase* timer) {
auto& document = To<Document>(*context); auto& document = To<Document>(*context);
WebLocalFrameImpl* web_frame = WebLocalFrameImpl* web_frame =
WebLocalFrameImpl::FromFrame(document.GetFrame()); WebLocalFrameImpl::FromFrame(document.GetFrame());
web_frame->Client()->CheckIfAudioSinkExistsAndIsAuthorized( if (web_frame && web_frame->Client()) {
sink_id_, std::move(callbacks)); web_frame->Client()->CheckIfAudioSinkExistsAndIsAuthorized(
sink_id_, std::move(callbacks));
} else {
Reject(DOMException::Create(
DOMExceptionCode::kSecurityError,
"Impossible to authorize device if there is no frame"));
return;
}
} }
void SetSinkIdResolver::Trace(blink::Visitor* visitor) { void SetSinkIdResolver::Trace(blink::Visitor* visitor) {
......
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