Skip to content

Commit

Permalink
Introduce chrome://location-internals UI
Browse files Browse the repository at this point in the history
This page is added to help troubleshoot geolocation issues.
It will include
1. A button to start / stop navigator.geolocation.watchPosition
2. log WifiData, PositionCache and other useful information from GeolocationProviderImpl.
This will lead to faster resolution of issues and a better user experience.

Bug: 1110995
Change-Id: I2ea7d3ae9988869a952a03f877b78177e98a43be
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4468750
Reviewed-by: Demetrios Papadopoulos <dpapad@chromium.org>
Commit-Queue: Alvin Ji <alvinji@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1149979}
  • Loading branch information
Alvin Ji authored and Chromium LUCI CQ committed May 26, 2023
1 parent 86f8ba8 commit a527278
Show file tree
Hide file tree
Showing 22 changed files with 371 additions and 0 deletions.
2 changes: 2 additions & 0 deletions chrome/browser/resources/BUILD.gn
Expand Up @@ -278,6 +278,7 @@ repack("dev_ui_paks") {
"$root_gen_dir/chrome/dev_ui_browser_resources.pak",
"$root_gen_dir/chrome/internals_resources.pak",
"$root_gen_dir/chrome/invalidations_resources.pak",
"$root_gen_dir/chrome/location_internals_resources.pak",
"$root_gen_dir/chrome/media_resources.pak",
"$root_gen_dir/chrome/net_internals_resources.pak",
"$root_gen_dir/chrome/omnibox_resources.pak",
Expand All @@ -303,6 +304,7 @@ repack("dev_ui_paks") {
"//chrome/browser/resources/browsing_topics:resources",
"//chrome/browser/resources/internals:resources",
"//chrome/browser/resources/invalidations:resources",
"//chrome/browser/resources/location_internals:resources",
"//chrome/browser/resources/media:resources",
"//chrome/browser/resources/net_internals:resources",
"//chrome/browser/resources/omnibox:resources",
Expand Down
19 changes: 19 additions & 0 deletions chrome/browser/resources/location_internals/BUILD.gn
@@ -0,0 +1,19 @@
# Copyright 2023 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import("//ui/webui/resources/tools/build_webui.gni")

build_webui("build") {
grd_prefix = "location_internals"
static_files = [
"location_internals.css",
"location_internals.html",
]

non_web_component_files = [ "location_internals.ts" ]

ts_deps = [ "//ui/webui/resources/js:build_ts" ]

ts_composite = true
}
4 changes: 4 additions & 0 deletions chrome/browser/resources/location_internals/DIR_METADATA
@@ -0,0 +1,4 @@
monorail: {
component: "Blink>Geolocation"
}
team_email: "device-dev@chromium.org"
1 change: 1 addition & 0 deletions chrome/browser/resources/location_internals/OWNERS
@@ -0,0 +1 @@
file://content/browser/geolocation/OWNERS
29 changes: 29 additions & 0 deletions chrome/browser/resources/location_internals/location_internals.css
@@ -0,0 +1,29 @@
/* Copyright 2023 The Chromium Authors
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file. */

#container {
display: flex;
justify-content: space-around;
padding-inline-end: 20px;
padding-inline-start: 20px;
}

table {
border-collapse: collapse;
font-family: arial, sans-serif;
margin-top: 20px;
}

table caption {
font-size: 18px;
font-weight: bold;
text-align: start;
}

td,
th {
border: 1px solid #ddd;
padding: 8px;
text-align: start;
}
@@ -0,0 +1,48 @@
<!doctype html>
<html dir="$i18n{textdirection}" lang="$i18n{language}">

<head>
<meta charset="utf-8">
<title>Location Internals</title>
<link rel="stylesheet" href="chrome://resources/css/text_defaults.css">
<link rel="stylesheet" href="location_internals.css">
</head>

<body>
<h2 class="header">Location Internals</h2>
<header class="page-header">
<button id="watch-btn">Start Watching Position</button>
</header>
<div id="container">

<table id="watch-position">
<caption>WatchPosition</caption>
<thead>
<tr>
<th>Timestamp</th>
<th>Position</th>
<th>Accuracy</th>
<th>Altitude</th>
<th>AltitudeAccuracy</th>
<th>Heading</th>
<th>Speed</th>
</tr>
</thead>
<tbody>
<tr>
<td id="watch-position-timestamp"></td>
<td id="watch-position-position"></td>
<td id="watch-position-accuracy"></td>
<td id="watch-position-altitude"></td>
<td id="watch-position-altitude-accuracy"></td>
<td id="watch-position-heading"></td>
<td id="watch-position-speed"></td>
</tr>
</tbody>
</table>

</div>
<script type="module" src="location_internals.js"></script>
</body>

</html>
79 changes: 79 additions & 0 deletions chrome/browser/resources/location_internals/location_internals.ts
@@ -0,0 +1,79 @@
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import {assert} from 'chrome://resources/js/assert_ts.js';
import {getRequiredElement} from 'chrome://resources/js/util_ts.js';

let watchButton: HTMLElement;
let watchTable: HTMLElement;
let watchId: number = -1;

document.addEventListener('DOMContentLoaded', () => {
watchButton = getRequiredElement<HTMLElement>('watch-btn');
watchTable = getRequiredElement<HTMLElement>('watch-position');
watchButton.addEventListener('click', () => {
if (watchId === -1) {
watchId = navigator.geolocation.watchPosition(logSuccess, logError, {
enableHighAccuracy: true,
timeout: 5000,
maximumAge: 0,
});
watchButton.textContent = 'Stop Watching Position';
} else {
navigator.geolocation.clearWatch(watchId);
watchId = -1;
watchButton.textContent = 'Start Watching Position';
}
});
});

function logSuccess(position: GeolocationPosition) {
assert(watchTable);
const timeCell = getRequiredElement<HTMLElement>('watch-position-timestamp');
const positionCell =
getRequiredElement<HTMLElement>('watch-position-position');

timeCell.textContent = new Date(position.timestamp).toLocaleString();
positionCell.textContent =
`${position.coords.latitude} ° , ${position.coords.longitude} ° `;

if (position.coords.accuracy) {
const accuracyCell =
getRequiredElement<HTMLElement>('watch-position-accuracy');
accuracyCell.textContent = position.coords.accuracy.toString();
}

if (position.coords.altitude) {
const altitudeCell =
getRequiredElement<HTMLElement>('watch-position-altitude');
altitudeCell.textContent = position.coords.altitude.toString();
}

if (position.coords.altitudeAccuracy) {
const altitudeAccuracyCell =
getRequiredElement<HTMLElement>('watch-position-altitude-accuracy');
altitudeAccuracyCell.textContent =
position.coords.altitudeAccuracy.toString();
}

if (position.coords.heading) {
const headingCell =
getRequiredElement<HTMLElement>('watch-position-heading');
headingCell.textContent = position.coords.heading.toString();
}

if (position.coords.speed) {
const speedCell = getRequiredElement<HTMLElement>('watch-position-speed');
speedCell.textContent = position.coords.speed.toString();
}
}

function logError(error: GeolocationPositionError) {
assert(watchTable);
const timeCell = getRequiredElement<HTMLElement>('watch-position-timestamp');
const positionCell =
getRequiredElement<HTMLElement>('watch-position-position');
timeCell.textContent = new Date().toLocaleString();
positionCell.textContent = `${error.message}, code: ${error.code}`;
}
3 changes: 3 additions & 0 deletions chrome/browser/ui/BUILD.gn
Expand Up @@ -369,6 +369,8 @@ static_library("ui") {
"webui/invalidations/invalidations_ui.h",
"webui/local_state/local_state_ui.cc",
"webui/local_state/local_state_ui.h",
"webui/location_internals/location_internals_ui.cc",
"webui/location_internals/location_internals_ui.h",
"webui/log_web_ui_url.cc",
"webui/log_web_ui_url.h",
"webui/media/media_engagement_ui.cc",
Expand Down Expand Up @@ -522,6 +524,7 @@ static_library("ui") {
"//chrome/browser/resources/browsing_topics:resources",
"//chrome/browser/resources/internals:resources",
"//chrome/browser/resources/invalidations:resources",
"//chrome/browser/resources/location_internals:resources",
"//chrome/browser/resources/media:resources",
"//chrome/browser/resources/net_internals:resources",
"//chrome/browser/resources/omnibox:resources",
Expand Down
6 changes: 6 additions & 0 deletions chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
Expand Up @@ -48,6 +48,7 @@
#include "chrome/browser/ui/webui/intro/intro_ui.h"
#include "chrome/browser/ui/webui/invalidations/invalidations_ui.h"
#include "chrome/browser/ui/webui/local_state/local_state_ui.h"
#include "chrome/browser/ui/webui/location_internals/location_internals_ui.h"
#include "chrome/browser/ui/webui/log_web_ui_url.h"
#include "chrome/browser/ui/webui/media/media_engagement_ui.h"
#include "chrome/browser/ui/webui/media/media_history_ui.h"
Expand Down Expand Up @@ -480,6 +481,9 @@ WebUIFactoryFunction GetWebUIFactoryFunction(WebUI* web_ui,
}
if (url.host_piece() == chrome::kChromeUILocalStateHost)
return &NewWebUI<LocalStateUI>;
if (url.host_piece() == chrome::kChromeUILocationInternalsHost) {
return &NewWebUI<LocationInternalsUI>;
}
if (url.host_piece() == chrome::kChromeUIMemoryInternalsHost)
return &NewWebUI<MemoryInternalsUI>;
if (url.host_piece() == chrome::kChromeUIMetricsInternalsHost)
Expand Down Expand Up @@ -1137,6 +1141,7 @@ std::vector<GURL> ChromeWebUIControllerFactory::GetListOfAcceptableURLs() {
GURL(chrome::kChromeUIInternetConfigDialogURL),
GURL(chrome::kChromeUIInternetDetailDialogURL),
GURL(chrome::kOsUIInvalidationsURL),
GURL(chrome::kChromeUILocationInternalsURL),
GURL(chrome::kChromeUILockScreenNetworkURL),
GURL(chrome::kChromeUILockScreenStartReauthURL),
GURL(chrome::kChromeUIManageMirrorSyncURL),
Expand Down Expand Up @@ -1207,6 +1212,7 @@ std::vector<GURL> ChromeWebUIControllerFactory::GetListOfAcceptableURLs() {
GURL(chrome::kChromeUIGpuURL),
GURL(chrome::kChromeUIHistogramsURL),
GURL(chrome::kChromeUIInvalidationsUrl),
GURL(chrome::kChromeUILocationInternalsURL),
GURL(chrome::kChromeUIManagementURL),
GURL(chrome::kChromeUIPolicyURL),
GURL(chrome::kChromeUIRestartURL),
Expand Down
4 changes: 4 additions & 0 deletions chrome/browser/ui/webui/location_internals/DIR_METADATA
@@ -0,0 +1,4 @@
monorail: {
component: "Blink>Geolocation"
}
team_email: "device-dev@chromium.org"
4 changes: 4 additions & 0 deletions chrome/browser/ui/webui/location_internals/OWNERS
@@ -0,0 +1,4 @@
file://content/browser/geolocation/OWNERS

per-file *.mojom=set noparent
per-file *.mojom=file://ipc/SECURITY_OWNERS
@@ -0,0 +1,30 @@
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ui/webui/location_internals/location_internals_ui.h"

#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/webui/webui_util.h"
#include "chrome/common/url_constants.h"
#include "chrome/grit/location_internals_resources.h"
#include "chrome/grit/location_internals_resources_map.h"
#include "content/public/browser/web_ui_data_source.h"
#include "services/network/public/mojom/content_security_policy.mojom.h"
#include "ui/resources/grit/webui_resources.h"

LocationInternalsUI::LocationInternalsUI(content::WebUI* web_ui)
: ui::MojoWebUIController(web_ui) {
// Set up the chrome://location-internals source.
content::WebUIDataSource* source = content::WebUIDataSource::CreateAndAdd(
Profile::FromWebUI(web_ui), chrome::kChromeUILocationInternalsHost);

webui::SetupWebUIDataSource(source,
base::make_span(kLocationInternalsResources,
kLocationInternalsResourcesSize),
IDR_LOCATION_INTERNALS_LOCATION_INTERNALS_HTML);
}

LocationInternalsUI::~LocationInternalsUI() = default;

WEB_UI_CONTROLLER_TYPE_IMPL(LocationInternalsUI)
25 changes: 25 additions & 0 deletions chrome/browser/ui/webui/location_internals/location_internals_ui.h
@@ -0,0 +1,25 @@
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_UI_WEBUI_LOCATION_INTERNALS_LOCATION_INTERNALS_UI_H_
#define CHROME_BROWSER_UI_WEBUI_LOCATION_INTERNALS_LOCATION_INTERNALS_UI_H_

#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "ui/webui/mojo_web_ui_controller.h"

// The WebUI for chrome://location-internals
class LocationInternalsUI : public ui::MojoWebUIController {
public:
explicit LocationInternalsUI(content::WebUI* web_ui);

LocationInternalsUI(const LocationInternalsUI&) = delete;
LocationInternalsUI& operator=(const LocationInternalsUI&) = delete;

~LocationInternalsUI() override;

private:
WEB_UI_CONTROLLER_TYPE_DECL();
};

#endif // CHROME_BROWSER_UI_WEBUI_LOCATION_INTERNALS_LOCATION_INTERNALS_UI_H_
@@ -0,0 +1,19 @@
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/common/webui_url_constants.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "url/gurl.h"

using LocationInternalsUIBrowserTest = InProcessBrowserTest;

IN_PROC_BROWSER_TEST_F(LocationInternalsUIBrowserTest,
OpenLocationInternalsWebUI) {
ASSERT_TRUE(ui_test_utils::NavigateToURL(
browser(),
GURL(content::GetWebUIURL(chrome::kChromeUILocationInternalsHost))));
}
2 changes: 2 additions & 0 deletions chrome/common/webui_url_constants.cc
Expand Up @@ -129,6 +129,7 @@ const char kChromeUIInvalidationsUrl[] = "chrome://invalidations";
const char kChromeUIKillHost[] = "kill";
const char kChromeUILauncherInternalsHost[] = "launcher-internals";
const char kChromeUILocalStateHost[] = "local-state";
const char kChromeUILocationInternalsHost[] = "location-internals";
const char kChromeUIManagementHost[] = "management";
const char kChromeUIManagementURL[] = "chrome://management";
const char kChromeUIMediaEngagementHost[] = "media-engagement";
Expand Down Expand Up @@ -293,6 +294,7 @@ const char kCfmNetworkSettingsURL[] = "chrome://cfm-network-settings";
#if BUILDFLAG(IS_CHROMEOS)
const char kChromeUIGpuURL[] = "chrome://gpu";
const char kChromeUIHistogramsURL[] = "chrome://histograms";
const char kChromeUILocationInternalsURL[] = "chrome://location-internals";
#endif

#if BUILDFLAG(IS_CHROMEOS_ASH)
Expand Down
2 changes: 2 additions & 0 deletions chrome/common/webui_url_constants.h
Expand Up @@ -125,6 +125,7 @@ extern const char kChromeUIInvalidationsUrl[];
extern const char kChromeUIKillHost[];
extern const char kChromeUILauncherInternalsHost[];
extern const char kChromeUILocalStateHost[];
extern const char kChromeUILocationInternalsHost[];
extern const char kChromeUIManagementHost[];
extern const char kChromeUIManagementURL[];
extern const char kChromeUIMediaEngagementHost[];
Expand Down Expand Up @@ -268,6 +269,7 @@ extern const char kChromeUIWebUITestHost[];
#if BUILDFLAG(IS_CHROMEOS)
extern const char kChromeUIGpuURL[];
extern const char kChromeUIHistogramsURL[];
extern const char kChromeUILocationInternalsURL[];
extern const char kChromeUIKerberosInBrowserHost[];
extern const char kChromeUIKerberosInBrowserURL[];
extern const char kChromeUINotifGeneratorURL[];
Expand Down
1 change: 1 addition & 0 deletions chrome/test/BUILD.gn
Expand Up @@ -2455,6 +2455,7 @@ if (!is_android) {
"../browser/ui/webui/identity_internals_ui_browsertest.h",
"../browser/ui/webui/inspect_ui_browsertest.cc",
"../browser/ui/webui/interstitials/interstitial_ui_browsertest.cc",
"../browser/ui/webui/location_internals/location_internals_ui_browsertest.cc",
"../browser/ui/webui/log_web_ui_url_browsertest.cc",
"../browser/ui/webui/management/management_a11y_browsertest.cc",
"../browser/ui/webui/management/management_a11y_browsertest.h",
Expand Down

0 comments on commit a527278

Please sign in to comment.