Add a Physical Web WebUI
Adds a WebUI page that receives a list of URLs broadcast by
nearby devices along with associated page metadata and displays
them as a list of clickable items.
BUG=630769
Review-Url: https://codereview.chromium.org/2248913007
Cr-Commit-Position: refs/heads/master@{#416393}
diff --git a/components/components_strings.grd b/components/components_strings.grd
index 0610650..2d620709 100644
--- a/components/components_strings.grd
+++ b/components/components_strings.grd
@@ -203,6 +203,7 @@
<part file="pageinfo_strings.grdp" />
<part file="password_manager_strings.grdp" />
<part file="pdf_strings.grdp" />
+ <part file="physical_web_ui_strings.grdp" />
<part file="policy_strings.grdp" />
<part file="security_interstitials_strings.grdp" />
<part file="ssl_errors_strings.grdp" />
diff --git a/components/physical_web.gypi b/components/physical_web.gypi
new file mode 100644
index 0000000..eb9e971
--- /dev/null
+++ b/components/physical_web.gypi
@@ -0,0 +1,30 @@
+# Copyright 2016 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.
+
+{
+ 'targets': [
+ {
+ # GN version: //components/physical_web/data_source
+ 'target_name': 'physical_web_data_source',
+ 'type': 'static_library',
+ 'dependencies': [
+ '../base/base.gyp:base',
+ ],
+ 'sources': [
+ # Note: sources list duplicated in GN build.
+ 'physical_web/data_source/physical_web_data_source.h',
+ ],
+ },
+ {
+ # GN version: //components/physical_web/webui
+ 'target_name': 'physical_web_ui',
+ 'type': 'static_library',
+ 'sources': [
+ # Note: sources list duplicated in GN build.
+ 'physical_web/webui/physical_web_ui_constants.cc',
+ 'physical_web/webui/physical_web_ui_constants.h',
+ ],
+ },
+ ],
+}
diff --git a/components/physical_web/webui/BUILD.gn b/components/physical_web/webui/BUILD.gn
new file mode 100644
index 0000000..f3d6432
--- /dev/null
+++ b/components/physical_web/webui/BUILD.gn
@@ -0,0 +1,14 @@
+# Copyright 2016 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.
+
+source_set("webui") {
+ sources = [
+ "physical_web_ui_constants.cc",
+ "physical_web_ui_constants.h",
+ ]
+
+ deps = [
+ "//base",
+ ]
+}
diff --git a/components/physical_web/webui/physical_web_ui_constants.cc b/components/physical_web/webui/physical_web_ui_constants.cc
new file mode 100644
index 0000000..b16c4a9b
--- /dev/null
+++ b/components/physical_web/webui/physical_web_ui_constants.cc
@@ -0,0 +1,27 @@
+// Copyright 2016 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 "components/physical_web/webui/physical_web_ui_constants.h"
+
+namespace physical_web_ui {
+
+// Resource paths.
+const char kPhysicalWebJS[] = "physical_web.js";
+const char kPhysicalWebCSS[] = "physical_web.css";
+
+// Message handlers.
+const char kRequestNearbyUrls[] = "requestNearbyURLs";
+
+// Strings.
+const char kTitle[] = "title";
+const char kPageInfo[] = "pageInfo";
+const char kPageInfoDescription[] = "pageInfoDescription";
+const char kPageInfoIcon[] = "pageInfoIcon";
+const char kPageInfoTitle[] = "pageInfoTitle";
+const char kResolvedUrl[] = "resolvedUrl";
+const char kScannedUrl[] = "scannedUrl";
+const char kReturnNearbyUrls[] = "returnNearbyURLs";
+const char kMetadata[] = "metadata";
+
+} // namespace physical_web_ui
diff --git a/components/physical_web/webui/physical_web_ui_constants.h b/components/physical_web/webui/physical_web_ui_constants.h
new file mode 100644
index 0000000..8319801
--- /dev/null
+++ b/components/physical_web/webui/physical_web_ui_constants.h
@@ -0,0 +1,33 @@
+// Copyright 2016 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.
+
+#ifndef COMPONENTS_PHYSICAL_WEB_WEBUI_PHYSICAL_WEB_UI_CONSTANTS_H_
+#define COMPONENTS_PHYSICAL_WEB_WEBUI_PHYSICAL_WEB_UI_CONSTANTS_H_
+
+namespace physical_web_ui {
+
+// Resource paths.
+// Must match the resource file names.
+extern const char kPhysicalWebJS[];
+extern const char kPhysicalWebCSS[];
+
+// Message handlers.
+// Must match the constants used in the resource files.
+extern const char kRequestNearbyUrls[];
+
+// Strings.
+// Must match the constants used in the resource files.
+extern const char kTitle[];
+extern const char kPageInfo[];
+extern const char kPageInfoDescription[];
+extern const char kPageInfoIcon[];
+extern const char kPageInfoTitle[];
+extern const char kResolvedUrl[];
+extern const char kScannedUrl[];
+extern const char kReturnNearbyUrls[];
+extern const char kMetadata[];
+
+} // namespace physical_web_ui
+
+#endif // COMPONENTS_PHYSICAL_WEB_WEBUI_PHYSICAL_WEB_UI_CONSTANTS_H_
diff --git a/components/physical_web/webui/resources/physical_web.css b/components/physical_web/webui/resources/physical_web.css
new file mode 100644
index 0000000..9c5e888
--- /dev/null
+++ b/components/physical_web/webui/resources/physical_web.css
@@ -0,0 +1,50 @@
+/* Copyright (c) 2016 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. */
+
+body {
+ font-family: Sans-Serif;
+ font-size: 12px;
+}
+.physicalWebTemplate {
+ display: flex;
+ width: 290px;
+ margin-bottom: 15px;
+ text-decoration: none;
+}
+
+.physicalWebIcon {
+ width: 32px;
+}
+.physicalWebText {
+ flex: 1;
+}
+.physicalWebIcon img {
+ padding-top: 1px;
+ width: 75%;
+}
+.physicalWebTemplate .title {
+ display: block;
+ color: #222;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ margin-bottom: 3px;
+}
+.physicalWebTemplate .resolvedUrl {
+ display: block;
+ font-size: 80%;
+ color: #888;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ margin-bottom: 4px;
+}
+.physicalWebTemplate .description {
+ display: block;
+ height: 2.5em;
+ font-size: 90%;
+ color: #444;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
diff --git a/components/physical_web/webui/resources/physical_web.html b/components/physical_web/webui/resources/physical_web.html
new file mode 100644
index 0000000..61e8488
--- /dev/null
+++ b/components/physical_web/webui/resources/physical_web.html
@@ -0,0 +1,43 @@
+<!doctype html>
+<html i18n-values="dir:textdirection;lang:language">
+<head>
+<meta charset="utf-8">
+<title i18n-content="title"></title>
+<if expr="is_android or is_ios">
+<meta name="viewport" content="width=device-width, user-scalable=no">
+</if>
+<link rel="stylesheet" href="chrome://resources/css/text_defaults.css">
+<link rel="stylesheet" href="chrome://physical-web/physical_web.css">
+
+<if expr="is_ios">
+<!-- TODO(crbug.com/487000): Remove this once injected by web. -->
+<script src="chrome://resources/js/ios/web_ui.js"></script>
+</if>
+
+<script src="chrome://resources/js/load_time_data.js"></script>
+<script src="chrome://resources/js/util.js"></script>
+<script src="chrome://physical-web/physical_web.js"></script>
+<script src="chrome://physical-web/strings.js"></script>
+</head>
+<body>
+<div id="body-container" style="visibility:visible">
+
+ <h1 i18n-content="title"></h1>
+
+ <a class="physicalWebTemplate" id="physicalWebTemplate" jsvalues="href:resolvedUrl" jsselect="metadata">
+ <div class="physicalWebIcon">
+ <img jsvalues="src:icon" />
+ </div>
+ <div class="physicalWebText">
+ <div class="title" jscontent="title"></div>
+ <div class="resolvedUrl" jscontent="resolvedUrl"></div>
+ <div class="description" jscontent="description"></div>
+ </div>
+ </a>
+
+</div>
+
+<script src="chrome://resources/js/i18n_template.js"></script>
+<script src="chrome://resources/js/jstemplate_compiled.js"></script>
+</body>
+</html>
diff --git a/components/physical_web/webui/resources/physical_web.js b/components/physical_web/webui/resources/physical_web.js
new file mode 100644
index 0000000..459fb18
--- /dev/null
+++ b/components/physical_web/webui/resources/physical_web.js
@@ -0,0 +1,31 @@
+// Copyright (c) 2016 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.
+
+/**
+ * Takes the |nearbyUrlsData| input argument which holds metadata for web pages
+ * broadcast by nearby devices.
+ * @param {Object} nearbyUrlsData Information about web pages broadcast by
+ * nearby devices
+ */
+function renderTemplate(nearbyUrlsData) {
+ // This is the javascript code that processes the template:
+ jstProcess(new JsEvalContext(nearbyUrlsData), $('physicalWebTemplate'));
+}
+
+function requestNearbyURLs() {
+ chrome.send('requestNearbyURLs');
+}
+
+function handleClickPhysicalWebItem(node) {
+ // do something
+}
+
+function returnNearbyURLs(nearbyUrlsData) {
+ var bodyContainer = $('body-container');
+ renderTemplate(nearbyUrlsData);
+
+ bodyContainer.style.visibility = 'visible';
+}
+
+document.addEventListener('DOMContentLoaded', requestNearbyURLs);
diff --git a/components/physical_web_ui_strings.grdp b/components/physical_web_ui_strings.grdp
new file mode 100644
index 0000000..cc34d51
--- /dev/null
+++ b/components/physical_web_ui_strings.grdp
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<grit-part>
+ <message name="IDS_PHYSICAL_WEB_UI_TITLE" desc="Title of a built-in page that displays a list of Physical Web URLs (URLs broadcast by nearby devices).">
+ Physical Web
+ </message>
+</grit-part>
diff --git a/components/resources/components_resources.grd b/components/resources/components_resources.grd
index 3291db2..4a7e4df 100644
--- a/components/resources/components_resources.grd
+++ b/components/resources/components_resources.grd
@@ -15,6 +15,7 @@
<part file="gcm_driver_resources.grdp" />
<part file="net_log_resources.grdp" />
<part file="neterror_resources.grdp" />
+ <part file="physical_web_ui_resources.grdp" />
<part file="printing_resources.grdp" />
<part file="proximity_auth_resources.grdp" />
<part file="security_interstitials_resources.grdp" />
diff --git a/components/resources/physical_web_ui_resources.grdp b/components/resources/physical_web_ui_resources.grdp
new file mode 100644
index 0000000..0da8416
--- /dev/null
+++ b/components/resources/physical_web_ui_resources.grdp
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<grit-part>
+ <include name="IDR_PHYSICAL_WEB_UI_HTML" file="../physical_web/webui/resources/physical_web.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" />
+ <include name="IDR_PHYSICAL_WEB_UI_JS" file="../physical_web/webui/resources/physical_web.js" type="BINDATA" />
+ <include name="IDR_PHYSICAL_WEB_UI_CSS" file="../physical_web/webui/resources/physical_web.css" type="BINDATA" />
+</grit-part>
\ No newline at end of file
diff --git a/ios/chrome/browser/BUILD.gn b/ios/chrome/browser/BUILD.gn
index d031d0b..35c4faf 100644
--- a/ios/chrome/browser/BUILD.gn
+++ b/ios/chrome/browser/BUILD.gn
@@ -564,6 +564,8 @@
"ui/webui/mojo_web_ui_ios_controller.h",
"ui/webui/net_export/net_export_ui.cc",
"ui/webui/net_export/net_export_ui.h",
+ "ui/webui/physical_web_ui.cc",
+ "ui/webui/physical_web_ui.h",
"ui/webui/sync_internals/sync_internals_message_handler.cc",
"ui/webui/sync_internals/sync_internals_message_handler.h",
"ui/webui/sync_internals/sync_internals_ui.cc",
@@ -653,6 +655,7 @@
"//components/password_manager/core/common",
"//components/password_manager/sync/browser",
"//components/physical_web/data_source",
+ "//components/physical_web/webui",
"//components/policy/core/common",
"//components/pref_registry",
"//components/prefs",
diff --git a/ios/chrome/browser/DEPS b/ios/chrome/browser/DEPS
index 471301ae..926634a 100644
--- a/ios/chrome/browser/DEPS
+++ b/ios/chrome/browser/DEPS
@@ -45,6 +45,7 @@
"+components/password_manager/core/common",
"+components/password_manager/sync/browser",
"+components/physical_web/data_source",
+ "+components/physical_web/webui",
"+components/pref_registry",
"+components/prefs",
"+components/profile_metrics",
diff --git a/ios/chrome/browser/chrome_url_constants.cc b/ios/chrome/browser/chrome_url_constants.cc
index 9767f871..1dc2079 100644
--- a/ios/chrome/browser/chrome_url_constants.cc
+++ b/ios/chrome/browser/chrome_url_constants.cc
@@ -17,6 +17,7 @@
const char kChromeUIFlagsURL[] = "chrome://flags/";
const char kChromeUIHistoryURL[] = "chrome://history/";
const char kChromeUINewTabURL[] = "chrome://newtab/";
+const char kChromeUIPhysicalWebURL[] = "chrome://physical-web/";
const char kChromeUISettingsURL[] = "chrome://settings/";
const char kChromeUITermsURL[] = "chrome://terms/";
const char kChromeUIVersionURL[] = "chrome://version/";
@@ -36,6 +37,7 @@
const char kChromeUINetExportHost[] = "net-export";
const char kChromeUINewTabHost[] = "newtab";
const char kChromeUIOmahaHost[] = "omaha";
+const char kChromeUIPhysicalWebHost[] = "physical-web";
const char kChromeUIPolicyHost[] = "policy";
const char kChromeUISignInInternalsHost[] = "signin-internals";
const char kChromeUISyncInternalsHost[] = "sync-internals";
@@ -46,9 +48,11 @@
// These hosts will also be suggested by BuiltinProvider.
// 'histograms' is chrome WebUI on iOS, content WebUI on other platforms.
const char* const kChromeHostURLs[] = {
- kChromeUIBookmarksHost, kChromeUIChromeURLsHost, kChromeUICreditsHost,
- kChromeUIFlagsHost, kChromeUIHistogramHost, kChromeUINetExportHost,
- kChromeUINewTabHost, kChromeUISyncInternalsHost, kChromeUITermsHost,
+ kChromeUIBookmarksHost, kChromeUIChromeURLsHost,
+ kChromeUICreditsHost, kChromeUIFlagsHost,
+ kChromeUIHistogramHost, kChromeUINetExportHost,
+ kChromeUINewTabHost, kChromeUISyncInternalsHost,
+ kChromeUIPhysicalWebHost, kChromeUITermsHost,
kChromeUIVersionHost,
};
const size_t kNumberOfChromeHostURLs = arraysize(kChromeHostURLs);
diff --git a/ios/chrome/browser/chrome_url_constants.h b/ios/chrome/browser/chrome_url_constants.h
index bfb289e..3960571 100644
--- a/ios/chrome/browser/chrome_url_constants.h
+++ b/ios/chrome/browser/chrome_url_constants.h
@@ -27,6 +27,7 @@
extern const char kChromeUIFlagsURL[];
extern const char kChromeUIHistoryURL[];
extern const char kChromeUINewTabURL[];
+extern const char kChromeUIPhysicalWebURL[];
extern const char kChromeUISettingsURL[];
extern const char kChromeUITermsURL[];
extern const char kChromeUIVersionURL[];
@@ -47,6 +48,7 @@
extern const char kChromeUINetExportHost[];
extern const char kChromeUINewTabHost[];
extern const char kChromeUIOmahaHost[];
+extern const char kChromeUIPhysicalWebHost[];
extern const char kChromeUIPolicyHost[];
extern const char kChromeUISignInInternalsHost[];
extern const char kChromeUISyncInternalsHost[];
diff --git a/ios/chrome/browser/ui/webui/physical_web_ui.cc b/ios/chrome/browser/ui/webui/physical_web_ui.cc
new file mode 100644
index 0000000..3c807ee
--- /dev/null
+++ b/ios/chrome/browser/ui/webui/physical_web_ui.cc
@@ -0,0 +1,99 @@
+// Copyright 2016 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 "ios/chrome/browser/ui/webui/physical_web_ui.h"
+
+#include "base/bind.h"
+#include "base/macros.h"
+#include "base/metrics/user_metrics.h"
+#include "base/values.h"
+#include "components/grit/components_resources.h"
+#include "components/physical_web/data_source/physical_web_data_source.h"
+#include "components/physical_web/webui/physical_web_ui_constants.h"
+#include "components/strings/grit/components_strings.h"
+#include "ios/chrome/browser/application_context.h"
+#include "ios/chrome/browser/browser_state/chrome_browser_state.h"
+#include "ios/chrome/browser/chrome_url_constants.h"
+#include "ios/web/public/web_ui_ios_data_source.h"
+#include "ios/web/public/webui/web_ui_ios.h"
+#include "ios/web/public/webui/web_ui_ios_message_handler.h"
+
+namespace {
+
+web::WebUIIOSDataSource* CreatePhysicalWebUIDataSource() {
+ web::WebUIIOSDataSource* html_source =
+ web::WebUIIOSDataSource::Create(kChromeUIPhysicalWebHost);
+
+ // Localized and data strings.
+ html_source->AddLocalizedString(physical_web_ui::kTitle,
+ IDS_PHYSICAL_WEB_UI_TITLE);
+
+ html_source->SetJsonPath("strings.js");
+ html_source->AddResourcePath(physical_web_ui::kPhysicalWebJS,
+ IDR_PHYSICAL_WEB_UI_JS);
+ html_source->AddResourcePath(physical_web_ui::kPhysicalWebCSS,
+ IDR_PHYSICAL_WEB_UI_CSS);
+ html_source->SetDefaultResource(IDR_PHYSICAL_WEB_UI_HTML);
+ return html_source;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// PhysicalWebDOMHandler
+//
+////////////////////////////////////////////////////////////////////////////////
+
+// The handler for Javascript messages for the chrome:physical-web page.
+class PhysicalWebDOMHandler : public web::WebUIIOSMessageHandler {
+ public:
+ PhysicalWebDOMHandler() {}
+ ~PhysicalWebDOMHandler() override {}
+
+ void RegisterMessages() override;
+
+ void HandleRequestNearbyURLs(const base::ListValue* args);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(PhysicalWebDOMHandler);
+};
+
+void PhysicalWebDOMHandler::RegisterMessages() {
+ web_ui()->RegisterMessageCallback(
+ physical_web_ui::kRequestNearbyUrls,
+ base::Bind(&PhysicalWebDOMHandler::HandleRequestNearbyURLs,
+ base::Unretained(this)));
+}
+
+void PhysicalWebDOMHandler::HandleRequestNearbyURLs(
+ const base::ListValue* args) {
+ base::DictionaryValue results;
+
+ std::unique_ptr<base::ListValue> metadata =
+ GetApplicationContext()->GetPhysicalWebDataSource()->GetMetadata();
+
+ results.Set(physical_web_ui::kMetadata, metadata.release());
+
+ web_ui()->CallJavascriptFunction(physical_web_ui::kReturnNearbyUrls, results);
+}
+
+} // namespace
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// PhysicalWebUI
+//
+////////////////////////////////////////////////////////////////////////////////
+
+PhysicalWebUI::PhysicalWebUI(web::WebUIIOS* web_ui)
+ : web::WebUIIOSController(web_ui) {
+ PhysicalWebDOMHandler* handler = new PhysicalWebDOMHandler();
+ web_ui->AddMessageHandler(handler);
+
+ web::WebUIIOSDataSource::Add(ios::ChromeBrowserState::FromWebUIIOS(web_ui),
+ CreatePhysicalWebUIDataSource());
+
+ base::RecordAction(base::UserMetricsAction("PhysicalWeb.WebUI.Open"));
+}
+
+PhysicalWebUI::~PhysicalWebUI() {}
diff --git a/ios/chrome/browser/ui/webui/physical_web_ui.h b/ios/chrome/browser/ui/webui/physical_web_ui.h
new file mode 100644
index 0000000..8fe669e
--- /dev/null
+++ b/ios/chrome/browser/ui/webui/physical_web_ui.h
@@ -0,0 +1,23 @@
+// Copyright 2016 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.
+
+#ifndef IOS_CHROME_BROWSER_UI_WEBUI_PHYSICAL_WEB_UI_H_
+#define IOS_CHROME_BROWSER_UI_WEBUI_PHYSICAL_WEB_UI_H_
+
+#include <string>
+
+#include "base/macros.h"
+#include "ios/web/public/webui/web_ui_ios_controller.h"
+
+// The WebUI handler for chrome://physical-web.
+class PhysicalWebUI : public web::WebUIIOSController {
+ public:
+ explicit PhysicalWebUI(web::WebUIIOS* web_ui);
+ ~PhysicalWebUI() override;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(PhysicalWebUI);
+};
+
+#endif // IOS_CHROME_BROWSER_UI_WEBUI_PHYSICAL_WEB_UI_H_
diff --git a/ios/chrome/ios_chrome.gyp b/ios/chrome/ios_chrome.gyp
index cac5400..c21c6176 100644
--- a/ios/chrome/ios_chrome.gyp
+++ b/ios/chrome/ios_chrome.gyp
@@ -90,6 +90,7 @@
'../../components/components.gyp:password_manager_core_browser',
'../../components/components.gyp:password_manager_sync_browser',
'../../components/components.gyp:physical_web_data_source',
+ '../../components/components.gyp:physical_web_ui',
'../../components/components.gyp:pref_registry',
'../../components/components.gyp:profile_metrics',
'../../components/components.gyp:proxy_config',
@@ -692,6 +693,8 @@
'browser/ui/webui/mojo_web_ui_ios_controller.h',
'browser/ui/webui/net_export/net_export_ui.cc',
'browser/ui/webui/net_export/net_export_ui.h',
+ 'browser/ui/webui/physical_web_ui.cc',
+ 'browser/ui/webui/physical_web_ui.h',
'browser/ui/webui/sync_internals/sync_internals_message_handler.cc',
'browser/ui/webui/sync_internals/sync_internals_message_handler.h',
'browser/ui/webui/sync_internals/sync_internals_ui.cc',
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml
index 7818331..9507377 100644
--- a/tools/metrics/actions/actions.xml
+++ b/tools/metrics/actions/actions.xml
@@ -12837,6 +12837,13 @@
<description>A Physical Web URL was selected.</description>
</action>
+<action name="PhysicalWeb.WebUI.Open">
+ <owner>[email protected]</owner>
+ <owner>[email protected]</owner>
+ <owner>[email protected]</owner>
+ <description>The Physical Web WebUI was opened or refreshed.</description>
+</action>
+
<action name="PlatformVerificationAccepted">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<description>Please enter the description of this user action.</description>