diff options
10 files changed, 195 insertions, 3 deletions
diff --git a/android_webview/apk/java/proguard.flags b/android_webview/apk/java/proguard.flags index 8dbce53..d8f80cc 100644 --- a/android_webview/apk/java/proguard.flags +++ b/android_webview/apk/java/proguard.flags @@ -75,6 +75,11 @@ public void setSmartClipResultHandler(android.os.Handler); } +# AwDebug is accessed by reflection. +-keep class org.chromium.android_webview.AwDebug { + public static boolean dumpWithoutCrashing(...); +} + # Ignore notes and warnings about the support library, which uses reflection and # may reference classes no longer in the SDK. -dontnote android.support.** diff --git a/android_webview/crash_reporter/aw_microdump_crash_reporter.cc b/android_webview/crash_reporter/aw_microdump_crash_reporter.cc index ce94174..165c4b3 100644 --- a/android_webview/crash_reporter/aw_microdump_crash_reporter.cc +++ b/android_webview/crash_reporter/aw_microdump_crash_reporter.cc @@ -5,9 +5,11 @@ #include "android_webview/crash_reporter/aw_microdump_crash_reporter.h" #include "android_webview/common/aw_version_info_values.h" +#include "base/debug/dump_without_crashing.h" #include "base/files/file_path.h" #include "base/lazy_instance.h" #include "base/scoped_native_library.h" +#include "base/synchronization/lock.h" #include "build/build_config.h" #include "components/crash/content/app/breakpad_linux.h" #include "components/crash/content/app/crash_reporter_client.h" @@ -19,7 +21,7 @@ namespace { class AwCrashReporterClient : public ::crash_reporter::CrashReporterClient { public: - AwCrashReporterClient() {} + AwCrashReporterClient() : dump_fd_(-1) {} // crash_reporter::CrashReporterClient implementation. bool IsRunningUnattended() override { return false; } @@ -35,7 +37,19 @@ class AwCrashReporterClient : public ::crash_reporter::CrashReporterClient { // only when NO_UNWIND_TABLES == 1). bool ShouldEnableBreakpadMicrodumps() override { return true; } + int GetAndroidMinidumpDescriptor() override { return dump_fd_; } + + bool DumpWithoutCrashingToFd(int fd) { + base::AutoLock lock(dump_lock_); + dump_fd_ = fd; + base::debug::DumpWithoutCrashing(); + dump_fd_ = -1; + return true; + } + private: + int dump_fd_; + base::Lock dump_lock_; DISALLOW_COPY_AND_ASSIGN(AwCrashReporterClient); }; @@ -120,5 +134,9 @@ void AddGpuFingerprintToMicrodumpCrashHandler( breakpad::AddGpuFingerprintToMicrodumpCrashHandler(gpu_fingerprint); } +bool DumpWithoutCrashingToFd(int fd) { + return g_crash_reporter_client.Pointer()->DumpWithoutCrashingToFd(fd); +} + } // namespace crash_reporter } // namespace android_webview diff --git a/android_webview/crash_reporter/aw_microdump_crash_reporter.h b/android_webview/crash_reporter/aw_microdump_crash_reporter.h index 5fcda99..067363f 100644 --- a/android_webview/crash_reporter/aw_microdump_crash_reporter.h +++ b/android_webview/crash_reporter/aw_microdump_crash_reporter.h @@ -13,7 +13,7 @@ namespace crash_reporter { void EnableMicrodumpCrashReporter(); void AddGpuFingerprintToMicrodumpCrashHandler( const std::string& gpu_fingerprint); - +bool DumpWithoutCrashingToFd(int fd); } // namespace crash_reporter } // namespace android_webview diff --git a/android_webview/java/src/org/chromium/android_webview/AwDebug.java b/android_webview/java/src/org/chromium/android_webview/AwDebug.java new file mode 100644 index 0000000..72b125a --- /dev/null +++ b/android_webview/java/src/org/chromium/android_webview/AwDebug.java @@ -0,0 +1,43 @@ +// Copyright 2015 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. + +package org.chromium.android_webview; + +import org.chromium.base.annotations.JNINamespace; + +import java.io.File; +import java.io.IOException; + +/** + * Provides Android WebView debugging entrypoints. + * + * Methods in this class can be called from any thread, including threads created by + * the client of WebView. + */ +@JNINamespace("android_webview") +public class AwDebug { + /** + * Dump webview state (predominantly a minidump for all threads, + * but including other information) to the file descriptor fd. + * + * It is expected that this method is found by reflection, as it + * is not currently exposed by the android framework, and thus it + * needs to be protected from the unwanted attention of ProGuard. + * + * The File argument must refer to a pre-existing file, which must + * be able to be re-opened for reading and writing via its + * canonical path. The file will be truncated upon re-opening. + */ + public static boolean dumpWithoutCrashing(File dumpFile) { + String dumpPath; + try { + dumpPath = dumpFile.getCanonicalPath(); + } catch (IOException e) { + return false; + } + return nativeDumpWithoutCrashing(dumpPath); + } + + private static native boolean nativeDumpWithoutCrashing(String dumpPath); +} diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwDebugTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwDebugTest.java new file mode 100644 index 0000000..33bebb6 --- /dev/null +++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwDebugTest.java @@ -0,0 +1,33 @@ +// Copyright 2012 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. + +package org.chromium.android_webview.test; + +import android.os.Build; +import android.test.suitebuilder.annotation.SmallTest; + +import org.chromium.android_webview.AwDebug; +import org.chromium.base.test.util.Feature; +import org.chromium.base.test.util.MinAndroidSdkLevel; + +import java.io.File; + +/** + * A test suite for AwDebug class. + */ +@MinAndroidSdkLevel(Build.VERSION_CODES.KITKAT) +public class AwDebugTest extends AwTestBase { + @SmallTest + @Feature({"AndroidWebView", "Debug"}) + public void testDump() throws Throwable { + File f = File.createTempFile("dump", ".dmp"); + try { + assertTrue(AwDebug.dumpWithoutCrashing(f)); + assertTrue(f.canRead()); + assertTrue(f.length() != 0); + } finally { + assertTrue(f.delete()); + } + } +} diff --git a/android_webview/native/android_webview_jni_registrar.cc b/android_webview/native/android_webview_jni_registrar.cc index add2d2c..275e29b 100644 --- a/android_webview/native/android_webview_jni_registrar.cc +++ b/android_webview/native/android_webview_jni_registrar.cc @@ -11,6 +11,7 @@ #include "android_webview/native/aw_contents_client_bridge.h" #include "android_webview/native/aw_contents_io_thread_client_impl.h" #include "android_webview/native/aw_contents_statics.h" +#include "android_webview/native/aw_debug.h" #include "android_webview/native/aw_dev_tools_server.h" #include "android_webview/native/aw_form_database.h" #include "android_webview/native/aw_http_auth_handler.h" @@ -42,6 +43,7 @@ static base::android::RegistrationMethod kWebViewRegisteredMethods[] = { { "AwContentsClientBridge", RegisterAwContentsClientBridge }, { "AwContentsIoThreadClientImpl", RegisterAwContentsIoThreadClientImpl }, { "AwContentsStatics", RegisterAwContentsStatics }, + { "AwDebug", RegisterAwDebug }, { "AwDevToolsServer", RegisterAwDevToolsServer }, { "AwFormDatabase", RegisterAwFormDatabase }, { "AwPicture", RegisterAwPicture }, diff --git a/android_webview/native/aw_debug.cc b/android_webview/native/aw_debug.cc new file mode 100644 index 0000000..fcfb50b --- /dev/null +++ b/android_webview/native/aw_debug.cc @@ -0,0 +1,42 @@ +// Copyright 2015 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/native/aw_debug.h" + +#include "android_webview/crash_reporter/aw_microdump_crash_reporter.h" +#include "base/android/jni_android.h" +#include "base/android/jni_string.h" +#include "base/debug/dump_without_crashing.h" +#include "base/files/file.h" +#include "base/files/file_path.h" +#include "base/threading/thread_restrictions.h" +#include "jni/AwDebug_jni.h" + +using base::android::ConvertJavaStringToUTF16; +using base::android::ConvertUTF8ToJavaString; +using base::android::ScopedJavaLocalRef; + +namespace android_webview { + +static jboolean DumpWithoutCrashing(JNIEnv* env, + const JavaParamRef<jclass>& clazz, + const JavaParamRef<jstring>& dump_path) { + // This may be called from any thread, and we might be in a state + // where it is impossible to post tasks, so we have to be prepared + // to do IO from this thread. + base::ThreadRestrictions::ScopedAllowIO allow_io; + base::File target(base::FilePath(ConvertJavaStringToUTF8(env, dump_path)), + base::File::FLAG_OPEN_TRUNCATED | base::File::FLAG_READ | + base::File::FLAG_WRITE); + if (!target.IsValid()) + return false; + // breakpad_linux::HandleCrashDump will close this fd once it is done. + return crash_reporter::DumpWithoutCrashingToFd(target.TakePlatformFile()); +} + +bool RegisterAwDebug(JNIEnv* env) { + return RegisterNativesImpl(env); +} + +} // namespace android_webview diff --git a/android_webview/native/aw_debug.h b/android_webview/native/aw_debug.h new file mode 100644 index 0000000..c1eadaa --- /dev/null +++ b/android_webview/native/aw_debug.h @@ -0,0 +1,21 @@ +// Copyright 2015 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_NATIVE_AW_DEBUG_H_ +#define ANDROID_WEBVIEW_NATIVE_AW_DEBUG_H_ + +#include <jni.h> + +#include "base/android/jni_weak_ref.h" +#include "base/android/scoped_java_ref.h" +#include "base/memory/scoped_ptr.h" +#include "content/public/browser/web_contents_observer.h" + +namespace android_webview { + +bool RegisterAwDebug(JNIEnv* env); + +} // namespace android_webview + +#endif // ANDROID_WEBVIEW_NATIVE_AW_DEBUG_H_ diff --git a/android_webview/native/webview_native.gyp b/android_webview/native/webview_native.gyp index 33d5401..9cdb1eb 100644 --- a/android_webview/native/webview_native.gyp +++ b/android_webview/native/webview_native.gyp @@ -51,6 +51,8 @@ 'aw_contents_io_thread_client_impl.h', 'aw_contents_statics.cc', 'aw_contents_statics.h', + 'aw_debug.cc', + 'aw_debug.h', 'aw_dev_tools_server.cc', 'aw_dev_tools_server.h', 'aw_form_database.cc', @@ -132,6 +134,7 @@ '../java/src/org/chromium/android_webview/AwContentsIoThreadClient.java', '../java/src/org/chromium/android_webview/AwContentsStatics.java', '../java/src/org/chromium/android_webview/AwCookieManager.java', + '../java/src/org/chromium/android_webview/AwDebug.java', '../java/src/org/chromium/android_webview/AwDevToolsServer.java', '../java/src/org/chromium/android_webview/AwFormDatabase.java', '../java/src/org/chromium/android_webview/AwHttpAuthHandler.java', diff --git a/components/crash/content/app/breakpad_linux.cc b/components/crash/content/app/breakpad_linux.cc index d92953e..f93dda7 100644 --- a/components/crash/content/app/breakpad_linux.cc +++ b/components/crash/content/app/breakpad_linux.cc @@ -603,7 +603,7 @@ bool CrashDone(const MinidumpDescriptor& minidump, return false; } - DCHECK(!minidump.IsFD()); + DCHECK(!(upload && minidump.IsFD())); BreakpadInfo info = {0}; info.filename = minidump.path(); @@ -812,6 +812,19 @@ void EnableNonBrowserCrashDumping(const std::string& process_type, nullptr, CrashDoneInProcessNoUpload, nullptr, true, -1); } +void GenerateMinidumpOnDemandForAndroid() { + // TODO(tobiasjs) this still calls FinalizeCrashDoneAndroid, which + // generates logspam. Consider refactoring. + int dump_fd = GetCrashReporterClient()->GetAndroidMinidumpDescriptor(); + if (dump_fd >= 0) { + MinidumpDescriptor minidump_descriptor(dump_fd); + minidump_descriptor.set_size_limit(-1); + ExceptionHandler(minidump_descriptor, nullptr, CrashDoneNoUpload, nullptr, + false, -1) + .WriteMinidump(); + } +} + void MicrodumpInfo::SetGpuFingerprint(const std::string& gpu_fingerprint) { DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(!microdump_gpu_fingerprint_); @@ -860,6 +873,18 @@ void MicrodumpInfo::Initialize(const std::string& process_type, reinterpret_cast<void*>(is_browser_process), true, // Install handlers. -1); // Server file descriptor. -1 for in-process. + + if (process_type == "webview") { + // We do not use |DumpProcess()| for handling programatically + // generated dumps for WebView because we only know the file + // descriptor to which we are dumping at the time of the call to + // |DumpWithoutCrashing()|. Therefore we need to construct the + // |MinidumpDescriptor| and |ExceptionHandler| instances as + // needed, instead of setting up |g_breakpad| at initialization + // time. + base::debug::SetDumpWithoutCrashingFunction( + &GenerateMinidumpOnDemandForAndroid); + } } #else |