geolocation.h 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. /*
  2. * Copyright (C) 2008, 2009, 2010, 2011 Apple Inc. All Rights Reserved.
  3. * Copyright 2010, The Android Open Source Project
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. *
  14. * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
  15. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  16. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  17. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
  18. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  19. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  20. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  21. * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  22. * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  23. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  24. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25. */
  26. #ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_GEOLOCATION_GEOLOCATION_H_
  27. #define THIRD_PARTY_BLINK_RENDERER_MODULES_GEOLOCATION_GEOLOCATION_H_
  28. #include "services/device/public/mojom/geolocation.mojom-blink.h"
  29. #include "third_party/blink/public/mojom/geolocation/geolocation_service.mojom-blink.h"
  30. #include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h"
  31. #include "third_party/blink/renderer/bindings/modules/v8/v8_position_callback.h"
  32. #include "third_party/blink/renderer/bindings/modules/v8/v8_position_error_callback.h"
  33. #include "third_party/blink/renderer/bindings/modules/v8/v8_position_options.h"
  34. #include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h"
  35. #include "third_party/blink/renderer/core/page/page_visibility_observer.h"
  36. #include "third_party/blink/renderer/modules/geolocation/geo_notifier.h"
  37. #include "third_party/blink/renderer/modules/geolocation/geolocation_position_error.h"
  38. #include "third_party/blink/renderer/modules/geolocation/geolocation_watchers.h"
  39. #include "third_party/blink/renderer/modules/geolocation/geoposition.h"
  40. #include "third_party/blink/renderer/modules/modules_export.h"
  41. #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
  42. #include "third_party/blink/renderer/platform/heap/handle.h"
  43. #include "third_party/blink/renderer/platform/mojo/heap_mojo_remote.h"
  44. #include "third_party/blink/renderer/platform/timer.h"
  45. namespace blink {
  46. namespace mojom {
  47. enum class PermissionStatus;
  48. } // namespace mojom
  49. class LocalDOMWindow;
  50. class LocalFrame;
  51. class ExecutionContext;
  52. class MODULES_EXPORT Geolocation final
  53. : public ScriptWrappable,
  54. public ActiveScriptWrappable<Geolocation>,
  55. public ExecutionContextLifecycleObserver,
  56. public PageVisibilityObserver {
  57. DEFINE_WRAPPERTYPEINFO();
  58. public:
  59. static Geolocation* Create(ExecutionContext*);
  60. explicit Geolocation(ExecutionContext*);
  61. ~Geolocation() override;
  62. void Trace(Visitor*) const override;
  63. // Inherited from ExecutionContextLifecycleObserver and
  64. // PageVisibilityObserver.
  65. void ContextDestroyed() override;
  66. LocalDOMWindow* GetWindow() const;
  67. LocalFrame* GetFrame() const;
  68. // Creates a oneshot and attempts to obtain a position that meets the
  69. // constraints of the options.
  70. void getCurrentPosition(V8PositionCallback*,
  71. V8PositionErrorCallback* = nullptr,
  72. const PositionOptions* = PositionOptions::Create());
  73. // Creates a watcher that will be notified whenever a new position is
  74. // available that meets the constraints of the options.
  75. int watchPosition(V8PositionCallback*,
  76. V8PositionErrorCallback* = nullptr,
  77. const PositionOptions* = PositionOptions::Create());
  78. // Removes all references to the watcher, it will not be updated again.
  79. void clearWatch(int watch_id);
  80. // Notifies this that a new position is available. Must never be called
  81. // before permission is granted by the user.
  82. void PositionChanged();
  83. // Discards the notifier because a fatal error occurred for it.
  84. void FatalErrorOccurred(GeoNotifier*);
  85. // Adds the notifier to the set awaiting a cached position. Runs the success
  86. // callbacks for them if permission has been granted. Requests permission if
  87. // it is unknown.
  88. void RequestUsesCachedPosition(GeoNotifier*);
  89. // Discards the notifier if it is a oneshot because it timed it.
  90. void RequestTimedOut(GeoNotifier*);
  91. // Returns true if this geolocation still owns the given notifier.
  92. bool DoesOwnNotifier(GeoNotifier*) const;
  93. // Inherited from PageVisibilityObserver.
  94. void PageVisibilityChanged() override;
  95. // TODO(yukishiino): This is a short-term speculative fix for
  96. // crbug.com/792604. Remove this once the bug is fixed.
  97. bool HasPendingActivity() const final;
  98. private:
  99. // Customized HeapHashSet class that checks notifiers' timers. Notifier's
  100. // timer may be active only when the notifier is owned by the Geolocation.
  101. class GeoNotifierSet : private HeapHashSet<Member<GeoNotifier>> {
  102. using BaseClass = HeapHashSet<Member<GeoNotifier>>;
  103. public:
  104. using BaseClass::Trace;
  105. using BaseClass::const_iterator;
  106. using BaseClass::iterator;
  107. using BaseClass::begin;
  108. using BaseClass::end;
  109. using BaseClass::size;
  110. auto insert(GeoNotifier* value) {
  111. DCHECK(!value->IsTimerActive());
  112. return BaseClass::insert(value);
  113. }
  114. void erase(GeoNotifier* value) {
  115. DCHECK(!value->IsTimerActive());
  116. return BaseClass::erase(value);
  117. }
  118. void clear() {
  119. #if DCHECK_IS_ON()
  120. for (const auto& notifier : *this) {
  121. DCHECK(!notifier->IsTimerActive());
  122. }
  123. #endif
  124. BaseClass::clear();
  125. }
  126. using BaseClass::Contains;
  127. using BaseClass::IsEmpty;
  128. auto InsertWithoutTimerCheck(GeoNotifier* value) {
  129. return BaseClass::insert(value);
  130. }
  131. void ClearWithoutTimerCheck() { BaseClass::clear(); }
  132. };
  133. bool HasListeners() const {
  134. return !one_shots_.IsEmpty() || !watchers_->IsEmpty();
  135. }
  136. void StopTimers();
  137. // Runs the success callbacks on all notifiers. A position must be available
  138. // and the user must have given permission.
  139. void MakeSuccessCallbacks();
  140. // Sends the given error to all notifiers, unless the error is not fatal and
  141. // the notifier is due to receive a cached position. Clears the oneshots,
  142. // and also clears the watchers if the error is fatal.
  143. void HandleError(GeolocationPositionError*);
  144. // Connects to the Geolocation mojo service and starts polling for updates.
  145. void StartUpdating(GeoNotifier*);
  146. void StopUpdating();
  147. void UpdateGeolocationConnection(GeoNotifier*);
  148. void QueryNextPosition();
  149. // Attempts to obtain a position for the given notifier, either by using
  150. // the cached position or by requesting one from the Geolocation service.
  151. // Sets a fatal error if permission is denied or no position can be
  152. // obtained.
  153. void StartRequest(GeoNotifier*);
  154. bool HaveSuitableCachedPosition(const PositionOptions*);
  155. // Record whether the origin trying to access Geolocation would be
  156. // allowed to access a feature that can only be accessed by secure origins.
  157. // See https://goo.gl/Y0ZkNV
  158. void RecordOriginTypeAccess() const;
  159. void OnPositionUpdated(device::mojom::blink::GeopositionPtr);
  160. void OnGeolocationConnectionError();
  161. void OnGeolocationPermissionStatusUpdated(GeoNotifier*,
  162. mojom::PermissionStatus);
  163. GeoNotifierSet one_shots_;
  164. Member<GeolocationWatchers> watchers_;
  165. // GeoNotifiers that are in the middle of invocation.
  166. //
  167. // |HandleError(error)| and |MakeSuccessCallbacks| need to clear |one_shots_|
  168. // (and optionally |watchers_|) before invoking the callbacks, in order to
  169. // avoid clearing notifiers added by calls to Geolocation methods
  170. // from the callbacks. Thus, something else needs to make the notifiers being
  171. // invoked alive with wrapper-tracing because V8 GC may run during the
  172. // callbacks. |one_shots_being_invoked_| and |watchers_being_invoked_| perform
  173. // wrapper-tracing.
  174. // TODO(https://crbug.com/796145): Remove this hack once on-stack objects
  175. // get supported by either of wrapper-tracing or unified GC.
  176. GeoNotifierSet one_shots_being_invoked_;
  177. HeapVector<Member<GeoNotifier>> watchers_being_invoked_;
  178. Member<Geoposition> last_position_;
  179. HeapMojoRemote<device::mojom::blink::Geolocation> geolocation_;
  180. HeapMojoRemote<mojom::blink::GeolocationService> geolocation_service_;
  181. bool enable_high_accuracy_ = false;
  182. // Whether a GeoNotifier is waiting for a position update.
  183. bool updating_ = false;
  184. // Set to true when |geolocation_| is disconnected. This is used to
  185. // detect when |geolocation_| is disconnected and reconnected while
  186. // running callbacks in response to a call to OnPositionUpdated().
  187. bool disconnected_geolocation_ = false;
  188. };
  189. } // namespace blink
  190. #endif // THIRD_PARTY_BLINK_RENDERER_MODULES_GEOLOCATION_GEOLOCATION_H_