Merge mozilla-central to mozilla-inbound

This commit is contained in:
Matt Brubeck 2011-09-30 21:02:01 -07:00
Родитель cce8ca30ec f5af8007c3
Коммит bea15ba99c
54 изменённых файлов: 1161 добавлений и 477 удалений

Просмотреть файл

@ -1360,7 +1360,7 @@ nsHTMLTableAccessible::IsProbablyForLayout(bool *aIsProbablyForLayout)
#define RETURN_LAYOUT_ANSWER(isLayout, heuristic) { *aIsProbablyForLayout = isLayout; return NS_OK; }
#endif
*aIsProbablyForLayout = PR_FALSE;
*aIsProbablyForLayout = false;
if (IsDefunct())
return NS_ERROR_FAILURE;
@ -1369,7 +1369,7 @@ nsHTMLTableAccessible::IsProbablyForLayout(bool *aIsProbablyForLayout)
if (docAccessible) {
PRUint64 docState = docAccessible->State();
if (docState & states::EDITABLE) { // Need to see all elements while document is being edited
RETURN_LAYOUT_ANSWER(PR_FALSE, "In editable document");
RETURN_LAYOUT_ANSWER(false, "In editable document");
}
}
@ -1377,45 +1377,77 @@ nsHTMLTableAccessible::IsProbablyForLayout(bool *aIsProbablyForLayout)
// but for which we still expose table semantics (treegrid, for example).
bool hasNonTableRole = (Role() != nsIAccessibleRole::ROLE_TABLE);
if (hasNonTableRole) {
RETURN_LAYOUT_ANSWER(PR_FALSE, "Has role attribute");
RETURN_LAYOUT_ANSWER(false, "Has role attribute");
}
if (mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::role)) {
// Role attribute is present, but overridden roles have already been dealt with.
// Only landmarks and other roles that don't override the role from native
// markup are left to deal with here.
RETURN_LAYOUT_ANSWER(PR_FALSE, "Has role attribute, weak role, and role is table");
RETURN_LAYOUT_ANSWER(false, "Has role attribute, weak role, and role is table");
}
// Check for legitimate data table elements or attributes
// Check for legitimate data table attributes.
nsAutoString summary;
if ((mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::summary, summary) &&
!summary.IsEmpty()) ||
HasDescendant(NS_LITERAL_STRING("caption"), PR_FALSE) ||
HasDescendant(NS_LITERAL_STRING("th")) ||
HasDescendant(NS_LITERAL_STRING("thead")) ||
HasDescendant(NS_LITERAL_STRING("tfoot")) ||
HasDescendant(NS_LITERAL_STRING("colgroup"))) {
RETURN_LAYOUT_ANSWER(PR_FALSE, "Has caption, summary, th, thead, tfoot or colgroup -- legitimate table structures");
if (mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::summary, summary) &&
!summary.IsEmpty())
RETURN_LAYOUT_ANSWER(false, "Has summary -- legitimate table structures");
// Check for legitimate data table elements.
nsAccessible* caption = FirstChild();
if (caption && caption->Role() == nsIAccessibleRole::ROLE_CAPTION &&
caption->HasChildren()) {
RETURN_LAYOUT_ANSWER(false,
"Not empty caption -- legitimate table structures");
}
for (nsIContent* childElm = mContent->GetFirstChild(); childElm;
childElm = childElm->GetNextSibling()) {
if (!childElm->IsHTML())
continue;
if (childElm->Tag() == nsGkAtoms::col ||
childElm->Tag() == nsGkAtoms::colgroup ||
childElm->Tag() == nsGkAtoms::tfoot ||
childElm->Tag() == nsGkAtoms::thead) {
RETURN_LAYOUT_ANSWER(false,
"Has col, colgroup, tfoot or thead -- legitimate table structures");
}
if (childElm->Tag() == nsGkAtoms::tbody) {
for (nsIContent* rowElm = childElm->GetFirstChild(); rowElm;
rowElm = rowElm->GetNextSibling()) {
if (rowElm->IsHTML() && rowElm->Tag() == nsGkAtoms::tr) {
for (nsIContent* cellElm = rowElm->GetFirstChild(); cellElm;
cellElm = cellElm->GetNextSibling()) {
if (cellElm->IsHTML() && cellElm->Tag() == nsGkAtoms::th) {
RETURN_LAYOUT_ANSWER(false,
"Has th -- legitimate table structures");
}
}
}
}
}
}
if (HasDescendant(NS_LITERAL_STRING("table"))) {
RETURN_LAYOUT_ANSWER(PR_TRUE, "Has a nested table within it");
RETURN_LAYOUT_ANSWER(true, "Has a nested table within it");
}
// If only 1 column or only 1 row, it's for layout
PRInt32 columns, rows;
GetColumnCount(&columns);
if (columns <=1) {
RETURN_LAYOUT_ANSWER(PR_TRUE, "Has only 1 column");
RETURN_LAYOUT_ANSWER(true, "Has only 1 column");
}
GetRowCount(&rows);
if (rows <=1) {
RETURN_LAYOUT_ANSWER(PR_TRUE, "Has only 1 row");
RETURN_LAYOUT_ANSWER(true, "Has only 1 row");
}
// Check for many columns
if (columns >= 5) {
RETURN_LAYOUT_ANSWER(PR_FALSE, ">=5 columns");
RETURN_LAYOUT_ANSWER(false, ">=5 columns");
}
// Now we know there are 2-4 columns and 2 or more rows
@ -1434,7 +1466,7 @@ nsHTMLTableAccessible::IsProbablyForLayout(bool *aIsProbablyForLayout)
nsMargin border;
cellFrame->GetBorder(border);
if (border.top && border.bottom && border.left && border.right) {
RETURN_LAYOUT_ANSWER(PR_FALSE, "Has nonzero border-width on table cell");
RETURN_LAYOUT_ANSWER(false, "Has nonzero border-width on table cell");
}
/**
@ -1462,21 +1494,21 @@ nsHTMLTableAccessible::IsProbablyForLayout(bool *aIsProbablyForLayout)
lastRowColor = color;
styleDecl->GetPropertyValue(NS_LITERAL_STRING("background-color"), color);
if (rowCount > 0 && PR_FALSE == lastRowColor.Equals(color)) {
RETURN_LAYOUT_ANSWER(PR_FALSE, "2 styles of row background color, non-bordered");
RETURN_LAYOUT_ANSWER(false, "2 styles of row background color, non-bordered");
}
}
// Check for many rows
const PRInt32 kMaxLayoutRows = 20;
if (rows > kMaxLayoutRows) { // A ton of rows, this is probably for data
RETURN_LAYOUT_ANSWER(PR_FALSE, ">= kMaxLayoutRows (20) and non-bordered");
RETURN_LAYOUT_ANSWER(false, ">= kMaxLayoutRows (20) and non-bordered");
}
// Check for very wide table
nsAutoString styledWidth;
GetComputedStyleValue(EmptyString(), NS_LITERAL_STRING("width"), styledWidth);
if (styledWidth.EqualsLiteral("100%")) {
RETURN_LAYOUT_ANSWER(PR_TRUE, "<=4 columns and 100% width");
RETURN_LAYOUT_ANSWER(true, "<=4 columns and 100% width");
}
if (styledWidth.Find(NS_LITERAL_STRING("px"))) { // Hardcoded in pixels
nsIFrame *tableFrame = GetFrame();
@ -1494,24 +1526,24 @@ nsHTMLTableAccessible::IsProbablyForLayout(bool *aIsProbablyForLayout)
if (percentageOfDocWidth > 95) {
// 3-4 columns, no borders, not a lot of rows, and 95% of the doc's width
// Probably for layout
RETURN_LAYOUT_ANSWER(PR_TRUE, "<=4 columns, width hardcoded in pixels and 95% of document width");
RETURN_LAYOUT_ANSWER(true, "<=4 columns, width hardcoded in pixels and 95% of document width");
}
}
}
// Two column rules
if (rows * columns <= 10) {
RETURN_LAYOUT_ANSWER(PR_TRUE, "2-4 columns, 10 cells or less, non-bordered");
RETURN_LAYOUT_ANSWER(true, "2-4 columns, 10 cells or less, non-bordered");
}
if (HasDescendant(NS_LITERAL_STRING("embed")) ||
HasDescendant(NS_LITERAL_STRING("object")) ||
HasDescendant(NS_LITERAL_STRING("applet")) ||
HasDescendant(NS_LITERAL_STRING("iframe"))) {
RETURN_LAYOUT_ANSWER(PR_TRUE, "Has no borders, and has iframe, object, applet or iframe, typical of advertisements");
RETURN_LAYOUT_ANSWER(true, "Has no borders, and has iframe, object, applet or iframe, typical of advertisements");
}
RETURN_LAYOUT_ANSWER(PR_FALSE, "no layout factor strong enough, so will guess data");
RETURN_LAYOUT_ANSWER(false, "no layout factor strong enough, so will guess data");
}

Просмотреть файл

@ -36,9 +36,6 @@
// table with empty caption
testAttrs("table4.2", attr, true);
// table with two captions
testAbsentAttrs("table4.3", attr);
// table with th element
testAbsentAttrs("table5", attr);
@ -48,8 +45,9 @@
// table with tfoot element
testAbsentAttrs("table7", attr);
// table with colgroup element
// table with colgroup or col elements
testAbsentAttrs("table8", attr);
testAbsentAttrs("table8.2", attr);
// layout table with nested table
testAttrs("table9", attr, true);
@ -87,6 +85,14 @@
// tree grid, no layout table
testAbsentAttrs("table20", attr);
// layout table containing nested data table (having data structures)
testAttrs("table21", attr, true);
testAttrs("table21.2", attr, true);
testAttrs("table21.3", attr, true);
testAttrs("table21.4", attr, true);
testAttrs("table21.5", attr, true);
testAttrs("table21.6", attr, true);
SimpleTest.finish();
}
@ -101,6 +107,11 @@
title="Don't treat tables that have a landmark role as layout table">
Mozilla Bug 495388
</a>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=690222"
title="Data table elements used to determine layout-guess attribute shouldn't be picked from nested tables">
Mozilla Bug 690222
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
@ -178,15 +189,6 @@
</tr>
</table>
<!-- table with two captions -->
<table id="table4.3">
<caption> </caption>
<tr>
<td>Cell1</td><td>cell2</td>
</tr>
<caption>a caption</caption>
</table>
<!-- table with th element -->
<table id="table5">
<tr>
@ -212,10 +214,17 @@
</tfoot>
</table>
<!-- table with colgroup element -->
<!-- table with colgroup and col elements -->
<table id="table8">
<colgroup width="20"></colgroup>
<tr>
<colgroup><td>Cell1</td><td>cell2</td></colgroup>
<td>Cell1</td><td>cell2</td>
</tr>
</table>
<table id="table8.2">
<col width="20">
<tr>
<td>Cell1</td><td>cell2</td>
</tr>
</table>
@ -339,5 +348,68 @@
<table id="table20" role="treegrid">
<tr role="treeitem"><td>Cell1</td><td>Cell2</td></tr>
</table>
<!-- layout table with nested data table containing data table elements -->
<table id="table21">
<tr>
<td>
<table>
<caption>table</caption>
<tr><td>Cell</td></tr>
</table>
</td>
</tr>
</table>
<table id="table21.2">
<tr>
<td>
<table>
<colgroup width="20"></colgroup>
<tr><th>Cell</th></tr>
</table>
</td>
</tr>
</table>
<table id="table21.3">
<tr>
<td>
<table>
<col width="20"></col>
<tr><th>Cell</th></tr>
</table>
</td>
</tr>
</table>
<table id="table21.4">
<tr>
<td>
<table>
<tr><th>Cell</th></tr>
</table>
</td>
</tr>
</table>
<table id="table21.5">
<tr>
<td>
<table>
<thead>
<tr><td>Cell</td></tr>
</thead>
</table>
</td>
</tr>
</table>
<table id="table21.6">
<tr>
<td>
<table>
<tfoot>
<tr><td>Cell</td></tr>
</tfoot>
</table>
</td>
</tr>
</table>
</body>
</html>

Просмотреть файл

@ -51,9 +51,7 @@ DIRS = \
include $(topsrcdir)/config/rules.mk
_TEST_FILES = test_bug408328.html \
bug408328-data.xml \
test_bug368464.html \
_TEST_FILES = bug408328-data.xml \
bug368464-data.xml \
test_bug494328.html \
bug494328-data.xml \

Просмотреть файл

@ -51,6 +51,8 @@ _HTTP_FILES = \
_CHROME_FILES = \
test_423060.xul \
test_bug368464.html \
test_bug408328.html \
$(NULL)
libs:: $(_HTTP_FILES)

Просмотреть файл

@ -5,12 +5,12 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=368464
-->
<head>
<title>Test that RSS 0.90 isn't sniffed</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=368464">Mozilla Bug 368464</a>
<p id="display"><iframe id="testFrame" src="bug368464-data.xml"></iframe></p>
<p id="display"><iframe id="testFrame" src="http://mochi.test:8888/tests/browser/components/feeds/test/bug368464-data.xml"></iframe></p>
<div id="content" style="display: none">
</div>
@ -21,7 +21,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=368464
SimpleTest.waitForExplicitFinish();
addLoadEvent(function() {
netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
ok($("testFrame").contentDocument.documentElement.id != "feedHandler",
"RSS 0.90 shouldn't be sniffed as a feed");
});

Просмотреть файл

@ -5,12 +5,12 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=408328
-->
<head>
<title>Test feed preview safe-linkification</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=408328">Mozilla Bug 408328</a>
<p id="display"><iframe id="testFrame" src="bug408328-data.xml"></iframe></p>
<p id="display"><iframe id="testFrame" src="http://mochi.test:8888/tests/browser/components/feeds/test/bug408328-data.xml"></iframe></p>
<div id="content" style="display: none">
</div>
@ -21,7 +21,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=408328
SimpleTest.waitForExplicitFinish();
addLoadEvent(function() {
netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
var links = $("testFrame").contentDocument.getElementById("feedContent").getElementsByTagName("a");
is(links.length, 5, "wrong number of linked items in feed preview");
for (var i = 0; i < links.length; i++) {

Просмотреть файл

@ -449,7 +449,17 @@ class DeviceManagerADB(DeviceManager):
# failure: None
def updateApp(self, appBundlePath, processName=None, destPath=None, ipAddr=None, port=30000):
return self.runCmd(["install", "-r", appBundlePath]).stdout.read()
# external function
# returns:
# success: time in ms
# failure: None
def getCurrentTime(self):
timestr = self.runCmd(["shell", "date", "+%s"]).stdout.read().strip()
if (not timestr or not timestr.isdigit()):
return None
return str(int(timestr)*1000)
# Returns information about the device:
# Directive indicates the information you want to get, your choices are:
# os - name of the os

Просмотреть файл

@ -265,8 +265,12 @@ ContentChild::Init(MessageLoop* aIOLoop,
Open(aChannel, aParentHandle, aIOLoop);
sSingleton = this;
#if defined(ANDROID) && defined(MOZ_CRASHREPORTER)
PCrashReporterChild* crashreporter = SendPCrashReporterConstructor();
#ifdef MOZ_CRASHREPORTER
SendPCrashReporterConstructor(CrashReporter::CurrentThreadId(),
XRE_GetProcessType());
#if defined(ANDROID)
PCrashReporterChild* crashreporter = ManagedPCrashReporterChild()[0];
InfallibleTArray<Mapping> mappings;
const struct mapping_info *info = getLibraryMapping();
while (info && info->name) {
@ -278,6 +282,7 @@ ContentChild::Init(MessageLoop* aIOLoop,
info++;
}
crashreporter->SendAddLibraryMappings(mappings);
#endif
#endif
return true;
@ -418,9 +423,14 @@ ContentChild::DeallocPBrowser(PBrowserChild* iframe)
}
PCrashReporterChild*
ContentChild::AllocPCrashReporter()
ContentChild::AllocPCrashReporter(const mozilla::dom::NativeThreadId& id,
const PRUint32& processType)
{
#ifdef MOZ_CRASHREPORTER
return new CrashReporterChild();
#else
return nsnull;
#endif
}
bool

Просмотреть файл

@ -80,8 +80,11 @@ public:
virtual PBrowserChild* AllocPBrowser(const PRUint32& aChromeFlags);
virtual bool DeallocPBrowser(PBrowserChild*);
virtual PCrashReporterChild* AllocPCrashReporter();
virtual bool DeallocPCrashReporter(PCrashReporterChild*);
virtual PCrashReporterChild*
AllocPCrashReporter(const mozilla::dom::NativeThreadId& id,
const PRUint32& processType);
virtual bool
DeallocPCrashReporter(PCrashReporterChild*);
virtual PMemoryReportRequestChild*
AllocPMemoryReportRequest();

Просмотреть файл

@ -355,27 +355,14 @@ ContentParent::ActorDestroy(ActorDestroyReason why)
props->SetPropertyAsBool(NS_LITERAL_STRING("abnormal"), PR_TRUE);
#ifdef MOZ_CRASHREPORTER
nsAutoString dumpID;
nsCOMPtr<nsILocalFile> crashDump;
TakeMinidump(getter_AddRefs(crashDump)) &&
CrashReporter::GetIDFromMinidump(crashDump, dumpID);
MOZ_ASSERT(ManagedPCrashReporterParent().Length() > 0);
CrashReporterParent* crashReporter =
static_cast<CrashReporterParent*>(ManagedPCrashReporterParent()[0]);
crashReporter->GenerateCrashReport(this, NULL);
nsAutoString dumpID(crashReporter->ChildDumpID());
props->SetPropertyAsAString(NS_LITERAL_STRING("dumpID"), dumpID);
if (!dumpID.IsEmpty()) {
CrashReporter::AnnotationTable notes;
notes.Init();
notes.Put(NS_LITERAL_CSTRING("ProcessType"), NS_LITERAL_CSTRING("content"));
char startTime[32];
sprintf(startTime, "%lld", static_cast<long long>(mProcessStartTime));
notes.Put(NS_LITERAL_CSTRING("StartupTime"),
nsDependentCString(startTime));
// TODO: Additional per-process annotations.
CrashReporter::AppendExtraData(dumpID, notes);
}
#endif
obs->NotifyObservers((nsIPropertyBag2*) props, "ipc:content-shutdown", nsnull);
@ -415,12 +402,19 @@ ContentParent::DestroyTestShell(TestShellParent* aTestShell)
return PTestShellParent::Send__delete__(aTestShell);
}
TestShellParent*
ContentParent::GetTestShellSingleton()
{
if (!ManagedPTestShellParent().Length())
return nsnull;
return static_cast<TestShellParent*>(ManagedPTestShellParent()[0]);
}
ContentParent::ContentParent()
: mGeolocationWatchID(-1)
, mRunToCompletionDepth(0)
, mShouldCallUnblockChild(false)
, mIsAlive(true)
, mProcessStartTime(time(NULL))
, mSendPermissionUpdates(false)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
@ -791,9 +785,23 @@ ContentParent::DeallocPBrowser(PBrowserParent* frame)
}
PCrashReporterParent*
ContentParent::AllocPCrashReporter()
ContentParent::AllocPCrashReporter(const NativeThreadId& tid,
const PRUint32& processType)
{
#ifdef MOZ_CRASHREPORTER
return new CrashReporterParent();
#else
return nsnull;
#endif
}
bool
ContentParent::RecvPCrashReporterConstructor(PCrashReporterParent* actor,
const NativeThreadId& tid,
const PRUint32& processType)
{
static_cast<CrashReporterParent*>(actor)->SetChildData(tid, processType);
return true;
}
bool

Просмотреть файл

@ -91,6 +91,7 @@ public:
TestShellParent* CreateTestShell();
bool DestroyTestShell(TestShellParent* aTestShell);
TestShellParent* GetTestShellSingleton();
void ReportChildAlreadyBlocked();
bool RequestRunToCompletion();
@ -99,6 +100,10 @@ public:
void SetChildMemoryReporters(const InfallibleTArray<MemoryReport>& report);
GeckoChildProcessHost* Process() {
return mSubprocess;
}
bool NeedsPermissionsUpdate() {
return mSendPermissionUpdates;
}
@ -123,8 +128,12 @@ private:
virtual PBrowserParent* AllocPBrowser(const PRUint32& aChromeFlags);
virtual bool DeallocPBrowser(PBrowserParent* frame);
virtual PCrashReporterParent* AllocPCrashReporter();
virtual PCrashReporterParent* AllocPCrashReporter(const NativeThreadId& tid,
const PRUint32& processType);
virtual bool DeallocPCrashReporter(PCrashReporterParent* crashreporter);
virtual bool RecvPCrashReporterConstructor(PCrashReporterParent* actor,
const NativeThreadId& tid,
const PRUint32& processType);
virtual PMemoryReportRequestParent* AllocPMemoryReportRequest();
virtual bool DeallocPMemoryReportRequest(PMemoryReportRequestParent* actor);
@ -230,11 +239,12 @@ private:
bool mIsAlive;
nsCOMPtr<nsIPrefServiceInternal> mPrefService;
time_t mProcessStartTime;
bool mSendPermissionUpdates;
nsRefPtr<nsFrameMessageManager> mMessageManager;
friend class CrashReporterParent;
};
} // namespace dom

Просмотреть файл

@ -0,0 +1,75 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: set sw=4 ts=8 et tw=80 :
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Crash Reporter.
*
* The Initial Developer of the Original Code is
* The Mozilla Foundation
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Josh Matthews <josh@joshmatthews.net>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "mozilla/plugins/PluginModuleChild.h"
#include "ContentChild.h"
#include "CrashReporterChild.h"
#include "nsXULAppAPI.h"
using mozilla::plugins::PluginModuleChild;
namespace mozilla {
namespace dom {
/*static*/
PCrashReporterChild*
CrashReporterChild::GetCrashReporter()
{
const InfallibleTArray<PCrashReporterChild*>* reporters = nsnull;
switch (XRE_GetProcessType()) {
case GeckoProcessType_Content: {
ContentChild* child = ContentChild::GetSingleton();
reporters = &child->ManagedPCrashReporterChild();
break;
}
case GeckoProcessType_Plugin: {
PluginModuleChild* child = PluginModuleChild::current();
reporters = &child->ManagedPCrashReporterChild();
break;
}
default:
break;
}
if (reporters && reporters->Length() > 0) {
return reporters->ElementAt(0);
}
return nsnull;
}
}
}

Просмотреть файл

@ -36,7 +36,15 @@
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef mozilla_dom_CrashReporterChild_h
#define mozilla_dom_CrashReporterChild_h
#include "mozilla/dom/PCrashReporterChild.h"
#ifdef MOZ_CRASHREPORTER
#include "nsExceptionHandler.h"
#include "nsXULAppAPI.h"
#endif
namespace mozilla {
namespace dom {
@ -45,11 +53,16 @@ class CrashReporterChild :
{
public:
CrashReporterChild() {
MOZ_COUNT_CTOR(CrashReporterChild);
MOZ_COUNT_CTOR(CrashReporterChild);
}
virtual ~CrashReporterChild() {
MOZ_COUNT_DTOR(CrashReporterChild);
~CrashReporterChild() {
MOZ_COUNT_DTOR(CrashReporterChild);
}
static PCrashReporterChild* GetCrashReporter();
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_CrashReporterChild_h

Просмотреть файл

@ -37,12 +37,11 @@
*
* ***** END LICENSE BLOCK ***** */
#include "CrashReporterParent.h"
#if defined(MOZ_CRASHREPORTER)
#include "nsExceptionHandler.h"
#endif
#include "base/process_util.h"
#include <time.h>
using namespace base;
namespace mozilla {
@ -73,9 +72,32 @@ CrashReporterParent::RecvAddLibraryMappings(const InfallibleTArray<Mapping>& map
return true;
}
bool
CrashReporterParent::RecvAnnotateCrashReport(const nsCString& key,
const nsCString& data)
{
#ifdef MOZ_CRASHREPORTER
mNotes.Put(key, data);
#endif
return true;
}
bool
CrashReporterParent::RecvAppendAppNotes(const nsCString& data)
{
mAppNotes.Append(data);
return true;
}
CrashReporterParent::CrashReporterParent()
: mStartTime(time(NULL))
, mInitialized(false)
{
MOZ_COUNT_CTOR(CrashReporterParent);
#ifdef MOZ_CRASHREPORTER
mNotes.Init(4);
#endif
}
CrashReporterParent::~CrashReporterParent()
@ -83,5 +105,67 @@ CrashReporterParent::~CrashReporterParent()
MOZ_COUNT_DTOR(CrashReporterParent);
}
void
CrashReporterParent::SetChildData(const NativeThreadId& tid,
const PRUint32& processType)
{
mInitialized = true;
mMainThread = tid;
mProcessType = processType;
}
#ifdef MOZ_CRASHREPORTER
bool
CrashReporterParent::GenerateHangCrashReport(const AnnotationTable* processNotes)
{
if (mChildDumpID.IsEmpty())
return false;
GenerateChildData(processNotes);
CrashReporter::AnnotationTable notes;
if (!notes.Init(4))
return false;
notes.Put(nsDependentCString("HangID"), NS_ConvertUTF16toUTF8(mHangID));
if (!CrashReporter::AppendExtraData(mParentDumpID, notes))
NS_WARNING("problem appending parent data to .extra");
return true;
}
bool
CrashReporterParent::GenerateChildData(const AnnotationTable* processNotes)
{
MOZ_ASSERT(mInitialized);
nsCAutoString type;
switch (mProcessType) {
case GeckoProcessType_Content:
type = NS_LITERAL_CSTRING("content");
break;
case GeckoProcessType_Plugin:
type = NS_LITERAL_CSTRING("plugin");
break;
default:
NS_ERROR("unknown process type");
break;
}
mNotes.Put(NS_LITERAL_CSTRING("ProcessType"), type);
char startTime[32];
sprintf(startTime, "%lld", static_cast<PRInt64>(mStartTime));
mNotes.Put(NS_LITERAL_CSTRING("StartupTime"), nsDependentCString(startTime));
if (!mAppNotes.IsEmpty())
mNotes.Put(NS_LITERAL_CSTRING("Notes"), mAppNotes);
bool ret = CrashReporter::AppendExtraData(mChildDumpID, mNotes);
if (ret && processNotes)
ret = CrashReporter::AppendExtraData(mChildDumpID, *processNotes);
if (!ret)
NS_WARNING("problem appending child data to .extra");
return ret;
}
#endif
} // namespace dom
} // namespace mozilla

Просмотреть файл

@ -1,4 +1,4 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: set sw=4 ts=8 et tw=80 :
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
@ -37,21 +37,162 @@
*
* ***** END LICENSE BLOCK ***** */
#include "mozilla/dom/PCrashReporterParent.h"
#include "mozilla/dom/TabMessageUtils.h"
#include "nsXULAppAPI.h"
#include "nsILocalFile.h"
#ifdef MOZ_CRASHREPORTER
#include "nsExceptionHandler.h"
#endif
namespace mozilla {
namespace dom {
class ProcessReporter;
class CrashReporterParent :
public PCrashReporterParent
{
#ifdef MOZ_CRASHREPORTER
typedef CrashReporter::AnnotationTable AnnotationTable;
#endif
public:
CrashReporterParent();
virtual ~CrashReporterParent();
CrashReporterParent();
virtual ~CrashReporterParent();
#ifdef MOZ_CRASHREPORTER
/* Attempt to generate a parent/child pair of minidumps from the given
toplevel actor in the event of a hang. Returns true if successful,
false otherwise.
*/
template<class Toplevel>
bool
GeneratePairedMinidump(Toplevel* t);
/* Attempt to create a bare-bones crash report for a hang, along with extra
process-specific annotations present in the given AnnotationTable. Returns
true if successful, false otherwise.
*/
bool
GenerateHangCrashReport(const AnnotationTable* processNotes);
/* Attempt to create a bare-bones crash report, along with extra process-
specific annotations present in the given AnnotationTable. Returns true if
successful, false otherwise.
*/
template<class Toplevel>
bool
GenerateCrashReport(Toplevel* t, const AnnotationTable* processNotes);
/* Instantiate a new crash reporter actor from a given parent that manages
the protocol.
*/
template<class Toplevel>
static void CreateCrashReporter(Toplevel* actor);
#endif
/* Initialize this reporter with data from the child process */
void
SetChildData(const NativeThreadId& id, const PRUint32& processType);
/* Returns the shared hang ID of a parent/child paired minidump.
GeneratePairedMinidump must be called first.
*/
const nsString& HangID() {
return mHangID;
}
/* Returns the ID of the parent minidump.
GeneratePairedMinidump must be called first.
*/
const nsString& ParentDumpID() {
return mParentDumpID;
}
/* Returns the ID of the child minidump.
GeneratePairedMinidump or GenerateCrashReport must be called first.
*/
const nsString& ChildDumpID() {
return mChildDumpID;
}
protected:
virtual void ActorDestroy(ActorDestroyReason why);
virtual bool
RecvAddLibraryMappings(const InfallibleTArray<Mapping>& m);
virtual bool
RecvAnnotateCrashReport(const nsCString& key, const nsCString& data);
virtual bool
RecvAppendAppNotes(const nsCString& data);
#ifdef MOZ_CRASHREPORTER
bool
GenerateChildData(const AnnotationTable* processNotes);
AnnotationTable mNotes;
#endif
nsCString mAppNotes;
nsString mHangID;
nsString mChildDumpID;
nsString mParentDumpID;
NativeThreadId mMainThread;
time_t mStartTime;
PRUint32 mProcessType;
bool mInitialized;
};
#ifdef MOZ_CRASHREPORTER
template<class Toplevel>
inline bool
CrashReporterParent::GeneratePairedMinidump(Toplevel* t)
{
CrashReporter::ProcessHandle child;
#ifdef XP_MACOSX
child = t->Process()->GetChildTask();
#else
child = t->OtherProcess();
#endif
nsCOMPtr<nsILocalFile> childDump;
nsCOMPtr<nsILocalFile> parentDump;
if (CrashReporter::CreatePairedMinidumps(child,
mMainThread,
&mHangID,
getter_AddRefs(childDump),
getter_AddRefs(parentDump)) &&
CrashReporter::GetIDFromMinidump(childDump, mChildDumpID) &&
CrashReporter::GetIDFromMinidump(parentDump, mParentDumpID)) {
return true;
}
return false;
}
template<class Toplevel>
inline bool
CrashReporterParent::GenerateCrashReport(Toplevel* t,
const AnnotationTable* processNotes)
{
nsCOMPtr<nsILocalFile> crashDump;
if (t->TakeMinidump(getter_AddRefs(crashDump)) &&
CrashReporter::GetIDFromMinidump(crashDump, mChildDumpID)) {
return GenerateChildData(processNotes);
}
return false;
}
template<class Toplevel>
/* static */ void
CrashReporterParent::CreateCrashReporter(Toplevel* actor)
{
#ifdef MOZ_CRASHREPORTER
NativeThreadId id;
PRUint32 processType;
PCrashReporterParent* p =
actor->CallPCrashReporterConstructor(&id, &processType);
if (p) {
static_cast<CrashReporterParent*>(p)->SetChildData(id, processType);
} else {
NS_ERROR("Error creating crash reporter actor");
}
#endif
}
#endif
} // namespace dom
} // namespace mozilla

Просмотреть файл

@ -65,6 +65,7 @@ EXPORTS_mozilla/dom = \
CrashReporterParent.h \
TabParent.h \
TabChild.h \
TabMessageUtils.h \
$(NULL)
CPPSRCS = \
@ -72,6 +73,7 @@ CPPSRCS = \
ContentParent.cpp \
ContentChild.cpp \
CrashReporterParent.cpp \
CrashReporterChild.cpp \
TabParent.cpp \
TabChild.cpp \
TabMessageUtils.cpp \
@ -88,7 +90,6 @@ CPPSRCS += \
$(NULL)
endif
include $(topsrcdir)/config/config.mk
include $(topsrcdir)/ipc/chromium/chromium-config.mk
include $(topsrcdir)/config/rules.mk

Просмотреть файл

@ -47,6 +47,7 @@ include protocol PMemoryReportRequest;
include "mozilla/chrome/RegistryMessageUtils.h";
include "mozilla/net/NeckoMessageUtils.h";
include "mozilla/dom/TabMessageUtils.h";
include "nsGeoPositionIPCSerialiser.h";
include "PPrefTuple.h";
@ -60,6 +61,7 @@ using OverrideMapping;
using IPC::URI;
using IPC::Permission;
using mozilla::null_t;
using mozilla::dom::NativeThreadId;
using gfxIntSize;
namespace mozilla {
@ -143,12 +145,13 @@ child:
parent:
PNecko();
PCrashReporter();
PStorage(StorageConstructData data);
PAudio(PRInt32 aNumChannels, PRInt32 aRate, PRInt32 aFormat);
sync PCrashReporter(NativeThreadId tid, PRUint32 processType);
// Services remoting
async StartVisitedQuery(URI uri);

Просмотреть файл

@ -38,6 +38,7 @@
* ***** END LICENSE BLOCK ***** */
include protocol PContent;
include protocol PPluginModule;
namespace mozilla {
namespace dom {
@ -51,11 +52,13 @@ struct Mapping {
};
protocol PCrashReporter {
manager PContent;
manager PContent or PPluginModule;
parent:
AddLibraryMappings(Mapping[] m);
AnnotateCrashReport(nsCString key, nsCString data);
AppendAppNotes(nsCString data);
__delete__();
};
}
}
}

Просмотреть файл

@ -43,6 +43,10 @@
#include "nsIPrivateDOMEvent.h"
#include "nsCOMPtr.h"
#ifdef MOZ_CRASHREPORTER
#include "nsExceptionHandler.h"
#endif
namespace mozilla {
namespace dom {
struct RemoteDOMEvent
@ -53,6 +57,13 @@ struct RemoteDOMEvent
bool ReadRemoteEvent(const IPC::Message* aMsg, void** aIter,
mozilla::dom::RemoteDOMEvent* aResult);
#ifdef MOZ_CRASHREPORTER
typedef CrashReporter::ThreadId NativeThreadId;
#else
// unused in this case
typedef int32 NativeThreadId;
#endif
}
}
@ -78,7 +89,6 @@ struct ParamTraits<mozilla::dom::RemoteDOMEvent>
}
};
}

Просмотреть файл

@ -40,14 +40,16 @@
include protocol PPluginIdentifier;
include protocol PPluginInstance;
include protocol PPluginScriptableObject;
include protocol PCrashReporter;
include "npapi.h";
include "mozilla/plugins/PluginMessageUtils.h";
include "mozilla/dom/TabMessageUtils.h";
using NPError;
using NPNVariable;
using base::FileDescriptor;
using mozilla::plugins::NativeThreadId;
using mozilla::dom::NativeThreadId;
using mac_plugin_interposing::NSCursorInfo;
using nsID;
@ -58,6 +60,7 @@ rpc protocol PPluginModule
{
manages PPluginInstance;
manages PPluginIdentifier;
manages PCrashReporter;
both:
/**
@ -84,9 +87,8 @@ child:
rpc NP_GetEntryPoints()
returns (NPError rv);
// Return the plugin's thread ID, if it can be found.
rpc NP_Initialize()
returns (NativeThreadId tid, NPError rv);
returns (NPError rv);
rpc PPluginInstance(nsCString aMimeType,
uint16_t aMode,
@ -114,6 +116,9 @@ child:
async SetParentHangTimeout(uint32_t seconds);
rpc PCrashReporter()
returns (NativeThreadId tid, PRUint32 processType);
parent:
/**
* This message is only used on X11 platforms.
@ -141,8 +146,6 @@ parent:
// native events, then "livelock" and some other glitches can occur.
rpc ProcessSomeEvents();
sync AppendNotesToCrashReport(nsCString aNotes);
// OS X Specific calls to manage the plugin's window
// when interposing system calls.
async PluginShowWindow(uint32_t aWindowId, bool aModal,

Просмотреть файл

@ -142,13 +142,6 @@ typedef base::SharedMemoryHandle WindowsSharedMemoryHandle;
typedef mozilla::null_t WindowsSharedMemoryHandle;
#endif
#ifdef MOZ_CRASHREPORTER
typedef CrashReporter::ThreadId NativeThreadId;
#else
// unused in this case
typedef int32 NativeThreadId;
#endif
// XXX maybe not the best place for these. better one?
#define VARSTR(v_) case v_: return #v_

Просмотреть файл

@ -66,6 +66,7 @@
#include "mozilla/plugins/BrowserStreamChild.h"
#include "mozilla/plugins/PluginStreamChild.h"
#include "PluginIdentifierChild.h"
#include "mozilla/dom/CrashReporterChild.h"
#include "nsNPAPIPlugin.h"
@ -81,6 +82,8 @@
#endif
using namespace mozilla::plugins;
using mozilla::dom::CrashReporterChild;
using mozilla::dom::PCrashReporterChild;
#if defined(XP_WIN)
const PRUnichar * kFlashFullscreenClass = L"ShockwaveFlashFullScreen";
@ -592,7 +595,6 @@ PluginModuleChild::InitGraphics()
// Do this after initializing GDK, or GDK will install its own handler.
XRE_InstallX11ErrorHandler();
#endif
return true;
}
@ -705,6 +707,33 @@ PluginModuleChild::QuickExit()
_exit(0);
}
PCrashReporterChild*
PluginModuleChild::AllocPCrashReporter(mozilla::dom::NativeThreadId* id,
PRUint32* processType)
{
return new CrashReporterChild();
}
bool
PluginModuleChild::DeallocPCrashReporter(PCrashReporterChild* actor)
{
delete actor;
return true;
}
bool
PluginModuleChild::AnswerPCrashReporterConstructor(
PCrashReporterChild* actor,
mozilla::dom::NativeThreadId* id,
PRUint32* processType)
{
#ifdef MOZ_CRASHREPORTER
*id = CrashReporter::CurrentThreadId();
*processType = XRE_GetProcessType();
#endif
return true;
}
void
PluginModuleChild::ActorDestroy(ActorDestroyReason why)
{
@ -1801,17 +1830,11 @@ PluginModuleChild::AnswerNP_GetEntryPoints(NPError* _retval)
}
bool
PluginModuleChild::AnswerNP_Initialize(NativeThreadId* tid, NPError* _retval)
PluginModuleChild::AnswerNP_Initialize(NPError* _retval)
{
PLUGIN_LOG_DEBUG_METHOD;
AssertPluginThread();
#ifdef MOZ_CRASHREPORTER
*tid = CrashReporter::CurrentThreadId();
#else
*tid = 0;
#endif
#ifdef OS_WIN
SetEventHooks();
#endif

Просмотреть файл

@ -91,6 +91,10 @@ typedef NS_NPAPIPLUGIN_CALLBACK(NPError, NP_PLUGINUNIXINIT) (const NPNetscapeFun
typedef NS_NPAPIPLUGIN_CALLBACK(NPError, NP_PLUGINSHUTDOWN) (void);
namespace mozilla {
namespace dom {
class PCrashReporterChild;
}
namespace plugins {
#ifdef MOZ_WIDGET_QT
@ -103,6 +107,7 @@ class PluginInstanceChild;
class PluginModuleChild : public PPluginModuleChild
{
typedef mozilla::dom::PCrashReporterChild PCrashReporterChild;
protected:
NS_OVERRIDE
virtual mozilla::ipc::RPCChannel::RacyRPCPolicy
@ -116,7 +121,7 @@ protected:
// Implement the PPluginModuleChild interface
virtual bool AnswerNP_GetEntryPoints(NPError* rv);
virtual bool AnswerNP_Initialize(NativeThreadId* tid, NPError* rv);
virtual bool AnswerNP_Initialize(NPError* rv);
virtual PPluginIdentifierChild*
AllocPPluginIdentifier(const nsCString& aString,
@ -174,6 +179,16 @@ protected:
virtual bool
RecvSetParentHangTimeout(const uint32_t& aSeconds);
virtual PCrashReporterChild*
AllocPCrashReporter(mozilla::dom::NativeThreadId* id,
PRUint32* processType);
virtual bool
DeallocPCrashReporter(PCrashReporterChild* actor);
virtual bool
AnswerPCrashReporterConstructor(PCrashReporterChild* actor,
mozilla::dom::NativeThreadId* id,
PRUint32* processType);
virtual void
ActorDestroy(ActorDestroyReason why);

Просмотреть файл

@ -56,12 +56,13 @@
#include "mozilla/ipc/SyncChannel.h"
#include "mozilla/plugins/PluginModuleParent.h"
#include "mozilla/plugins/BrowserStreamParent.h"
#include "mozilla/dom/PCrashReporterParent.h"
#include "PluginIdentifierParent.h"
#include "nsAutoPtr.h"
#include "nsCRT.h"
#ifdef MOZ_CRASHREPORTER
#include "nsExceptionHandler.h"
#include "mozilla/dom/CrashReporterParent.h"
#endif
#include "nsNPAPIPlugin.h"
#include "nsILocalFile.h"
@ -74,6 +75,8 @@ using base::KillProcess;
using mozilla::PluginLibrary;
using mozilla::ipc::SyncChannel;
using mozilla::dom::PCrashReporterParent;
using mozilla::dom::CrashReporterParent;
using namespace mozilla;
using namespace mozilla::plugins;
@ -111,19 +114,22 @@ PluginModuleParent::LoadModule(const char* aFilePath)
parent->mSubprocess->GetChildProcessHandle());
TimeoutChanged(kChildTimeoutPref, parent);
#ifdef MOZ_CRASHREPORTER
CrashReporterParent::CreateCrashReporter(parent.get());
#endif
return parent.forget();
}
PluginModuleParent::PluginModuleParent(const char* aFilePath)
: mSubprocess(new PluginProcessParent(aFilePath))
, mPluginThread(0)
, mShutdown(false)
, mClearSiteDataSupported(false)
, mGetSitesWithDataSupported(false)
, mNPNIface(NULL)
, mPlugin(NULL)
, mProcessStartTime(time(NULL))
, mTaskFactory(this)
{
NS_ASSERTION(mSubprocess, "Out of memory!");
@ -164,20 +170,10 @@ PluginModuleParent::~PluginModuleParent()
#ifdef MOZ_CRASHREPORTER
void
PluginModuleParent::WritePluginExtraDataForMinidump(const nsAString& id)
PluginModuleParent::WriteExtraDataForMinidump(CrashReporter::AnnotationTable& notes)
{
typedef nsDependentCString CS;
CrashReporter::AnnotationTable notes;
if (!notes.Init(32))
return;
notes.Put(CS("ProcessType"), CS("plugin"));
char startTime[32];
sprintf(startTime, "%lld", static_cast<PRInt64>(mProcessStartTime));
notes.Put(CS("StartupTime"), CS(startTime));
// Get the plugin filename, try to get just the file leafname
const std::string& pluginFile = mSubprocess->GetPluginFilePath();
size_t filePos = pluginFile.rfind(FILE_PATH_SEPARATOR);
@ -192,39 +188,12 @@ PluginModuleParent::WritePluginExtraDataForMinidump(const nsAString& id)
notes.Put(CS("PluginName"), CS(""));
notes.Put(CS("PluginVersion"), CS(""));
if (!mCrashNotes.IsEmpty())
notes.Put(CS("Notes"), CS(mCrashNotes.get()));
if (!mHangID.IsEmpty())
notes.Put(CS("HangID"), NS_ConvertUTF16toUTF8(mHangID));
if (!CrashReporter::AppendExtraData(id, notes))
NS_WARNING("problem appending plugin data to .extra");
}
void
PluginModuleParent::WriteExtraDataForHang()
{
// this writes HangID
WritePluginExtraDataForMinidump(mPluginDumpID);
CrashReporter::AnnotationTable notes;
if (!notes.Init(4))
return;
notes.Put(nsDependentCString("HangID"), NS_ConvertUTF16toUTF8(mHangID));
if (!CrashReporter::AppendExtraData(mBrowserDumpID, notes))
NS_WARNING("problem appending browser data to .extra");
const nsString& hangID = CrashReporter()->HangID();
if (!hangID.IsEmpty())
notes.Put(CS("HangID"), NS_ConvertUTF16toUTF8(hangID));
}
#endif // MOZ_CRASHREPORTER
bool
PluginModuleParent::RecvAppendNotesToCrashReport(const nsCString& aNotes)
{
mCrashNotes.Append(aNotes);
return true;
}
int
PluginModuleParent::TimeoutChanged(const char* aPref, void* aModule)
{
@ -254,29 +223,16 @@ bool
PluginModuleParent::ShouldContinueFromReplyTimeout()
{
#ifdef MOZ_CRASHREPORTER
nsCOMPtr<nsILocalFile> pluginDump;
nsCOMPtr<nsILocalFile> browserDump;
CrashReporter::ProcessHandle child;
#ifdef XP_MACOSX
child = mSubprocess->GetChildTask();
#else
child = OtherProcess();
#endif
if (CrashReporter::CreatePairedMinidumps(child,
mPluginThread,
&mHangID,
getter_AddRefs(pluginDump),
getter_AddRefs(browserDump)) &&
CrashReporter::GetIDFromMinidump(pluginDump, mPluginDumpID) &&
CrashReporter::GetIDFromMinidump(browserDump, mBrowserDumpID)) {
CrashReporterParent* crashReporter = CrashReporter();
if (crashReporter->GeneratePairedMinidump(this)) {
mBrowserDumpID = crashReporter->ParentDumpID();
mPluginDumpID = crashReporter->ChildDumpID();
PLUGIN_LOG_DEBUG(
("generated paired browser/plugin minidumps: %s/%s (ID=%s)",
NS_ConvertUTF16toUTF8(mBrowserDumpID).get(),
NS_ConvertUTF16toUTF8(mPluginDumpID).get(),
NS_ConvertUTF16toUTF8(mHangID).get()));
}
else {
("generated paired browser/plugin minidumps: %s/%s (ID=%s)",
NS_ConvertUTF16toUTF8(mBrowserDumpID).get(),
NS_ConvertUTF16toUTF8(mPluginDumpID).get(),
NS_ConvertUTF16toUTF8(crashReporter->HangID()).get()));
} else {
NS_WARNING("failed to capture paired minidumps from hang");
}
#endif
@ -294,21 +250,34 @@ PluginModuleParent::ShouldContinueFromReplyTimeout()
return false;
}
#ifdef MOZ_CRASHREPORTER
CrashReporterParent*
PluginModuleParent::CrashReporter()
{
MOZ_ASSERT(ManagedPCrashReporterParent().Length() > 0);
return static_cast<CrashReporterParent*>(ManagedPCrashReporterParent()[0]);
}
#endif
void
PluginModuleParent::ActorDestroy(ActorDestroyReason why)
{
switch (why) {
case AbnormalShutdown: {
#ifdef MOZ_CRASHREPORTER
nsCOMPtr<nsILocalFile> pluginDump;
if (TakeMinidump(getter_AddRefs(pluginDump)) &&
CrashReporter::GetIDFromMinidump(pluginDump, mPluginDumpID)) {
CrashReporterParent* crashReporter = CrashReporter();
CrashReporter::AnnotationTable notes;
notes.Init(4);
WriteExtraDataForMinidump(notes);
if (crashReporter->GenerateCrashReport(this, &notes)) {
mPluginDumpID = crashReporter->ChildDumpID();
PLUGIN_LOG_DEBUG(("got child minidump: %s",
NS_ConvertUTF16toUTF8(mPluginDumpID).get()));
WritePluginExtraDataForMinidump(mPluginDumpID);
}
else if (!mPluginDumpID.IsEmpty() && !mBrowserDumpID.IsEmpty()) {
WriteExtraDataForHang();
crashReporter->GenerateHangCrashReport(&notes);
}
else {
NS_WARNING("[PluginModuleParent::ActorDestroy] abnormal shutdown without minidump!");
@ -781,7 +750,7 @@ PluginModuleParent::NP_Initialize(NPNetscapeFuncs* bFuncs, NPPluginFuncs* pFuncs
return NS_ERROR_FAILURE;
}
if (!CallNP_Initialize(&mPluginThread, error)) {
if (!CallNP_Initialize(error)) {
return NS_ERROR_FAILURE;
}
else if (*error != NPERR_NO_ERROR) {
@ -805,7 +774,7 @@ PluginModuleParent::NP_Initialize(NPNetscapeFuncs* bFuncs, NPError* error)
return NS_ERROR_FAILURE;
}
if (!CallNP_Initialize(&mPluginThread, error))
if (!CallNP_Initialize(error))
return NS_ERROR_FAILURE;
#if defined XP_WIN && MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
@ -1106,6 +1075,24 @@ PluginModuleParent::RecvPluginHideWindow(const uint32_t& aWindowId)
#endif
}
PCrashReporterParent*
PluginModuleParent::AllocPCrashReporter(mozilla::dom::NativeThreadId* id,
PRUint32* processType)
{
#ifdef MOZ_CRASHREPORTER
return new CrashReporterParent();
#else
return nsnull;
#endif
}
bool
PluginModuleParent::DeallocPCrashReporter(PCrashReporterParent* actor)
{
delete actor;
return true;
}
bool
PluginModuleParent::RecvSetCursor(const NSCursorInfo& aCursorInfo)
{

Просмотреть файл

@ -65,6 +65,11 @@
#include "nsITimer.h"
namespace mozilla {
namespace dom {
class PCrashReporterParent;
class CrashReporterParent;
}
namespace plugins {
//-----------------------------------------------------------------------------
@ -85,6 +90,8 @@ class PluginModuleParent : public PPluginModuleParent, PluginLibrary
{
private:
typedef mozilla::PluginLibrary PluginLibrary;
typedef mozilla::dom::PCrashReporterParent PCrashReporterParent;
typedef mozilla::dom::CrashReporterParent CrashReporterParent;
protected:
@ -184,9 +191,6 @@ protected:
NS_OVERRIDE virtual bool
RecvProcessNativeEventsInRPCCall();
virtual bool
RecvAppendNotesToCrashReport(const nsCString& aNotes);
NS_OVERRIDE virtual bool
RecvPluginShowWindow(const uint32_t& aWindowId, const bool& aModal,
const int32_t& aX, const int32_t& aY,
@ -195,6 +199,12 @@ protected:
NS_OVERRIDE virtual bool
RecvPluginHideWindow(const uint32_t& aWindowId);
NS_OVERRIDE virtual PCrashReporterParent*
AllocPCrashReporter(mozilla::dom::NativeThreadId* id,
PRUint32* processType);
NS_OVERRIDE virtual bool
DeallocPCrashReporter(PCrashReporterParent* actor);
NS_OVERRIDE virtual bool
RecvSetCursor(const NSCursorInfo& aCursorInfo);
@ -302,13 +312,15 @@ private:
#endif
private:
void WritePluginExtraDataForMinidump(const nsAString& id);
void WriteExtraDataForHang();
CrashReporterParent* CrashReporter();
#ifdef MOZ_CRASHREPORTER
void WriteExtraDataForMinidump(CrashReporter::AnnotationTable& notes);
#endif
void CleanupFromTimeout();
static int TimeoutChanged(const char* aPref, void* aModule);
void NotifyPluginCrashed();
nsCString mCrashNotes;
PluginProcessParent* mSubprocess;
// the plugin thread in mSubprocess
NativeThreadId mPluginThread;
@ -318,7 +330,6 @@ private:
const NPNetscapeFuncs* mNPNIface;
nsDataHashtable<nsVoidPtrHashKey, PluginIdentifierParent*> mIdentifiers;
nsNPAPIPlugin* mPlugin;
time_t mProcessStartTime;
ScopedRunnableMethodFactory<PluginModuleParent> mTaskFactory;
nsString mPluginDumpID;
nsString mBrowserDumpID;
@ -334,6 +345,8 @@ private:
// object instead of the plugin process's lifetime
ScopedClose mPluginXSocketFdDup;
#endif
friend class mozilla::dom::CrashReporterParent;
};
} // namespace plugins

Просмотреть файл

@ -175,17 +175,5 @@ PluginProcessChild::CleanUp()
nsRegion::ShutdownStatic();
}
/* static */
void
PluginProcessChild::AppendNotesToCrashReport(const nsCString& aNotes)
{
AssertPluginThread();
PluginProcessChild* p = PluginProcessChild::current();
if (p) {
p->mPlugin.SendAppendNotesToCrashReport(aNotes);
}
}
} // namespace plugins
} // namespace mozilla

Просмотреть файл

@ -61,9 +61,6 @@ public:
NS_OVERRIDE virtual bool Init();
NS_OVERRIDE virtual void CleanUp();
// For use on the plugin thread.
static void AppendNotesToCrashReport(const nsCString& aNotes);
protected:
static PluginProcessChild* current() {
return static_cast<PluginProcessChild*>(ProcessChild::current());

Просмотреть файл

@ -99,16 +99,18 @@
<activity android:name="Restarter"
android:process="@ANDROID_PACKAGE_NAME@Restarter"
android:theme="@style/GreyTheme">
android:theme="@style/GreyTheme"
android:excludeFromRecents="true">
<intent-filter>
<action android:name="org.mozilla.gecko.restart"/>
</intent-filter>
</activity>
#if MOZ_CRASHREPORTER
<activity android:name="CrashReporter"
android:label="@string/crash_reporter_title"
android:icon="@drawable/crash_reporter" >
<activity android:name="CrashReporter"
android:label="@string/crash_reporter_title"
android:icon="@drawable/crash_reporter"
android:excludeFromRecents="true">
<intent-filter>
<action android:name="org.mozilla.gecko.reportCrash" />
</intent-filter>

Просмотреть файл

@ -1677,7 +1677,7 @@ GLContextEGL::CreateTextureImage(const nsIntSize& aSize,
GLenum aWrapMode,
bool aUseNearestFilter)
{
nsRefPtr<TextureImage> t = new gl::TiledTextureImage(this, aSize, aContentType);
nsRefPtr<TextureImage> t = new gl::TiledTextureImage(this, aSize, aContentType, aUseNearestFilter);
return t.forget();
};

Просмотреть файл

@ -146,3 +146,18 @@ TestShellCommandParent::ReleaseCallback()
{
mCallback.Release();
}
bool
TestShellCommandParent::ExecuteCallback(const nsString& aResponse)
{
return static_cast<TestShellParent*>(Manager())->CommandDone(
this, aResponse);
}
void
TestShellCommandParent::ActorDestroy(ActorDestroyReason why)
{
if (why == AbnormalShutdown) {
ExecuteCallback(EmptyString());
}
}

Просмотреть файл

@ -92,9 +92,12 @@ public:
void ReleaseCallback();
protected:
bool ExecuteCallback(const nsString& aResponse);
void ActorDestroy(ActorDestroyReason why);
bool Recv__delete__(const nsString& aResponse) {
return static_cast<TestShellParent*>(Manager())->CommandDone(
this, aResponse);
return ExecuteCallback(aResponse);
}
private:

Просмотреть файл

@ -726,8 +726,10 @@ xpc_qsDOMString::xpc_qsDOMString(JSContext *cx, jsval v, jsval *pval,
size_t len;
const jschar *chars = JS_GetStringCharsZAndLength(cx, s, &len);
if (!chars)
if (!chars) {
mValid = JS_FALSE;
return;
}
new(mBuf) implementation_type(chars, len);
mValid = JS_TRUE;
@ -772,8 +774,10 @@ xpc_qsAUTF8String::xpc_qsAUTF8String(JSContext *cx, jsval v, jsval *pval)
size_t len;
const PRUnichar *chars = JS_GetStringCharsZAndLength(cx, s, &len);
if (!chars)
if (!chars) {
mValid = JS_FALSE;
return;
}
new(mBuf) implementation_type(chars, len);
mValid = JS_TRUE;

Просмотреть файл

@ -941,7 +941,9 @@ function StartCurrentURI(aState)
// there's already a canvas for this URL
setTimeout(RecordResult, 0);
} else {
gDumpLog("REFTEST TEST-START | " + gCurrentURL + "\n");
var currentTest = gTotalTests - gURLs.length;
gDumpLog("REFTEST TEST-START | " + gCurrentURL + " | " + currentTest + " / " + gTotalTests +
" (" + Math.floor(100 * (currentTest / gTotalTests)) + "%)\n");
LogInfo("START " + gCurrentURL);
var type = gURLs[0].type
if (TYPE_SCRIPT == type) {

Просмотреть файл

@ -41,6 +41,9 @@ var TabsPopup = {
Elements.tabs.addEventListener("TabRemove", this, true);
this._updateTabsCount();
// Bind resizeHandler so we can pass it to addEventListener/removeEventListener.
this.resizeHandler = this.resizeHandler.bind(this);
},
get box() {
@ -117,12 +120,7 @@ var TabsPopup = {
this.box.anchorTo(this.button, "after_end");
BrowserUI.pushPopup(this, [this.box, this.button]);
window.addEventListener("resize", function resizeHandler(aEvent) {
if (aEvent.target != window)
return;
if (!Util.isPortrait())
TabsPopup._hidePortraitMenu();
}, false);
window.addEventListener("resize", this.resizeHandler, false);
},
toggle: function toggle() {
@ -140,7 +138,7 @@ var TabsPopup = {
if (!this.box.hidden) {
this.box.hidden = true;
BrowserUI.popPopup(this);
window.removeEventListener("resize", resizeHandler, false);
window.removeEventListener("resize", this.resizeHandler, false);
}
},
@ -172,6 +170,13 @@ var TabsPopup = {
cmd.setAttribute("label", Browser.tabs.length);
},
resizeHandler: function resizeHandler(aEvent) {
if (aEvent.target != window)
return;
if (!Util.isPortrait())
this._hidePortraitMenu();
},
handleEvent: function handleEvent(aEvent) {
this._updateTabsCount();
}

Просмотреть файл

@ -1356,14 +1356,16 @@ Browser.MainDragger.prototype = {
let isTablet = Util.isTablet();
this._panToolbars = !isTablet;
this._grabSidebar = false;
this._canGrabSidebar = false;
// In landscape portrait mode, swiping from the left margin drags the tab sidebar.
this._grabSidebar = isTablet && !Util.isPortrait() &&
((Util.localeDir == Util.LOCALE_DIR_LTR) ?
(clientX - bcr.left < 30) :
(bcr.right - clientX < 30));
if (this._grabSidebar)
Browser.grabSidebar();
if (isTablet && !Util.isPortrait()) {
let grabSidebarMargin = TabsPopup.visible ? 30 : 5;
// Don't actually grab until we see whether the swipe is horizontal in dragMove.
this._canGrabSidebar = ((Util.localeDir == Util.LOCALE_DIR_LTR)
? (clientX - bcr.left < 30)
: (bcr.right - clientX < 30));
}
if (this._sidebarTimeout) {
clearTimeout(this._sidebarTimeout);
@ -1376,6 +1378,7 @@ Browser.MainDragger.prototype = {
Browser.ungrabSidebar();
return;
}
if (this._contentView && this._contentView._updateCacheViewport)
this._contentView._updateCacheViewport();
this._contentView = null;
@ -1384,6 +1387,10 @@ Browser.MainDragger.prototype = {
},
dragMove: function dragMove(dx, dy, scroller, aIsKinetic) {
if (this._canGrabSidebar && !this._grabSidebar && dx) {
this._grabSidebar = true;
Browser.grabSidebar();
}
if (this._grabSidebar) {
Browser.slideSidebarBy(dx);
return;

Просмотреть файл

@ -65,22 +65,23 @@ function starttest() {
is(computedStyle(divObj, 'display'), 'block', 'computedStyle did not get right display value');
document.body.removeChild(div1);
//use waitForFocus
/* note: expectChildProcessCrash is not being tested here, as it causes wildly variable
* run times. It is currently being tested in:
* dom/plugins/test/test_hanging.html and dom/plugins/test/test_crashing.html
*/
//note: this also adds a short wait period
SimpleTest.executeSoon(
function () {
//finish() calls a slew of SimpleTest functions
SimpleTest.finish();
//call this after finish so we can make sure it works and doesn't hang our process
SimpleTest.expectUncaughtException();
throw "i am an uncaught exception"
/**
* Actually testing a crash of a child process ended up with wildly variable runtimes,
* on the scale of >1 second, so just make sure we can safely call the method
*/
SimpleTest.expectChildProcessCrash();
var endTime = new Date();
SimpleTest.info("Profile::SimpleTestRunTime: " + (endTime-startTime));
//expect and throw exception here. Otherwise, any code that follows the throw call will never be executed
SimpleTest.expectUncaughtException();
//make sure we catch this error
throw "i am an uncaught exception"
}
);
}

Просмотреть файл

@ -78,6 +78,9 @@ skip-if = !debug
[include:toolkit/crashreporter/test/unit/xpcshell.ini]
skip-if = os == "linux" || !crashreporter
[include:toolkit/crashreporter/test/unit_ipc/xpcshell.ini]
skip-if.os == "linux" || !crashreporter
#XXX: we don't actually set os = maemo
[include:toolkit/crashreporter/client/maemo-unit/xpcshell.ini]
run-if = os == "maemo"

Просмотреть файл

@ -10,9 +10,9 @@
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
<stack flex="1">
<label id="topleft" value="Top Left" left="15" top="15"/>
<label id="topleft" value="Top Left Corner" left="15" top="15"/>
<label id="topright" value="Top Right" right="15" top="15"/>
<label id="bottomleft" value="Bottom Left" left="15" bottom="15"/>
<label id="bottomleft" value="Bottom Left Corner" left="15" bottom="15"/>
<label id="bottomright" value="Bottom Right" right="15" bottom="15"/>
<!-- Our SimpleTest/TestRunner.js runs tests inside an iframe which sizes are W=500 H=300.
'left' and 'top' values need to be set so that the panel (popup) has enough room to display on its 4 sides. -->
@ -35,7 +35,7 @@
SimpleTest.waitForExplicitFinish();
var expectedAnchor = null;
var expectedSide = "", expectedAnchorEdge = "";
var expectedSide = "", expectedAnchorEdge = "", expectedPack = "";
var zoomFactor = 1;
var runNextTest;
@ -49,96 +49,107 @@ function nextTest()
{
var panel = $("panel");
function openPopup(position, anchor, expected, anchorEdge)
function openPopup(position, anchor, expected, anchorEdge, pack)
{
expectedAnchor = anchor instanceof Node ? anchor : $(anchor);
expectedSide = expected;
expectedAnchorEdge = anchorEdge;
expectedPack = pack;
panel.removeAttribute("side");
panel.openPopup(expectedAnchor, position, 0, 0, false, false, null);
}
openPopup("after_start", "topleft", "top", "left");
openPopup("after_start", "topleft", "top", "left", "start");
yield;
openPopup("after_start", "bottomleft", "bottom", "left");
openPopup("after_start", "bottomleft", "bottom", "left", "start");
yield;
openPopup("before_start", "topleft", "top", "left");
openPopup("before_start", "topleft", "top", "left", "start");
yield;
openPopup("before_start", "bottomleft", "bottom", "left");
openPopup("before_start", "bottomleft", "bottom", "left", "start");
yield;
openPopup("after_start", "middle", "top", "left");
openPopup("after_start", "middle", "top", "left", "start");
yield;
openPopup("before_start", "middle", "bottom", "left");
openPopup("before_start", "middle", "bottom", "left", "start");
yield;
openPopup("after_start", "topright", "top", "right");
openPopup("after_start", "topright", "top", "right", "end");
yield;
openPopup("after_start", "bottomright", "bottom", "right");
openPopup("after_start", "bottomright", "bottom", "right", "end");
yield;
openPopup("before_start", "topright", "top", "right");
openPopup("before_start", "topright", "top", "right", "end");
yield;
openPopup("before_start", "bottomright", "bottom", "right");
openPopup("before_start", "bottomright", "bottom", "right", "end");
yield;
openPopup("start_before", "topleft", "left", "top");
openPopup("after_end", "middle", "top", "right", "end");
yield;
openPopup("start_before", "topright", "right", "top");
yield;
openPopup("end_before", "topleft", "left", "top");
yield;
openPopup("end_before", "topright", "right", "top");
yield;
openPopup("start_before", "middle", "right", "top");
yield;
openPopup("end_before", "middle", "left", "top");
openPopup("before_end", "middle", "bottom", "right", "end");
yield;
openPopup("start_before", "bottomleft", "left", "bottom");
openPopup("start_before", "topleft", "left", "top", "start");
yield;
openPopup("start_before", "bottomright", "right", "bottom");
openPopup("start_before", "topright", "right", "top", "start");
yield;
openPopup("end_before", "bottomleft", "left", "bottom");
openPopup("end_before", "topleft", "left", "top", "start");
yield;
openPopup("end_before", "bottomright", "right", "bottom");
openPopup("end_before", "topright", "right", "top", "start");
yield;
openPopup("start_before", "middle", "right", "top", "start");
yield;
openPopup("end_before", "middle", "left", "top", "start");
yield;
openPopup("topcenter bottomleft", "bottomleft", "bottom", "center left");
openPopup("start_before", "bottomleft", "left", "bottom", "end");
yield;
openPopup("bottomcenter topleft", "topleft", "top", "center left");
openPopup("start_before", "bottomright", "right", "bottom", "end");
yield;
openPopup("topcenter bottomright", "bottomright", "bottom", "center right");
openPopup("end_before", "bottomleft", "left", "bottom", "end");
yield;
openPopup("bottomcenter topright", "topright", "top", "center right");
yield;
openPopup("topcenter bottomleft", "middle", "bottom", "center left");
yield;
openPopup("bottomcenter topleft", "middle", "top", "center left");
openPopup("end_before", "bottomright", "right", "bottom", "end");
yield;
openPopup("leftcenter topright", "middle", "right", "center top");
openPopup("start_after", "middle", "right", "bottom", "end");
yield;
openPopup("rightcenter bottomleft", "middle", "left", "center bottom");
openPopup("end_after", "middle", "left", "bottom", "end");
yield;
openPopup("topcenter bottomleft", "bottomleft", "bottom", "center left", "start");
yield;
openPopup("bottomcenter topleft", "topleft", "top", "center left", "start");
yield;
openPopup("topcenter bottomright", "bottomright", "bottom", "center right", "end");
yield;
openPopup("bottomcenter topright", "topright", "top", "center right", "end");
yield;
openPopup("topcenter bottomleft", "middle", "bottom", "center left", "start");
yield;
openPopup("bottomcenter topleft", "middle", "top", "center left", "start");
yield;
openPopup("leftcenter topright", "middle", "right", "center top", "start");
yield;
openPopup("rightcenter bottomleft", "middle", "left", "center bottom", "end");
yield;
/*
XXXndeakin disable these parts of the test which often cause problems, see bug 626563
openPopup("after_start", frames[0].document.getElementById("input"), "top", "left");
openPopup("after_start", frames[0].document.getElementById("input"), "top", "left", "start");
yield;
setScale(frames[0], 1.5);
openPopup("after_start", frames[0].document.getElementById("input"), "top", "left");
openPopup("after_start", frames[0].document.getElementById("input"), "top", "left", "start");
yield;
setScale(frames[0], 2.5);
openPopup("before_start", frames[0].document.getElementById("input"), "bottom", "left");
openPopup("before_start", frames[0].document.getElementById("input"), "bottom", "left", "start");
yield;
setScale(frames[0], 1);
*/
$("bigpanel").openPopup($("topleft"), "after_start", 0, 0, false, false, null);
$("bigpanel").openPopup($("topleft"), "after_start", 0, 0, false, false, null, "start");
yield;
SimpleTest.finish();
@ -221,6 +232,7 @@ function checkPanelPosition(panel)
var arrow = document.getAnonymousElementByAttribute(panel, "anonid", "arrow");
is(arrow.getAttribute("side"), expectedSide, "panel arrow side");
is(arrow.hidden, false, "panel hidden");
is(arrow.parentNode.pack, expectedPack, "panel arrow pack");
panel.hidePopup();
}

Просмотреть файл

@ -315,7 +315,7 @@
</xul:box>
</content>
<implementation>
<field name="_fadeTimer"/>
<field name="_fadeTimer">null</field>
</implementation>
<handlers>
<handler event="popupshowing">
@ -383,10 +383,10 @@
// If the popup is on the left of the anchor.
if (smallerTo(popupLeft, anchorLeft, epsilon) && smallerTo(popupRight, anchorRight, epsilon)) {
pack = (popupLeft + popupRect.width / 2 < anchorLeft) ? "end" : "start";
pack = "end";
// If the popup is on the right of the anchor.
} else if (smallerTo(anchorLeft, popupLeft, epsilon) && smallerTo(anchorRight, popupRight, epsilon)) {
pack = (popupLeft + popupRect.width / 2 > anchorRight) ? "start" : "end";
pack = "start"; //(popupLeft + popupRect.width / 2 > anchorRight) ? "start" : "end";
// If the popup is not on the right nor on the left.
// Basically, that means one is above the other and one is bigger
// than the other.

Просмотреть файл

@ -127,4 +127,6 @@ ifdef ENABLE_TESTS
TOOL_DIRS = test
endif
include $(topsrcdir)/config/config.mk
include $(topsrcdir)/ipc/chromium/chromium-config.mk
include $(topsrcdir)/config/rules.mk

Просмотреть файл

@ -37,7 +37,11 @@
*
* ***** END LICENSE BLOCK ***** */
#include "mozilla/dom/CrashReporterChild.h"
#include "nsXULAppAPI.h"
#include "nsExceptionHandler.h"
#include "nsThreadUtils.h"
#if defined(XP_WIN32)
#ifdef WIN32_LEAN_AND_MEAN
@ -112,6 +116,8 @@ using google_breakpad::CrashGenerationServer;
using google_breakpad::ClientInfo;
using mozilla::Mutex;
using mozilla::MutexAutoLock;
using mozilla::dom::CrashReporterChild;
using mozilla::dom::PCrashReporterChild;
namespace CrashReporter {
@ -231,6 +237,10 @@ static const char* kSubprocessBlacklist[] = {
"URL"
};
// If annotations are attempted before the crash reporter is enabled,
// they queue up here.
class DelayedNote;
nsTArray<nsAutoPtr<DelayedNote> >* gDelayedAnnotations;
#ifdef XP_MACOSX
static cpu_type_t pref_cpu_types[2] = {
@ -801,7 +811,7 @@ nsresult SetExceptionHandler(nsILocalFile* aXREDirectory,
bool GetEnabled()
{
return gExceptionHandler != nsnull && !gExceptionHandler->IsOutOfProcess();
return gExceptionHandler != nsnull;
}
bool GetMinidumpPath(nsAString& aPath)
@ -1095,11 +1105,13 @@ static PLDHashOperator EnumerateEntries(const nsACString& key,
return PL_DHASH_NEXT;
}
nsresult AnnotateCrashReport(const nsACString& key, const nsACString& data)
// This function is miscompiled with MSVC 2005/2008 when PGO is on.
#ifdef _MSC_VER
#pragma optimize("", off)
#endif
static nsresult
EscapeAnnotation(const nsACString& key, const nsACString& data, nsCString& escapedData)
{
if (!GetEnabled())
return NS_ERROR_NOT_INITIALIZED;
if (DoFindInReadable(key, NS_LITERAL_CSTRING("=")) ||
DoFindInReadable(key, NS_LITERAL_CSTRING("\n")))
return NS_ERROR_INVALID_ARG;
@ -1107,7 +1119,7 @@ nsresult AnnotateCrashReport(const nsACString& key, const nsACString& data)
if (DoFindInReadable(data, NS_LITERAL_CSTRING("\0")))
return NS_ERROR_INVALID_ARG;
nsCString escapedData(data);
escapedData = data;
// escape backslashes
ReplaceChar(escapedData, NS_LITERAL_CSTRING("\\"),
@ -1115,8 +1127,67 @@ nsresult AnnotateCrashReport(const nsACString& key, const nsACString& data)
// escape newlines
ReplaceChar(escapedData, NS_LITERAL_CSTRING("\n"),
NS_LITERAL_CSTRING("\\n"));
return NS_OK;
}
#ifdef _MSC_VER
#pragma optimize("", on)
#endif
nsresult rv = crashReporterAPIData_Hash->Put(key, escapedData);
class DelayedNote
{
public:
DelayedNote(const nsACString& aKey, const nsACString& aData)
: mKey(aKey), mData(aData), mType(Annotation) {}
DelayedNote(const nsACString& aData)
: mData(aData), mType(AppNote) {}
void Run()
{
if (mType == Annotation) {
AnnotateCrashReport(mKey, mData);
} else {
AppendAppNotesToCrashReport(mData);
}
}
private:
nsCString mKey;
nsCString mData;
enum AnnotationType { Annotation, AppNote } mType;
};
static void
EnqueueDelayedNote(DelayedNote* aNote)
{
if (!gDelayedAnnotations) {
gDelayedAnnotations = new nsTArray<nsAutoPtr<DelayedNote> >();
}
gDelayedAnnotations->AppendElement(aNote);
}
nsresult AnnotateCrashReport(const nsACString& key, const nsACString& data)
{
if (!GetEnabled())
return NS_ERROR_NOT_INITIALIZED;
nsCString escapedData;
nsresult rv = EscapeAnnotation(key, data, escapedData);
if (NS_FAILED(rv))
return rv;
if (XRE_GetProcessType() != GeckoProcessType_Default) {
PCrashReporterChild* reporter = CrashReporterChild::GetCrashReporter();
if (!reporter) {
EnqueueDelayedNote(new DelayedNote(key, data));
return NS_OK;
}
if (!reporter->SendAnnotateCrashReport(nsCString(key), escapedData))
return NS_ERROR_FAILURE;
return NS_OK;
}
rv = crashReporterAPIData_Hash->Put(key, escapedData);
NS_ENSURE_SUCCESS(rv, rv);
// now rebuild the file contents
@ -1135,6 +1206,26 @@ nsresult AppendAppNotesToCrashReport(const nsACString& data)
if (DoFindInReadable(data, NS_LITERAL_CSTRING("\0")))
return NS_ERROR_INVALID_ARG;
if (XRE_GetProcessType() != GeckoProcessType_Default) {
PCrashReporterChild* reporter = CrashReporterChild::GetCrashReporter();
if (!reporter) {
EnqueueDelayedNote(new DelayedNote(data));
return NS_OK;
}
// Since we don't go through AnnotateCrashReport in the parent process,
// we must ensure that the data is escaped and valid before the parent
// sees it.
nsCString escapedData;
nsresult rv = EscapeAnnotation(NS_LITERAL_CSTRING("Notes"), data, escapedData);
if (NS_FAILED(rv))
return rv;
if (!reporter->SendAppendAppNotes(escapedData))
return NS_ERROR_FAILURE;
return NS_OK;
}
notesField->Append(data);
return AnnotateCrashReport(NS_LITERAL_CSTRING("Notes"), *notesField);
}
@ -1874,7 +1965,7 @@ SetRemoteExceptionHandler(const nsACString& crashPipe)
gExceptionHandler = new google_breakpad::
ExceptionHandler(L"",
NULL, // no filter callback
FPEFilter,
NULL, // no minidump callback
NULL, // no callback context
google_breakpad::ExceptionHandler::HANDLER_ALL,
@ -1925,6 +2016,13 @@ SetRemoteExceptionHandler()
true, // install signal handlers
kMagicChildCrashReportFd);
if (gDelayedAnnotations) {
for (PRUint32 i = 0; i < gDelayedAnnotations->Length(); i++) {
gDelayedAnnotations->ElementAt(i)->Run();
}
delete gDelayedAnnotations;
}
// we either do remote or nothing, no fallback to regular crash reporting
return gExceptionHandler->IsOutOfProcess();
}

Просмотреть файл

@ -44,7 +44,7 @@ relativesrcdir = toolkit/crashreporter/test
include $(DEPTH)/config/autoconf.mk
MODULE = crashreporter_test
XPCSHELL_TESTS = unit
XPCSHELL_TESTS = unit unit_ipc
LIBRARY_NAME = testcrasher
NO_DIST_INSTALL = 1
@ -95,4 +95,5 @@ endif
libs:: $(SHARED_LIBRARY) $(EXTRA_JS_MODULES)
$(INSTALL) $^ $(DEPTH)/_tests/xpcshell/$(relativesrcdir)/unit/
$(INSTALL) $^ $(DEPTH)/_tests/xpcshell/$(relativesrcdir)/unit_ipc/

Просмотреть файл

@ -2,11 +2,19 @@
let cwd = Components.classes["@mozilla.org/file/directory_service;1"]
.getService(Components.interfaces.nsIProperties)
.get("CurWorkD", Components.interfaces.nsILocalFile);
let crashReporter =
Components.classes["@mozilla.org/toolkit/crash-reporter;1"]
.getService(Components.interfaces.nsICrashReporter);
crashReporter.enabled = true;
crashReporter.minidumpPath = cwd;
// the crash reporter is already enabled in content processes,
// and setting the minidump path is not allowed
let processType = Components.classes["@mozilla.org/xre/runtime;1"].
getService(Components.interfaces.nsIXULRuntime).processType;
if (processType == Components.interfaces.nsIXULRuntime.PROCESS_TYPE_DEFAULT) {
crashReporter.enabled = true;
crashReporter.minidumpPath = cwd;
}
let ios = Components.classes["@mozilla.org/network/io-service;1"]
.getService(Components.interfaces.nsIIOService);

Просмотреть файл

@ -65,6 +65,11 @@ function do_crash(setup, callback, canReturnZero)
do_check_neq(process.exitValue, 0);
}
handleMinidump(callback);
}
function handleMinidump(callback)
{
// find minidump
let minidump = null;
let en = do_get_cwd().directoryEntries;
@ -101,6 +106,44 @@ function do_crash(setup, callback, canReturnZero)
extrafile.remove(false);
}
function do_content_crash(setup, callback)
{
do_load_child_test_harness();
do_test_pending();
// Setting the minidump path won't work in the child, so we need to do
// that here.
let crashReporter =
Components.classes["@mozilla.org/toolkit/crash-reporter;1"]
.getService(Components.interfaces.nsICrashReporter);
crashReporter.minidumpPath = do_get_cwd();
let headfile = do_get_file("../unit/crasher_subprocess_head.js");
let tailfile = do_get_file("../unit/crasher_subprocess_tail.js");
if (setup) {
if (typeof(setup) == "function")
// funky, but convenient
setup = "("+setup.toSource()+")();";
}
let handleCrash = function() {
try {
handleMinidump(callback);
} catch (x) {
do_report_unexpected_exception(x);
}
do_test_finished();
};
sendCommand("load(\"" + headfile.path.replace(/\\/g, "/") + "\");", function()
sendCommand(setup, function()
sendCommand("load(\"" + tailfile.path.replace(/\\/g, "/") + "\");",
function() do_execute_soon(handleCrash)
)
)
);
}
// Utility functions for parsing .extra files
function parseKeyValuePairs(text) {
var lines = text.split('\n');

Просмотреть файл

@ -0,0 +1,22 @@
load("../unit/head_crashreporter.js");
function run_test()
{
if (!("@mozilla.org/toolkit/crash-reporter;1" in Components.classes)) {
dump("INFO | test_content_annotation.js | Can't test crashreporter in a non-libxul build.\n");
return;
}
// Try crashing with a pure virtual call
do_content_crash(function() {
crashType = CrashTestUtils.CRASH_RUNTIMEABORT;
crashReporter.annotateCrashReport("TestKey", "TestValue");
crashReporter.appendAppNotesToCrashReport("!!!foo!!!");
},
function(mdump, extra) {
do_check_eq(extra.TestKey, "TestValue");
do_check_true('StartupTime' in extra);
do_check_true('ProcessType' in extra);
do_check_neq(extra.Notes.indexOf("!!!foo!!!"), -1);
});
}

Просмотреть файл

@ -0,0 +1,5 @@
[DEFAULT]
head = head_crashreporter.js
tail =
[test_content_annotation.js]

Просмотреть файл

@ -361,7 +361,9 @@ XRE_InitChildProcess(int aArgc,
return 1;
}
#endif
SetupErrorHandling(aArgv[0]);
#if defined(MOZ_CRASHREPORTER)
if (aArgc < 1)
return 1;
@ -392,8 +394,6 @@ XRE_InitChildProcess(int aArgc,
gArgv = aArgv;
gArgc = aArgc;
SetupErrorHandling(aArgv[0]);
#if defined(MOZ_WIDGET_GTK2)
g_thread_init(NULL);
#endif
@ -712,16 +712,19 @@ XRE_ShutdownChildProcess()
}
namespace {
TestShellParent* gTestShellParent = nsnull;
ContentParent* gContentParent; //long-lived, manually refcounted
TestShellParent* GetOrCreateTestShellParent()
{
if (!gTestShellParent) {
ContentParent* parent = ContentParent::GetNewOrUsed();
NS_ENSURE_TRUE(parent, nsnull);
gTestShellParent = parent->CreateTestShell();
NS_ENSURE_TRUE(gTestShellParent, nsnull);
if (!gContentParent) {
NS_ADDREF(gContentParent = ContentParent::GetNewOrUsed());
} else if (!gContentParent->IsAlive()) {
return nsnull;
}
return gTestShellParent;
TestShellParent* tsp = gContentParent->GetTestShellSingleton();
if (!tsp) {
tsp = gContentParent->CreateTestShell();
}
return tsp;
}
}
@ -760,10 +763,16 @@ XRE_GetChildGlobalObject(JSContext* aCx, JSObject** aGlobalP)
bool
XRE_ShutdownTestShell()
{
if (!gTestShellParent)
return true;
return static_cast<ContentParent*>(gTestShellParent->Manager())->
DestroyTestShell(gTestShellParent);
if (!gContentParent) {
return true;
}
bool ret = true;
if (gContentParent->IsAlive()) {
ret = gContentParent->DestroyTestShell(
gContentParent->GetTestShellSingleton());
}
NS_RELEASE(gContentParent);
return ret;
}
#ifdef MOZ_X11

Просмотреть файл

@ -38,9 +38,6 @@
#include "nsX11ErrorHandler.h"
#include "mozilla/plugins/PluginProcessChild.h"
using mozilla::plugins::PluginProcessChild;
#include "prenv.h"
#include "nsXULAppAPI.h"
#include "nsExceptionHandler.h"
@ -156,15 +153,9 @@ X11Error(Display *display, XErrorEvent *event) {
#ifdef MOZ_CRASHREPORTER
switch (XRE_GetProcessType()) {
case GeckoProcessType_Default:
CrashReporter::AppendAppNotesToCrashReport(notes);
break;
case GeckoProcessType_Plugin:
if (CrashReporter::GetEnabled()) {
// This is assuming that X operations are performed on the plugin
// thread. If plugins are using X on another thread, then we'll need to
// handle that differently.
PluginProcessChild::AppendNotesToCrashReport(notes);
}
case GeckoProcessType_Content:
CrashReporter::AppendAppNotesToCrashReport(notes);
break;
default:
; // crash report notes not supported.

Просмотреть файл

@ -481,23 +481,10 @@ protected:
bool mKeyPressDispatched;
// Whether keypress event was consumed by web contents or chrome contents.
bool mKeyPressHandled;
// Whether the key event causes other key events via IME or something.
bool mCausedOtherKeyEvents;
KeyEventState(NSEvent* aNativeKeyEvent) : mKeyEvent(nsnull)
KeyEventState() : mKeyEvent(nsnull)
{
Clear();
Set(aNativeKeyEvent);
}
KeyEventState(const KeyEventState &aOther) : mKeyEvent(nsnull)
{
Clear();
mKeyEvent = [aOther.mKeyEvent retain];
mKeyDownHandled = aOther.mKeyDownHandled;
mKeyPressDispatched = aOther.mKeyPressDispatched;
mKeyPressHandled = aOther.mKeyPressHandled;
mCausedOtherKeyEvents = aOther.mCausedOtherKeyEvents;
}
~KeyEventState()
@ -521,18 +508,12 @@ protected:
mKeyDownHandled = false;
mKeyPressDispatched = false;
mKeyPressHandled = false;
mCausedOtherKeyEvents = false;
}
bool KeyDownOrPressHandled()
{
return mKeyDownHandled || mKeyPressHandled;
}
protected:
KeyEventState()
{
}
};
/**
@ -548,46 +529,15 @@ protected:
~AutoKeyEventStateCleaner()
{
NS_ASSERTION(mHandler->mCurrentKeyEvents.Length() > 0,
"The key event was removed by manually?");
mHandler->mCurrentKeyEvents.RemoveElementAt(0);
mHandler->mCurrentKeyEvent.Clear();
}
private:
nsRefPtr<TextInputHandlerBase> mHandler;
TextInputHandlerBase* mHandler;
};
/**
* mCurrentKeyEvents stores all key events which are being processed.
* When we call interpretKeyEvents, IME may generate other key events.
* mCurrentKeyEvents[0] is the latest key event.
*/
nsTArray<KeyEventState> mCurrentKeyEvents;
/**
*
*/
KeyEventState* PushKeyEvent(NSEvent* aNativeKeyEvent)
{
PRUint32 nestCount = mCurrentKeyEvents.Length();
for (PRUint32 i = 0; i < nestCount; i++) {
// When the key event is caused by another key event, all key events
// which are being handled should be marked as "consumed".
mCurrentKeyEvents[i].mCausedOtherKeyEvents = true;
}
KeyEventState keyEventState(aNativeKeyEvent);
return mCurrentKeyEvents.InsertElementAt(0, keyEventState);
}
/**
* GetCurrentKeyEvent() returns current processing key event.
*/
KeyEventState* GetCurrentKeyEvent()
{
if (mCurrentKeyEvents.Length() == 0) {
return nsnull;
}
return &mCurrentKeyEvents[0];
}
// XXX If keydown event was nested, the key event is overwritten by newer
// event. This is wrong behavior. Some IMEs are making such situation.
KeyEventState mCurrentKeyEvent;
/**
* IsPrintableChar() checks whether the unicode character is
@ -1169,8 +1119,7 @@ public:
*/
bool KeyPressWasHandled()
{
KeyEventState* currentKeyEvent = GetCurrentKeyEvent();
return currentKeyEvent && currentKeyEvent->mKeyPressHandled;
return mCurrentKeyEvent.mKeyPressHandled;
}
protected:

Просмотреть файл

@ -997,7 +997,7 @@ TextInputHandler::HandleKeyDownEvent(NSEvent* aNativeEvent)
nsRefPtr<nsChildView> kungFuDeathGrip(mWidget);
KeyEventState* currentKeyEvent = PushKeyEvent(aNativeEvent);
mCurrentKeyEvent.Set(aNativeEvent);
AutoKeyEventStateCleaner remover(this);
BOOL nonDeadKeyPress = [[aNativeEvent characters] length] > 0;
@ -1015,12 +1015,12 @@ TextInputHandler::HandleKeyDownEvent(NSEvent* aNativeEvent)
}
#endif // #ifndef NP_NO_CARBON
currentKeyEvent->mKeyDownHandled = DispatchEvent(keydownEvent);
mCurrentKeyEvent.mKeyDownHandled = DispatchEvent(keydownEvent);
if (Destroyed()) {
PR_LOG(gLog, PR_LOG_ALWAYS,
("%p TextInputHandler::HandleKeyDownEvent, "
"widget was destroyed by keydown event", this));
return currentKeyEvent->KeyDownOrPressHandled();
return mCurrentKeyEvent.KeyDownOrPressHandled();
}
// The key down event may have shifted the focus, in which
@ -1030,7 +1030,7 @@ TextInputHandler::HandleKeyDownEvent(NSEvent* aNativeEvent)
PR_LOG(gLog, PR_LOG_ALWAYS,
("%p TextInputHandler::HandleKeyDownEvent, "
"view lost focus by keydown event", this));
return currentKeyEvent->KeyDownOrPressHandled();
return mCurrentKeyEvent.KeyDownOrPressHandled();
}
// If this is the context menu key command, send a context menu key event.
@ -1052,7 +1052,31 @@ TextInputHandler::HandleKeyDownEvent(NSEvent* aNativeEvent)
Destroyed() ? " and widget was destroyed" : ""));
[mView maybeInitContextMenuTracking];
// Bail, there is nothing else to do here.
return (cmEventHandled || currentKeyEvent->KeyDownOrPressHandled());
return (cmEventHandled || mCurrentKeyEvent.KeyDownOrPressHandled());
}
nsKeyEvent keypressEvent(true, NS_KEY_PRESS, mWidget);
InitKeyEvent(aNativeEvent, keypressEvent);
// if this is a non-letter keypress, or the control key is down,
// dispatch the keydown to gecko, so that we trap delete,
// control-letter combinations etc before Cocoa tries to use
// them for keybindings.
// XXX This is wrong. IME may be handle the non-letter keypress event as
// its owning shortcut key. See bug 477291.
if ((!keypressEvent.isChar || keypressEvent.isControl) &&
!IsIMEComposing()) {
if (mCurrentKeyEvent.mKeyDownHandled) {
keypressEvent.flags |= NS_EVENT_FLAG_NO_DEFAULT;
}
mCurrentKeyEvent.mKeyPressHandled = DispatchEvent(keypressEvent);
mCurrentKeyEvent.mKeyPressDispatched = true;
if (Destroyed()) {
PR_LOG(gLog, PR_LOG_ALWAYS,
("%p TextInputHandler::HandleKeyDownEvent, "
"widget was destroyed by keypress event", this));
return mCurrentKeyEvent.KeyDownOrPressHandled();
}
}
}
@ -1074,7 +1098,7 @@ TextInputHandler::HandleKeyDownEvent(NSEvent* aNativeEvent)
PR_LOG(gLog, PR_LOG_ALWAYS,
("%p TextInputHandler::HandleKeyDownEvent, widget was destroyed",
this));
return currentKeyEvent->KeyDownOrPressHandled();
return mCurrentKeyEvent.KeyDownOrPressHandled();
}
PR_LOG(gLog, PR_LOG_ALWAYS,
@ -1082,7 +1106,7 @@ TextInputHandler::HandleKeyDownEvent(NSEvent* aNativeEvent)
"IsIMEComposing()=%s",
this, TrueOrFalse(wasComposing), TrueOrFalse(IsIMEComposing())));
if (!currentKeyEvent->mKeyPressDispatched && nonDeadKeyPress &&
if (!mCurrentKeyEvent.mKeyPressDispatched && nonDeadKeyPress &&
!wasComposing && !IsIMEComposing()) {
nsKeyEvent keypressEvent(true, NS_KEY_PRESS, mWidget);
InitKeyEvent(aNativeEvent, keypressEvent);
@ -1100,11 +1124,10 @@ TextInputHandler::HandleKeyDownEvent(NSEvent* aNativeEvent)
// our default action for this key.
if (!(interpretKeyEventsCalled &&
IsNormalCharInputtingEvent(keypressEvent))) {
if (currentKeyEvent->mKeyDownHandled ||
currentKeyEvent->mCausedOtherKeyEvents) {
if (mCurrentKeyEvent.mKeyDownHandled) {
keypressEvent.flags |= NS_EVENT_FLAG_NO_DEFAULT;
}
currentKeyEvent->mKeyPressHandled = DispatchEvent(keypressEvent);
mCurrentKeyEvent.mKeyPressHandled = DispatchEvent(keypressEvent);
PR_LOG(gLog, PR_LOG_ALWAYS,
("%p TextInputHandler::HandleKeyDownEvent, keypress event dispatched",
this));
@ -1116,9 +1139,9 @@ TextInputHandler::HandleKeyDownEvent(NSEvent* aNativeEvent)
PR_LOG(gLog, PR_LOG_ALWAYS,
("%p TextInputHandler::HandleKeyDownEvent, "
"keydown handled=%s, keypress handled=%s",
this, TrueOrFalse(currentKeyEvent->mKeyDownHandled),
TrueOrFalse(currentKeyEvent->mKeyPressHandled)));
return currentKeyEvent->KeyDownOrPressHandled();
this, TrueOrFalse(mCurrentKeyEvent.mKeyDownHandled),
TrueOrFalse(mCurrentKeyEvent.mKeyPressHandled)));
return mCurrentKeyEvent.KeyDownOrPressHandled();
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(false);
}
@ -1289,17 +1312,13 @@ TextInputHandler::InsertText(NSAttributedString *aAttrString)
return;
}
KeyEventState* currentKeyEvent = GetCurrentKeyEvent();
PR_LOG(gLog, PR_LOG_ALWAYS,
("%p TextInputHandler::InsertText, aAttrString=\"%s\", "
"IsIMEComposing()=%s, IgnoreIMEComposition()=%s, "
"keyevent=%p, keypressDispatched=%s",
this, GetCharacters([aAttrString string]), TrueOrFalse(IsIMEComposing()),
TrueOrFalse(IgnoreIMEComposition()),
currentKeyEvent ? currentKeyEvent->mKeyEvent : nsnull,
currentKeyEvent ?
TrueOrFalse(currentKeyEvent->mKeyPressDispatched) : "N/A"));
TrueOrFalse(IgnoreIMEComposition()), mCurrentKeyEvent.mKeyEvent,
TrueOrFalse(mCurrentKeyEvent.mKeyPressDispatched)));
if (IgnoreIMEComposition()) {
return;
@ -1318,7 +1337,7 @@ TextInputHandler::InsertText(NSAttributedString *aAttrString)
// Don't let the same event be fired twice when hitting
// enter/return! (Bug 420502)
if (currentKeyEvent && currentKeyEvent->mKeyPressDispatched) {
if (mCurrentKeyEvent.mKeyPressDispatched) {
return;
}
@ -1340,8 +1359,8 @@ TextInputHandler::InsertText(NSAttributedString *aAttrString)
EventRecord carbonEvent;
#endif // #ifndef NP_NO_CARBON
if (currentKeyEvent) {
NSEvent* keyEvent = currentKeyEvent->mKeyEvent;
if (mCurrentKeyEvent.mKeyEvent) {
NSEvent* keyEvent = mCurrentKeyEvent.mKeyEvent;
// XXX The ASCII characters inputting mode of egbridge (Japanese IME)
// might send the keyDown event with wrong keyboard layout if other
@ -1354,7 +1373,7 @@ TextInputHandler::InsertText(NSAttributedString *aAttrString)
}
#endif // #ifndef NP_NO_CARBON
if (currentKeyEvent->mKeyDownHandled) {
if (mCurrentKeyEvent.mKeyDownHandled) {
keypressEvent.flags |= NS_EVENT_FLAG_NO_DEFAULT;
}
@ -1381,9 +1400,9 @@ TextInputHandler::InsertText(NSAttributedString *aAttrString)
// Note: mWidget might have become null here. Don't count on it from here on.
if (currentKeyEvent) {
currentKeyEvent->mKeyPressHandled = keyPressHandled;
currentKeyEvent->mKeyPressDispatched = true;
if (mCurrentKeyEvent.mKeyEvent) {
mCurrentKeyEvent.mKeyPressHandled = keyPressHandled;
mCurrentKeyEvent.mKeyPressDispatched = true;
}
NS_OBJC_END_TRY_ABORT_BLOCK;
@ -1392,38 +1411,13 @@ TextInputHandler::InsertText(NSAttributedString *aAttrString)
bool
TextInputHandler::DoCommandBySelector(const char* aSelector)
{
nsRefPtr<nsChildView> kungFuDeathGrip(mWidget);
KeyEventState* currentKeyEvent = GetCurrentKeyEvent();
PR_LOG(gLog, PR_LOG_ALWAYS,
("%p TextInputHandler::DoCommandBySelector, aSelector=\"%s\", "
"Destroyed()=%s, keypressHandled=%s, causedOtherKeyEvents=%s",
"Destroyed()=%s, keypressHandled=%s",
this, aSelector ? aSelector : "", TrueOrFalse(Destroyed()),
currentKeyEvent ?
TrueOrFalse(currentKeyEvent->mKeyPressHandled) : "N/A",
currentKeyEvent ?
TrueOrFalse(currentKeyEvent->mCausedOtherKeyEvents) : "N/A"));
TrueOrFalse(mCurrentKeyEvent.mKeyPressHandled)));
if (currentKeyEvent && !currentKeyEvent->mKeyPressDispatched) {
nsKeyEvent keypressEvent(true, NS_KEY_PRESS, mWidget);
InitKeyEvent(currentKeyEvent->mKeyEvent, keypressEvent);
if (currentKeyEvent->mKeyDownHandled ||
currentKeyEvent->mCausedOtherKeyEvents) {
keypressEvent.flags |= NS_EVENT_FLAG_NO_DEFAULT;
}
currentKeyEvent->mKeyPressHandled = DispatchEvent(keypressEvent);
currentKeyEvent->mKeyPressDispatched = true;
PR_LOG(gLog, PR_LOG_ALWAYS,
("%p TextInputHandler::DoCommandBySelector, keypress event "
"dispatched, Destroyed()=%s, keypressHandled=%s",
this, TrueOrFalse(Destroyed()),
TrueOrFalse(currentKeyEvent->mKeyPressHandled)));
}
return !Destroyed() && currentKeyEvent &&
(currentKeyEvent->mKeyPressHandled ||
currentKeyEvent->mCausedOtherKeyEvents);
return !Destroyed() && mCurrentKeyEvent.mKeyPressHandled;
}

Просмотреть файл

@ -373,17 +373,18 @@ TaskbarPreview::GetWindowHook() {
void
TaskbarPreview::EnableCustomDrawing(HWND aHWND, bool aEnable) {
BOOL enabled = aEnable;
nsUXThemeData::dwmSetWindowAttributePtr(
aHWND,
DWMWA_FORCE_ICONIC_REPRESENTATION,
&aEnable,
sizeof(aEnable));
&enabled,
sizeof(enabled));
nsUXThemeData::dwmSetWindowAttributePtr(
aHWND,
DWMWA_HAS_ICONIC_BITMAP,
&aEnable,
sizeof(aEnable));
&enabled,
sizeof(enabled));
}

Просмотреть файл

@ -434,6 +434,8 @@ nsresult nsClipboard::GetNativeDataOffClipboard(IDataObject * aDataObject, UINT
static CLIPFORMAT fileDescriptorFlavorA = ::RegisterClipboardFormat( CFSTR_FILEDESCRIPTORA );
static CLIPFORMAT fileDescriptorFlavorW = ::RegisterClipboardFormat( CFSTR_FILEDESCRIPTORW );
static CLIPFORMAT fileFlavor = ::RegisterClipboardFormat( CFSTR_FILECONTENTS );
static CLIPFORMAT preferredDropEffect = ::RegisterClipboardFormat(CFSTR_PREFERREDDROPEFFECT);
switch (stm.tymed) {
case TYMED_HGLOBAL:
{
@ -537,9 +539,17 @@ nsresult nsClipboard::GetNativeDataOffClipboard(IDataObject * aDataObject, UINT
// do that in FindPlatformHTML(). For now, return the allocLen. This
// case is mostly to ensure we don't try to call strlen on the buffer.
*aLen = allocLen;
} else if (fe.cfFormat == preferredDropEffect) {
// As per the MSDN doc entitled: "Shell Clipboard Formats"
// CFSTR_PREFERREDDROPEFFECT should return a DWORD
// Reference: http://msdn.microsoft.com/en-us/library/bb776902(v=vs.85).aspx
NS_ASSERTION(allocLen == sizeof(DWORD),
"CFSTR_PREFERREDDROPEFFECT should return a DWORD");
*aLen = allocLen;
} else {
*aLen = nsCRT::strlen(reinterpret_cast<PRUnichar*>(*aData)) *
sizeof(PRUnichar);
}
else
*aLen = nsCRT::strlen(reinterpret_cast<PRUnichar*>(*aData)) * sizeof(PRUnichar);
result = NS_OK;
}
}

Просмотреть файл

@ -62,7 +62,8 @@ static POINTL gDragLastPoint;
*/
nsNativeDragTarget::nsNativeDragTarget(nsIWidget * aWnd)
: m_cRef(0),
mEffectsAllowed(DROPEFFECT_MOVE | DROPEFFECT_COPY | DROPEFFECT_LINK),
mEffectsAllowed(DROPEFFECT_MOVE | DROPEFFECT_COPY | DROPEFFECT_LINK),
mEffectsPreferred(DROPEFFECT_NONE),
mTookOwnRef(PR_FALSE), mWindow(aWnd), mDropTargetHelper(nsnull)
{
mHWnd = (HWND)mWindow->GetNativeData(NS_NATIVE_WINDOW);
@ -127,44 +128,52 @@ void
nsNativeDragTarget::GetGeckoDragAction(DWORD grfKeyState, LPDWORD pdwEffect,
PRUint32 * aGeckoAction)
{
// If a window is disabled or a modal window is on top of
// it (which implies it is disabled), then we should not allow dropping.
// If a window is disabled or a modal window is on top of it
// (which implies it is disabled), then we should not allow dropping.
bool isEnabled;
if (NS_SUCCEEDED(mWindow->IsEnabled(&isEnabled)) && !isEnabled) {
*pdwEffect = DROPEFFECT_NONE;
*aGeckoAction = nsIDragService::DRAGDROP_ACTION_NONE;
return;
}
// Only a single effect should be specified outgoing for the parameter pdwEffect.
// When Shift and Control are pressed, we should specify a LINK effect.
else if (!mMovePreferred && (grfKeyState & MK_CONTROL) &&
(grfKeyState & MK_SHIFT) && (mEffectsAllowed & DROPEFFECT_LINK)) {
*pdwEffect = DROPEFFECT_LINK;
*aGeckoAction = nsIDragService::DRAGDROP_ACTION_LINK;
// If the user explicitly uses a modifier key, they want the associated action
// Shift + Control -> LINK, Shift -> MOVE, Ctrl -> COPY
DWORD desiredEffect = DROPEFFECT_NONE;
if ((grfKeyState & MK_CONTROL) && (grfKeyState & MK_SHIFT)) {
desiredEffect = DROPEFFECT_LINK;
} else if (grfKeyState & MK_SHIFT) {
desiredEffect = DROPEFFECT_MOVE;
} else if (grfKeyState & MK_CONTROL) {
desiredEffect = DROPEFFECT_COPY;
}
// When Shift is pressed we should specify a MOVE effect.
else if ((mEffectsAllowed & DROPEFFECT_MOVE) &&
(mMovePreferred || (grfKeyState & MK_SHIFT))) {
// Determine the desired effect from what is allowed and preferred.
if (!(desiredEffect &= mEffectsAllowed)) {
// No modifier key effect is set which is also allowed, check
// the preference of the data.
desiredEffect = mEffectsPreferred & mEffectsAllowed;
if (!desiredEffect) {
// No preference is set, so just fall back to the allowed effect itself
desiredEffect = mEffectsAllowed;
}
}
// Otherwise we should specify the first available effect
// from MOVE, COPY, or LINK.
if (desiredEffect & DROPEFFECT_MOVE) {
*pdwEffect = DROPEFFECT_MOVE;
*aGeckoAction = nsIDragService::DRAGDROP_ACTION_MOVE;
}
// When Control is pressed we should specify a COPY effect.
else if ((mEffectsAllowed & DROPEFFECT_COPY) && (grfKeyState & MK_CONTROL)) {
} else if (desiredEffect & DROPEFFECT_COPY) {
*pdwEffect = DROPEFFECT_COPY;
*aGeckoAction = nsIDragService::DRAGDROP_ACTION_COPY;
}
// Otherwise we should specify the first available effect from MOVE, COPY, or LINK.
else if (mEffectsAllowed & DROPEFFECT_MOVE) {
*pdwEffect = DROPEFFECT_MOVE;
*aGeckoAction = nsIDragService::DRAGDROP_ACTION_MOVE;
}
else if (mEffectsAllowed & DROPEFFECT_COPY) {
*pdwEffect = DROPEFFECT_COPY;
*aGeckoAction = nsIDragService::DRAGDROP_ACTION_COPY;
}
else if (mEffectsAllowed & DROPEFFECT_LINK) {
} else if (desiredEffect & DROPEFFECT_LINK) {
*pdwEffect = DROPEFFECT_LINK;
*aGeckoAction = nsIDragService::DRAGDROP_ACTION_LINK;
}
} else {
*pdwEffect = DROPEFFECT_NONE;
*aGeckoAction = nsIDragService::DRAGDROP_ACTION_NONE;
}
}
inline
@ -275,15 +284,11 @@ nsNativeDragTarget::DragEnter(LPDATAOBJECT pIDataSource,
nsresult loadResult = nsClipboard::GetNativeDataOffClipboard(
pIDataSource, 0, ::RegisterClipboardFormat(CFSTR_PREFERREDDROPEFFECT), nsnull, &tempOutData, &tempDataLen);
if (NS_SUCCEEDED(loadResult) && tempOutData) {
NS_ASSERTION(tempDataLen == 2, "Expected word size");
WORD preferredEffect = *((WORD*)tempOutData);
// Mask effect coming from function call with effect preferred by the source.
mMovePreferred = (preferredEffect & DROPEFFECT_MOVE) != 0;
mEffectsPreferred = *((DWORD*)tempOutData);
nsMemory::Free(tempOutData);
} else {
mMovePreferred = PR_FALSE;
// We have no preference if we can't obtain it
mEffectsPreferred = DROPEFFECT_NONE;
}
// Set the native data object into drag service

Просмотреть файл

@ -113,7 +113,7 @@ protected:
ULONG m_cRef; // reference count
HWND mHWnd;
DWORD mEffectsAllowed;
bool mMovePreferred;
DWORD mEffectsPreferred;
bool mTookOwnRef;
// Gecko Stuff