Index: third_party/WebKit/Source/modules/sensor/Sensor.cpp |
diff --git a/third_party/WebKit/Source/modules/sensor/Sensor.cpp b/third_party/WebKit/Source/modules/sensor/Sensor.cpp |
index ca613f9e1e8670fb65e75c1ba499ec3b0a9a2004..5c07a6de5e691e9dd6376081ab91d555295fb222 100644 |
--- a/third_party/WebKit/Source/modules/sensor/Sensor.cpp |
+++ b/third_party/WebKit/Source/modules/sensor/Sensor.cpp |
@@ -9,16 +9,22 @@ |
#include "core/dom/ExecutionContextTask.h" |
#include "core/inspector/ConsoleMessage.h" |
#include "device/generic_sensor/public/interfaces/sensor.mojom-blink.h" |
+#include "modules/permissions/PermissionUtils.h" |
#include "modules/sensor/SensorErrorEvent.h" |
#include "modules/sensor/SensorPollingStrategy.h" |
#include "modules/sensor/SensorProviderProxy.h" |
#include "modules/sensor/SensorReading.h" |
#include "modules/sensor/SensorReadingEvent.h" |
+#include "platform/UserGestureIndicator.h" |
using namespace device::mojom::blink; |
namespace blink { |
+using mojom::blink::PermissionName; |
+using mojom::blink::PermissionService; |
+using mojom::blink::PermissionStatus; |
+ |
Sensor::Sensor(ScriptState* scriptState, |
const SensorOptions& sensorOptions, |
ExceptionState& exceptionState, |
@@ -30,7 +36,8 @@ Sensor::Sensor(ScriptState* scriptState, |
m_sensorOptions(sensorOptions), |
m_type(type), |
m_state(Sensor::SensorState::IDLE), |
- m_storedData() { |
+ m_storedData(), |
+ m_sensorPermission(PermissionStatus::ASK) { |
// Check secure context. |
String errorMessage; |
if (!scriptState->getExecutionContext()->isSecureContext(errorMessage)) { |
@@ -46,6 +53,16 @@ Sensor::Sensor(ScriptState* scriptState, |
return; |
} |
+ // Get permission service. |
+ PermissionService* permissionService = |
+ getPermissionService(scriptState->getExecutionContext()); |
+ |
+ if (!permissionService) { |
+ exceptionState.throwDOMException( |
+ InvalidStateError, |
+ "In its current state, the global scope can't request permissions"); |
+ } |
+ |
// Check the given frequency value. |
if (m_sensorOptions.hasFrequency()) { |
double frequency = m_sensorOptions.frequency(); |
@@ -63,7 +80,25 @@ Sensor::Sensor(ScriptState* scriptState, |
} |
} |
-Sensor::~Sensor() = default; |
+Sensor::~Sensor() { |
+ m_permissionService.reset(); |
+} |
+ |
+void Sensor::permissionServiceConnectionError() { |
+ m_permissionService.reset(); |
+} |
+ |
+PermissionService* Sensor::getPermissionService( |
+ ExecutionContext* executionContext) { |
+ if (!m_permissionService && |
+ connectToPermissionService(executionContext, |
+ mojo::GetProxy(&m_permissionService))) { |
+ m_permissionService.set_connection_error_handler(convertToBaseCallback( |
+ WTF::bind(&Sensor::permissionServiceConnectionError, |
+ wrapWeakPersistent(this)))); |
+ } |
+ return m_permissionService.get(); |
+} |
void Sensor::start(ScriptState* scriptState, ExceptionState& exceptionState) { |
if (m_state != Sensor::SensorState::IDLE && |
@@ -82,7 +117,64 @@ void Sensor::start(ScriptState* scriptState, ExceptionState& exceptionState) { |
return; |
} |
- startListening(); |
+ // If the algorithm is not allowed to show a popup, throw SecurityError. |
+ if (!UserGestureIndicator::consumeUserGesture()) { |
+ exceptionState.throwDOMException( |
+ SecurityError, |
+ "Must be handling a user gesture to show a permission request."); |
+ return; |
+ } |
+ |
+ // Check permissions. |
+ m_permissionService->HasPermission( |
shalamov
2016/10/27 08:47:25
What happens if you call start(), then permission
|
+ createPermissionDescriptor(PermissionName::SENSORS), |
+ scriptState->getExecutionContext()->getSecurityOrigin(), |
+ convertToBaseCallback( |
+ WTF::bind(&Sensor::onPermissionUpdate, wrapPersistent(this), |
+ wrapPersistent(scriptState->getExecutionContext())))); |
+ |
+ // Keep listening for next change in permission. |
+ // TODO(riju): Re-use same onPermissionUpdate callback for everything? |
+ m_permissionService->GetNextPermissionChange( |
shalamov
2016/10/27 08:47:25
I think logic should be different.
Initially we d
|
+ createPermissionDescriptor(PermissionName::SENSORS), |
+ scriptState->getExecutionContext()->getSecurityOrigin(), |
+ m_sensorPermission, |
+ convertToBaseCallback( |
+ WTF::bind(&Sensor::onPermissionUpdate, wrapPersistent(this), |
+ wrapPersistent(scriptState->getExecutionContext())))); |
+} |
+ |
+void Sensor::requestPermission(ExecutionContext* executionContext, |
+ PermissionStatus status) { |
+ m_permissionService->RequestPermission( |
+ createPermissionDescriptor(PermissionName::SENSORS), |
+ executionContext->getSecurityOrigin(), |
+ UserGestureIndicator::processingUserGesture(), |
+ convertToBaseCallback(WTF::bind(&Sensor::onPermissionUpdate, |
+ wrapPersistent(this), |
+ wrapPersistent(executionContext)))); |
+} |
+ |
+void Sensor::onPermissionUpdate(ExecutionContext* executionContext, |
shalamov
2016/10/27 08:47:25
I think permission checking should not be bound to
|
+ PermissionStatus status) { |
+ m_sensorPermission = status; |
+ |
+ // m_permissionService.reset(); |
+ |
+ if (m_sensorPermission == PermissionStatus::GRANTED) { |
+ startListening(); |
shalamov
2016/10/27 08:47:25
ditto, what if user called stop() before permissio
|
+ } else if (m_sensorPermission == PermissionStatus::ASK) { |
+ requestPermission(executionContext, status); |
+ } else if (m_sensorPermission == PermissionStatus::DENIED) { |
+ stopListening(); |
+ |
+ ConsoleMessage* consoleMessage = ConsoleMessage::create( |
+ JSMessageSource, InfoMessageLevel, "Permission Rejected."); |
+ executionContext->addConsoleMessage(consoleMessage); |
+ |
+ reportError(PermissionDeniedError, |
+ "start() call has failed as permission was denied."); |
+ } |
} |
void Sensor::stop(ScriptState*, ExceptionState& exceptionState) { |
@@ -154,6 +246,7 @@ void Sensor::contextDestroyed() { |
if (m_state == Sensor::SensorState::ACTIVE || |
m_state == Sensor::SensorState::ACTIVATING) |
stopListening(); |
+ m_permissionService.reset(); |
} |
void Sensor::onSensorInitialized() { |