blob: 8aca2511e928c63b4c9c168c014c94c59893c041 [file] [log] [blame]
// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIASTREAM_MEDIA_DEVICES_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIASTREAM_MEDIA_DEVICES_H_
#include "base/functional/callback.h"
#include "base/gtest_prod_util.h"
#include "build/build_config.h"
#include "third_party/blink/public/mojom/mediastream/media_devices.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver_with_tracker.h"
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/dom/events/event_target.h"
#include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h"
#include "third_party/blink/renderer/modules/event_target_modules.h"
#include "third_party/blink/renderer/modules/mediastream/media_device_info.h"
#include "third_party/blink/renderer/modules/mediastream/media_stream_track.h"
#include "third_party/blink/renderer/modules/mediastream/user_media_request.h"
#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/platform/heap/collection_support/heap_hash_map.h"
#include "third_party/blink/renderer/platform/heap/collection_support/heap_hash_set.h"
#include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
#include "third_party/blink/renderer/platform/mojo/heap_mojo_receiver.h"
#include "third_party/blink/renderer/platform/mojo/heap_mojo_remote.h"
#include "third_party/blink/renderer/platform/scheduler/public/post_cancellable_task.h"
#include "third_party/blink/renderer/platform/supplementable.h"
namespace blink {
class CaptureHandleConfig;
class DisplayMediaStreamOptions;
class ExceptionState;
class LocalFrame;
class Navigator;
class MediaTrackSupportedConstraints;
class ScriptPromise;
class ScriptPromiseResolver;
class ScriptState;
class UserMediaStreamConstraints;
// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
enum class EnumerateDevicesResult {
kOk = 0,
kUnknownError = 1,
kErrorCaptureServiceCrash = 2,
kErrorMediaDevicesDispatcherHostDisconnected = 3,
kTimedOut = 4,
kMaxValue = kTimedOut
};
class MODULES_EXPORT MediaDevices final
: public EventTargetWithInlineData,
public ActiveScriptWrappable<MediaDevices>,
public Supplement<Navigator>,
public ExecutionContextLifecycleObserver,
public mojom::blink::MediaDevicesListener {
DEFINE_WRAPPERTYPEINFO();
public:
static const char kSupplementName[];
static MediaDevices* mediaDevices(Navigator&);
explicit MediaDevices(Navigator&);
~MediaDevices() override;
ScriptPromise enumerateDevices(ScriptState*, ExceptionState&);
MediaTrackSupportedConstraints* getSupportedConstraints() const;
ScriptPromise getUserMedia(ScriptState*,
const UserMediaStreamConstraints*,
ExceptionState&);
ScriptPromise SendUserMediaRequest(
UserMediaRequestType,
ScriptPromiseResolverWithTracker<UserMediaRequestResult>*,
const MediaStreamConstraints*,
ExceptionState&);
ScriptPromise getAllScreensMedia(ScriptState*, ExceptionState&);
ScriptPromise getDisplayMediaSet(ScriptState*,
const DisplayMediaStreamOptions*,
ExceptionState&);
ScriptPromise getDisplayMedia(ScriptState*,
const DisplayMediaStreamOptions*,
ExceptionState&);
void setCaptureHandleConfig(ScriptState*,
const CaptureHandleConfig*,
ExceptionState&);
// Using ProduceCropTarget(), CropTarget.fromElement() can communicate
// with the browser process through the mojom pipe that `this` owns.
// TODO(crbug.com/1332628): Move most of the logic into crop_target.cc/h,
// leaving only communication in MediaDevices.
ScriptPromise ProduceCropTarget(ScriptState*, Element*, ExceptionState&);
// EventTarget overrides.
const AtomicString& InterfaceName() const override;
ExecutionContext* GetExecutionContext() const override;
void RemoveAllEventListeners() override;
// ScriptWrappable
bool HasPendingActivity() const override;
// ExecutionContextLifecycleObserver overrides.
void ContextDestroyed() override;
// mojom::blink::MediaDevicesListener implementation.
void OnDevicesChanged(mojom::blink::MediaDeviceType,
const Vector<WebMediaDeviceInfo>&) override;
// Callback for testing only.
using EnumerateDevicesTestCallback =
base::OnceCallback<void(const MediaDeviceInfoVector&)>;
void SetDispatcherHostForTesting(
mojo::PendingRemote<mojom::blink::MediaDevicesDispatcherHost>);
void SetEnumerateDevicesCallbackForTesting(
EnumerateDevicesTestCallback test_callback) {
enumerate_devices_test_callback_ = std::move(test_callback);
}
void SetConnectionErrorCallbackForTesting(base::OnceClosure test_callback) {
connection_error_test_callback_ = std::move(test_callback);
}
void SetDeviceChangeCallbackForTesting(base::OnceClosure test_callback) {
device_change_test_callback_ = std::move(test_callback);
}
void Trace(Visitor*) const override;
DEFINE_ATTRIBUTE_EVENT_LISTENER(devicechange, kDevicechange)
protected:
// EventTarget overrides.
void AddedEventListener(const AtomicString& event_type,
RegisteredEventListener&) override;
void RemovedEventListener(const AtomicString& event_type,
const RegisteredEventListener&) override;
private:
FRIEND_TEST_ALL_PREFIXES(MediaDevicesTest, ObserveDeviceChangeEvent);
void ScheduleDispatchEvent(Event*);
void DispatchScheduledEvents();
void StartObserving();
void StopObserving();
void DevicesEnumerated(
ScriptPromiseResolverWithTracker<EnumerateDevicesResult>* result_tracker,
const Vector<Vector<WebMediaDeviceInfo>>&,
Vector<mojom::blink::VideoInputDeviceCapabilitiesPtr>,
Vector<mojom::blink::AudioInputDeviceCapabilitiesPtr>);
void OnDispatcherHostConnectionError();
mojom::blink::MediaDevicesDispatcherHost& GetDispatcherHost(LocalFrame*);
#if !BUILDFLAG(IS_ANDROID)
// Manage the window of opportunity that occurs immediately after
// display-capture starts. The application can call
// CaptureController.setFocusBehavior() on the microtask where the
// Promise<MediaStream> was resolved; later calls raise an exception.
// |id| identifies the source, and therefore the track, on the browser-side.
void EnqueueMicrotaskToCloseFocusWindowOfOpportunity(const String&,
CaptureController*);
void CloseFocusWindowOfOpportunity(const String&, CaptureController*);
// Receives a message from the browser process with the crop-ID it has
// assigned to |element|.
void ResolveProduceCropIdPromise(Element* element,
const WTF::String& crop_id);
#endif
bool stopped_;
// Async runner may be null when there is no valid execution context.
// No async work may be posted in this scenario.
TaskHandle dispatch_scheduled_events_task_handle_;
HeapVector<Member<Event>> scheduled_events_;
HeapMojoRemote<mojom::blink::MediaDevicesDispatcherHost> dispatcher_host_;
HeapMojoReceiver<mojom::blink::MediaDevicesListener, MediaDevices> receiver_;
struct RequestMetadata {
base::TimeTicks start_time;
};
HeapHashMap<Member<ScriptPromiseResolverWithTracker<EnumerateDevicesResult>>,
RequestMetadata>
enumerate_device_requests_;
#if !BUILDFLAG(IS_ANDROID)
// 1. When produceCropId() is first called for an Element, it has no crop-ID
// associated. We produce a Resolver, map the Element to it, and fire
// off a message to the browser process, asking for a new crop-ID to be
// generated.
// 2. Subsequent calls to produceCropId(), which occur before the browser
// process has had time to respond, yield a copy of the original Promise
// associated with this Element.
// 3. When the message browser process responds with a crop-ID for the
// Element, we store the new crop-ID on the Element itself, resolve all
// Promises returned for this Element, and eject the resolver from this
// container.
// 4. Later calls to produceCropId() for this given Element discover that
// a crop-ID is already assigned. They immediately return a resolved
// Promise with the crop-ID.
HeapHashMap<Member<Element>, Member<ScriptPromiseResolver>>
crop_id_resolvers_;
#endif
EnumerateDevicesTestCallback enumerate_devices_test_callback_;
base::OnceClosure connection_error_test_callback_;
base::OnceClosure device_change_test_callback_;
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIASTREAM_MEDIA_DEVICES_H_