Skip to content

Commit

Permalink
Add WebView-specific whitelist for crash keys.
Browse files Browse the repository at this point in the history
WebView shouldn't upload data representing all crash keys declared by
Chrome since some of that data could be private.
To be able to re-use the existing crash-keys mechanism we here add a
WebView-only whitelist that will be applied at the time data is set for
a key, rather than at registration time.
In this way we ensure that all keys that are being set are also being
registered, while allowing WebView to avoid adding all registered keys.

BUG=691560

Review-Url: https://codereview.chromium.org/2717223003
Cr-Commit-Position: refs/heads/master@{#454611}
  • Loading branch information
gsennton authored and Commit bot committed Mar 3, 2017
1 parent 6eb31f1 commit 59b1a9c
Show file tree
Hide file tree
Showing 11 changed files with 290 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "android_webview/common/crash_reporter/crash_keys.h"
#include "base/android/build_info.h"
#include "base/base_paths_android.h"
#include "base/debug/crash_logging.h"
#include "base/debug/dump_without_crashing.h"
#include "base/files/file_path.h"
#include "base/lazy_instance.h"
Expand All @@ -36,6 +37,8 @@ class AwCrashReporterClient : public ::crash_reporter::CrashReporterClient {

// crash_reporter::CrashReporterClient implementation.
size_t RegisterCrashKeys() override;
bool UseCrashKeysWhiteList() override { return true; }
const char* const* GetCrashKeyWhiteList() override;

bool IsRunningUnattended() override { return false; }
bool GetCollectStatsConsent() override {
Expand Down Expand Up @@ -86,6 +89,10 @@ size_t AwCrashReporterClient::RegisterCrashKeys() {
return crash_keys::RegisterWebViewCrashKeys();
}

const char* const* AwCrashReporterClient::GetCrashKeyWhiteList() {
return crash_keys::kWebViewCrashKeyWhiteList;
}

base::LazyInstance<AwCrashReporterClient>::Leaky g_crash_reporter_client =
LAZY_INSTANCE_INITIALIZER;

Expand Down
147 changes: 136 additions & 11 deletions android_webview/common/crash_reporter/crash_keys.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,40 +5,165 @@
#include "android_webview/common/crash_reporter/crash_keys.h"

#include "base/debug/crash_logging.h"
#include "components/crash/content/app/breakpad_linux.h"
#include "components/crash/core/common/crash_keys.h"

using namespace crash_keys;

namespace android_webview {
namespace crash_keys {

const char kActiveURL[] = "url-chunk";

const char kFontKeyName[] = "font_key_name";

const char kShutdownType[] = "shutdown-type";
const char kBrowserUnpinTrace[] = "browser-unpin-trace";

const char kGPUDriverVersion[] = "gpu-driver";
const char kGPUPixelShaderVersion[] = "gpu-psver";
const char kGPUVertexShaderVersion[] = "gpu-vsver";
const char kGPUVendor[] = "gpu-gl-vendor";
const char kGPURenderer[] = "gpu-gl-renderer";

const char kInputEventFilterSendFailure[] = "input-event-filter-send-failure";

const char kViewCount[] = "view-count";

const char kZeroEncodeDetails[] = "zero-encode-details";

size_t RegisterWebViewCrashKeys() {
base::debug::CrashKey fixed_keys[] = {
{ kGPUDriverVersion, kSmallSize },
{ kGPUPixelShaderVersion, kSmallSize },
{ kGPUVertexShaderVersion, kSmallSize },
{ kGPUVendor, kSmallSize },
{ kGPURenderer, kSmallSize },
{"AW_WHITELISTED_DEBUG_KEY", kSmallSize},
{"AW_NONWHITELISTED_DEBUG_KEY", kSmallSize},
{kClientId, kSmallSize},
{kChannel, kSmallSize},
{kActiveURL, kLargeSize},
{kNumVariations, kSmallSize},
{kVariations, kHugeSize},
{kShutdownType, kSmallSize},
{kBrowserUnpinTrace, kMediumSize},
{kGPUDriverVersion, kSmallSize},
{kGPUPixelShaderVersion, kSmallSize},
{kGPUVertexShaderVersion, kSmallSize},
{kGPUVendor, kSmallSize},
{kGPURenderer, kSmallSize},

// content/:
{ "bad_message_reason", kSmallSize },
{ "discardable-memory-allocated", kSmallSize },
{ "discardable-memory-free", kSmallSize },
{ "mojo-message-error", kMediumSize },
{ "total-discardable-memory-allocated", kSmallSize },
// content/:
{"bad_message_reason", kSmallSize},
{"discardable-memory-allocated", kSmallSize},
{"discardable-memory-free", kSmallSize},
{kFontKeyName, kSmallSize},
{"mojo-message-error", kMediumSize},
{"ppapi_path", kMediumSize},
{"subresource_url", kLargeSize},
{"total-discardable-memory-allocated", kSmallSize},
{kInputEventFilterSendFailure, kSmallSize},
{kBug464926CrashKey, kSmallSize},
{kViewCount, kSmallSize},

// media/:
{kZeroEncodeDetails, kSmallSize},

// gin/:
{"v8-ignition", kSmallSize},

// sandbox/:
{"seccomp-sigsys", kMediumSize},

// Temporary for http://crbug.com/575245.
{"swapout_frame_id", kSmallSize},
{"swapout_proxy_id", kSmallSize},
{"swapout_view_id", kSmallSize},
{"commit_frame_id", kSmallSize},
{"commit_proxy_id", kSmallSize},
{"commit_view_id", kSmallSize},
{"commit_main_render_frame_id", kSmallSize},
{"newproxy_proxy_id", kSmallSize},
{"newproxy_view_id", kSmallSize},
{"newproxy_opener_id", kSmallSize},
{"newproxy_parent_id", kSmallSize},
{"rvinit_view_id", kSmallSize},
{"rvinit_proxy_id", kSmallSize},
{"rvinit_main_frame_id", kSmallSize},
{"initrf_frame_id", kSmallSize},
{"initrf_proxy_id", kSmallSize},
{"initrf_view_id", kSmallSize},
{"initrf_main_frame_id", kSmallSize},
{"initrf_view_is_live", kSmallSize},

// Temporary for https://crbug.com/591478.
{"initrf_parent_proxy_exists", kSmallSize},
{"initrf_render_view_is_live", kSmallSize},
{"initrf_parent_is_in_same_site_instance", kSmallSize},
{"initrf_parent_process_is_live", kSmallSize},
{"initrf_root_is_in_same_site_instance", kSmallSize},
{"initrf_root_is_in_same_site_instance_as_parent", kSmallSize},
{"initrf_root_process_is_live", kSmallSize},
{"initrf_root_proxy_is_live", kSmallSize},

// Temporary for https://crbug.com/626802.
{"newframe_routing_id", kSmallSize},
{"newframe_proxy_id", kSmallSize},
{"newframe_opener_id", kSmallSize},
{"newframe_parent_id", kSmallSize},
{"newframe_widget_id", kSmallSize},
{"newframe_widget_hidden", kSmallSize},
{"newframe_replicated_origin", kSmallSize},
{"newframe_oopifs_possible", kSmallSize},

// Temporary for https://crbug.com/630103.
{"origin_mismatch_url", kLargeSize},
{"origin_mismatch_origin", kMediumSize},
{"origin_mismatch_transition", kSmallSize},
{"origin_mismatch_redirects", kSmallSize},
{"origin_mismatch_same_page", kSmallSize},

// Temporary for https://crbug.com/612711.
{"aci_wrong_sp_extension_id", kSmallSize},

// Temporary for https://crbug.com/668633.
{"swdh_set_hosted_version_worker_pid", kSmallSize},
{"swdh_set_hosted_version_host_pid", kSmallSize},
{"swdh_set_hosted_version_is_new_process", kSmallSize},
{"swdh_set_hosted_version_restart_count", kSmallSize},
};

// This dynamic set of keys is used for sets of key value pairs when gathering
// a collection of data, like command line switches or extension IDs.
std::vector<base::debug::CrashKey> keys(fixed_keys,
fixed_keys + arraysize(fixed_keys));

GetCrashKeysForCommandLineSwitches(&keys);

return base::debug::InitCrashKeys(&keys.at(0), keys.size(), kChunkMaxLength);
}

// clang-format off
const char* const kWebViewCrashKeyWhiteList[] = {
"AW_WHITELISTED_DEBUG_KEY",
kGPUDriverVersion,
kGPUPixelShaderVersion,
kGPUVertexShaderVersion,
kGPUVendor,
kGPURenderer,

// content/:
"bad_message_reason",
"discardable-memory-allocated",
"discardable-memory-free",
"mojo-message-error-1",
"mojo-message-error-2",
"mojo-message-error-3",
"mojo-message-error-4",
"total-discardable-memory-allocated",
nullptr};
// clang-format on

void InitCrashKeysForWebViewTesting() {
breakpad::InitCrashKeysForTesting();
}

} // namespace crash_keys

} // namespace android_webview
5 changes: 5 additions & 0 deletions android_webview/common/crash_reporter/crash_keys.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,18 @@
#define ANDROID_WEBVIEW_COMMON_CRASH_KEYS_H_

#include <stddef.h>
#include <string>

namespace android_webview {
namespace crash_keys {

// Registers all of the potential crash keys that can be sent to the crash
// reporting server. Returns the size of the union of all keys.
size_t RegisterWebViewCrashKeys();
void InitCrashKeysForWebViewTesting();
void SetCrashKeyValue(const std::string& key, const std::string& value);

extern const char* const kWebViewCrashKeyWhiteList[];

// Crash Key Name Constants ////////////////////////////////////////////////////

Expand Down
10 changes: 10 additions & 0 deletions android_webview/java/src/org/chromium/android_webview/AwDebug.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,15 @@ public static boolean dumpWithoutCrashing(File dumpFile) {
return nativeDumpWithoutCrashing(dumpPath);
}

public static void initCrashKeysForTesting() {
nativeInitCrashKeysForWebViewTesting();
}

public static void setCrashKeyValue(String key, String value) {
nativeSetCrashKeyValue(key, value);
}

private static native boolean nativeDumpWithoutCrashing(String dumpPath);
private static native void nativeInitCrashKeysForWebViewTesting();
private static native void nativeSetCrashKeyValue(String key, String value);
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,21 @@
import org.chromium.base.test.util.parameter.ParameterizedTest;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Scanner;

/**
* A test suite for AwDebug class.
*/
// Only works in single-process mode, crbug.com/568825.
@ParameterizedTest.Set
public class AwDebugTest extends AwTestBase {
private static final String TAG = "cr_AwDebugTest";
private static final String WHITELISTED_DEBUG_KEY = "AW_WHITELISTED_DEBUG_KEY";
private static final String NON_WHITELISTED_DEBUG_KEY = "AW_NONWHITELISTED_DEBUG_KEY";
private static final String DEBUG_VALUE = "AW_DEBUG_VALUE";

@SmallTest
@Feature({"AndroidWebView", "Debug"})
public void testDump() throws Throwable {
Expand All @@ -30,4 +38,74 @@ public void testDump() throws Throwable {
assertTrue(f.delete());
}
}

@SmallTest
@Feature({"AndroidWebView", "Debug"})
public void testDumpContainsWhitelistedKey() throws Throwable {
File f = File.createTempFile("dump", ".dmp");
try {
AwDebug.initCrashKeysForTesting();
AwDebug.setCrashKeyValue(WHITELISTED_DEBUG_KEY, DEBUG_VALUE);
assertTrue(AwDebug.dumpWithoutCrashing(f));
assertContainsCrashKeyValue(f, WHITELISTED_DEBUG_KEY, DEBUG_VALUE);
} finally {
assertTrue(f.delete());
}
}

@SmallTest
@Feature({"AndroidWebView", "Debug"})
public void testDumpDoesNotContainNonWhitelistedKey() throws Throwable {
File f = File.createTempFile("dump", ".dmp");
try {
AwDebug.initCrashKeysForTesting();
AwDebug.setCrashKeyValue(NON_WHITELISTED_DEBUG_KEY, DEBUG_VALUE);
assertTrue(AwDebug.dumpWithoutCrashing(f));
assertNotContainsCrashKeyValue(f, NON_WHITELISTED_DEBUG_KEY);
} finally {
assertTrue(f.delete());
}
}

private void assertNotContainsCrashKeyValue(File dump, String key) throws IOException {
String dumpContents = readEntireFile(dump);
// We are expecting the following to NOT be in the dumpContents:
//
// Content-Disposition: form-data; name="AW_DEBUG_KEY"
// AW_DEBUG_VALUE
assertFalse(dumpContents.contains(getDebugKeyLine(key)));
}

private void assertContainsCrashKeyValue(File dump, String key, String expectedValue)
throws IOException {
String dumpContents = readEntireFile(dump);
// We are expecting the following lines:
//
// Content-Disposition: form-data; name="AW_DEBUG_KEY"
// AW_DEBUG_VALUE
String debugKeyLine = getDebugKeyLine(key);
assertTrue(dumpContents.contains(debugKeyLine));

int debugKeyIndex = dumpContents.indexOf(debugKeyLine);
// Read the word after the line containing the debug key
Scanner debugValueScanner =
new Scanner(dumpContents.substring(debugKeyIndex + debugKeyLine.length()));
assertTrue(debugValueScanner.hasNext());
assertEquals(expectedValue, debugValueScanner.next());
}

private static String getDebugKeyLine(String debugKey) {
return "Content-Disposition: form-data; name=\"" + debugKey + "\"";
}

private static String readEntireFile(File file) throws IOException {
FileInputStream fileInputStream = new FileInputStream(file);
try {
byte[] data = new byte[(int) file.length()];
fileInputStream.read(data);
return new String(data);
} finally {
fileInputStream.close();
}
}
}
15 changes: 15 additions & 0 deletions android_webview/native/aw_debug.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
#include "android_webview/native/aw_debug.h"

#include "android_webview/common/crash_reporter/aw_microdump_crash_reporter.h"
#include "android_webview/common/crash_reporter/crash_keys.h"
#include "base/android/jni_android.h"
#include "base/android/jni_string.h"
#include "base/debug/crash_logging.h"
#include "base/debug/dump_without_crashing.h"
#include "base/files/file.h"
#include "base/files/file_path.h"
Expand Down Expand Up @@ -36,6 +38,19 @@ static jboolean DumpWithoutCrashing(JNIEnv* env,
return crash_reporter::DumpWithoutCrashingToFd(target.TakePlatformFile());
}

static void InitCrashKeysForWebViewTesting(JNIEnv* env,
const JavaParamRef<jclass>& clazz) {
crash_keys::InitCrashKeysForWebViewTesting();
}

static void SetCrashKeyValue(JNIEnv* env,
const JavaParamRef<jclass>& clazz,
const JavaParamRef<jstring>& key,
const JavaParamRef<jstring>& value) {
base::debug::SetCrashKeyValue(ConvertJavaStringToUTF8(env, key),
ConvertJavaStringToUTF8(env, value));
}

bool RegisterAwDebug(JNIEnv* env) {
return RegisterNativesImpl(env);
}
Expand Down
3 changes: 1 addition & 2 deletions chrome/common/crash_keys.cc
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,8 @@ size_t RegisterChromeCrashKeys() {
// The following keys may be chunked by the underlying crash logging system,
// but ultimately constitute a single key-value pair.
//
// If you're adding keys here, please also add them to the following list:
// If you're adding keys here, please also add them to the following lists:
// chrome/app/chrome_crash_reporter_client_win.cc::RegisterCrashKeysHelper(),
// and consider adding the new keys to the following list as well:
// android_webview/common/crash_reporter/crash_keys.cc::
// RegisterWebViewCrashKeys().
base::debug::CrashKey fixed_keys[] = {
Expand Down
Loading

0 comments on commit 59b1a9c

Please sign in to comment.