blob: 04cbcc4a4b40b433ef9a3efed5522c663b8fdb70 [file] [log] [blame]
// Copyright 2014 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 "modules/device_orientation/DeviceOrientationController.h"
#include "core/frame/Deprecation.h"
#include "core/frame/FrameConsole.h"
#include "core/frame/HostsUsingFeatures.h"
#include "core/frame/Settings.h"
#include "core/inspector/ConsoleMessage.h"
#include "modules/EventModules.h"
#include "modules/device_orientation/DeviceOrientationData.h"
#include "modules/device_orientation/DeviceOrientationDispatcher.h"
#include "modules/device_orientation/DeviceOrientationEvent.h"
#include "platform/feature_policy/FeaturePolicy.h"
#include "platform/weborigin/SecurityOrigin.h"
#include "platform/wtf/Assertions.h"
#include "public/platform/Platform.h"
namespace blink {
DeviceOrientationController::DeviceOrientationController(Document& document)
: DeviceSingleWindowEventController(document),
Supplement<Document>(document) {}
DeviceOrientationController::~DeviceOrientationController() = default;
void DeviceOrientationController::DidUpdateData() {
if (override_orientation_data_)
return;
DispatchDeviceEvent(LastEvent());
}
const char* DeviceOrientationController::SupplementName() {
return "DeviceOrientationController";
}
DeviceOrientationController& DeviceOrientationController::From(
Document& document) {
DeviceOrientationController* controller =
static_cast<DeviceOrientationController*>(
Supplement<Document>::From(document, SupplementName()));
if (!controller) {
controller = new DeviceOrientationController(document);
Supplement<Document>::ProvideTo(document, SupplementName(), controller);
}
return *controller;
}
void DeviceOrientationController::DidAddEventListener(
LocalDOMWindow* window,
const AtomicString& event_type) {
if (event_type != EventTypeName())
return;
LocalFrame* frame = GetDocument().GetFrame();
if (frame) {
if (GetDocument().IsSecureContext()) {
UseCounter::Count(frame, WebFeature::kDeviceOrientationSecureOrigin);
} else {
Deprecation::CountDeprecation(
frame, WebFeature::kDeviceOrientationInsecureOrigin);
HostsUsingFeatures::CountAnyWorld(
GetDocument(),
HostsUsingFeatures::Feature::kDeviceOrientationInsecureHost);
if (GetDocument()
.GetFrame()
->GetSettings()
->GetStrictPowerfulFeatureRestrictions())
return;
}
}
if (!has_event_listener_) {
Platform::Current()->RecordRapporURL("DeviceSensors.DeviceOrientation",
WebURL(GetDocument().Url()));
if (!IsSameSecurityOriginAsMainFrame()) {
Platform::Current()->RecordRapporURL(
"DeviceSensors.DeviceOrientationCrossOrigin",
WebURL(GetDocument().Url()));
}
if (!CheckPolicyFeatures({FeaturePolicyFeature::kAccelerometer,
FeaturePolicyFeature::kGyroscope})) {
LogToConsolePolicyFeaturesDisabled(frame, EventTypeName());
return;
}
}
DeviceSingleWindowEventController::DidAddEventListener(window, event_type);
}
DeviceOrientationData* DeviceOrientationController::LastData() const {
return override_orientation_data_
? override_orientation_data_.Get()
: DispatcherInstance().LatestDeviceOrientationData();
}
bool DeviceOrientationController::HasLastData() {
return LastData();
}
void DeviceOrientationController::RegisterWithDispatcher() {
DispatcherInstance().AddController(this);
}
void DeviceOrientationController::UnregisterWithDispatcher() {
DispatcherInstance().RemoveController(this);
}
Event* DeviceOrientationController::LastEvent() const {
return DeviceOrientationEvent::Create(EventTypeName(), LastData());
}
bool DeviceOrientationController::IsNullEvent(Event* event) const {
DeviceOrientationEvent* orientation_event = ToDeviceOrientationEvent(event);
return !orientation_event->Orientation()->CanProvideEventData();
}
const AtomicString& DeviceOrientationController::EventTypeName() const {
return EventTypeNames::deviceorientation;
}
void DeviceOrientationController::SetOverride(
DeviceOrientationData* device_orientation_data) {
DCHECK(device_orientation_data);
override_orientation_data_ = device_orientation_data;
DispatchDeviceEvent(LastEvent());
}
void DeviceOrientationController::ClearOverride() {
if (!override_orientation_data_)
return;
override_orientation_data_.Clear();
if (LastData())
DidUpdateData();
}
DeviceOrientationDispatcher& DeviceOrientationController::DispatcherInstance()
const {
return DeviceOrientationDispatcher::Instance(false);
}
void DeviceOrientationController::Trace(blink::Visitor* visitor) {
visitor->Trace(override_orientation_data_);
DeviceSingleWindowEventController::Trace(visitor);
Supplement<Document>::Trace(visitor);
}
// static
void DeviceOrientationController::LogToConsolePolicyFeaturesDisabled(
LocalFrame* frame,
const AtomicString& event_name) {
if (!frame)
return;
const String& message = String::Format(
"The %s events are blocked by feature policy. "
"See "
"https://github.com/WICG/feature-policy/blob/gh-pages/"
"features.md#sensor-features",
event_name.Ascii().data());
ConsoleMessage* console_message = ConsoleMessage::Create(
kJSMessageSource, kWarningMessageLevel, std::move(message));
frame->Console().AddMessage(console_message);
}
} // namespace blink