Implement `navigator.getUserAgent()`

This patch is smaller than it looks. It basically does the following:

1.  It introduces `blink::UserAgentMetadata`, and a corresponding mojo
    type in order to hold the various shards of data we'd like to expose
    about user agents (brand, version, platform, architecture, and
    model).

2.  It threads these new types down from //chrome and //content/shell's
    implementations of `ContentBrowserClient` down into Blink via the
    same route we're using for the existing user-agent string
    (ChromeContentBrowserClient -> RenderProcessHost -> RenderThread
    -> Platform -> LocalFrameClient -> FrameLoader).

3.  It extends `Navigator` with a new `NavigatorUserAgent` mixin that
    exposes `navigator.getUserAgent()`. This returns a promise that
    resolves with a newly defined `UserAgent` IDL dictionary type.

So, the patch is huge, but not really that complex.

Bug: 928670
Change-Id: I4f267e373864162264ad4d721650942b147b378d
Reviewed-on: https://chromium-review.googlesource.com/c/1458098
Commit-Queue: Mike West <mkwst@chromium.org>
Reviewed-by: Yoav Weiss <yoavweiss@chromium.org>
Reviewed-by: Kinuko Yasuda <kinuko@chromium.org>
Cr-Commit-Position: refs/heads/master@{#631613}
diff --git a/html/webappapis/system-state-and-capabilities/the-navigator-object/navigator_user_agent.tentative.html b/html/webappapis/system-state-and-capabilities/the-navigator-object/navigator_user_agent.tentative.html
new file mode 100644
index 0000000..dd4c531
--- /dev/null
+++ b/html/webappapis/system-state-and-capabilities/the-navigator-object/navigator_user_agent.tentative.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+  test(t => {
+    assert_false("getUserAgent" in navigator);
+  }, "navigator.getUserAgent() is not available in non-secure contexts.");
+</script>
diff --git a/html/webappapis/system-state-and-capabilities/the-navigator-object/navigator_user_agent.tentative.https.html b/html/webappapis/system-state-and-capabilities/the-navigator-object/navigator_user_agent.tentative.https.html
new file mode 100644
index 0000000..5f0dba6
--- /dev/null
+++ b/html/webappapis/system-state-and-capabilities/the-navigator-object/navigator_user_agent.tentative.https.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/webrtc/dictionary-helper.js"></script>
+<script>
+  test(t => {
+    assert_true("getUserAgent" in navigator);
+  }, "navigator.getUserAgent() is exposed.");
+
+  promise_test(t => {
+    return navigator.getUserAgent()
+      .then(ua => {
+        // TODO(web-platform-tests/wpt#9106): Use `idlharness.js` once it supports dictionaries.
+        assert_string_field(ua, "brand");
+        assert_string_field(ua, "version");
+        assert_string_field(ua, "platform");
+        assert_string_field(ua, "architecture");
+        assert_string_field(ua, "model");
+      });
+  }, "navigator.getUserAgent() returns a UserAgentMetadata object.");
+</script>