blob: edec6c1fd77584367327a3736de435cbdf02e69a [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.
#include "third_party/blink/renderer/core/frame/viewport_data.h"
#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_client.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/page/chrome_client.h"
#include "third_party/blink/renderer/core/page/page.h"
namespace blink {
ViewportData::ViewportData(Document& document) : document_(document) {}
void ViewportData::Trace(Visitor* visitor) {
visitor->Trace(document_);
}
void ViewportData::Shutdown() {
// TODO(https://crbug.com/800641): Use InterfaceInvalidator once it works with
// associated interfaces.
display_cutout_host_.reset();
}
bool ViewportData::ShouldMergeWithLegacyDescription(
ViewportDescription::Type origin) const {
return document_->GetSettings() &&
document_->GetSettings()->GetViewportMetaMergeContentQuirk() &&
legacy_viewport_description_.IsMetaViewportType() &&
legacy_viewport_description_.type == origin;
}
void ViewportData::SetViewportDescription(
const ViewportDescription& viewport_description) {
if (viewport_description.IsLegacyViewportType()) {
if (viewport_description == legacy_viewport_description_)
return;
legacy_viewport_description_ = viewport_description;
} else {
if (viewport_description == viewport_description_)
return;
viewport_description_ = viewport_description;
// The UA-defined min-width is considered specifically by Android WebView
// quirks mode.
if (!viewport_description.IsSpecifiedByAuthor())
viewport_default_min_width_ = viewport_description.min_width;
}
UpdateViewportDescription();
}
ViewportDescription ViewportData::GetViewportDescription() const {
ViewportDescription applied_viewport_description = viewport_description_;
bool viewport_meta_enabled =
document_->GetSettings() &&
document_->GetSettings()->GetViewportMetaEnabled();
if (legacy_viewport_description_.type !=
ViewportDescription::kUserAgentStyleSheet &&
viewport_meta_enabled)
applied_viewport_description = legacy_viewport_description_;
if (ShouldOverrideLegacyDescription(viewport_description_.type))
applied_viewport_description = viewport_description_;
return applied_viewport_description;
}
void ViewportData::UpdateViewportDescription() {
if (!document_->GetFrame())
return;
// If the viewport_fit has changed we should send this to the browser. We
// use the legacy viewport description which contains the viewport_fit
// defined from the layout meta tag.
mojom::ViewportFit current_viewport_fit =
GetViewportDescription().GetViewportFit();
// If we are forcing to expand into the display cutout then we should override
// the viewport fit value.
if (force_expand_display_cutout_)
current_viewport_fit = mojom::ViewportFit::kCoverForcedByUserAgent;
if (viewport_fit_ != current_viewport_fit) {
if (AssociatedInterfaceProvider* provider =
document_->GetFrame()
->Client()
->GetRemoteNavigationAssociatedInterfaces()) {
// Bind the mojo interface.
if (!display_cutout_host_.is_bound()) {
provider->GetInterface(&display_cutout_host_);
DCHECK(display_cutout_host_.is_bound());
}
// Even though we bind the mojo interface above there still may be cases
// where this will fail (e.g. unit tests).
display_cutout_host_->NotifyViewportFitChanged(current_viewport_fit);
}
viewport_fit_ = current_viewport_fit;
}
if (document_->GetFrame()->IsMainFrame()) {
document_->GetPage()->GetChromeClient().DispatchViewportPropertiesDidChange(
GetViewportDescription());
}
}
void ViewportData::SetExpandIntoDisplayCutout(bool expand) {
if (force_expand_display_cutout_ == expand)
return;
force_expand_display_cutout_ = expand;
UpdateViewportDescription();
}
} // namespace blink