blob: 37e6bab3729e1a03d79457b3931844e79053d782 [file] [log] [blame]
// Copyright 2018 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_PORTAL_HTML_PORTAL_ELEMENT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_PORTAL_HTML_PORTAL_ELEMENT_H_
#include "base/optional.h"
#include "mojo/public/cpp/bindings/associated_receiver.h"
#include "mojo/public/cpp/bindings/associated_remote.h"
#include "mojo/public/cpp/bindings/pending_associated_receiver.h"
#include "third_party/blink/public/common/tokens/tokens.h"
#include "third_party/blink/public/mojom/portal/portal.mojom-blink-forward.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/dom/node.h"
#include "third_party/blink/renderer/core/html/html_frame_owner_element.h"
#include "third_party/blink/renderer/platform/scheduler/public/frame_or_worker_scheduler.h"
#include "third_party/blink/renderer/platform/wtf/casting.h"
namespace blink {
class Document;
class PortalActivateOptions;
class PortalContents;
class PostMessageOptions;
class ScriptState;
// The HTMLPortalElement implements the <portal> HTML element. The portal
// element can be used to embed another top-level browsing context, which can be
// activated using script. The portal element is still under development and not
// part of the HTML standard. It can be enabled by passing
// --enable-features=Portals. See also https://github.com/WICG/portals.
class CORE_EXPORT HTMLPortalElement : public HTMLFrameOwnerElement {
DEFINE_WRAPPERTYPEINFO();
public:
// |portal_token|, |remote_portal| and |portal_client_receiver| are all empty
// when an empty HTMLPortalElement is constructed, (it hasn't yet been
// attached to an actual contents).
explicit HTMLPortalElement(
Document& document,
const PortalToken* portal_token = nullptr,
mojo::PendingAssociatedRemote<mojom::blink::Portal> remote_portal = {},
mojo::PendingAssociatedReceiver<mojom::blink::PortalClient>
portal_client_receiver = {});
~HTMLPortalElement() override;
bool IsHTMLPortalElement() const final { return true; }
// ScriptWrappable overrides.
void Trace(Visitor* visitor) const override;
// idl implementation.
ScriptPromise activate(ScriptState*, PortalActivateOptions*, ExceptionState&);
void postMessage(ScriptState* script_state,
const ScriptValue& message,
const PostMessageOptions* options,
ExceptionState& exception_state);
EventListener* onmessage();
void setOnmessage(EventListener* listener);
EventListener* onmessageerror();
void setOnmessageerror(EventListener* listener);
const PortalToken& GetToken() const;
mojom::blink::FrameOwnerElementType OwnerType() const override {
return mojom::blink::FrameOwnerElementType::kPortal;
}
// Consumes the portal interface. When a Portal is activated, or if the
// renderer receives a connection error, this function will gracefully
// terminate the portal interface.
void ConsumePortal();
// Invoked when this element should no longer keep its guest contents alive
// due to recent adoption.
void ExpireAdoptionLifetime();
// Called by PortalContents when it is about to be destroyed.
void PortalContentsWillBeDestroyed(PortalContents*);
private:
// Returns a null string if the checks passed, and a suitable error otherwise.
String PreActivateChecksCommon();
// Performs a default activation (e.g. due to an unprevented click), as
// opposed to one requested by invoking HTMLPortalElement::activate.
void ActivateDefault();
// Checks whether the Portals feature is enabled for this document, and logs a
// warning to the developer if not. Doing basically anything with an
// HTMLPortalElement in a document which doesn't support portals is forbidden.
bool CheckPortalsEnabledOrWarn() const;
bool CheckPortalsEnabledOrThrow(ExceptionState&) const;
// Checks if, when inserted, we were beyond the frame limit. If so, we will
// disable navigating the portal and insertion (and will display a warning in
// the console).
bool CheckWithinFrameLimitOrWarn() const;
// Checks that the number of frames and portals on the page are within the
// limit.
bool IsCurrentlyWithinFrameLimit() const;
enum class GuestContentsEligibility {
// Can have a guest contents.
kEligible,
// Ineligible as it is not top-level.
kNotTopLevel,
// Ineligible as it is sandboxed.
kSandboxed,
// Ineligible as the host's protocol is not in the HTTP family.
kNotHTTPFamily,
// Ineligible for additional reasons.
kIneligible,
};
GuestContentsEligibility GetGuestContentsEligibility() const;
bool CanHaveGuestContents() const {
return GetGuestContentsEligibility() == GuestContentsEligibility::kEligible;
}
// Navigates the portal to |url_|.
void Navigate();
// Node overrides
InsertionNotificationRequest InsertedInto(ContainerNode&) override;
void RemovedFrom(ContainerNode&) override;
void DefaultEventHandler(Event&) override;
// Element overrides
bool IsURLAttribute(const Attribute&) const override;
void ParseAttribute(const AttributeModificationParams&) override;
LayoutObject* CreateLayoutObject(const ComputedStyle&, LegacyLayout) override;
bool SupportsFocus() const override;
// HTMLFrameOwnerElement overrides
void DisconnectContentFrame() override;
ParsedFeaturePolicy ConstructContainerPolicy() const override {
return ParsedFeaturePolicy();
}
void AttachLayoutTree(AttachContext& context) override;
network::mojom::ReferrerPolicy ReferrerPolicyAttribute() override;
Member<PortalContents> portal_;
network::mojom::ReferrerPolicy referrer_policy_ =
network::mojom::ReferrerPolicy::kDefault;
// Temporarily set to keep this element alive after adoption.
bool was_just_adopted_ = false;
// Disable BackForwardCache when using the portal feature, because we do not
// handle the state inside the portal after putting the page in cache.
FrameOrWorkerScheduler::SchedulingAffectingFeatureHandle
feature_handle_for_scheduler_;
};
// Type casting. Custom since adoption could lead to an HTMLPortalElement ending
// up in a document that doesn't have Portals enabled.
template <>
struct DowncastTraits<HTMLPortalElement> {
static bool AllowFrom(const HTMLElement& element) {
return element.IsHTMLPortalElement();
}
static bool AllowFrom(const Node& node) {
if (const HTMLElement* html_element = DynamicTo<HTMLElement>(node))
return html_element->IsHTMLPortalElement();
return false;
}
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_HTML_PORTAL_HTML_PORTAL_ELEMENT_H_