summaryrefslogtreecommitdiffstats
path: root/chrome/common
diff options
context:
space:
mode:
authorjam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-07-08 18:31:20 +0000
committerjam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-07-08 18:31:20 +0000
commitbd11ba32a3a9844a15ed2a0c2cf6a4140c2853ae (patch)
tree32c018c626c1b6580224fdd8ff7b2cc7aeadcbab /chrome/common
parent6f65cc3b4114080938c42bc1f3f55c0188f27163 (diff)
downloadchromium_src-bd11ba32a3a9844a15ed2a0c2cf6a4140c2853ae.zip
chromium_src-bd11ba32a3a9844a15ed2a0c2cf6a4140c2853ae.tar.gz
chromium_src-bd11ba32a3a9844a15ed2a0c2cf6a4140c2853ae.tar.bz2
Add the page url to plugin crashes to aid debugging.
Review URL: http://codereview.chromium.org/149305 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@20173 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/common')
-rw-r--r--chrome/common/child_process_logging.h55
-rw-r--r--chrome/common/child_process_logging_linux.cc22
-rw-r--r--chrome/common/child_process_logging_mac.mm71
-rw-r--r--chrome/common/child_process_logging_mac_unittest.mm138
-rw-r--r--chrome/common/child_process_logging_win.cc31
-rw-r--r--chrome/common/plugin_messages.h5
6 files changed, 322 insertions, 0 deletions
diff --git a/chrome/common/child_process_logging.h b/chrome/common/child_process_logging.h
new file mode 100644
index 0000000..43b34d2
--- /dev/null
+++ b/chrome/common/child_process_logging.h
@@ -0,0 +1,55 @@
+// Copyright (c) 2009 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 CHROME_COMMON_CHILD_PROCESS_LOGGING_H_
+#define CHROME_COMMON_CHILD_PROCESS_LOGGING_H_
+
+#include "base/basictypes.h"
+#include "googleurl/src/gurl.h"
+
+namespace child_process_logging {
+
+// Sets the URL that is logged if the child process crashes. Use GURL() to clear
+// the URL.
+void SetActiveURL(const GURL& url);
+
+// Simple wrapper class that sets the active URL in it's constructor and clears
+// the active URL in the destructor.
+class ScopedActiveURLSetter {
+ public:
+ explicit ScopedActiveURLSetter(const GURL& url) {
+ SetActiveURL(url);
+ }
+
+ ~ScopedActiveURLSetter() {
+ SetActiveURL(GURL());
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ScopedActiveURLSetter);
+};
+
+} // namespace child_process_logging
+
+#if defined(OS_MACOSX) && __OBJC__
+// Exported for testing purposes.
+
+@class NSString;
+
+typedef void (*SetCrashKeyValueFuncPtr)(NSString*, NSString*);
+typedef void (*ClearCrashKeyValueFuncPtr)(NSString*);
+
+namespace child_process_logging {
+void SetActiveURLImpl(const GURL& url,
+ SetCrashKeyValueFuncPtr set_key_func,
+ ClearCrashKeyValueFuncPtr clear_key_func);
+
+extern const int kMaxNumCrashURLChunks;
+extern const int kMaxNumURLChunkValueLength;
+extern const char *kUrlChunkFormatStr;
+} // namespace child_process_logging
+
+#endif // defined(OS_MACOSX) && __OBJC__
+
+#endif // CHROME_COMMON_CHILD_PROCESS_LOGGING_H_
diff --git a/chrome/common/child_process_logging_linux.cc b/chrome/common/child_process_logging_linux.cc
new file mode 100644
index 0000000..59b16f6
--- /dev/null
+++ b/chrome/common/child_process_logging_linux.cc
@@ -0,0 +1,22 @@
+// Copyright (c) 2009 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 "chrome/common/child_process_logging.h"
+
+#include <string>
+
+#include "base/logging.h"
+#include "googleurl/src/gurl.h"
+
+namespace child_process_logging {
+
+// We use a static string to hold the most recent active url. If we crash, the
+// crash handler code will send the contents of this string to the browser.
+std::string active_url;
+
+void SetActiveURL(const GURL& url) {
+ active_url = url.possibly_invalid_spec();
+}
+
+} // namespace child_process_logging
diff --git a/chrome/common/child_process_logging_mac.mm b/chrome/common/child_process_logging_mac.mm
new file mode 100644
index 0000000..a05b79d
--- /dev/null
+++ b/chrome/common/child_process_logging_mac.mm
@@ -0,0 +1,71 @@
+// Copyright (c) 2009 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 "chrome/common/child_process_logging.h"
+
+#import <Foundation/Foundation.h>
+
+#include "base/string_util.h"
+#include "googleurl/src/gurl.h"
+#import "chrome/app/breakpad_mac.h"
+
+namespace child_process_logging {
+
+const int kMaxNumCrashURLChunks = 8;
+const int kMaxNumURLChunkValueLength = 255;
+const char *kUrlChunkFormatStr = "url-chunk-%d";
+
+void SetActiveURLImpl(const GURL& url,
+ SetCrashKeyValueFuncPtr set_key_func,
+ ClearCrashKeyValueFuncPtr clear_key_func) {
+
+ NSString *kUrlChunkFormatStr_utf8 = [NSString
+ stringWithUTF8String:kUrlChunkFormatStr];
+
+ // First remove any old url chunks we might have lying around.
+ for (int i = 0; i < kMaxNumCrashURLChunks; i++) {
+ // On Windows the url-chunk items are 1-based, so match that.
+ NSString *key = [NSString stringWithFormat:kUrlChunkFormatStr_utf8, i+1];
+ clear_key_func(key);
+ }
+
+ const std::string& raw_url_utf8 = url.possibly_invalid_spec();
+ NSString *raw_url = [NSString stringWithUTF8String:raw_url_utf8.c_str()];
+ size_t raw_url_length = [raw_url length];
+
+ // Bail on zero-length URLs.
+ if (raw_url_length == 0) {
+ return;
+ }
+
+ // Parcel the URL up into up to 8, 255 byte segments.
+ size_t start_ofs = 0;
+ for (int i = 0;
+ i < kMaxNumCrashURLChunks && start_ofs < raw_url_length;
+ ++i) {
+
+ // On Windows the url-chunk items are 1-based, so match that.
+ NSString *key = [NSString stringWithFormat:kUrlChunkFormatStr_utf8, i+1];
+ NSRange range;
+ range.location = start_ofs;
+ range.length = std::min((size_t)kMaxNumURLChunkValueLength,
+ raw_url_length - start_ofs);
+ NSString *value = [raw_url substringWithRange:range];
+ set_key_func(key, value);
+
+ // Next chunk.
+ start_ofs += kMaxNumURLChunkValueLength;
+ }
+}
+
+void SetActiveURL(const GURL& url) {
+ // If Breakpad isn't initialized then bail.
+ if (IsCrashReporterDisabled()) {
+ return;
+ }
+
+ SetActiveURLImpl(url, SetCrashKeyValue, ClearCrashKeyValue);
+}
+
+} // namespace child_process_logging
diff --git a/chrome/common/child_process_logging_mac_unittest.mm b/chrome/common/child_process_logging_mac_unittest.mm
new file mode 100644
index 0000000..276f19b
--- /dev/null
+++ b/chrome/common/child_process_logging_mac_unittest.mm
@@ -0,0 +1,138 @@
+// Copyright (c) 2009 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 "chrome/common/child_process_logging.h"
+
+#import <Foundation/Foundation.h>
+
+#include "base/logging.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/platform_test.h"
+
+typedef PlatformTest ChildProcessLoggingTest;
+
+namespace {
+
+// Class to mock breakpad's setkeyvalue/clearkeyvalue functions needed for
+// SetActiveRendererURLImpl.
+// The Keys are stored in a static dictionary and methods are provided to
+// verify correctness.
+class MockBreakpadKeyValueStore {
+ public:
+ MockBreakpadKeyValueStore() {
+ // Only one of these objects can be active at once.
+ DCHECK(dict == NULL);
+ dict = [[NSMutableDictionary alloc] init];
+ }
+
+ ~MockBreakpadKeyValueStore() {
+ // Only one of these objects can be active at once.
+ DCHECK(dict != NULL);
+ [dict release];
+ dict = NULL;
+ }
+
+ static void SetKeyValue(NSString* key, NSString* value) {
+ DCHECK(dict != NULL);
+ [dict setObject:value forKey:key];
+ }
+
+ static void ClearKeyValue(NSString *key) {
+ DCHECK(dict != NULL);
+ [dict removeObjectForKey:key];
+ }
+
+ int CountDictionaryEntries() {
+ return [dict count];
+ }
+
+ bool VerifyDictionaryContents(const std::string &url) {
+ using child_process_logging::kMaxNumCrashURLChunks;
+ using child_process_logging::kMaxNumURLChunkValueLength;
+ using child_process_logging::kUrlChunkFormatStr;
+
+ int num_url_chunks = CountDictionaryEntries();
+ EXPECT_TRUE(num_url_chunks <= kMaxNumCrashURLChunks);
+
+ NSString *kUrlChunkFormatStr_utf8 = [NSString
+ stringWithUTF8String:kUrlChunkFormatStr];
+
+ NSString *accumulated_url = @"";
+ for (int i = 0; i < num_url_chunks; ++i) {
+ // URL chunk names are 1-based.
+ NSString *key = [NSString stringWithFormat:kUrlChunkFormatStr_utf8, i+1];
+ EXPECT_TRUE(key != NULL);
+ NSString *value = [dict objectForKey:key];
+ EXPECT_TRUE([value length] > 0);
+ EXPECT_TRUE([value length] <= (unsigned)kMaxNumURLChunkValueLength);
+ accumulated_url = [accumulated_url stringByAppendingString:value];
+ }
+
+ NSString *expected_url = [NSString stringWithUTF8String:url.c_str()];
+ return([accumulated_url isEqualToString:expected_url]);
+ }
+
+ private:
+ static NSMutableDictionary* dict;
+ DISALLOW_COPY_AND_ASSIGN(MockBreakpadKeyValueStore);
+};
+
+} // namespace
+
+// Call through to SetActiveURLImpl using the functions from
+// MockBreakpadKeyValueStore.
+void SetActiveURLWithMock(const GURL& url) {
+ using child_process_logging::SetActiveURLImpl;
+
+ SetCrashKeyValueFuncPtr setFunc = MockBreakpadKeyValueStore::SetKeyValue;
+ ClearCrashKeyValueFuncPtr clearFunc =
+ MockBreakpadKeyValueStore::ClearKeyValue;
+
+ SetActiveURLImpl(url, setFunc, clearFunc);
+}
+
+TEST_F(ChildProcessLoggingTest, TestUrlSplitting) {
+ using child_process_logging::kMaxNumCrashURLChunks;
+ using child_process_logging::kMaxNumURLChunkValueLength;
+
+ const std::string short_url("http://abc/");
+ std::string long_url("http://");
+ std::string overflow_url("http://");
+
+ long_url += std::string(kMaxNumURLChunkValueLength * 2, 'a');
+ long_url += "/";
+
+ int max_num_chars_stored_in_dump = kMaxNumURLChunkValueLength *
+ kMaxNumCrashURLChunks;
+ overflow_url += std::string(max_num_chars_stored_in_dump + 1, 'a');
+ overflow_url += "/";
+
+ // Check that Clearing NULL URL works.
+ MockBreakpadKeyValueStore mock;
+ SetActiveURLWithMock(GURL());
+ EXPECT_EQ(mock.CountDictionaryEntries(), 0);
+
+ // Check that we can set a URL.
+ SetActiveURLWithMock(GURL(short_url.c_str()));
+ EXPECT_TRUE(mock.VerifyDictionaryContents(short_url));
+ EXPECT_EQ(mock.CountDictionaryEntries(), 1);
+ SetActiveURLWithMock(GURL());
+ EXPECT_EQ(mock.CountDictionaryEntries(), 0);
+
+ // Check that we can replace a long url with a short url.
+ SetActiveURLWithMock(GURL(long_url.c_str()));
+ EXPECT_TRUE(mock.VerifyDictionaryContents(long_url));
+ SetActiveURLWithMock(GURL(short_url.c_str()));
+ EXPECT_TRUE(mock.VerifyDictionaryContents(short_url));
+ SetActiveURLWithMock(GURL());
+ EXPECT_EQ(mock.CountDictionaryEntries(), 0);
+
+
+ // Check that overflow works correctly.
+ SetActiveURLWithMock(GURL(overflow_url.c_str()));
+ EXPECT_TRUE(mock.VerifyDictionaryContents(
+ overflow_url.substr(0, max_num_chars_stored_in_dump)));
+ SetActiveURLWithMock(GURL());
+ EXPECT_EQ(mock.CountDictionaryEntries(), 0);
+}
diff --git a/chrome/common/child_process_logging_win.cc b/chrome/common/child_process_logging_win.cc
new file mode 100644
index 0000000..2221713
--- /dev/null
+++ b/chrome/common/child_process_logging_win.cc
@@ -0,0 +1,31 @@
+// Copyright (c) 2009 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 "chrome/common/child_process_logging.h"
+
+#include <windows.h>
+
+#include "base/string_util.h"
+#include "chrome/common/chrome_constants.h"
+#include "googleurl/src/gurl.h"
+
+namespace child_process_logging {
+
+typedef void (__cdecl *MainSetActiveURL)(const wchar_t*);
+
+void SetActiveURL(const GURL& url) {
+ HMODULE exe_module = GetModuleHandle(chrome::kBrowserProcessExecutableName);
+ if (!exe_module)
+ return;
+
+ MainSetActiveURL set_active_url =
+ reinterpret_cast<MainSetActiveURL>(
+ GetProcAddress(exe_module, "SetActiveURL"));
+ if (!set_active_url)
+ return;
+
+ (set_active_url)(UTF8ToWide(url.possibly_invalid_spec()).c_str());
+}
+
+} // namespace child_process_logging
diff --git a/chrome/common/plugin_messages.h b/chrome/common/plugin_messages.h
index 111a7db..3b43b8b 100644
--- a/chrome/common/plugin_messages.h
+++ b/chrome/common/plugin_messages.h
@@ -32,6 +32,7 @@
struct PluginMsg_Init_Params {
gfx::NativeViewId containing_window;
GURL url;
+ GURL page_url;
std::vector<std::string> arg_names;
std::vector<std::string> arg_values;
#if defined(OS_WIN)
@@ -109,6 +110,7 @@ struct ParamTraits<PluginMsg_Init_Params> {
static void Write(Message* m, const param_type& p) {
WriteParam(m, p.containing_window);
WriteParam(m, p.url);
+ WriteParam(m, p.page_url);
DCHECK(p.arg_names.size() == p.arg_values.size());
WriteParam(m, p.arg_names);
WriteParam(m, p.arg_values);
@@ -120,6 +122,7 @@ struct ParamTraits<PluginMsg_Init_Params> {
static bool Read(const Message* m, void** iter, param_type* p) {
return ReadParam(m, iter, &p->containing_window) &&
ReadParam(m, iter, &p->url) &&
+ ReadParam(m, iter, &p->page_url) &&
ReadParam(m, iter, &p->arg_names) &&
ReadParam(m, iter, &p->arg_values) &&
#if defined(OS_WIN)
@@ -133,6 +136,8 @@ struct ParamTraits<PluginMsg_Init_Params> {
l->append(L", ");
LogParam(p.url, l);
l->append(L", ");
+ LogParam(p.page_url, l);
+ l->append(L", ");
LogParam(p.arg_names, l);
l->append(L", ");
LogParam(p.arg_values, l);