7

console.log(navigator.geolocation) //undefined

console.log(navigator):

WorkerNavigator {hardwareConcurrency: 8, appCodeName: "Mozilla", appName: "Netscape", appVersion: "5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKi…L, like Gecko) Chrome/73.0.3683.103 Safari/537.36", …}
appCodeName: "Mozilla"
appName: "Netscape"
appVersion: "5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36"
connection: NetworkInformation {onchange: null, effectiveType: "4g", rtt: 100, downlink: 4.3, saveData: false}
deviceMemory: 8
hardwareConcurrency: 8
language: "en-US"
languages: (3) ["en-US", "en", "es"]
locks: LockManager {}
onLine: true
permissions: Permissions {}
platform: "MacIntel"
product: (...)
storage: StorageManager {}
usb: USB {onconnect: null, ondisconnect: null}
userAgent: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36"
get product: ƒ getValue()
set product: ƒ setValue(newValue)
__proto__: WorkerNavigator

I am using React Native 0.59 on iOS.

In info.plist, I have both: Privacy - Location When In Use Usage Description and Privacy - Location Always and When In Use Usage Description

CocoaPods: http://dpaste.com/2W9Y57E Info.plist: http://dpaste.com/1CTG8GP

TIMEX
  • 259,804
  • 351
  • 777
  • 1,080
  • Why does `navigator` turn into `WorkerNavigator`? – TIMEX May 06 '19 at 03:15
  • [does your iphone have geolocation enabled](https://www.badgermapping.com/knowledgebase/turn-geolocation-iphone/)? – Fabrizio Bertoglio May 08 '19 at 08:24
  • Can you post your `Info.plist` and also if you're using cocoapods – Pritish Vaidya May 08 '19 at 11:41
  • Do you have `RCTGeolocation.xcodeproj` as a sub-project under libraries? Open xcode and check the section under libraries. Share the way you have created this project as by default it should work. if you are using cocoapod for react, then you need to add subspec `RCTGeolocation` – manishg May 08 '19 at 19:03
  • @manishg I did not have `RCTGeolocation.xcodeproj` in Libraries, but I just added it. I also linked binary `libRCTGeolocation.a` to libraries. However, when I console.log(navigator), I still get `WorkerNavigator` without the geolocation option. – TIMEX May 08 '19 at 20:47
  • @manishg what do you mean add to subspecs? What if I want to keep my Podfile as-is? – TIMEX May 08 '19 at 20:57
  • react-native uses [`navigator.geolocation`](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/geolocation) as a browser polyfill. The issue may be with the mobile browser. You could try to test the `navigator` interface in your mobile safari browser [with the developer tools following this instructions](https://stackoverflow.com/a/55807314/7295772) – Fabrizio Bertoglio May 09 '19 at 08:27
  • @TIMEX I still believe the JS binding is not done correctly. I would dig more to see if the libraries are linked correctly. Maybe compare your project with the build log or project structure of a sample project created using “react native init”. I looked at your cocoa pod snippet and I see that you are not using react pod so you don’t need the subspec – manishg May 09 '19 at 22:33
  • @TIMEX I believe it is an issue with `navigator.geolocation` and I include the [`geolocation api interface` specifications](https://w3c.github.io/geolocation-api/#geolocation_interface). There is a [bug](https://bugs.chromium.org/p/chromium/issues/detail?id=630305) affecting `Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36`. You can find [the open github issue in the `w3c/geolocation-api` repo](https://github.com/w3c/geolocation-api/issues/11). – Fabrizio Bertoglio May 10 '19 at 22:04
  • @TIMEX [Geolocation API Removed from Unsecured Origins in Chrome 50](https://developers.google.com/web/updates/2016/04/geolocation-on-secure-contexts-only). Starting with Chrome 50, Chrome no longer supports obtaining the user's location using the HTML5 Geolocation API **from pages delivered by non-secure connections**. This means that **the page that's making the Geolocation API call must be served from a secure context such as HTTPS**. – Fabrizio Bertoglio May 10 '19 at 22:08
  • another question is why the [interface](https://w3c.github.io/geolocation-api/#navigator_interface) `partial interface Navigator { readonly attribute Geolocation geolocation; };` is missing the geolocation. You can head to any website and deny authorization to be geolocated (I just did) and `navigator.geolocation` will be defined, the only difference is that `navigator.geolocation.getCurrentPosition()` will not return the `position`. – Fabrizio Bertoglio May 10 '19 at 22:20

2 Answers2

5

The WorkerNavigator interface represents a subset of the Navigator interface allowed to be accessed from a Worker. Such an object is initialized for each worker and is available via the WorkerGlobalScope.navigator property obtained by calling window.self.navigator.

The Worker interface of the Web Workers API represents a background task that can be easily created and can send messages back to its creator. Creating a worker is as simple as calling the Worker() constructor and specifying a script to be run in the worker thread.

running navigator on any web page will return a Navigator instance

>> navigator
Navigator { permissions: Permissions, mimeTypes: MimeTypeArray, plugins: PluginArray, doNotTrack: "unspecified", maxTouchPoints: 0, mediaCapabilities: MediaCapabilities, oscpu: "Intel Mac OS X 10.13", vendor: "", vendorSub: "", productSub: "20100101" }

running navigator inside the react-native app will return a WorkerNavigator instance. The WorkerNavigator is a background task.

>> navigator
WorkerNavigator { geolocation: Object, hardwareConcurrency: 4, appCodeName: "Mozilla", appName: "Netscape"… }

The WorkerNavigator interface is not fully compatible/tested with all browsers, but I tested the functionality on the Iphone X emulator and navigator.geolocation is defined.

Worker Navigator Compatability with Browsers

Several posts on stackoverflow complain about Chrome or Safari returning WorkerNavigator geolocation undefined and as explained in the following answer

Does navigator.geolocation belong to navigator in Chrome?

navigator.geolocation belongs to navigator in the main thread only, but doesn't belong to navigator in the worker thread.

two navigators have independent implementations on the C++ side. That is why navigator.geolocation is not supported in the worker thread.

Chromium includes separates interfaces for the Navigator and the WorkerNavigator C++ implementation.

Navigator is an attribute of DOMWindow, while WorkerNavigator is an attribute of WorkerGlobalScope.

Users on StackOverflow complain that chrome webworker does not have the geolocation attribute

The navigator attribute of the WorkerGlobalScope interface must return an instance of the WorkerNavigator interface, which represents the identity and state of the user agent (the client):

[Exposed=Worker]
interface WorkerNavigator {};
WorkerNavigator includes NavigatorID;
WorkerNavigator includes NavigatorLanguage;
WorkerNavigator includes NavigatorOnLine;
WorkerNavigator includes NavigatorConcurrentHardware;

The geolocation method is not included in the WorkerNavigation and WorkerLocation interfaces

The Navigator is initialized for each worker and is available via the WorkerGlobalScope.navigator property obtained by calling window.self.navigator.

as described in the WorkerNavigator api docs, it does not include the geolocation() method.

If you persist having this issue you may consider following this guide, manually creating your worker and testing the methods on different browsers.

navigator.permissions? to detect geolocation support

The WorkerNavigator.permissions read-only property returns a Permissions object that can be used to query and update permission status of APIs covered by the Permissions API.

self.permissions.query({name:'notifications'}).then(function(result) {
  if (result.state === 'granted') {
    showNotification();
  } else if (result.state === 'prompt') {
    requestNotificationPermission()
  }
});

More information here

Steps to Troubleshoot the Issue

  1. You are running console.log with the react-native-debugger tools and maybe the output is the one given from your mac browser and not your phone. Disable debugging on your emulator and show us the output of console.warn(navigator) and console.warn(navigator.geolocation)

    appVersion: "5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103
    Safari/537.36"
    

As in the image below, console.warn(navigator) will return a WorkerNavigator Object in the react-native-debugger-tools, while it returns {product:"ReactNative", "geolocation": {}} in the emulator. React-native will not display the console.log inside the emulator.

enter image description here

  1. Do you experiment this issue only on Iphone or also on Android?
  2. are you wrongly importing the geolocation object on top of your component?

    import { navigator } from ...
    
  3. Do you know that the native geolocation library offers much more accurate api and a wider devices support?

  4. Your issue seems to be connected to some browser not fully supporting the WorkerNavigator interface. Do you disagree on this last point and can you provide us some proof that we are wrong. React-Native is using the browser api to run geolocation in the background. You can recreate the same scenario in your iphone emulator safari developer console following this instructions to create the WorkerNavigator instance and then retrieving your location. You could demonstrate the WorkerNavigator works on your Emulator Safari/Chrome browsers.
  5. Have you consider opening an issue at the w3c/geolocation-api repository? Have you considered opening a bug report in chromium?
Fabrizio Bertoglio
  • 5,890
  • 4
  • 16
  • 57
  • 1
    So how do I fix it? I just want to use `navigator.geolocation`, but it's undefined. – TIMEX May 15 '19 at 08:03
  • @TIMEX I updated my post with the chapter **Steps to Troubleshoot the Issue**, I would like to see the output of `console.warn(navigator)` and `console.warn(navigator.geolocation)` with the `react-native-debugger` tools disabled. Please provide me any additional feedback to help you troubleshoot this issue. Thanks – Fabrizio Bertoglio May 15 '19 at 09:27
1

None of the things the other guy said were able, clearly, to solve my problem. At least for me that I'm using RN 0.60, I discovered that they extracted it (like many other packages) in an external package. I thought about it of course, considering the decisions about the so called "lean core", but in rn docs nothing was written on the location extraction.

So here this is the package and here you find the new guide to configure it: https://github.com/react-native-community/react-native-geolocation

Don't know if it isn't available in 0.59 too

Giacomo Cerquone
  • 2,352
  • 5
  • 24
  • 33