[Android WebView] Tracing API: add trace argument filtering by default.

MERGE to M65

Add filtering of trace arguments data by default to the WebView Tracing
API. Only specifically whitelisted strings are allowed in trace args
to avoid exposing any potential PII and address privacy concerns.

Currently only a few metadata category events are whitelisted, e.g.
the "process_name", "thread_name" arguments which are useful for
viewing in "chrome://tracing".

BUG=804414

Change-Id: I1477cd363d36cd9a3b5cf3c6bd4de0e8a3a63e63
Reviewed-on: https://chromium-review.googlesource.com/879144
Commit-Queue: Tim Volodine <timvolodine@chromium.org>
Reviewed-by: Richard Coles <torne@chromium.org>
Cr-Original-Commit-Position: refs/heads/master@{#531609}(cherry picked from commit 4595b036c1f527b31ec3279759b6e2bcdfca2084)
Reviewed-on: https://chromium-review.googlesource.com/929021
Reviewed-by: Tim Volodine <timvolodine@chromium.org>
Cr-Commit-Position: refs/branch-heads/3325@{#532}
Cr-Branched-From: bc084a8b5afa3744a74927344e304c02ae54189f-refs/heads/master@{#530369}
diff --git a/android_webview/BUILD.gn b/android_webview/BUILD.gn
index 2b5eebd3..4e12f9a 100644
--- a/android_webview/BUILD.gn
+++ b/android_webview/BUILD.gn
@@ -617,6 +617,8 @@
     "browser/surfaces_instance.cc",
     "browser/surfaces_instance.h",
     "browser/token_binding_manager_bridge.cc",
+    "browser/tracing/aw_trace_event_args_whitelist.cc",
+    "browser/tracing/aw_trace_event_args_whitelist.h",
     "browser/tracing/aw_tracing_controller.cc",
     "browser/tracing/aw_tracing_controller.h",
     "browser/tracing/aw_tracing_delegate.cc",
diff --git a/android_webview/browser/tracing/aw_trace_event_args_whitelist.cc b/android_webview/browser/tracing/aw_trace_event_args_whitelist.cc
new file mode 100644
index 0000000..4436ce6
--- /dev/null
+++ b/android_webview/browser/tracing/aw_trace_event_args_whitelist.cc
@@ -0,0 +1,74 @@
+// Copyright 2018 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 "android_webview/browser/tracing/aw_trace_event_args_whitelist.h"
+
+#include "base/bind.h"
+#include "base/strings/pattern.h"
+#include "base/strings/string_tokenizer.h"
+#include "base/strings/string_util.h"
+#include "base/trace_event/trace_event.h"
+
+namespace {
+
+struct WhitelistEntry {
+  const char* category_name;
+  const char* event_name;
+  const char* const* arg_name_filter;
+};
+
+const WhitelistEntry kEventArgsWhitelist[] = {
+    {"__metadata", "thread_name", nullptr},
+    {"__metadata", "process_name", nullptr},
+    {"__metadata", "process_uptime_seconds", nullptr},
+    {"__metadata", "stackFrames", nullptr},
+    {"__metadata", "typeNames", nullptr},
+    {nullptr, nullptr, nullptr}};
+
+}  // namespace
+
+namespace android_webview {
+
+// TODO(timvolodine): refactor this into base/ to avoid code duplication
+// with chrome/common/trace_event_args_whitelist.cc, see crbug.com/805045.
+bool IsTraceArgumentNameWhitelisted(const char* const* granular_filter,
+                                    const char* arg_name) {
+  for (int i = 0; granular_filter[i] != nullptr; ++i) {
+    if (base::MatchPattern(arg_name, granular_filter[i]))
+      return true;
+  }
+
+  return false;
+}
+
+bool IsTraceEventArgsWhitelisted(
+    const char* category_group_name,
+    const char* event_name,
+    base::trace_event::ArgumentNameFilterPredicate* arg_name_filter) {
+  DCHECK(arg_name_filter);
+  base::CStringTokenizer category_group_tokens(
+      category_group_name, category_group_name + strlen(category_group_name),
+      ",");
+  while (category_group_tokens.GetNext()) {
+    const std::string& category_group_token = category_group_tokens.token();
+    for (int i = 0; kEventArgsWhitelist[i].category_name != nullptr; ++i) {
+      const WhitelistEntry& whitelist_entry = kEventArgsWhitelist[i];
+      DCHECK(whitelist_entry.event_name);
+
+      if (base::MatchPattern(category_group_token,
+                             whitelist_entry.category_name) &&
+          base::MatchPattern(event_name, whitelist_entry.event_name)) {
+        if (whitelist_entry.arg_name_filter) {
+          *arg_name_filter = base::Bind(&IsTraceArgumentNameWhitelisted,
+                                        whitelist_entry.arg_name_filter);
+        }
+        return true;
+      }
+    }
+  }
+
+  return false;
+}
+
+}  // namespace android_webview
diff --git a/android_webview/browser/tracing/aw_trace_event_args_whitelist.h b/android_webview/browser/tracing/aw_trace_event_args_whitelist.h
new file mode 100644
index 0000000..e5dc071
--- /dev/null
+++ b/android_webview/browser/tracing/aw_trace_event_args_whitelist.h
@@ -0,0 +1,21 @@
+// Copyright 2018 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 ANDROID_WEBVIEW_BROWSER_TRACING_AW_TRACE_EVENT_ARGS_WHITELIST_H_
+#define ANDROID_WEBVIEW_BROWSER_TRACING_AW_TRACE_EVENT_ARGS_WHITELIST_H_
+
+#include "base/trace_event/trace_event_impl.h"
+
+namespace android_webview {
+
+// Used to filter trace event arguments against a whitelist of events that
+// have been manually vetted to not include any PII.
+bool IsTraceEventArgsWhitelisted(
+    const char* category_group_name,
+    const char* event_name,
+    base::trace_event::ArgumentNameFilterPredicate* arg_name_filter);
+
+}  // namespace android_webview
+
+#endif  // ANDROID_WEBVIEW_BROWSER_TRACING_AW_TRACE_EVENT_ARGS_WHITELIST_H_
diff --git a/android_webview/browser/tracing/aw_tracing_controller.cc b/android_webview/browser/tracing/aw_tracing_controller.cc
index 8184684..74aa5ff 100644
--- a/android_webview/browser/tracing/aw_tracing_controller.cc
+++ b/android_webview/browser/tracing/aw_tracing_controller.cc
@@ -91,6 +91,8 @@
       base::android::ConvertJavaStringToUTF8(env, jcategories);
   base::trace_event::TraceConfig trace_config(
       categories, static_cast<base::trace_event::TraceRecordMode>(jmode));
+  // Required for filtering out potential PII.
+  trace_config.EnableArgumentFilter();
   return content::TracingController::GetInstance()->StartTracing(
       trace_config, content::TracingController::StartTracingDoneCallback());
 }
diff --git a/android_webview/lib/aw_main_delegate.cc b/android_webview/lib/aw_main_delegate.cc
index 820f6e3..574d297 100644
--- a/android_webview/lib/aw_main_delegate.cc
+++ b/android_webview/lib/aw_main_delegate.cc
@@ -12,6 +12,7 @@
 #include "android_webview/browser/browser_view_renderer.h"
 #include "android_webview/browser/command_line_helper.h"
 #include "android_webview/browser/deferred_gpu_command_service.h"
+#include "android_webview/browser/tracing/aw_trace_event_args_whitelist.h"
 #include "android_webview/common/aw_descriptors.h"
 #include "android_webview/common/aw_paths.h"
 #include "android_webview/common/aw_switches.h"
@@ -161,6 +162,11 @@
   safe_browsing::SafeBrowsingApiHandler::SetInstance(
       safe_browsing_api_handler_.get());
 
+  // Used only if the argument filter is enabled in tracing config,
+  // as is the case by default in aw_tracing_controller.cc
+  base::trace_event::TraceLog::GetInstance()->SetArgumentFilterPredicate(
+      base::Bind(&IsTraceEventArgsWhitelisted));
+
   return false;
 }