blob: f28bf5b8bba508ba6c678d6e104626aa5e96ae6b [file] [log] [blame]
// Copyright 2017 The Chromium Authors. All rights reserved.
// 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_CORE_HTML_MEDIA_AUTOPLAY_POLICY_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_MEDIA_AUTOPLAY_POLICY_H_
#include "base/optional.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/bindings/exception_code.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
namespace blink {
class AutoplayUmaHelper;
class Document;
class HTMLMediaElement;
class IntersectionObserver;
class IntersectionObserverEntry;
// AutoplayPolicy is the class for handles autoplay logics.
class CORE_EXPORT AutoplayPolicy final
: public GarbageCollected<AutoplayPolicy> {
public:
// Different autoplay policy types.
enum class Type {
kNoUserGestureRequired = 0,
// A local user gesture on the element is required.
kUserGestureRequired,
// The document needs to have received a user activation or received one
// before navigating.
kDocumentUserActivationRequired,
};
static Type GetAutoplayPolicyForDocument(const Document&);
// Return true if the given |document| is allowed to play.
// This method may check parent frames if allow=autoplay (Feature Policy) was
// used, in which case, the frame will be allowed to play if its parents are,
// and so on.
// Otherwise, frames are allowed to play if they have been activated or, for
// the main frame, if it has a high MEI.
static bool IsDocumentAllowedToPlay(const Document&);
// Returns true if the given |document| has high media engagement.
static bool DocumentHasHighMediaEngagement(const Document&);
// Returns true if the given |document| should force allow autoplay.
static bool DocumentHasForceAllowFlag(const Document&);
// Returns true if the given |document| has the user exception flag.
static bool DocumentHasUserExceptionFlag(const Document&);
// Returns true if the given |document| should autoplay muted videos.
static bool DocumentShouldAutoplayMutedVideos(const Document&);
// Returns true if the given |document| is capturing user media.
static bool DocumentIsCapturingUserMedia(const Document&);
explicit AutoplayPolicy(HTMLMediaElement*);
void VideoWillBeDrawnToCanvas() const;
// Called when the media element is moved to a new document.
void DidMoveToNewDocument(Document& old_document);
// Stop autoplaying the video element whenever its visible.
// TODO(mlamouri): hide these methods from HTMLMediaElement.
void StopAutoplayMutedWhenVisible();
// Request autoplay by attribute. This method will check the autoplay
// restrictions and record metrics. This method can only be called once per
// time the readyState changes to HAVE_ENOUGH_DATA.
bool RequestAutoplayByAttribute();
// Request the playback via play() method. This method will check the autoplay
// restrictions and record metrics. This method can only be called once
// per call of play().
base::Optional<DOMExceptionCode> RequestPlay();
// Returns whether an umute action should pause an autoplaying element. The
// method will check autoplay restrictions and record metrics. This method can
// only be called once per call of setMuted().
bool RequestAutoplayUnmute();
// Indicates the media element is or will autoplay because of being
// muted.
bool IsOrWillBeAutoplayingMuted() const;
// Unlock user gesture if a user gesture can be utilized.
void TryUnlockingUserGesture();
// Return true if and only if a user gesture is requried for playback. Even
// if isLockedPendingUserGesture() return true, this might return false if
// the requirement is currently overridden. This does not check if a user
// gesture is currently being processed.
bool IsGestureNeededForPlayback() const;
// Returns an error string to be used by the HTMLMediaElement when the play()
// method fails because of autoplay restrictions.
String GetPlayErrorMessage() const;
// Returns whether the media element was initiated via autoplay.
// In this context, autoplay means that it was initiated before any user
// activation was received on the page and before a user initiated same-domain
// navigation. In other words, with the unified autoplay policy applied, it
// should only return `true` when MEI allowed autoplay.
bool WasAutoplayInitiated() const;
// Ensure that `autoplay_initiated_` has a value. It is set to `false` to
// avoid false positives.
void EnsureAutoplayInitiatedSet();
virtual void Trace(Visitor*) const;
private:
friend class AutoplayUmaHelper;
friend class AutoplayUmaHelperTest;
// Start autoplaying the video element whenever its visible.
void StartAutoplayMutedWhenVisible();
// Returns whether the media element is eligible to autoplay muted.
bool IsEligibleForAutoplayMuted() const;
bool ShouldAutoplay();
// Return true if and only if a user gesture is required to unlock this
// media element for unrestricted autoplay/script control. Don't confuse
// this with isGestureNeededForPlayback(). The latter is usually what one
// should use, if checking to see if an action is allowed.
bool IsLockedPendingUserGesture() const;
bool IsAutoplayingMutedInternal(bool muted) const;
bool IsOrWillBeAutoplayingMutedInternal(bool muted) const;
// Called when the video visibility changes while autoplaying muted, will
// pause the video when invisible and resume the video when visible.
void OnIntersectionChangedForAutoplay(
const HeapVector<Member<IntersectionObserverEntry>>& entries);
// Returns whether the current autoplay policy is
// kDocumentUserActivationRequired. This is a helper method for readability.
bool IsUsingDocumentUserActivationRequiredPolicy() const;
// Sets `autoplay_initiated_` if it wasn't already set.
void MaybeSetAutoplayInitiated();
bool locked_pending_user_gesture_ : 1;
Member<HTMLMediaElement> element_ = nullptr;
Member<IntersectionObserver> autoplay_intersection_observer_ = nullptr;
Member<AutoplayUmaHelper> autoplay_uma_helper_;
base::Optional<bool> autoplay_initiated_;
DISALLOW_COPY_AND_ASSIGN(AutoplayPolicy);
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_HTML_MEDIA_AUTOPLAY_POLICY_H_